From 97397e63da63e6effaeb4542187e8fb3ef022b0b Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 8 Aug 2018 13:09:51 -0400 Subject: [PATCH 01/93] simple distribution overview --- docs/spec/simple-distribution/end_block.md | 36 ++ .../future_improvements.md | 16 + docs/spec/simple-distribution/overview.md | 64 +++ docs/spec/simple-distribution/state.md | 100 +++++ docs/spec/simple-distribution/transactions.md | 399 ++++++++++++++++++ docs/spec/simple-distribution/triggers.md | 31 ++ 6 files changed, 646 insertions(+) create mode 100644 docs/spec/simple-distribution/end_block.md create mode 100644 docs/spec/simple-distribution/future_improvements.md create mode 100644 docs/spec/simple-distribution/overview.md create mode 100644 docs/spec/simple-distribution/state.md create mode 100644 docs/spec/simple-distribution/transactions.md create mode 100644 docs/spec/simple-distribution/triggers.md diff --git a/docs/spec/simple-distribution/end_block.md b/docs/spec/simple-distribution/end_block.md new file mode 100644 index 0000000000..bc6847ef4b --- /dev/null +++ b/docs/spec/simple-distribution/end_block.md @@ -0,0 +1,36 @@ +# End Block + +At each endblock, the fees received are sorted to the proposer, community fund, +and global pool. When the validator is the proposer of the round, that +validator (and their delegators) receives between 1% and 5% of fee rewards, the +reserve tax is then charged, then the remainder is distributed proportionally +by voting power to all bonded validators independent of whether they voted +(social distribution). Note the social distribution is applied to proposer +validator in addition to the proposer reward. + +The amount of proposer reward is calculated from pre-commits Tendermint +messages in order to incentivize validators to wait and include additional +pre-commits in the block. All provision rewards are added to a provision reward +pool which validator holds individually +(`ValidatorDistribution.ProvisionsRewardPool`). + +``` +func SortFees(feesCollected sdk.Coins, global Global, proposer ValidatorDistribution, + sumPowerPrecommitValidators, totalBondedTokens, communityTax sdk.Dec) + + feesCollectedDec = MakeDecCoins(feesCollected) + proposerReward = feesCollectedDec * (0.01 + 0.04 + * sumPowerPrecommitValidators / totalBondedTokens) + proposer.ProposerPool += proposerReward + + communityFunding = feesCollectedDec * communityTax + global.CommunityFund += communityFunding + + poolReceived = feesCollectedDec - proposerReward - communityFunding + global.Pool += poolReceived + global.EverReceivedPool += poolReceived + global.LastReceivedPool = poolReceived + + SetValidatorDistribution(proposer) + SetGlobal(global) +``` diff --git a/docs/spec/simple-distribution/future_improvements.md b/docs/spec/simple-distribution/future_improvements.md new file mode 100644 index 0000000000..954fb4d623 --- /dev/null +++ b/docs/spec/simple-distribution/future_improvements.md @@ -0,0 +1,16 @@ +## Future Improvements + +### Power Change + +Within the current implementation all power changes ever made are indefinitely stored +within the current state. In the future this state should be trimmed on an epoch basis. Delegators +which will have not withdrawn their fees will be penalized in some way, depending on what is +computationally feasible this may include: + - burning non-withdrawn fees + - requiring more expensive withdrawal costs which include proofs from archive nodes of historical state + +In addition or as an alternative it may make sense to implement a "rolling" epoch which cycles through +all the delegators in small groups (for example 5 delegators per block) and just runs the withdrawal transaction +at standard rates and takes transaction fees from the withdrawal amount. + + diff --git a/docs/spec/simple-distribution/overview.md b/docs/spec/simple-distribution/overview.md new file mode 100644 index 0000000000..62cec2e768 --- /dev/null +++ b/docs/spec/simple-distribution/overview.md @@ -0,0 +1,64 @@ +# Distribution + +## Overview + +This _simple_ distribution mechanism describes a functional way to passively +distribute rewards between validator and delegators. Note that this mechanism does +not distribute funds in as precisely as active reward distribution and will therefor +be upgraded in the future. + +The mechanism operates as follows. Collected rewards are pooled globally and +divided out passively to validators and delegators. Each validator has the +opportunity to charge commission to the delegators on the rewards collected on +behalf of the delegators by the validators. Fees are paid directly into a +global reward pool, and validator proposer-reward pool. Due to the nature of +passive accounting whenever changes to parameters which affect the rate of reward +distribution occurs, withdrawal of rewards must also occur when: + + - withdrawing one must withdrawal the maximum amount they are entitled + too, leaving nothing in the pool, + - bonding, unbonding, or re-delegating tokens to an existing account a + full withdrawal of the rewards must occur (as the rules for lazy accounting + change), + - a validator chooses to change the commission on rewards, all accumulated + commission rewards must be simultaneously withdrawn. + +The above scenarios are covered in `triggers.md`. + +The distribution mechanism outlines herein is used to lazily distribute the +following rewards between validators and associated delegators: + - multi-token fees to be socially distributed, + - proposer reward pool, + - inflated atom provisions, and + - validator commission on all rewards earned by their delegators stake + +Fees are pooled within a global pool, as well as validator specific +proposer-reward pools. The mechanisms used allow for validators and delegators +to independently and lazily withdrawn their rewards. + +Within this spec + +As a part of the lazy computations, each validator and delegator holds an +accumulation term which is used to estimate what their approximate fair portion +of tokens held in the global pool is owed to them. This approximation of owed +rewards would be equivalent to the active distribution under the situation that +there was a constant flow of incoming reward tokens every block. Because this +is not the case, the approximation of owed rewards will deviate from the active +distribution based on fluctuations of incoming reward tokens as well as timing +of reward withdrawal by other delegators and validators from the reward pool. + + +## Affect on Staking + +Charging commission on Atom provisions while also allowing for Atom-provisions +to be auto-bonded (distributed directly to the validators bonded stake) is +problematic within DPoS. Fundamentally these two mechnisms are mutually +exclusive. If there are atoms commissions and auto-bonding Atoms, the portion +of Atoms the reward distribution calculation would become very large as the Atom +portion for each delegator would change each block making a withdrawal of rewards +for a delegator require a calculation for every single block since the last +withdrawal. In conclusion we can only have atom commission and unbonded atoms +provisions, or bonded atom provisions with no Atom commission, and we elect to +implement the former. Stakeholders wishing to rebond their provisions may elect +to set up a script to periodically withdraw and rebond rewards. + diff --git a/docs/spec/simple-distribution/state.md b/docs/spec/simple-distribution/state.md new file mode 100644 index 0000000000..7865c085ec --- /dev/null +++ b/docs/spec/simple-distribution/state.md @@ -0,0 +1,100 @@ +## State + +### Global + +All globally tracked parameters for distribution are stored within +`Global`. Rewards are collected and added to the reward pool and +distributed to validators/delegators from here. + +Note that the reward pool holds decimal coins (`DecCoins`) to allow +for fractions of coins to be received from operations like inflation. +When coins are distributed from the pool they are truncated back to +`sdk.Coins` which are non-decimal. + + - Global: `0x00 -> amino(global)` + +```golang +// coins with decimal +type DecCoins []DecCoin + +type DecCoin struct { + Amount sdk.Dec + Denom string +} + +type Global struct { + PrevBondedTokens sdk.Dec // bonded token amount for the global pool on the previous block + Adjustment sdk.Dec // global adjustment factor for lazy calculations + Pool DecCoins // funds for all validators which have yet to be withdrawn + PrevReceivedPool DecCoins // funds added to the pool on the previous block + EverReceivedPool DecCoins // total funds ever added to the pool + CommunityFund DecCoins // pool for community funds yet to be spent +} +``` + +### Validator Distribution + +Validator distribution information for the relevant validator is updated each time: + 1. delegation amount to a validator are updated, + 2. a validator successfully proposes a block and receives a reward, + 3. any delegator withdraws from a validator, or + 4. the validator withdraws it's commission. + + - ValidatorDistribution: `0x02 | ValOwnerAddr -> amino(validatorDistribution)` + +```golang +type ValidatorDistribution struct { + CommissionWithdrawalHeight int64 // last time this validator withdrew commission + Adjustment sdk.Dec // global pool adjustment factor + ProposerAdjustment DecCoins // proposer pool adjustment factor + ProposerPool DecCoins // reward pool collected from being the proposer + EverReceivedProposerReward DecCoins // all rewards ever collected from being the proposer + PrevReceivedProposerReward DecCoins // previous rewards collected from being the proposer + PrevBondedTokens sdk.Dec // bonded token amount on the previous block + PrevDelegatorShares sdk.Dec // amount of delegator shares for the validator on the previous block +} +``` + +### Delegation Distribution + +Each delegation holds multiple adjustment factors to specify its entitlement to +the rewards from a validator. `AdjustmentPool` is used to passively calculate +each bonds entitled fees from the `RewardPool`. `AdjustmentPool` is used to +passively calculate each bonds entitled fees from +`ValidatorDistribution.ProposerRewardPool` + + - DelegatorDistribution: ` 0x02 | DelegatorAddr | ValOwnerAddr -> amino(delegatorDist)` + +```golang +type DelegatorDist struct { + WithdrawalHeight int64 // last time this delegation withdrew rewards + Adjustment sdk.Dec // fee provisioning adjustment factor + AdjustmentProposer DecCoins // proposers pool adjustment factor + PrevTokens sdk.Dec // bonded tokens held by the delegation on the previous block + PrevShares sdk.Dec // delegator shares held by the delegation on the previous block +} +``` + +### Power Change + +Every instance that the voting power changes, information about the state of +the validator set during the change must be recorded as a `PowerChange` for +other validators to run through. Each power change is indexed by its block +height. + + - PowerChange: `0x03 | amino(Height) -> amino(validatorDist)` + +```golang +type PowerChange struct { + Height int64 // block height at change + ValidatorBondedTokens sdk.Dec // following used to create distribution scenarios + ValidatorDelegatorShares sdk.Dec + ValidatorDelegatorShareExRate sdk.Dec + ValidatorCommission sdk.Dec + PoolBondedTokens sdk.Dec + Global Global + ValDistr ValidatorDistribution + DelegationShares sdk.Dec + DelDistr DelegatorDistribution +} +``` diff --git a/docs/spec/simple-distribution/transactions.md b/docs/spec/simple-distribution/transactions.md new file mode 100644 index 0000000000..1401c3b851 --- /dev/null +++ b/docs/spec/simple-distribution/transactions.md @@ -0,0 +1,399 @@ +# Transactions + +## TxWithdrawDelegation + +When a delegator wishes to withdraw their transaction fees it must send +`TxWithdrawDelegation`. Note that parts of this transaction logic are also +triggered each with any change in individual delegations, such as an unbond, +redelegation, or delegation of additional tokens to a specific validator. + +Each time a withdrawal is made by a recipient the adjustment term must be +modified for each block with a change in distributors shares since the time of +last withdrawal. This is accomplished by iterating over all relevant +`PowerChange`'s stored in distribution state. + + +```golang +type TxWithdrawDelegation struct { + delegatorAddr sdk.AccAddress + withdrawAddr sdk.AccAddress // address to make the withdrawal to +} + +func WithdrawDelegator(delegatorAddr, withdrawAddr sdk.AccAddress) + entitlement = GetDelegatorEntitlement(delegatorAddr) + AddCoins(withdrawAddr, totalEntitlment.TruncateDecimal()) + +func GetDelegatorEntitlement(delegatorAddr sdk.AccAddress) DecCoins + + // compile all the distribution scenarios + delegations = GetDelegations(delegatorAddr) + DelDistr = GetDelegationDistribution(delegation.DelegatorAddr, + delegation.ValidatorAddr) + pcs = GetPowerChanges(DelDistr.WithdrawalHeight) + + // update all adjustment factors for each delegation since last withdrawal + for pc = range pcs + for delegation = range delegations + DelDistr = GetDelegationDistribution(delegation.DelegatorAddr, + delegation.ValidatorAddr) + pc.ProcessPowerChangeDelegation(delegation, DelDistr) + + // collect all entitled fees + entitlement = 0 + for delegation = range delegations + global = GetGlobal() + pool = GetPool() + DelDistr = GetDelegationDistribution(delegation.DelegatorAddr, + delegation.ValidatorAddr) + ValDistr = GetValidatorDistribution(delegation.ValidatorAddr) + validator = GetValidator(delegation.ValidatorAddr) + + scenerio1 = NewDelegationFromGlobalPool(delegation, validator, + pool, global, ValDistr, DelDistr) + scenerio2 = NewDelegationFromProvisionPool(delegation, validator, + ValDistr, DelDistr) + entitlement += scenerio1.WithdrawalEntitlement() + entitlement += scenerio2.WithdrawalEntitlement() + + return entitlement + +func (pc PowerChange) ProcessPowerChangeDelegation(delegation sdk.Delegation, + DelDistr DelegationDistribution) + + // get the historical scenarios + scenario1 = pc.DelegationFromGlobalPool(delegation, DelDistr) + scenario2 = pc.DelegationFromProvisionPool(delegation, DelDistr) + + // process the adjustment factors + scenario1.UpdateAdjustmentForPowerChange(pc.Height) + scenario2.UpdateAdjustmentForPowerChange(pc.Height) +``` + +## TxWithdrawValidator + +When a validator wishes to withdraw their transaction fees it must send +`TxWithdrawDelegation`. Note that parts of this transaction logic is also +triggered each with any change in individual delegations, such as an unbond, +redelegation, or delegation of additional tokens to a specific validator. This +transaction withdraws the validators commission rewards, as well as any rewards +earning on their self-delegation. + +```golang +type TxWithdrawValidator struct { + ownerAddr sdk.AccAddress // validator address to withdraw from + withdrawAddr sdk.AccAddress // address to make the withdrawal to +} + +func WithdrawalValidator(ownerAddr, withdrawAddr sdk.AccAddress) + + // update the delegator adjustment factors and also withdrawal delegation fees + entitlement = GetDelegatorEntitlement(ownerAddr) + + // update the validator adjustment factors for commission + ValDistr = GetValidatorDistribution(ownerAddr.ValidatorAddr) + pcs = GetPowerChanges(ValDistr.CommissionWithdrawalHeight) + for pc = range pcs + pc.ProcessPowerChangeCommission() + + // withdrawal validator commission rewards + global = GetGlobal() + pool = GetPool() + ValDistr = GetValidatorDistribution(delegation.ValidatorAddr) + validator = GetValidator(delegation.ValidatorAddr) + + scenerio1 = NewCommissionFromGlobalPool(validator, + pool, global, ValDistr) + scenerio2 = CommissionFromProposerPool(validator, ValDistr) + entitlement += scenerio1.WithdrawalEntitlement() + entitlement += scenerio2.WithdrawalEntitlement() + + AddCoins(withdrawAddr, totalEntitlment.TruncateDecimal()) + +func (pc PowerChange) ProcessPowerChangeCommission() + + // get the historical scenarios + scenario1 = pc.CommissionFromGlobalPool() + scenario2 = pc.CommissionFromProposerPool() + + // process the adjustment factors + scenario1.UpdateAdjustmentForPowerChange(pc.Height) + scenario2.UpdateAdjustmentForPowerChange(pc.Height) +``` + +## Common Calculations + +### Distribution scenario + +A common form of abstracted calculations exists between validators and +delegations attempting to withdrawal their rewards, either from `Global.Pool` +or from `ValidatorDistribution.ProposerPool`. With the following interface +fulfilled the entitled fees for the various scenarios can be calculated. + +```golang +type DistributionScenario interface { + DistributorTokens() DecCoins // current tokens from distributor + DistributorCumulativeTokens() DecCoins // total tokens ever received + DistributorPrevReceivedTokens() DecCoins // last value of tokens received + DistributorShares() sdk.Dec // current shares + DistributorPrevShares() sdk.Dec // shares last block + + RecipientAdjustment() sdk.Dec + RecipientShares() sdk.Dec // current shares + RecipientPrevShares() sdk.Dec // shares last block + + ModifyAdjustments(withdrawal sdk.Dec) // proceedure to modify adjustment factors +} +``` + +#### Entitled reward from distribution scenario + +The entitlement to the distributor's tokens held can be accounted for lazily. +To begin this calculation we must determine the recipient's _simple pool_ and +_projected pool_. The simple pool represents a lazy accounting of what a +recipient's entitlement to the distributor's tokens would be if all recipients +for that distributor had static shares (equal to the current shares), and no +recipients had ever withdrawn their entitled rewards. The projected pool +represents the anticipated recipient's entitlement to the distributors tokens +based on the current blocks token input (for example fees reward received) to +the distributor, and the distributor's tokens and shares of the previous block +assuming that neither had changed in the current block. Using the simple and +projected pools we can determine all cumulative changes which have taken place +outside of the recipient and adjust the recipient's _adjustment factor_ to +account for these changes and ultimately keep track of the correct entitlement +to the distributors tokens. + +``` +func (d DistributionScenario) RecipientCount(height int64) sdk.Dec + return v.RecipientShares() * height + +func (d DistributionScenario) GlobalCount(height int64) sdk.Dec + return d.DistributorShares() * height + +func (d DistributionScenario) SimplePool() DecCoins + return d.RecipientCount() / d.GlobalCount() * d.DistributorCumulativeTokens + +func (d DistributionScenario) ProjectedPool(height int64) DecCoins + return d.RecipientPrevShares() * (height-1) + / (d.DistributorPrevShares() * (height-1)) + * d.DistributorCumulativeTokens + + d.RecipientShares() / d.DistributorShares() + * d.DistributorPrevReceivedTokens() +``` + +The `DistributionScenario` _adjustment_ terms account for changes in +recipient/distributor shares and recipient withdrawals. The adjustment factor +must be modified whenever the recipient withdraws from the distributor or the +distributor's/recipient's shares are changed. + - When the shares of the recipient is changed the adjustment factor is + increased/decreased by the difference between the _simple_ and _projected_ + pools. In other words, the cumulative difference in the shares if the shares + has been the new shares as opposed to the old shares for the entire duration of + the blockchain up the previous block. + - When a recipient makes a withdrawal the adjustment factor is increased by the + withdrawal amount. + +``` +func (d DistributionScenario) UpdateAdjustmentForPowerChange(height int64) + simplePool = d.SimplePool() + projectedPool = d.ProjectedPool(height) + AdjustmentChange = simplePool - projectedPool + if AdjustmentChange > 0 + d.ModifyAdjustments(AdjustmentChange) + +func (d DistributionScenario) WithdrawalEntitlement() DecCoins + entitlement = d.SimplePool() - d.RecipientAdjustment() + d.ModifyAdjustments(entitlement) + return entitlement +``` + +### Distribution scenarios + +Note that the distribution scenario structures are found in `state.md`. + +#### Delegation's entitlement to Global.Pool + +For delegations (including validator's self-delegation) all fees from fee pool +are subject to commission rate from the owner of the validator. The global +shares should be taken as true number of global bonded shares. The recipients +shares should be taken as the bonded tokens less the validator's commission. + +``` +type DelegationFromGlobalPool struct { + DelegationShares sdk.Dec + ValidatorCommission sdk.Dec + ValidatorBondedTokens sdk.Dec + ValidatorDelegatorShareExRate sdk.Dec + PoolBondedTokens sdk.Dec + Global Global + ValDistr ValidatorDistribution + DelDistr DelegatorDistribution +} + +func (d DelegationFromGlobalPool) DistributorTokens() DecCoins + return d.Global.Pool + +func (d DelegationFromGlobalPool) DistributorCumulativeTokens() DecCoins + return d.Global.EverReceivedPool + +func (d DelegationFromGlobalPool) DistributorPrevReceivedTokens() DecCoins + return d.Global.PrevReceivedPool + +func (d DelegationFromGlobalPool) DistributorShares() sdk.Dec + return d.PoolBondedTokens + +func (d DelegationFromGlobalPool) DistributorPrevShares() sdk.Dec + return d.Global.PrevBondedTokens + +func (d DelegationFromGlobalPool) RecipientShares() sdk.Dec + return d.DelegationShares * d.ValidatorDelegatorShareExRate() * + d.ValidatorBondedTokens() * (1 - d.ValidatorCommission) + +func (d DelegationFromGlobalPool) RecipientPrevShares() sdk.Dec + return d.DelDistr.PrevTokens + +func (d DelegationFromGlobalPool) RecipientAdjustment() sdk.Dec + return d.DelDistr.Adjustment + +func (d DelegationFromGlobalPool) ModifyAdjustments(withdrawal sdk.Dec) + d.ValDistr.Adjustment += withdrawal + d.DelDistr.Adjustment += withdrawal + d.global.Adjustment += withdrawal + SetValidatorDistribution(d.ValDistr) + SetDelegatorDistribution(d.DelDistr) + SetGlobal(d.Global) +``` + +#### Delegation's entitlement to ValidatorDistribution.ProposerPool + +Delegations (including validator's self-delegation) are still subject +commission on the rewards gained from the proposer pool. Global shares in this +context is actually the validators total delegations shares. The recipient's +shares is taken as the effective delegation shares less the validator's +commission. + +``` +type DelegationFromProposerPool struct { + DelegationShares sdk.Dec + ValidatorCommission sdk.Dec + ValidatorDelegatorShares sdk.Dec + ValDistr ValidatorDistribution + DelDistr DelegatorDistribution +} + +func (d DelegationFromProposerPool) DistributorTokens() DecCoins + return d.ValDistr.ProposerPool + +func (d DelegationFromProposerPool) DistributorCumulativeTokens() DecCoins + return d.ValDistr.EverReceivedProposerReward + +func (d DelegationFromProposerPool) DistributorPrevReceivedTokens() DecCoins + return d.ValDistr.PrevReceivedProposerReward + +func (d DelegationFromProposerPool) DistributorShares() sdk.Dec + return d.ValidatorDelegatorShares + +func (d DelegationFromProposerPool) DistributorPrevShares() sdk.Dec + return d.ValDistr.PrevDelegatorShares + +func (d DelegationFromProposerPool) RecipientShares() sdk.Dec + return d.DelegationShares * (1 - d.ValidatorCommission) + +func (d DelegationFromProposerPool) RecipientPrevShares() sdk.Dec + return d.DelDistr.PrevShares + +func (d DelegationFromProposerPool) RecipientAdjustment() sdk.Dec + return d.DelDistr.AdjustmentProposer + +func (d DelegationFromProposerPool) ModifyAdjustments(withdrawal sdk.Dec) + d.ValDistr.AdjustmentProposer += withdrawal + d.DelDistr.AdjustmentProposer += withdrawal + SetValidatorDistribution(d.ValDistr) + SetDelegatorDistribution(d.DelDistr) +``` + +#### Validators's commission entitlement to Global.Pool + +Similar to a delegator's entitlement, but with recipient shares based on the +commission portion of bonded tokens. + +``` +type CommissionFromGlobalPool struct { + ValidatorBondedTokens sdk.Dec + ValidatorCommission sdk.Dec + PoolBondedTokens sdk.Dec + Global Global + ValDistr ValidatorDistribution +} + +func (c CommissionFromGlobalPool) DistributorTokens() DecCoins + return c.Global.Pool + +func (c CommissionFromGlobalPool) DistributorCumulativeTokens() DecCoins + return c.Global.EverReceivedPool + +func (c CommissionFromGlobalPool) DistributorPrevReceivedTokens() DecCoins + return c.Global.PrevReceivedPool + +func (c CommissionFromGlobalPool) DistributorShares() sdk.Dec + return c.PoolBondedTokens + +func (c CommissionFromGlobalPool) DistributorPrevShares() sdk.Dec + return c.Global.PrevBondedTokens + +func (c CommissionFromGlobalPool) RecipientShares() sdk.Dec + return c.ValidatorBondedTokens() * c.ValidatorCommission + +func (c CommissionFromGlobalPool) RecipientPrevShares() sdk.Dec + return c.ValDistr.PrevBondedTokens * c.ValidatorCommission + +func (c CommissionFromGlobalPool) RecipientAdjustment() sdk.Dec + return c.ValDistr.Adjustment + +func (c CommissionFromGlobalPool) ModifyAdjustments(withdrawal sdk.Dec) + c.ValDistr.Adjustment += withdrawal + c.Global.Adjustment += withdrawal + SetValidatorDistribution(c.ValDistr) + SetGlobal(c.Global) +``` + +#### Validators's commission entitlement to ValidatorDistribution.ProposerPool + +Similar to a delegators entitlement to the proposer pool, but with recipient +shares based on the commission portion of the total delegator shares. + +``` +type CommissionFromProposerPool struct { + ValidatorDelegatorShares sdk.Dec + ValidatorCommission sdk.Dec + ValDistr ValidatorDistribution +} + +func (c CommissionFromProposerPool) DistributorTokens() DecCoins + return c.ValDistr.ProposerPool + +func (c CommissionFromProposerPool) DistributorCumulativeTokens() DecCoins + return c.ValDistr.EverReceivedProposerReward + +func (c CommissionFromProposerPool) DistributorPrevReceivedTokens() DecCoins + return c.ValDistr.PrevReceivedProposerReward + +func (c CommissionFromProposerPool) DistributorShares() sdk.Dec + return c.ValidatorDelegatorShares + +func (c CommissionFromProposerPool) DistributorPrevShares() sdk.Dec + return c.ValDistr.PrevDelegatorShares + +func (c CommissionFromProposerPool) RecipientShares() sdk.Dec + return c.ValidatorDelegatorShares * (c.ValidatorCommission) + +func (c CommissionFromProposerPool) RecipientPrevShares() sdk.Dec + return c.ValDistr.PrevDelegatorShares * (c.ValidatorCommission) + +func (c CommissionFromProposerPool) RecipientAdjustment() sdk.Dec + return c.ValDistr.AdjustmentProposer + +func (c CommissionFromProposerPool) ModifyAdjustments(withdrawal sdk.Dec) + c.ValDistr.AdjustmentProposer += withdrawal + SetValidatorDistribution(c.ValDistr) +``` + diff --git a/docs/spec/simple-distribution/triggers.md b/docs/spec/simple-distribution/triggers.md new file mode 100644 index 0000000000..8800609a44 --- /dev/null +++ b/docs/spec/simple-distribution/triggers.md @@ -0,0 +1,31 @@ +# Triggers + +## Create validator distribution + + - triggered-by: validator entering bonded validator group (`stake.bondValidator()`) + +Whenever a new validator is added to the Tendermint validator set they are +entitled to begin earning rewards of atom provisions and fees. At this point +`ValidatorDistribution.Pool()` must be zero (as the validator has not yet +earned any rewards) meaning that the initial value for `validator.Adjustment` +must be set to the value of `validator.SimplePool()` for the height which the +validator is added on the validator set. + +## Create or modify delegation distribution + + - triggered-by: `stake.TxDelegate`, `stake.TxBeginRedelegate`, `stake.TxBeginUnbonding` + +The pool of a new delegator bond will be 0 for the height at which the bond was +added. This is achieved by setting `DelegationDistribution.WithdrawalHeight` to +the height which the bond was added. Additionally the `AdjustmentPool` and +`AdjustmentProposerPool` must be set to the equivalent values of +`DelegationDistribution.SimplePool()` and +`DelegationDistribution.SimpleProposerPool()` for the height of delegation. + +## Commission rate change + + - triggered-by: `stake.TxEditValidator` + +If a validator changes its commission rate, all commission on fees must be +simultaneously withdrawn using the transaction `TxWithdrawValidator` + From eb6f51ed459ad49073f907199b118ca23e0acffc Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 8 Aug 2018 13:28:30 -0400 Subject: [PATCH 02/93] piggy bank state --- docs/spec/simple-distribution/state.md | 56 ++++++-------------------- 1 file changed, 12 insertions(+), 44 deletions(-) diff --git a/docs/spec/simple-distribution/state.md b/docs/spec/simple-distribution/state.md index 7865c085ec..757287004a 100644 --- a/docs/spec/simple-distribution/state.md +++ b/docs/spec/simple-distribution/state.md @@ -23,11 +23,8 @@ type DecCoin struct { } type Global struct { - PrevBondedTokens sdk.Dec // bonded token amount for the global pool on the previous block - Adjustment sdk.Dec // global adjustment factor for lazy calculations + Accum sdk.Dec // global accumulation factor for lazy calculations Pool DecCoins // funds for all validators which have yet to be withdrawn - PrevReceivedPool DecCoins // funds added to the pool on the previous block - EverReceivedPool DecCoins // total funds ever added to the pool CommunityFund DecCoins // pool for community funds yet to be spent } ``` @@ -44,57 +41,28 @@ Validator distribution information for the relevant validator is updated each ti ```golang type ValidatorDistribution struct { - CommissionWithdrawalHeight int64 // last time this validator withdrew commission - Adjustment sdk.Dec // global pool adjustment factor - ProposerAdjustment DecCoins // proposer pool adjustment factor - ProposerPool DecCoins // reward pool collected from being the proposer - EverReceivedProposerReward DecCoins // all rewards ever collected from being the proposer - PrevReceivedProposerReward DecCoins // previous rewards collected from being the proposer - PrevBondedTokens sdk.Dec // bonded token amount on the previous block - PrevDelegatorShares sdk.Dec // amount of delegator shares for the validator on the previous block + CommissionWithdrawalHeight int64 // last time this validator withdrew commission + Accum sdk.Dec // global pool accumulation factor + ProposerAccum sdk.Dec // proposer pool accumulation factor + ProposerPool DecCoins // reward pool collected from being the proposer } ``` ### Delegation Distribution -Each delegation holds multiple adjustment factors to specify its entitlement to -the rewards from a validator. `AdjustmentPool` is used to passively calculate -each bonds entitled fees from the `RewardPool`. `AdjustmentPool` is used to -passively calculate each bonds entitled fees from +Each delegation holds multiple accumulation factors to specify its entitlement to +the rewards from a validator. `Accum` is used to passively calculate +each bonds entitled rewards from the `RewardPool`. `AccumProposer` is used to +passively calculate each bonds entitled rewards from `ValidatorDistribution.ProposerRewardPool` - DelegatorDistribution: ` 0x02 | DelegatorAddr | ValOwnerAddr -> amino(delegatorDist)` ```golang type DelegatorDist struct { - WithdrawalHeight int64 // last time this delegation withdrew rewards - Adjustment sdk.Dec // fee provisioning adjustment factor - AdjustmentProposer DecCoins // proposers pool adjustment factor - PrevTokens sdk.Dec // bonded tokens held by the delegation on the previous block - PrevShares sdk.Dec // delegator shares held by the delegation on the previous block + WithdrawalHeight int64 // last time this delegation withdrew rewards + Accum sdk.Dec // reward provisioning accumulation factor + AccumProposer sdk.Dec // proposers pool accumulation factor } ``` -### Power Change - -Every instance that the voting power changes, information about the state of -the validator set during the change must be recorded as a `PowerChange` for -other validators to run through. Each power change is indexed by its block -height. - - - PowerChange: `0x03 | amino(Height) -> amino(validatorDist)` - -```golang -type PowerChange struct { - Height int64 // block height at change - ValidatorBondedTokens sdk.Dec // following used to create distribution scenarios - ValidatorDelegatorShares sdk.Dec - ValidatorDelegatorShareExRate sdk.Dec - ValidatorCommission sdk.Dec - PoolBondedTokens sdk.Dec - Global Global - ValDistr ValidatorDistribution - DelegationShares sdk.Dec - DelDistr DelegatorDistribution -} -``` From 2d613cefe7da94d9e9bdd30314e914c1447c499f Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 8 Aug 2018 14:24:38 -0400 Subject: [PATCH 03/93] move lamborghini distribution to subfolder --- .../WIP-lamborghini-distribution/README.md | 2 + .../end_block.md | 0 .../example_sheet/distribution.xlsx | Bin .../future_improvements.md | 0 .../WIP-lamborghini-distribution/overview.md | 54 ++++++++++ .../WIP-lamborghini-distribution/state.md | 100 ++++++++++++++++++ .../transactions.md | 0 .../WIP-lamborghini-distribution}/triggers.md | 0 docs/spec/distribution/overview.md | 54 ++++++---- docs/spec/distribution/state.md | 56 +++------- docs/spec/simple-distribution/overview.md | 64 ----------- docs/spec/simple-distribution/state.md | 68 ------------ 12 files changed, 200 insertions(+), 198 deletions(-) create mode 100644 docs/spec/distribution/WIP-lamborghini-distribution/README.md rename docs/spec/{simple-distribution => distribution/WIP-lamborghini-distribution}/end_block.md (100%) rename docs/spec/distribution/{ => WIP-lamborghini-distribution}/example_sheet/distribution.xlsx (100%) rename docs/spec/{simple-distribution => distribution/WIP-lamborghini-distribution}/future_improvements.md (100%) create mode 100644 docs/spec/distribution/WIP-lamborghini-distribution/overview.md create mode 100644 docs/spec/distribution/WIP-lamborghini-distribution/state.md rename docs/spec/{simple-distribution => distribution/WIP-lamborghini-distribution}/transactions.md (100%) rename docs/spec/{simple-distribution => distribution/WIP-lamborghini-distribution}/triggers.md (100%) delete mode 100644 docs/spec/simple-distribution/overview.md delete mode 100644 docs/spec/simple-distribution/state.md diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/README.md b/docs/spec/distribution/WIP-lamborghini-distribution/README.md new file mode 100644 index 0000000000..c09042f7f9 --- /dev/null +++ b/docs/spec/distribution/WIP-lamborghini-distribution/README.md @@ -0,0 +1,2 @@ +Please note that this folder is a WIP specification for an advanced fee distribution +mechanism which is not set to be implemented. diff --git a/docs/spec/simple-distribution/end_block.md b/docs/spec/distribution/WIP-lamborghini-distribution/end_block.md similarity index 100% rename from docs/spec/simple-distribution/end_block.md rename to docs/spec/distribution/WIP-lamborghini-distribution/end_block.md diff --git a/docs/spec/distribution/example_sheet/distribution.xlsx b/docs/spec/distribution/WIP-lamborghini-distribution/example_sheet/distribution.xlsx similarity index 100% rename from docs/spec/distribution/example_sheet/distribution.xlsx rename to docs/spec/distribution/WIP-lamborghini-distribution/example_sheet/distribution.xlsx diff --git a/docs/spec/simple-distribution/future_improvements.md b/docs/spec/distribution/WIP-lamborghini-distribution/future_improvements.md similarity index 100% rename from docs/spec/simple-distribution/future_improvements.md rename to docs/spec/distribution/WIP-lamborghini-distribution/future_improvements.md diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/overview.md b/docs/spec/distribution/WIP-lamborghini-distribution/overview.md new file mode 100644 index 0000000000..5e28e8b3b0 --- /dev/null +++ b/docs/spec/distribution/WIP-lamborghini-distribution/overview.md @@ -0,0 +1,54 @@ +# Distribution + +## Overview + +Collected fees are pooled globally and divided out passively to validators and +delegators. Each validator has the opportunity to charge commission to the +delegators on the fees collected on behalf of the delegators by the validators. +Fees are paid directly into a global fee pool, and validator proposer-reward +pool. Due to the nature of passive accounting whenever changes to parameters +which affect the rate of fee distribution occurs, withdrawal of fees must also +occur when: + + - withdrawing one must withdrawal the maximum amount they are entitled + too, leaving nothing in the pool, + - bonding, unbonding, or re-delegating tokens to an existing account a + full withdrawal of the fees must occur (as the rules for lazy accounting + change), + - a validator chooses to change the commission on fees, all accumulated + commission fees must be simultaneously withdrawn. + +The above scenarios are covered in `triggers.md`. + +The distribution mechanism outlines herein is used to lazily distribute the +following between validators and associated delegators: + - multi-token fees to be socially distributed, + - proposer reward pool, + - inflated atom provisions, and + - validator commission on all rewards earned by their delegators stake + +Fees are pooled within a global pool, as well as validator specific +proposer-reward pools. The mechanisms used allow for validators and delegators +to independently and lazily withdrawn their rewards. As a part of the lazy +computations adjustment factors must be maintained for each validator and +delegator to determine the true proportion of fees in each pool which they are +entitled too. Adjustment factors are updated every time a validator or +delegator's voting power changes. Validators and delegators must withdraw all +fees they are entitled too before they can change their portion of bonded +Atoms. + +## Affect on Staking + + +Charging commission on Atom provisions while also allowing for Atom-provisions +to be auto-bonded (distributed directly to the validators bonded stake) is +problematic within DPoS. Fundamentally these two mechnisms are mutually +exclusive. If there are atoms commissions and auto-bonding Atoms, the portion +of Atoms the fee distribution calculation would become very large as the Atom +portion for each delegator would change each block making a withdrawal of fees +for a delegator require a calculation for every single block since the last +withdrawal. In conclusion we can only have atom commission and unbonded atoms +provisions, or bonded atom provisions with no Atom commission, and we elect to +implement the former. Stakeholders wishing to rebond their provisions may elect +to set up a script to periodically withdraw and rebond fees. + diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/state.md b/docs/spec/distribution/WIP-lamborghini-distribution/state.md new file mode 100644 index 0000000000..7865c085ec --- /dev/null +++ b/docs/spec/distribution/WIP-lamborghini-distribution/state.md @@ -0,0 +1,100 @@ +## State + +### Global + +All globally tracked parameters for distribution are stored within +`Global`. Rewards are collected and added to the reward pool and +distributed to validators/delegators from here. + +Note that the reward pool holds decimal coins (`DecCoins`) to allow +for fractions of coins to be received from operations like inflation. +When coins are distributed from the pool they are truncated back to +`sdk.Coins` which are non-decimal. + + - Global: `0x00 -> amino(global)` + +```golang +// coins with decimal +type DecCoins []DecCoin + +type DecCoin struct { + Amount sdk.Dec + Denom string +} + +type Global struct { + PrevBondedTokens sdk.Dec // bonded token amount for the global pool on the previous block + Adjustment sdk.Dec // global adjustment factor for lazy calculations + Pool DecCoins // funds for all validators which have yet to be withdrawn + PrevReceivedPool DecCoins // funds added to the pool on the previous block + EverReceivedPool DecCoins // total funds ever added to the pool + CommunityFund DecCoins // pool for community funds yet to be spent +} +``` + +### Validator Distribution + +Validator distribution information for the relevant validator is updated each time: + 1. delegation amount to a validator are updated, + 2. a validator successfully proposes a block and receives a reward, + 3. any delegator withdraws from a validator, or + 4. the validator withdraws it's commission. + + - ValidatorDistribution: `0x02 | ValOwnerAddr -> amino(validatorDistribution)` + +```golang +type ValidatorDistribution struct { + CommissionWithdrawalHeight int64 // last time this validator withdrew commission + Adjustment sdk.Dec // global pool adjustment factor + ProposerAdjustment DecCoins // proposer pool adjustment factor + ProposerPool DecCoins // reward pool collected from being the proposer + EverReceivedProposerReward DecCoins // all rewards ever collected from being the proposer + PrevReceivedProposerReward DecCoins // previous rewards collected from being the proposer + PrevBondedTokens sdk.Dec // bonded token amount on the previous block + PrevDelegatorShares sdk.Dec // amount of delegator shares for the validator on the previous block +} +``` + +### Delegation Distribution + +Each delegation holds multiple adjustment factors to specify its entitlement to +the rewards from a validator. `AdjustmentPool` is used to passively calculate +each bonds entitled fees from the `RewardPool`. `AdjustmentPool` is used to +passively calculate each bonds entitled fees from +`ValidatorDistribution.ProposerRewardPool` + + - DelegatorDistribution: ` 0x02 | DelegatorAddr | ValOwnerAddr -> amino(delegatorDist)` + +```golang +type DelegatorDist struct { + WithdrawalHeight int64 // last time this delegation withdrew rewards + Adjustment sdk.Dec // fee provisioning adjustment factor + AdjustmentProposer DecCoins // proposers pool adjustment factor + PrevTokens sdk.Dec // bonded tokens held by the delegation on the previous block + PrevShares sdk.Dec // delegator shares held by the delegation on the previous block +} +``` + +### Power Change + +Every instance that the voting power changes, information about the state of +the validator set during the change must be recorded as a `PowerChange` for +other validators to run through. Each power change is indexed by its block +height. + + - PowerChange: `0x03 | amino(Height) -> amino(validatorDist)` + +```golang +type PowerChange struct { + Height int64 // block height at change + ValidatorBondedTokens sdk.Dec // following used to create distribution scenarios + ValidatorDelegatorShares sdk.Dec + ValidatorDelegatorShareExRate sdk.Dec + ValidatorCommission sdk.Dec + PoolBondedTokens sdk.Dec + Global Global + ValDistr ValidatorDistribution + DelegationShares sdk.Dec + DelDistr DelegatorDistribution +} +``` diff --git a/docs/spec/simple-distribution/transactions.md b/docs/spec/distribution/WIP-lamborghini-distribution/transactions.md similarity index 100% rename from docs/spec/simple-distribution/transactions.md rename to docs/spec/distribution/WIP-lamborghini-distribution/transactions.md diff --git a/docs/spec/simple-distribution/triggers.md b/docs/spec/distribution/WIP-lamborghini-distribution/triggers.md similarity index 100% rename from docs/spec/simple-distribution/triggers.md rename to docs/spec/distribution/WIP-lamborghini-distribution/triggers.md diff --git a/docs/spec/distribution/overview.md b/docs/spec/distribution/overview.md index 5e28e8b3b0..62cec2e768 100644 --- a/docs/spec/distribution/overview.md +++ b/docs/spec/distribution/overview.md @@ -2,26 +2,31 @@ ## Overview -Collected fees are pooled globally and divided out passively to validators and -delegators. Each validator has the opportunity to charge commission to the -delegators on the fees collected on behalf of the delegators by the validators. -Fees are paid directly into a global fee pool, and validator proposer-reward -pool. Due to the nature of passive accounting whenever changes to parameters -which affect the rate of fee distribution occurs, withdrawal of fees must also -occur when: +This _simple_ distribution mechanism describes a functional way to passively +distribute rewards between validator and delegators. Note that this mechanism does +not distribute funds in as precisely as active reward distribution and will therefor +be upgraded in the future. + +The mechanism operates as follows. Collected rewards are pooled globally and +divided out passively to validators and delegators. Each validator has the +opportunity to charge commission to the delegators on the rewards collected on +behalf of the delegators by the validators. Fees are paid directly into a +global reward pool, and validator proposer-reward pool. Due to the nature of +passive accounting whenever changes to parameters which affect the rate of reward +distribution occurs, withdrawal of rewards must also occur when: - withdrawing one must withdrawal the maximum amount they are entitled too, leaving nothing in the pool, - bonding, unbonding, or re-delegating tokens to an existing account a - full withdrawal of the fees must occur (as the rules for lazy accounting + full withdrawal of the rewards must occur (as the rules for lazy accounting change), - - a validator chooses to change the commission on fees, all accumulated - commission fees must be simultaneously withdrawn. + - a validator chooses to change the commission on rewards, all accumulated + commission rewards must be simultaneously withdrawn. The above scenarios are covered in `triggers.md`. The distribution mechanism outlines herein is used to lazily distribute the -following between validators and associated delegators: +following rewards between validators and associated delegators: - multi-token fees to be socially distributed, - proposer reward pool, - inflated atom provisions, and @@ -29,26 +34,31 @@ following between validators and associated delegators: Fees are pooled within a global pool, as well as validator specific proposer-reward pools. The mechanisms used allow for validators and delegators -to independently and lazily withdrawn their rewards. As a part of the lazy -computations adjustment factors must be maintained for each validator and -delegator to determine the true proportion of fees in each pool which they are -entitled too. Adjustment factors are updated every time a validator or -delegator's voting power changes. Validators and delegators must withdraw all -fees they are entitled too before they can change their portion of bonded -Atoms. +to independently and lazily withdrawn their rewards. + +Within this spec + +As a part of the lazy computations, each validator and delegator holds an +accumulation term which is used to estimate what their approximate fair portion +of tokens held in the global pool is owed to them. This approximation of owed +rewards would be equivalent to the active distribution under the situation that +there was a constant flow of incoming reward tokens every block. Because this +is not the case, the approximation of owed rewards will deviate from the active +distribution based on fluctuations of incoming reward tokens as well as timing +of reward withdrawal by other delegators and validators from the reward pool. + ## Affect on Staking - Charging commission on Atom provisions while also allowing for Atom-provisions to be auto-bonded (distributed directly to the validators bonded stake) is problematic within DPoS. Fundamentally these two mechnisms are mutually exclusive. If there are atoms commissions and auto-bonding Atoms, the portion -of Atoms the fee distribution calculation would become very large as the Atom -portion for each delegator would change each block making a withdrawal of fees +of Atoms the reward distribution calculation would become very large as the Atom +portion for each delegator would change each block making a withdrawal of rewards for a delegator require a calculation for every single block since the last withdrawal. In conclusion we can only have atom commission and unbonded atoms provisions, or bonded atom provisions with no Atom commission, and we elect to implement the former. Stakeholders wishing to rebond their provisions may elect -to set up a script to periodically withdraw and rebond fees. +to set up a script to periodically withdraw and rebond rewards. diff --git a/docs/spec/distribution/state.md b/docs/spec/distribution/state.md index 7865c085ec..757287004a 100644 --- a/docs/spec/distribution/state.md +++ b/docs/spec/distribution/state.md @@ -23,11 +23,8 @@ type DecCoin struct { } type Global struct { - PrevBondedTokens sdk.Dec // bonded token amount for the global pool on the previous block - Adjustment sdk.Dec // global adjustment factor for lazy calculations + Accum sdk.Dec // global accumulation factor for lazy calculations Pool DecCoins // funds for all validators which have yet to be withdrawn - PrevReceivedPool DecCoins // funds added to the pool on the previous block - EverReceivedPool DecCoins // total funds ever added to the pool CommunityFund DecCoins // pool for community funds yet to be spent } ``` @@ -44,57 +41,28 @@ Validator distribution information for the relevant validator is updated each ti ```golang type ValidatorDistribution struct { - CommissionWithdrawalHeight int64 // last time this validator withdrew commission - Adjustment sdk.Dec // global pool adjustment factor - ProposerAdjustment DecCoins // proposer pool adjustment factor - ProposerPool DecCoins // reward pool collected from being the proposer - EverReceivedProposerReward DecCoins // all rewards ever collected from being the proposer - PrevReceivedProposerReward DecCoins // previous rewards collected from being the proposer - PrevBondedTokens sdk.Dec // bonded token amount on the previous block - PrevDelegatorShares sdk.Dec // amount of delegator shares for the validator on the previous block + CommissionWithdrawalHeight int64 // last time this validator withdrew commission + Accum sdk.Dec // global pool accumulation factor + ProposerAccum sdk.Dec // proposer pool accumulation factor + ProposerPool DecCoins // reward pool collected from being the proposer } ``` ### Delegation Distribution -Each delegation holds multiple adjustment factors to specify its entitlement to -the rewards from a validator. `AdjustmentPool` is used to passively calculate -each bonds entitled fees from the `RewardPool`. `AdjustmentPool` is used to -passively calculate each bonds entitled fees from +Each delegation holds multiple accumulation factors to specify its entitlement to +the rewards from a validator. `Accum` is used to passively calculate +each bonds entitled rewards from the `RewardPool`. `AccumProposer` is used to +passively calculate each bonds entitled rewards from `ValidatorDistribution.ProposerRewardPool` - DelegatorDistribution: ` 0x02 | DelegatorAddr | ValOwnerAddr -> amino(delegatorDist)` ```golang type DelegatorDist struct { - WithdrawalHeight int64 // last time this delegation withdrew rewards - Adjustment sdk.Dec // fee provisioning adjustment factor - AdjustmentProposer DecCoins // proposers pool adjustment factor - PrevTokens sdk.Dec // bonded tokens held by the delegation on the previous block - PrevShares sdk.Dec // delegator shares held by the delegation on the previous block + WithdrawalHeight int64 // last time this delegation withdrew rewards + Accum sdk.Dec // reward provisioning accumulation factor + AccumProposer sdk.Dec // proposers pool accumulation factor } ``` -### Power Change - -Every instance that the voting power changes, information about the state of -the validator set during the change must be recorded as a `PowerChange` for -other validators to run through. Each power change is indexed by its block -height. - - - PowerChange: `0x03 | amino(Height) -> amino(validatorDist)` - -```golang -type PowerChange struct { - Height int64 // block height at change - ValidatorBondedTokens sdk.Dec // following used to create distribution scenarios - ValidatorDelegatorShares sdk.Dec - ValidatorDelegatorShareExRate sdk.Dec - ValidatorCommission sdk.Dec - PoolBondedTokens sdk.Dec - Global Global - ValDistr ValidatorDistribution - DelegationShares sdk.Dec - DelDistr DelegatorDistribution -} -``` diff --git a/docs/spec/simple-distribution/overview.md b/docs/spec/simple-distribution/overview.md deleted file mode 100644 index 62cec2e768..0000000000 --- a/docs/spec/simple-distribution/overview.md +++ /dev/null @@ -1,64 +0,0 @@ -# Distribution - -## Overview - -This _simple_ distribution mechanism describes a functional way to passively -distribute rewards between validator and delegators. Note that this mechanism does -not distribute funds in as precisely as active reward distribution and will therefor -be upgraded in the future. - -The mechanism operates as follows. Collected rewards are pooled globally and -divided out passively to validators and delegators. Each validator has the -opportunity to charge commission to the delegators on the rewards collected on -behalf of the delegators by the validators. Fees are paid directly into a -global reward pool, and validator proposer-reward pool. Due to the nature of -passive accounting whenever changes to parameters which affect the rate of reward -distribution occurs, withdrawal of rewards must also occur when: - - - withdrawing one must withdrawal the maximum amount they are entitled - too, leaving nothing in the pool, - - bonding, unbonding, or re-delegating tokens to an existing account a - full withdrawal of the rewards must occur (as the rules for lazy accounting - change), - - a validator chooses to change the commission on rewards, all accumulated - commission rewards must be simultaneously withdrawn. - -The above scenarios are covered in `triggers.md`. - -The distribution mechanism outlines herein is used to lazily distribute the -following rewards between validators and associated delegators: - - multi-token fees to be socially distributed, - - proposer reward pool, - - inflated atom provisions, and - - validator commission on all rewards earned by their delegators stake - -Fees are pooled within a global pool, as well as validator specific -proposer-reward pools. The mechanisms used allow for validators and delegators -to independently and lazily withdrawn their rewards. - -Within this spec - -As a part of the lazy computations, each validator and delegator holds an -accumulation term which is used to estimate what their approximate fair portion -of tokens held in the global pool is owed to them. This approximation of owed -rewards would be equivalent to the active distribution under the situation that -there was a constant flow of incoming reward tokens every block. Because this -is not the case, the approximation of owed rewards will deviate from the active -distribution based on fluctuations of incoming reward tokens as well as timing -of reward withdrawal by other delegators and validators from the reward pool. - - -## Affect on Staking - -Charging commission on Atom provisions while also allowing for Atom-provisions -to be auto-bonded (distributed directly to the validators bonded stake) is -problematic within DPoS. Fundamentally these two mechnisms are mutually -exclusive. If there are atoms commissions and auto-bonding Atoms, the portion -of Atoms the reward distribution calculation would become very large as the Atom -portion for each delegator would change each block making a withdrawal of rewards -for a delegator require a calculation for every single block since the last -withdrawal. In conclusion we can only have atom commission and unbonded atoms -provisions, or bonded atom provisions with no Atom commission, and we elect to -implement the former. Stakeholders wishing to rebond their provisions may elect -to set up a script to periodically withdraw and rebond rewards. - diff --git a/docs/spec/simple-distribution/state.md b/docs/spec/simple-distribution/state.md deleted file mode 100644 index 757287004a..0000000000 --- a/docs/spec/simple-distribution/state.md +++ /dev/null @@ -1,68 +0,0 @@ -## State - -### Global - -All globally tracked parameters for distribution are stored within -`Global`. Rewards are collected and added to the reward pool and -distributed to validators/delegators from here. - -Note that the reward pool holds decimal coins (`DecCoins`) to allow -for fractions of coins to be received from operations like inflation. -When coins are distributed from the pool they are truncated back to -`sdk.Coins` which are non-decimal. - - - Global: `0x00 -> amino(global)` - -```golang -// coins with decimal -type DecCoins []DecCoin - -type DecCoin struct { - Amount sdk.Dec - Denom string -} - -type Global struct { - Accum sdk.Dec // global accumulation factor for lazy calculations - Pool DecCoins // funds for all validators which have yet to be withdrawn - CommunityFund DecCoins // pool for community funds yet to be spent -} -``` - -### Validator Distribution - -Validator distribution information for the relevant validator is updated each time: - 1. delegation amount to a validator are updated, - 2. a validator successfully proposes a block and receives a reward, - 3. any delegator withdraws from a validator, or - 4. the validator withdraws it's commission. - - - ValidatorDistribution: `0x02 | ValOwnerAddr -> amino(validatorDistribution)` - -```golang -type ValidatorDistribution struct { - CommissionWithdrawalHeight int64 // last time this validator withdrew commission - Accum sdk.Dec // global pool accumulation factor - ProposerAccum sdk.Dec // proposer pool accumulation factor - ProposerPool DecCoins // reward pool collected from being the proposer -} -``` - -### Delegation Distribution - -Each delegation holds multiple accumulation factors to specify its entitlement to -the rewards from a validator. `Accum` is used to passively calculate -each bonds entitled rewards from the `RewardPool`. `AccumProposer` is used to -passively calculate each bonds entitled rewards from -`ValidatorDistribution.ProposerRewardPool` - - - DelegatorDistribution: ` 0x02 | DelegatorAddr | ValOwnerAddr -> amino(delegatorDist)` - -```golang -type DelegatorDist struct { - WithdrawalHeight int64 // last time this delegation withdrew rewards - Accum sdk.Dec // reward provisioning accumulation factor - AccumProposer sdk.Dec // proposers pool accumulation factor -} -``` - From a0e05a8f0373d4b123200c98c60f9517484f22dd Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 8 Aug 2018 15:03:43 -0400 Subject: [PATCH 04/93] triggers, endblock, transactions --- docs/spec/distribution/end_block.md | 8 +- docs/spec/distribution/future_improvements.md | 16 -- docs/spec/distribution/transactions.md | 176 +----------------- docs/spec/distribution/triggers.md | 27 ++- 4 files changed, 21 insertions(+), 206 deletions(-) delete mode 100644 docs/spec/distribution/future_improvements.md diff --git a/docs/spec/distribution/end_block.md b/docs/spec/distribution/end_block.md index bc6847ef4b..19c9e83021 100644 --- a/docs/spec/distribution/end_block.md +++ b/docs/spec/distribution/end_block.md @@ -3,10 +3,10 @@ At each endblock, the fees received are sorted to the proposer, community fund, and global pool. When the validator is the proposer of the round, that validator (and their delegators) receives between 1% and 5% of fee rewards, the -reserve tax is then charged, then the remainder is distributed proportionally -by voting power to all bonded validators independent of whether they voted -(social distribution). Note the social distribution is applied to proposer -validator in addition to the proposer reward. +reserve community tax is then charged, then the remainder is distributed +proportionally by voting power to all bonded validators independent of whether +they voted (social distribution). Note the social distribution is applied to +proposer validator in addition to the proposer reward. The amount of proposer reward is calculated from pre-commits Tendermint messages in order to incentivize validators to wait and include additional diff --git a/docs/spec/distribution/future_improvements.md b/docs/spec/distribution/future_improvements.md deleted file mode 100644 index 954fb4d623..0000000000 --- a/docs/spec/distribution/future_improvements.md +++ /dev/null @@ -1,16 +0,0 @@ -## Future Improvements - -### Power Change - -Within the current implementation all power changes ever made are indefinitely stored -within the current state. In the future this state should be trimmed on an epoch basis. Delegators -which will have not withdrawn their fees will be penalized in some way, depending on what is -computationally feasible this may include: - - burning non-withdrawn fees - - requiring more expensive withdrawal costs which include proofs from archive nodes of historical state - -In addition or as an alternative it may make sense to implement a "rolling" epoch which cycles through -all the delegators in small groups (for example 5 delegators per block) and just runs the withdrawal transaction -at standard rates and takes transaction fees from the withdrawal amount. - - diff --git a/docs/spec/distribution/transactions.md b/docs/spec/distribution/transactions.md index 1401c3b851..7816757e53 100644 --- a/docs/spec/distribution/transactions.md +++ b/docs/spec/distribution/transactions.md @@ -131,17 +131,12 @@ fulfilled the entitled fees for the various scenarios can be calculated. ```golang type DistributionScenario interface { - DistributorTokens() DecCoins // current tokens from distributor - DistributorCumulativeTokens() DecCoins // total tokens ever received - DistributorPrevReceivedTokens() DecCoins // last value of tokens received - DistributorShares() sdk.Dec // current shares - DistributorPrevShares() sdk.Dec // shares last block + DistributorTokens() DecCoins // current tokens from distributor + DistributorShares() sdk.Dec // current shares + RecipientAccum() sdk.Dec + RecipientShares() sdk.Dec // current shares - RecipientAdjustment() sdk.Dec - RecipientShares() sdk.Dec // current shares - RecipientPrevShares() sdk.Dec // shares last block - - ModifyAdjustments(withdrawal sdk.Dec) // proceedure to modify adjustment factors + ModifyAccums(withdrawal sdk.Dec) // proceedure to modify adjustment factors } ``` @@ -169,18 +164,9 @@ func (d DistributionScenario) RecipientCount(height int64) sdk.Dec func (d DistributionScenario) GlobalCount(height int64) sdk.Dec return d.DistributorShares() * height -func (d DistributionScenario) SimplePool() DecCoins - return d.RecipientCount() / d.GlobalCount() * d.DistributorCumulativeTokens - -func (d DistributionScenario) ProjectedPool(height int64) DecCoins - return d.RecipientPrevShares() * (height-1) - / (d.DistributorPrevShares() * (height-1)) - * d.DistributorCumulativeTokens - + d.RecipientShares() / d.DistributorShares() - * d.DistributorPrevReceivedTokens() ``` -The `DistributionScenario` _adjustment_ terms account for changes in +The `DistributionScenario` _accum_ terms account for changes in recipient/distributor shares and recipient withdrawals. The adjustment factor must be modified whenever the recipient withdraws from the distributor or the distributor's/recipient's shares are changed. @@ -218,49 +204,6 @@ shares should be taken as true number of global bonded shares. The recipients shares should be taken as the bonded tokens less the validator's commission. ``` -type DelegationFromGlobalPool struct { - DelegationShares sdk.Dec - ValidatorCommission sdk.Dec - ValidatorBondedTokens sdk.Dec - ValidatorDelegatorShareExRate sdk.Dec - PoolBondedTokens sdk.Dec - Global Global - ValDistr ValidatorDistribution - DelDistr DelegatorDistribution -} - -func (d DelegationFromGlobalPool) DistributorTokens() DecCoins - return d.Global.Pool - -func (d DelegationFromGlobalPool) DistributorCumulativeTokens() DecCoins - return d.Global.EverReceivedPool - -func (d DelegationFromGlobalPool) DistributorPrevReceivedTokens() DecCoins - return d.Global.PrevReceivedPool - -func (d DelegationFromGlobalPool) DistributorShares() sdk.Dec - return d.PoolBondedTokens - -func (d DelegationFromGlobalPool) DistributorPrevShares() sdk.Dec - return d.Global.PrevBondedTokens - -func (d DelegationFromGlobalPool) RecipientShares() sdk.Dec - return d.DelegationShares * d.ValidatorDelegatorShareExRate() * - d.ValidatorBondedTokens() * (1 - d.ValidatorCommission) - -func (d DelegationFromGlobalPool) RecipientPrevShares() sdk.Dec - return d.DelDistr.PrevTokens - -func (d DelegationFromGlobalPool) RecipientAdjustment() sdk.Dec - return d.DelDistr.Adjustment - -func (d DelegationFromGlobalPool) ModifyAdjustments(withdrawal sdk.Dec) - d.ValDistr.Adjustment += withdrawal - d.DelDistr.Adjustment += withdrawal - d.global.Adjustment += withdrawal - SetValidatorDistribution(d.ValDistr) - SetDelegatorDistribution(d.DelDistr) - SetGlobal(d.Global) ``` #### Delegation's entitlement to ValidatorDistribution.ProposerPool @@ -272,43 +215,6 @@ shares is taken as the effective delegation shares less the validator's commission. ``` -type DelegationFromProposerPool struct { - DelegationShares sdk.Dec - ValidatorCommission sdk.Dec - ValidatorDelegatorShares sdk.Dec - ValDistr ValidatorDistribution - DelDistr DelegatorDistribution -} - -func (d DelegationFromProposerPool) DistributorTokens() DecCoins - return d.ValDistr.ProposerPool - -func (d DelegationFromProposerPool) DistributorCumulativeTokens() DecCoins - return d.ValDistr.EverReceivedProposerReward - -func (d DelegationFromProposerPool) DistributorPrevReceivedTokens() DecCoins - return d.ValDistr.PrevReceivedProposerReward - -func (d DelegationFromProposerPool) DistributorShares() sdk.Dec - return d.ValidatorDelegatorShares - -func (d DelegationFromProposerPool) DistributorPrevShares() sdk.Dec - return d.ValDistr.PrevDelegatorShares - -func (d DelegationFromProposerPool) RecipientShares() sdk.Dec - return d.DelegationShares * (1 - d.ValidatorCommission) - -func (d DelegationFromProposerPool) RecipientPrevShares() sdk.Dec - return d.DelDistr.PrevShares - -func (d DelegationFromProposerPool) RecipientAdjustment() sdk.Dec - return d.DelDistr.AdjustmentProposer - -func (d DelegationFromProposerPool) ModifyAdjustments(withdrawal sdk.Dec) - d.ValDistr.AdjustmentProposer += withdrawal - d.DelDistr.AdjustmentProposer += withdrawal - SetValidatorDistribution(d.ValDistr) - SetDelegatorDistribution(d.DelDistr) ``` #### Validators's commission entitlement to Global.Pool @@ -317,43 +223,6 @@ Similar to a delegator's entitlement, but with recipient shares based on the commission portion of bonded tokens. ``` -type CommissionFromGlobalPool struct { - ValidatorBondedTokens sdk.Dec - ValidatorCommission sdk.Dec - PoolBondedTokens sdk.Dec - Global Global - ValDistr ValidatorDistribution -} - -func (c CommissionFromGlobalPool) DistributorTokens() DecCoins - return c.Global.Pool - -func (c CommissionFromGlobalPool) DistributorCumulativeTokens() DecCoins - return c.Global.EverReceivedPool - -func (c CommissionFromGlobalPool) DistributorPrevReceivedTokens() DecCoins - return c.Global.PrevReceivedPool - -func (c CommissionFromGlobalPool) DistributorShares() sdk.Dec - return c.PoolBondedTokens - -func (c CommissionFromGlobalPool) DistributorPrevShares() sdk.Dec - return c.Global.PrevBondedTokens - -func (c CommissionFromGlobalPool) RecipientShares() sdk.Dec - return c.ValidatorBondedTokens() * c.ValidatorCommission - -func (c CommissionFromGlobalPool) RecipientPrevShares() sdk.Dec - return c.ValDistr.PrevBondedTokens * c.ValidatorCommission - -func (c CommissionFromGlobalPool) RecipientAdjustment() sdk.Dec - return c.ValDistr.Adjustment - -func (c CommissionFromGlobalPool) ModifyAdjustments(withdrawal sdk.Dec) - c.ValDistr.Adjustment += withdrawal - c.Global.Adjustment += withdrawal - SetValidatorDistribution(c.ValDistr) - SetGlobal(c.Global) ``` #### Validators's commission entitlement to ValidatorDistribution.ProposerPool @@ -362,38 +231,5 @@ Similar to a delegators entitlement to the proposer pool, but with recipient shares based on the commission portion of the total delegator shares. ``` -type CommissionFromProposerPool struct { - ValidatorDelegatorShares sdk.Dec - ValidatorCommission sdk.Dec - ValDistr ValidatorDistribution -} - -func (c CommissionFromProposerPool) DistributorTokens() DecCoins - return c.ValDistr.ProposerPool - -func (c CommissionFromProposerPool) DistributorCumulativeTokens() DecCoins - return c.ValDistr.EverReceivedProposerReward - -func (c CommissionFromProposerPool) DistributorPrevReceivedTokens() DecCoins - return c.ValDistr.PrevReceivedProposerReward - -func (c CommissionFromProposerPool) DistributorShares() sdk.Dec - return c.ValidatorDelegatorShares - -func (c CommissionFromProposerPool) DistributorPrevShares() sdk.Dec - return c.ValDistr.PrevDelegatorShares - -func (c CommissionFromProposerPool) RecipientShares() sdk.Dec - return c.ValidatorDelegatorShares * (c.ValidatorCommission) - -func (c CommissionFromProposerPool) RecipientPrevShares() sdk.Dec - return c.ValDistr.PrevDelegatorShares * (c.ValidatorCommission) - -func (c CommissionFromProposerPool) RecipientAdjustment() sdk.Dec - return c.ValDistr.AdjustmentProposer - -func (c CommissionFromProposerPool) ModifyAdjustments(withdrawal sdk.Dec) - c.ValDistr.AdjustmentProposer += withdrawal - SetValidatorDistribution(c.ValDistr) ``` diff --git a/docs/spec/distribution/triggers.md b/docs/spec/distribution/triggers.md index 8800609a44..93358fe2e7 100644 --- a/docs/spec/distribution/triggers.md +++ b/docs/spec/distribution/triggers.md @@ -1,26 +1,14 @@ # Triggers -## Create validator distribution - - - triggered-by: validator entering bonded validator group (`stake.bondValidator()`) - -Whenever a new validator is added to the Tendermint validator set they are -entitled to begin earning rewards of atom provisions and fees. At this point -`ValidatorDistribution.Pool()` must be zero (as the validator has not yet -earned any rewards) meaning that the initial value for `validator.Adjustment` -must be set to the value of `validator.SimplePool()` for the height which the -validator is added on the validator set. - ## Create or modify delegation distribution - triggered-by: `stake.TxDelegate`, `stake.TxBeginRedelegate`, `stake.TxBeginUnbonding` The pool of a new delegator bond will be 0 for the height at which the bond was -added. This is achieved by setting `DelegationDistribution.WithdrawalHeight` to -the height which the bond was added. Additionally the `AdjustmentPool` and -`AdjustmentProposerPool` must be set to the equivalent values of -`DelegationDistribution.SimplePool()` and -`DelegationDistribution.SimpleProposerPool()` for the height of delegation. +added, or the withdrawal has taken place. This is achieved by setting +`DelegatorDist.WithdrawalHeight` to the relevant height, withdrawing any +remaining fees, and setting `DelegatorDist.Accum` and +`DelegatorDist.ProposerAccum` to 0. ## Commission rate change @@ -29,3 +17,10 @@ the height which the bond was added. Additionally the `AdjustmentPool` and If a validator changes its commission rate, all commission on fees must be simultaneously withdrawn using the transaction `TxWithdrawValidator` +## Change in Validator State + + - triggered-by: `stake.Slash`, `stake.UpdateValidator` + +Whenever a validator is slashed or enters/leaves the validator group +`ValidatorUpdate` information must be recorded in order to properly calculate +the accum factors. From 5285489977f5126b1f9a954d0e7c80cb75229da5 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 8 Aug 2018 23:43:40 -0400 Subject: [PATCH 05/93] general updates --- docs/spec/distribution/state.md | 49 +++++++---- docs/spec/distribution/transactions.md | 108 ++++--------------------- docs/spec/distribution/triggers.md | 14 ++-- 3 files changed, 58 insertions(+), 113 deletions(-) diff --git a/docs/spec/distribution/state.md b/docs/spec/distribution/state.md index 757287004a..1157825945 100644 --- a/docs/spec/distribution/state.md +++ b/docs/spec/distribution/state.md @@ -23,9 +23,10 @@ type DecCoin struct { } type Global struct { - Accum sdk.Dec // global accumulation factor for lazy calculations - Pool DecCoins // funds for all validators which have yet to be withdrawn - CommunityFund DecCoins // pool for community funds yet to be spent + TotalValAccumUpdateHeight int64 // last height which the total validator accum was updated + TotalValAccum sdk.Dec // total valdator accum held by validators + Pool DecCoins // funds for all validators which have yet to be withdrawn + CommunityPool DecCoins // pool for community funds yet to be spent } ``` @@ -41,28 +42,48 @@ Validator distribution information for the relevant validator is updated each ti ```golang type ValidatorDistribution struct { - CommissionWithdrawalHeight int64 // last time this validator withdrew commission - Accum sdk.Dec // global pool accumulation factor - ProposerAccum sdk.Dec // proposer pool accumulation factor - ProposerPool DecCoins // reward pool collected from being the proposer + CommissionWithdrawalHeight int64 // last height this validator withdrew commission + + GlobalWithdrawalHeight int64 // last height this validator withdrew from the global pool + Pool DecCoins // reward pool collected held within this validator (includes proposer rewards) + + TotalDelAccumUpdateHeight int64 // last height which the total delegator accum was updated + TotalDelAccum sdk.Dec // total proposer pool accumulation factor held by delegators } ``` ### Delegation Distribution -Each delegation holds multiple accumulation factors to specify its entitlement to -the rewards from a validator. `Accum` is used to passively calculate -each bonds entitled rewards from the `RewardPool`. `AccumProposer` is used to -passively calculate each bonds entitled rewards from -`ValidatorDistribution.ProposerRewardPool` +Each delegation distribution only needs to record the height at which it last +withdrew fees. Because a delegation must withdraw fees each time it's +properties change (aka bonded tokens etc.) its properties will remain constant +and the delegator's _accumulation_ factor can be calculated passively knowing +only the height of the last withdrawal and its current properties. - DelegatorDistribution: ` 0x02 | DelegatorAddr | ValOwnerAddr -> amino(delegatorDist)` ```golang type DelegatorDist struct { WithdrawalHeight int64 // last time this delegation withdrew rewards - Accum sdk.Dec // reward provisioning accumulation factor - AccumProposer sdk.Dec // proposers pool accumulation factor } ``` +### Validator Update + +Every instance that a validator: + - enters into the bonded state, + - leaves the bonded state, + - is slashed, or + - changes its commission rate, + +information about the state change must be recorded as a `ValidatorUpdate`. +Each power change is indexed by validator and its block height. + + - ValidatorUpdate: `0x03 | ValOwnerAddr | amino(Height) -> amino(ValidatorUpdate)` + +```golang +type ValidatorUpdate struct { + Height int64 // block height of update + NewCommissionRate sdk.Dec // commission rate at this height +} +``` diff --git a/docs/spec/distribution/transactions.md b/docs/spec/distribution/transactions.md index 7816757e53..7d6bcc752c 100644 --- a/docs/spec/distribution/transactions.md +++ b/docs/spec/distribution/transactions.md @@ -1,3 +1,16 @@ + + + +Each delegation holds multiple accumulation factors to specify its entitlement to +the rewards from a validator. `Accum` is used to passively calculate +each bonds entitled rewards from the `RewardPool`. `AccumProposer` is used to +passively calculate each bonds entitled rewards from +`ValidatorDistribution.ProposerRewardPool` + + + + + # Transactions ## TxWithdrawDelegation @@ -10,7 +23,7 @@ redelegation, or delegation of additional tokens to a specific validator. Each time a withdrawal is made by a recipient the adjustment term must be modified for each block with a change in distributors shares since the time of last withdrawal. This is accomplished by iterating over all relevant -`PowerChange`'s stored in distribution state. +`ValidatorUpdate`'s stored in distribution state. ```golang @@ -57,7 +70,7 @@ func GetDelegatorEntitlement(delegatorAddr sdk.AccAddress) DecCoins return entitlement -func (pc PowerChange) ProcessPowerChangeDelegation(delegation sdk.Delegation, +func (pc ValidatorUpdate) ProcessPowerChangeDelegation(delegation sdk.Delegation, DelDistr DelegationDistribution) // get the historical scenarios @@ -109,7 +122,7 @@ func WithdrawalValidator(ownerAddr, withdrawAddr sdk.AccAddress) AddCoins(withdrawAddr, totalEntitlment.TruncateDecimal()) -func (pc PowerChange) ProcessPowerChangeCommission() +func (pc ValidatorUpdate) ProcessPowerChangeCommission() // get the historical scenarios scenario1 = pc.CommissionFromGlobalPool() @@ -122,75 +135,6 @@ func (pc PowerChange) ProcessPowerChangeCommission() ## Common Calculations -### Distribution scenario - -A common form of abstracted calculations exists between validators and -delegations attempting to withdrawal their rewards, either from `Global.Pool` -or from `ValidatorDistribution.ProposerPool`. With the following interface -fulfilled the entitled fees for the various scenarios can be calculated. - -```golang -type DistributionScenario interface { - DistributorTokens() DecCoins // current tokens from distributor - DistributorShares() sdk.Dec // current shares - RecipientAccum() sdk.Dec - RecipientShares() sdk.Dec // current shares - - ModifyAccums(withdrawal sdk.Dec) // proceedure to modify adjustment factors -} -``` - -#### Entitled reward from distribution scenario - -The entitlement to the distributor's tokens held can be accounted for lazily. -To begin this calculation we must determine the recipient's _simple pool_ and -_projected pool_. The simple pool represents a lazy accounting of what a -recipient's entitlement to the distributor's tokens would be if all recipients -for that distributor had static shares (equal to the current shares), and no -recipients had ever withdrawn their entitled rewards. The projected pool -represents the anticipated recipient's entitlement to the distributors tokens -based on the current blocks token input (for example fees reward received) to -the distributor, and the distributor's tokens and shares of the previous block -assuming that neither had changed in the current block. Using the simple and -projected pools we can determine all cumulative changes which have taken place -outside of the recipient and adjust the recipient's _adjustment factor_ to -account for these changes and ultimately keep track of the correct entitlement -to the distributors tokens. - -``` -func (d DistributionScenario) RecipientCount(height int64) sdk.Dec - return v.RecipientShares() * height - -func (d DistributionScenario) GlobalCount(height int64) sdk.Dec - return d.DistributorShares() * height - -``` - -The `DistributionScenario` _accum_ terms account for changes in -recipient/distributor shares and recipient withdrawals. The adjustment factor -must be modified whenever the recipient withdraws from the distributor or the -distributor's/recipient's shares are changed. - - When the shares of the recipient is changed the adjustment factor is - increased/decreased by the difference between the _simple_ and _projected_ - pools. In other words, the cumulative difference in the shares if the shares - has been the new shares as opposed to the old shares for the entire duration of - the blockchain up the previous block. - - When a recipient makes a withdrawal the adjustment factor is increased by the - withdrawal amount. - -``` -func (d DistributionScenario) UpdateAdjustmentForPowerChange(height int64) - simplePool = d.SimplePool() - projectedPool = d.ProjectedPool(height) - AdjustmentChange = simplePool - projectedPool - if AdjustmentChange > 0 - d.ModifyAdjustments(AdjustmentChange) - -func (d DistributionScenario) WithdrawalEntitlement() DecCoins - entitlement = d.SimplePool() - d.RecipientAdjustment() - d.ModifyAdjustments(entitlement) - return entitlement -``` ### Distribution scenarios @@ -206,17 +150,6 @@ shares should be taken as the bonded tokens less the validator's commission. ``` ``` -#### Delegation's entitlement to ValidatorDistribution.ProposerPool - -Delegations (including validator's self-delegation) are still subject -commission on the rewards gained from the proposer pool. Global shares in this -context is actually the validators total delegations shares. The recipient's -shares is taken as the effective delegation shares less the validator's -commission. - -``` -``` - #### Validators's commission entitlement to Global.Pool Similar to a delegator's entitlement, but with recipient shares based on the @@ -224,12 +157,3 @@ commission portion of bonded tokens. ``` ``` - -#### Validators's commission entitlement to ValidatorDistribution.ProposerPool - -Similar to a delegators entitlement to the proposer pool, but with recipient -shares based on the commission portion of the total delegator shares. - -``` -``` - diff --git a/docs/spec/distribution/triggers.md b/docs/spec/distribution/triggers.md index 93358fe2e7..0e02f04312 100644 --- a/docs/spec/distribution/triggers.md +++ b/docs/spec/distribution/triggers.md @@ -6,21 +6,21 @@ The pool of a new delegator bond will be 0 for the height at which the bond was added, or the withdrawal has taken place. This is achieved by setting -`DelegatorDist.WithdrawalHeight` to the relevant height, withdrawing any -remaining fees, and setting `DelegatorDist.Accum` and -`DelegatorDist.ProposerAccum` to 0. +`DelegatorDist.WithdrawalHeight` to the height of the triggering transaction. ## Commission rate change - triggered-by: `stake.TxEditValidator` If a validator changes its commission rate, all commission on fees must be -simultaneously withdrawn using the transaction `TxWithdrawValidator` +simultaneously withdrawn using the transaction `TxWithdrawValidator`. +Additionally the change and associated height must be recorded in a +`ValidatorUpdate` state record. ## Change in Validator State - triggered-by: `stake.Slash`, `stake.UpdateValidator` -Whenever a validator is slashed or enters/leaves the validator group -`ValidatorUpdate` information must be recorded in order to properly calculate -the accum factors. +Whenever a validator is slashed or enters/leaves the validator group all of the +validator entitled reward tokens must be simultaniously withdrawn from +`Global.Pool` and added to `ValidatorDistribution.Pool` From e7ebe35b0a530bf470c4c0351cc369821e123541 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 9 Aug 2018 00:34:19 -0400 Subject: [PATCH 06/93] updating transactions --- docs/spec/distribution/transactions.md | 95 +++++++++++++++++--------- 1 file changed, 61 insertions(+), 34 deletions(-) diff --git a/docs/spec/distribution/transactions.md b/docs/spec/distribution/transactions.md index 7d6bcc752c..30ea6ab469 100644 --- a/docs/spec/distribution/transactions.md +++ b/docs/spec/distribution/transactions.md @@ -1,16 +1,3 @@ - - - -Each delegation holds multiple accumulation factors to specify its entitlement to -the rewards from a validator. `Accum` is used to passively calculate -each bonds entitled rewards from the `RewardPool`. `AccumProposer` is used to -passively calculate each bonds entitled rewards from -`ValidatorDistribution.ProposerRewardPool` - - - - - # Transactions ## TxWithdrawDelegation @@ -42,14 +29,14 @@ func GetDelegatorEntitlement(delegatorAddr sdk.AccAddress) DecCoins delegations = GetDelegations(delegatorAddr) DelDistr = GetDelegationDistribution(delegation.DelegatorAddr, delegation.ValidatorAddr) - pcs = GetPowerChanges(DelDistr.WithdrawalHeight) + vus = GetValidatorUpdates(DelDistr.WithdrawalHeight) // update all adjustment factors for each delegation since last withdrawal - for pc = range pcs + for vu = range vus for delegation = range delegations DelDistr = GetDelegationDistribution(delegation.DelegatorAddr, delegation.ValidatorAddr) - pc.ProcessPowerChangeDelegation(delegation, DelDistr) + vu.ProcessPowerChangeDelegation(delegation, DelDistr) // collect all entitled fees entitlement = 0 @@ -70,16 +57,16 @@ func GetDelegatorEntitlement(delegatorAddr sdk.AccAddress) DecCoins return entitlement -func (pc ValidatorUpdate) ProcessPowerChangeDelegation(delegation sdk.Delegation, +func (vu ValidatorUpdate) ProcessPowerChangeDelegation(delegation sdk.Delegation, DelDistr DelegationDistribution) // get the historical scenarios - scenario1 = pc.DelegationFromGlobalPool(delegation, DelDistr) - scenario2 = pc.DelegationFromProvisionPool(delegation, DelDistr) + scenario1 = vu.DelegationFromGlobalPool(delegation, DelDistr) + scenario2 = vu.DelegationFromProvisionPool(delegation, DelDistr) // process the adjustment factors - scenario1.UpdateAdjustmentForPowerChange(pc.Height) - scenario2.UpdateAdjustmentForPowerChange(pc.Height) + scenario1.UpdateAdjustmentForPowerChange(vu.Height) + scenario2.UpdateAdjustmentForPowerChange(vu.Height) ``` ## TxWithdrawValidator @@ -91,7 +78,7 @@ redelegation, or delegation of additional tokens to a specific validator. This transaction withdraws the validators commission rewards, as well as any rewards earning on their self-delegation. -```golang +``` type TxWithdrawValidator struct { ownerAddr sdk.AccAddress // validator address to withdraw from withdrawAddr sdk.AccAddress // address to make the withdrawal to @@ -104,9 +91,9 @@ func WithdrawalValidator(ownerAddr, withdrawAddr sdk.AccAddress) // update the validator adjustment factors for commission ValDistr = GetValidatorDistribution(ownerAddr.ValidatorAddr) - pcs = GetPowerChanges(ValDistr.CommissionWithdrawalHeight) - for pc = range pcs - pc.ProcessPowerChangeCommission() + vus = GetValidatorUpdates(ValDistr.CommissionWithdrawalHeight) + for vu = range vus + vu.ProcessPowerChangeCommission() // withdrawal validator commission rewards global = GetGlobal() @@ -122,38 +109,78 @@ func WithdrawalValidator(ownerAddr, withdrawAddr sdk.AccAddress) AddCoins(withdrawAddr, totalEntitlment.TruncateDecimal()) -func (pc ValidatorUpdate) ProcessPowerChangeCommission() +func (vu ValidatorUpdate) ProcessPowerChangeCommission() // get the historical scenarios - scenario1 = pc.CommissionFromGlobalPool() - scenario2 = pc.CommissionFromProposerPool() + scenario1 = vu.CommissionFromGlobalPool() + scenario2 = vu.CommissionFromProposerPool() // process the adjustment factors - scenario1.UpdateAdjustmentForPowerChange(pc.Height) - scenario2.UpdateAdjustmentForPowerChange(pc.Height) + scenario1.UpdateAdjustmentForPowerChange(vu.Height) + scenario2.UpdateAdjustmentForPowerChange(vu.Height) ``` ## Common Calculations -### Distribution scenarios +### Update total validator accum -Note that the distribution scenario structures are found in `state.md`. +The total amount of validator accum must be calculated in order to determine +the amount of pool tokens which a validator is entitled to at a particular block. +This term is to be updated during a validator withdrawal. -#### Delegation's entitlement to Global.Pool +``` +func (g Global) UpdateTotalValAccum() + +TODO + +``` + +### Update total delegator accum + +Each delegation holds multiple accumulation factors to specify its entitlement to +the rewards from a validator. `Accum` is used to passively calculate +each bonds entitled rewards from the `RewardPool`. `AccumProposer` is used to +passively calculate each bonds entitled rewards from +`ValidatorDistribution.ProposerRewardPool` + +``` +TODO +``` + +### Global Pool to Validator Pool + +Everytime a validator or delegator make a withdraw or the validator is the +proposer and receives new tokens - the relavent validator must move tokens from +the passive global pool to thier own pool. + +``` +TODO +``` + + +### Delegation's entitlement to ValidatorDistribution.Pool For delegations (including validator's self-delegation) all fees from fee pool are subject to commission rate from the owner of the validator. The global shares should be taken as true number of global bonded shares. The recipients shares should be taken as the bonded tokens less the validator's commission. +Each delegation holds multiple accumulation factors to specify its entitlement to +the rewards from a validator. `Accum` is used to passively calculate +each bonds entitled rewards from the `RewardPool`. `AccumProposer` is used to +passively calculate each bonds entitled rewards from +`ValidatorDistribution.ProposerRewardPool` + ``` +TODO ``` -#### Validators's commission entitlement to Global.Pool +### Validators's commission entitlement to ValidatorDistribution.Pool Similar to a delegator's entitlement, but with recipient shares based on the commission portion of bonded tokens. ``` +TODO ``` From 5e5fad454849131246c30796f22e6de0d0a4e96a Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 14 Aug 2018 13:45:13 -0400 Subject: [PATCH 07/93] txs --- docs/spec/distribution/transactions.md | 43 +++++++++++++++++--------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/docs/spec/distribution/transactions.md b/docs/spec/distribution/transactions.md index 30ea6ab469..b8de54ca57 100644 --- a/docs/spec/distribution/transactions.md +++ b/docs/spec/distribution/transactions.md @@ -122,30 +122,43 @@ func (vu ValidatorUpdate) ProcessPowerChangeCommission() ## Common Calculations - ### Update total validator accum The total amount of validator accum must be calculated in order to determine -the amount of pool tokens which a validator is entitled to at a particular block. -This term is to be updated during a validator withdrawal. +the amount of pool tokens which a validator is entitled to at a particular +block. The accum is always additive to the existing accum. This term is to be +updates each time rewards are withdrawn from the system. ``` -func (g Global) UpdateTotalValAccum() - -TODO - +func (g Global) UpdateTotalValAccum(height int64, totalBondedTokens Dec) + blocks = height - g.TotalValAccumUpdateHeight + g.TotalValAccum += totalDelShares * blocks ``` ### Update total delegator accum -Each delegation holds multiple accumulation factors to specify its entitlement to -the rewards from a validator. `Accum` is used to passively calculate -each bonds entitled rewards from the `RewardPool`. `AccumProposer` is used to -passively calculate each bonds entitled rewards from -`ValidatorDistribution.ProposerRewardPool` +The total amount of delegator accum must be updated in order to determine the +amount of pool tokens which each delegator is entitled to, relative to the +other delegators for that validator. The accum is always additive to +the existing accum. This term is to be updated each time a +withdrawal is made from a validator. ``` -TODO +func (vd ValidatorDistribution) UpdateTotalDelAccum(height int64, totalDelShares Dec) + blocks = height - vd.TotalDelAccumUpdateHeight + vd.TotalDelAccum += totalDelShares * blocks +``` + +### Delegator accum + +Each delegation has a passively calculated accumulation factor to specify its +entitlement to the rewards from a validator. `Accum` is used to passively +calculate each bonds entitled rewards from the `Validator.Pool`. + +``` +func (dd DelegatorDist) Accum(height int64, delegatorShares Dec) Dec + blocks = height - dd.WithdrawalHeight + return delegatorShares * blocks ``` ### Global Pool to Validator Pool @@ -155,7 +168,9 @@ proposer and receives new tokens - the relavent validator must move tokens from the passive global pool to thier own pool. ``` -TODO +func (dd DelegatorDist) ValidatorUpdate(g Global, totalBondedShares, height int64, Tokens Dec) Dec + + g.UpdateTotalValAccum(height, totalBondedShares) ``` From 360eb75c8e6cbc11ac7b7ae885a8bb3f7d11db20 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 14 Aug 2018 23:33:40 -0400 Subject: [PATCH 08/93] working --- docs/spec/distribution/transactions.md | 45 +++++++++++++++----------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/docs/spec/distribution/transactions.md b/docs/spec/distribution/transactions.md index b8de54ca57..22e4e40776 100644 --- a/docs/spec/distribution/transactions.md +++ b/docs/spec/distribution/transactions.md @@ -120,14 +120,14 @@ func (vu ValidatorUpdate) ProcessPowerChangeCommission() scenario2.UpdateAdjustmentForPowerChange(vu.Height) ``` -## Common Calculations +## Common calculations ### Update total validator accum The total amount of validator accum must be calculated in order to determine the amount of pool tokens which a validator is entitled to at a particular block. The accum is always additive to the existing accum. This term is to be -updates each time rewards are withdrawn from the system. +updates each time rewards are withdrawn from the system. ``` func (g Global) UpdateTotalValAccum(height int64, totalBondedTokens Dec) @@ -135,7 +135,7 @@ func (g Global) UpdateTotalValAccum(height int64, totalBondedTokens Dec) g.TotalValAccum += totalDelShares * blocks ``` -### Update total delegator accum +### Update validator's accums The total amount of delegator accum must be updated in order to determine the amount of pool tokens which each delegator is entitled to, relative to the @@ -149,7 +149,7 @@ func (vd ValidatorDistribution) UpdateTotalDelAccum(height int64, totalDelShares vd.TotalDelAccum += totalDelShares * blocks ``` -### Delegator accum +### Get delegator accum Each delegation has a passively calculated accumulation factor to specify its entitlement to the rewards from a validator. `Accum` is used to passively @@ -161,37 +161,44 @@ func (dd DelegatorDist) Accum(height int64, delegatorShares Dec) Dec return delegatorShares * blocks ``` -### Global Pool to Validator Pool +### Global pool to validator pool Everytime a validator or delegator make a withdraw or the validator is the proposer and receives new tokens - the relavent validator must move tokens from the passive global pool to thier own pool. ``` -func (dd DelegatorDist) ValidatorUpdate(g Global, totalBondedShares, height int64, Tokens Dec) Dec - +func (vd ValidatorDistribution) TakeAccum(g Global, height int64, totalBonded, vdTokens Dec) g Global g.UpdateTotalValAccum(height, totalBondedShares) + g.UpdateValAccum(height, totalBondedShares) + + // update the validators pool + blocks = height - vd.GlobalWithdrawalHeight + accum = blocks * vdTokens + withdrawalTokens := g.Pool * accum / g.TotalValAccum + + vd.Pool += withdrawalTokens + g.Pool -= withdrawalTokens + + return g ``` -### Delegation's entitlement to ValidatorDistribution.Pool +### Delegation's withdrawal For delegations (including validator's self-delegation) all fees from fee pool -are subject to commission rate from the owner of the validator. The global -shares should be taken as true number of global bonded shares. The recipients -shares should be taken as the bonded tokens less the validator's commission. - -Each delegation holds multiple accumulation factors to specify its entitlement to -the rewards from a validator. `Accum` is used to passively calculate -each bonds entitled rewards from the `RewardPool`. `AccumProposer` is used to -passively calculate each bonds entitled rewards from -`ValidatorDistribution.ProposerRewardPool` +are subject to commission rate from the owner of the validator. ``` -TODO +func (dd DelegatorDist) WithdrawalRewards(g Global, vd ValidatorDistribution, + height int64, totalBonded, vdTokens Dec) g Global + + vd.TakeAccum(g, height, totalBonded, vdTokens) + + ``` -### Validators's commission entitlement to ValidatorDistribution.Pool +### Validators's commission withdrawal Similar to a delegator's entitlement, but with recipient shares based on the commission portion of bonded tokens. From 37ed3b1a6eae69e2f8a361849c01417c6fa598ce Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 15 Aug 2018 04:12:44 -0400 Subject: [PATCH 09/93] agasg --- docs/spec/distribution/transactions.md | 40 ++++++++++++++++---------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/docs/spec/distribution/transactions.md b/docs/spec/distribution/transactions.md index 22e4e40776..cf10d8e2e4 100644 --- a/docs/spec/distribution/transactions.md +++ b/docs/spec/distribution/transactions.md @@ -149,18 +149,6 @@ func (vd ValidatorDistribution) UpdateTotalDelAccum(height int64, totalDelShares vd.TotalDelAccum += totalDelShares * blocks ``` -### Get delegator accum - -Each delegation has a passively calculated accumulation factor to specify its -entitlement to the rewards from a validator. `Accum` is used to passively -calculate each bonds entitled rewards from the `Validator.Pool`. - -``` -func (dd DelegatorDist) Accum(height int64, delegatorShares Dec) Dec - blocks = height - dd.WithdrawalHeight - return delegatorShares * blocks -``` - ### Global pool to validator pool Everytime a validator or delegator make a withdraw or the validator is the @@ -177,6 +165,7 @@ func (vd ValidatorDistribution) TakeAccum(g Global, height int64, totalBonded, v accum = blocks * vdTokens withdrawalTokens := g.Pool * accum / g.TotalValAccum + g.TotalValAccum -= accumm vd.Pool += withdrawalTokens g.Pool -= withdrawalTokens @@ -191,10 +180,18 @@ are subject to commission rate from the owner of the validator. ``` func (dd DelegatorDist) WithdrawalRewards(g Global, vd ValidatorDistribution, - height int64, totalBonded, vdTokens Dec) g Global + height int64, totalBonded, vdTokens, totalDelShares, commissionRate Dec) (g Global, withdrawn Dec) - vd.TakeAccum(g, height, totalBonded, vdTokens) + vd.UpdateTotalDelAccum(height, totalDelShares) + g = vd.TakeAccum(g, height, totalBonded, vdTokens) + blocks = height - dd.WithdrawalHeight + accum = delegatorShares * blocks * (1 - commissionRate) + + withdrawalTokens := vd.Pool * accum / cd.TotalDelAccum + vd.Pool -= withdrawalTokens + vd.TotalDelAccum -= accum + return withdrawalTokens ``` @@ -204,5 +201,18 @@ Similar to a delegator's entitlement, but with recipient shares based on the commission portion of bonded tokens. ``` -TODO +func (dd DelegatorDist) WithdrawalCommission(g Global, vd ValidatorDistribution, + height int64, totalBonded, vdTokens, totalDelShares, commissionRate Dec) g Global + + vd.UpdateTotalDelAccum(height, totalDelShares) + g = vd.TakeAccum(g, height, totalBonded, vdTokens) + + blocks = height - vd.CommissionWithdrawalHeight + accum = delegatorShares * blocks * (commissionRate) + + withdrawalTokens := vd.Pool * accum / cd.TotalDelAccum + + vd.Pool -= withdrawalTokens + vd.TotalDelAccum -= accum + ``` From 31d5348c4ae164a187f3670ddf4535045d758444 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 15 Aug 2018 20:03:39 -0400 Subject: [PATCH 10/93] txs pretty much ready --- docs/spec/distribution/transactions.md | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/docs/spec/distribution/transactions.md b/docs/spec/distribution/transactions.md index cf10d8e2e4..4e8ad92e4b 100644 --- a/docs/spec/distribution/transactions.md +++ b/docs/spec/distribution/transactions.md @@ -133,6 +133,7 @@ updates each time rewards are withdrawn from the system. func (g Global) UpdateTotalValAccum(height int64, totalBondedTokens Dec) blocks = height - g.TotalValAccumUpdateHeight g.TotalValAccum += totalDelShares * blocks + g.TotalValAccumUpdateHeight = height ``` ### Update validator's accums @@ -147,6 +148,7 @@ withdrawal is made from a validator. func (vd ValidatorDistribution) UpdateTotalDelAccum(height int64, totalDelShares Dec) blocks = height - vd.TotalDelAccumUpdateHeight vd.TotalDelAccum += totalDelShares * blocks + vd.TotalDelAccumUpdateHeight = height ``` ### Global pool to validator pool @@ -162,6 +164,7 @@ func (vd ValidatorDistribution) TakeAccum(g Global, height int64, totalBonded, v // update the validators pool blocks = height - vd.GlobalWithdrawalHeight + vd.GlobalWithdrawalHeight = height accum = blocks * vdTokens withdrawalTokens := g.Pool * accum / g.TotalValAccum @@ -179,19 +182,22 @@ For delegations (including validator's self-delegation) all fees from fee pool are subject to commission rate from the owner of the validator. ``` -func (dd DelegatorDist) WithdrawalRewards(g Global, vd ValidatorDistribution, +func (dd DelegatorDist) WithdrawRewards(g Global, vd ValidatorDistribution, height int64, totalBonded, vdTokens, totalDelShares, commissionRate Dec) (g Global, withdrawn Dec) vd.UpdateTotalDelAccum(height, totalDelShares) g = vd.TakeAccum(g, height, totalBonded, vdTokens) blocks = height - dd.WithdrawalHeight + dd.WithdrawalHeight = height accum = delegatorShares * blocks * (1 - commissionRate) - withdrawalTokens := vd.Pool * accum / cd.TotalDelAccum + withdrawalTokens := vd.Pool * accum / vd.TotalDelAccum + vd.TotalDelAccum -= accum + vd.Pool -= withdrawalTokens vd.TotalDelAccum -= accum - return withdrawalTokens + return g, withdrawalTokens ``` @@ -201,18 +207,21 @@ Similar to a delegator's entitlement, but with recipient shares based on the commission portion of bonded tokens. ``` -func (dd DelegatorDist) WithdrawalCommission(g Global, vd ValidatorDistribution, - height int64, totalBonded, vdTokens, totalDelShares, commissionRate Dec) g Global +func (vd ValidatorDist) WithdrawCommission(g Global, vd ValidatorDistribution, + height int64, totalBonded, vdTokens, totalDelShares, commissionRate Dec) (g Global, withdrawn Dec) vd.UpdateTotalDelAccum(height, totalDelShares) g = vd.TakeAccum(g, height, totalBonded, vdTokens) blocks = height - vd.CommissionWithdrawalHeight + vd.CommissionWithdrawalHeight = height accum = delegatorShares * blocks * (commissionRate) - withdrawalTokens := vd.Pool * accum / cd.TotalDelAccum + withdrawalTokens := vd.Pool * accum / vd.TotalDelAccum + vd.TotalDelAccum -= accum vd.Pool -= withdrawalTokens vd.TotalDelAccum -= accum + return g, withdrawalTokens ``` From 5ef0f5d70ea2cc62c28d3ddfd8ba06f7e0e1b547 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 15 Aug 2018 23:33:26 -0400 Subject: [PATCH 11/93] finalize txs --- docs/spec/distribution/transactions.md | 122 ++++++++----------------- 1 file changed, 39 insertions(+), 83 deletions(-) diff --git a/docs/spec/distribution/transactions.md b/docs/spec/distribution/transactions.md index 4e8ad92e4b..fbae152eb8 100644 --- a/docs/spec/distribution/transactions.md +++ b/docs/spec/distribution/transactions.md @@ -2,124 +2,80 @@ ## TxWithdrawDelegation -When a delegator wishes to withdraw their transaction fees it must send +When a delegator wishes to withdraw their rewards it must send `TxWithdrawDelegation`. Note that parts of this transaction logic are also triggered each with any change in individual delegations, such as an unbond, redelegation, or delegation of additional tokens to a specific validator. -Each time a withdrawal is made by a recipient the adjustment term must be -modified for each block with a change in distributors shares since the time of -last withdrawal. This is accomplished by iterating over all relevant -`ValidatorUpdate`'s stored in distribution state. - - ```golang type TxWithdrawDelegation struct { delegatorAddr sdk.AccAddress withdrawAddr sdk.AccAddress // address to make the withdrawal to } -func WithdrawDelegator(delegatorAddr, withdrawAddr sdk.AccAddress) - entitlement = GetDelegatorEntitlement(delegatorAddr) +func WithdrawFromDelegator(delegatorAddr, withdrawAddr sdk.AccAddress) + height = GetHeight() + withdraw = GetDelegatorAllWithdraws(delegatorAddr, height) AddCoins(withdrawAddr, totalEntitlment.TruncateDecimal()) -func GetDelegatorEntitlement(delegatorAddr sdk.AccAddress) DecCoins +func GetDelegatorAllWithdraws(delegatorAddr sdk.AccAddress, height int64) DecCoins - // compile all the distribution scenarios + // get all distribution scenarios delegations = GetDelegations(delegatorAddr) - DelDistr = GetDelegationDistribution(delegation.DelegatorAddr, - delegation.ValidatorAddr) - vus = GetValidatorUpdates(DelDistr.WithdrawalHeight) - // update all adjustment factors for each delegation since last withdrawal - for vu = range vus - for delegation = range delegations - DelDistr = GetDelegationDistribution(delegation.DelegatorAddr, - delegation.ValidatorAddr) - vu.ProcessPowerChangeDelegation(delegation, DelDistr) - - // collect all entitled fees - entitlement = 0 + // collect all entitled rewards + withdraw = 0 + pool = stake.GetPool() + global = GetGlobal() for delegation = range delegations - global = GetGlobal() - pool = GetPool() - DelDistr = GetDelegationDistribution(delegation.DelegatorAddr, + delDistr = GetDelegationDistribution(delegation.DelegatorAddr, delegation.ValidatorAddr) - ValDistr = GetValidatorDistribution(delegation.ValidatorAddr) + valDistr = GetValidatorDistribution(delegation.ValidatorAddr) validator = GetValidator(delegation.ValidatorAddr) - scenerio1 = NewDelegationFromGlobalPool(delegation, validator, - pool, global, ValDistr, DelDistr) - scenerio2 = NewDelegationFromProvisionPool(delegation, validator, - ValDistr, DelDistr) - entitlement += scenerio1.WithdrawalEntitlement() - entitlement += scenerio2.WithdrawalEntitlement() - - return entitlement + global, ddWithdraw = delDistr.WithdrawRewards(global, valDistr, height, pool.BondedTokens, + validator.Tokens, validator.DelegatorShares, validator.Commission) + withdraw += ddWithdraw -func (vu ValidatorUpdate) ProcessPowerChangeDelegation(delegation sdk.Delegation, - DelDistr DelegationDistribution) - - // get the historical scenarios - scenario1 = vu.DelegationFromGlobalPool(delegation, DelDistr) - scenario2 = vu.DelegationFromProvisionPool(delegation, DelDistr) - - // process the adjustment factors - scenario1.UpdateAdjustmentForPowerChange(vu.Height) - scenario2.UpdateAdjustmentForPowerChange(vu.Height) + SetGlobal(global) + return withdraw ``` ## TxWithdrawValidator -When a validator wishes to withdraw their transaction fees it must send +When a validator wishes to withdraw their rewards it must send `TxWithdrawDelegation`. Note that parts of this transaction logic is also triggered each with any change in individual delegations, such as an unbond, redelegation, or delegation of additional tokens to a specific validator. This -transaction withdraws the validators commission rewards, as well as any rewards +transaction withdraws the validators commission fee, as well as any rewards earning on their self-delegation. ``` type TxWithdrawValidator struct { - ownerAddr sdk.AccAddress // validator address to withdraw from + operatorAddr sdk.AccAddress // validator address to withdraw from withdrawAddr sdk.AccAddress // address to make the withdrawal to } -func WithdrawalValidator(ownerAddr, withdrawAddr sdk.AccAddress) +func WithdrawFromValidator(operatorAddr, withdrawAddr sdk.AccAddress) - // update the delegator adjustment factors and also withdrawal delegation fees - entitlement = GetDelegatorEntitlement(ownerAddr) - - // update the validator adjustment factors for commission - ValDistr = GetValidatorDistribution(ownerAddr.ValidatorAddr) - vus = GetValidatorUpdates(ValDistr.CommissionWithdrawalHeight) - for vu = range vus - vu.ProcessPowerChangeCommission() - - // withdrawal validator commission rewards + height = GetHeight() global = GetGlobal() pool = GetPool() ValDistr = GetValidatorDistribution(delegation.ValidatorAddr) validator = GetValidator(delegation.ValidatorAddr) - scenerio1 = NewCommissionFromGlobalPool(validator, - pool, global, ValDistr) - scenerio2 = CommissionFromProposerPool(validator, ValDistr) - entitlement += scenerio1.WithdrawalEntitlement() - entitlement += scenerio2.WithdrawalEntitlement() - + // withdraw self-delegation + withdraw = GetDelegatorAllWithdraws(validator.OperatorAddr, height) + + // withdrawal validator commission rewards + global, commission = valDistr.WithdrawCommission(global, valDistr, height, pool.BondedTokens, + validator.Tokens, validator.DelegatorShares, validator.Commission) + withdraw += commission + SetGlobal(global) + AddCoins(withdrawAddr, totalEntitlment.TruncateDecimal()) - -func (vu ValidatorUpdate) ProcessPowerChangeCommission() - - // get the historical scenarios - scenario1 = vu.CommissionFromGlobalPool() - scenario2 = vu.CommissionFromProposerPool() - - // process the adjustment factors - scenario1.UpdateAdjustmentForPowerChange(vu.Height) - scenario2.UpdateAdjustmentForPowerChange(vu.Height) ``` - + ## Common calculations ### Update total validator accum @@ -153,9 +109,9 @@ func (vd ValidatorDistribution) UpdateTotalDelAccum(height int64, totalDelShares ### Global pool to validator pool -Everytime a validator or delegator make a withdraw or the validator is the -proposer and receives new tokens - the relavent validator must move tokens from -the passive global pool to thier own pool. +Every time a validator or delegator make a withdraw or the validator is the +proposer and receives new tokens - the relevant validator must move tokens from +the passive global pool to their own pool. ``` func (vd ValidatorDistribution) TakeAccum(g Global, height int64, totalBonded, vdTokens Dec) g Global @@ -178,12 +134,12 @@ func (vd ValidatorDistribution) TakeAccum(g Global, height int64, totalBonded, v ### Delegation's withdrawal -For delegations (including validator's self-delegation) all fees from fee pool -are subject to commission rate from the owner of the validator. +For delegations (including validator's self-delegation) all rewards from reward pool +are subject to commission rate from the operator of the validator. ``` func (dd DelegatorDist) WithdrawRewards(g Global, vd ValidatorDistribution, - height int64, totalBonded, vdTokens, totalDelShares, commissionRate Dec) (g Global, withdrawn Dec) + height int64, totalBonded, vdTokens, totalDelShares, commissionRate Dec) (g Global, withdrawn DecCoins) vd.UpdateTotalDelAccum(height, totalDelShares) g = vd.TakeAccum(g, height, totalBonded, vdTokens) @@ -208,7 +164,7 @@ commission portion of bonded tokens. ``` func (vd ValidatorDist) WithdrawCommission(g Global, vd ValidatorDistribution, - height int64, totalBonded, vdTokens, totalDelShares, commissionRate Dec) (g Global, withdrawn Dec) + height int64, totalBonded, vdTokens, totalDelShares, commissionRate Dec) (g Global, withdrawn DecCoins) vd.UpdateTotalDelAccum(height, totalDelShares) g = vd.TakeAccum(g, height, totalBonded, vdTokens) From 8fc9b95929a48a538c2f320d3eedeebf94082cc0 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 15 Aug 2018 23:49:07 -0400 Subject: [PATCH 12/93] pending --- PENDING.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/PENDING.md b/PENDING.md index 6cc6ce10cf..c0971cf80c 100644 --- a/PENDING.md +++ b/PENDING.md @@ -63,6 +63,7 @@ IMPROVEMENTS * [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. +* [spec] Added simple piggy bank distribution spec BUG FIXES * \#1666 Add intra-tx counter to the genesis validators @@ -85,4 +86,4 @@ BUG FIXES * \#1666 Add intra-tx counter to the genesis validators * [tests] \#1551: Fixed invalid LCD test JSON payload in `doIBCTransfer` * \#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) \ No newline at end of file +* [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) From 3c564c01b911e51f2428452b3489b3303ac14b9c Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 16 Aug 2018 16:41:32 -0400 Subject: [PATCH 13/93] clearer names, missing commission logic --- docs/spec/distribution/state.md | 14 ++--- docs/spec/distribution/transactions.md | 83 ++++++++++++++------------ docs/spec/distribution/triggers.md | 4 +- 3 files changed, 55 insertions(+), 46 deletions(-) diff --git a/docs/spec/distribution/state.md b/docs/spec/distribution/state.md index 1157825945..83e82f494d 100644 --- a/docs/spec/distribution/state.md +++ b/docs/spec/distribution/state.md @@ -38,10 +38,10 @@ Validator distribution information for the relevant validator is updated each ti 3. any delegator withdraws from a validator, or 4. the validator withdraws it's commission. - - ValidatorDistribution: `0x02 | ValOwnerAddr -> amino(validatorDistribution)` + - ValidatorDistInfo: `0x02 | ValOperatorAddr -> amino(validatorDistribution)` ```golang -type ValidatorDistribution struct { +type ValidatorDistInfo struct { CommissionWithdrawalHeight int64 // last height this validator withdrew commission GlobalWithdrawalHeight int64 // last height this validator withdrew from the global pool @@ -60,10 +60,10 @@ properties change (aka bonded tokens etc.) its properties will remain constant and the delegator's _accumulation_ factor can be calculated passively knowing only the height of the last withdrawal and its current properties. - - DelegatorDistribution: ` 0x02 | DelegatorAddr | ValOwnerAddr -> amino(delegatorDist)` + - DelegatorDistInfo: ` 0x02 | DelegatorAddr | ValOperatorAddr -> amino(delegatorDist)` ```golang -type DelegatorDist struct { +type DelegatorDistInfo struct { WithdrawalHeight int64 // last time this delegation withdrew rewards } ``` @@ -76,14 +76,14 @@ Every instance that a validator: - is slashed, or - changes its commission rate, -information about the state change must be recorded as a `ValidatorUpdate`. +information about the state change to each validator must be recorded as a `ValidatorUpdate`. Each power change is indexed by validator and its block height. - - ValidatorUpdate: `0x03 | ValOwnerAddr | amino(Height) -> amino(ValidatorUpdate)` + - ValidatorUpdate: `0x03 | ValOperatorAddr | amino(Height) -> amino(ValidatorUpdate)` ```golang type ValidatorUpdate struct { Height int64 // block height of update - NewCommissionRate sdk.Dec // commission rate at this height + OldCommissionRate sdk.Dec // commission rate at this height } ``` diff --git a/docs/spec/distribution/transactions.md b/docs/spec/distribution/transactions.md index fbae152eb8..364346ff48 100644 --- a/docs/spec/distribution/transactions.md +++ b/docs/spec/distribution/transactions.md @@ -8,12 +8,12 @@ triggered each with any change in individual delegations, such as an unbond, redelegation, or delegation of additional tokens to a specific validator. ```golang -type TxWithdrawDelegation struct { +type TxWithdrawDelegationRewards struct { delegatorAddr sdk.AccAddress withdrawAddr sdk.AccAddress // address to make the withdrawal to } -func WithdrawFromDelegator(delegatorAddr, withdrawAddr sdk.AccAddress) +func WithdrawDelegationRewards(delegatorAddr, withdrawAddr sdk.AccAddress) height = GetHeight() withdraw = GetDelegatorAllWithdraws(delegatorAddr, height) AddCoins(withdrawAddr, totalEntitlment.TruncateDecimal()) @@ -28,14 +28,23 @@ func GetDelegatorAllWithdraws(delegatorAddr sdk.AccAddress, height int64) DecCoi pool = stake.GetPool() global = GetGlobal() for delegation = range delegations - delDistr = GetDelegationDistribution(delegation.DelegatorAddr, + delInfo = GetDelegationDistInfo(delegation.DelegatorAddr, delegation.ValidatorAddr) - valDistr = GetValidatorDistribution(delegation.ValidatorAddr) + valInfo = GetValidatorDistInfo(delegation.ValidatorAddr) validator = GetValidator(delegation.ValidatorAddr) - global, ddWithdraw = delDistr.WithdrawRewards(global, valDistr, height, pool.BondedTokens, + // get all commission rate changes since last withdraw + vus = GetValidatorUpdates(delegation.ValidatorAddr, delInfo.WithdrawalHeight) + + for vu = range vus { + global, diWithdraw = delInfo.WithdrawRewards(global, valInfo, vu.Height, pool.BondedTokens, + validator.Tokens, validator.DelegatorShares, vu.OldCommissionRate) + withdraw += diWithdraw + } + + global, diWithdraw = delInfo.WithdrawRewards(global, valInfo, height, pool.BondedTokens, validator.Tokens, validator.DelegatorShares, validator.Commission) - withdraw += ddWithdraw + withdraw += diWithdraw SetGlobal(global) return withdraw @@ -51,24 +60,24 @@ transaction withdraws the validators commission fee, as well as any rewards earning on their self-delegation. ``` -type TxWithdrawValidator struct { +type TxWithdrawValidatorRewards struct { operatorAddr sdk.AccAddress // validator address to withdraw from withdrawAddr sdk.AccAddress // address to make the withdrawal to } -func WithdrawFromValidator(operatorAddr, withdrawAddr sdk.AccAddress) +func WithdrawValidatorRewards(operatorAddr, withdrawAddr sdk.AccAddress) height = GetHeight() global = GetGlobal() pool = GetPool() - ValDistr = GetValidatorDistribution(delegation.ValidatorAddr) + ValInfo = GetValidatorDistInfo(delegation.ValidatorAddr) validator = GetValidator(delegation.ValidatorAddr) // withdraw self-delegation withdraw = GetDelegatorAllWithdraws(validator.OperatorAddr, height) // withdrawal validator commission rewards - global, commission = valDistr.WithdrawCommission(global, valDistr, height, pool.BondedTokens, + global, commission = valInfo.WithdrawCommission(global, valInfo, height, pool.BondedTokens, validator.Tokens, validator.DelegatorShares, validator.Commission) withdraw += commission SetGlobal(global) @@ -101,10 +110,10 @@ the existing accum. This term is to be updated each time a withdrawal is made from a validator. ``` -func (vd ValidatorDistribution) UpdateTotalDelAccum(height int64, totalDelShares Dec) - blocks = height - vd.TotalDelAccumUpdateHeight - vd.TotalDelAccum += totalDelShares * blocks - vd.TotalDelAccumUpdateHeight = height +func (vi ValidatorDistInfo) UpdateTotalDelAccum(height int64, totalDelShares Dec) + blocks = height - vi.TotalDelAccumUpdateHeight + vi.TotalDelAccum += totalDelShares * blocks + vi.TotalDelAccumUpdateHeight = height ``` ### Global pool to validator pool @@ -114,18 +123,18 @@ proposer and receives new tokens - the relevant validator must move tokens from the passive global pool to their own pool. ``` -func (vd ValidatorDistribution) TakeAccum(g Global, height int64, totalBonded, vdTokens Dec) g Global +func (vi ValidatorDistInfo) TakeAccum(g Global, height int64, totalBonded, vdTokens Dec) g Global g.UpdateTotalValAccum(height, totalBondedShares) g.UpdateValAccum(height, totalBondedShares) // update the validators pool - blocks = height - vd.GlobalWithdrawalHeight - vd.GlobalWithdrawalHeight = height + blocks = height - vi.GlobalWithdrawalHeight + vi.GlobalWithdrawalHeight = height accum = blocks * vdTokens withdrawalTokens := g.Pool * accum / g.TotalValAccum g.TotalValAccum -= accumm - vd.Pool += withdrawalTokens + vi.Pool += withdrawalTokens g.Pool -= withdrawalTokens return g @@ -138,21 +147,21 @@ For delegations (including validator's self-delegation) all rewards from reward are subject to commission rate from the operator of the validator. ``` -func (dd DelegatorDist) WithdrawRewards(g Global, vd ValidatorDistribution, +func (di DelegatorDistInfo) WithdrawRewards(g Global, vi ValidatorDistInfo, height int64, totalBonded, vdTokens, totalDelShares, commissionRate Dec) (g Global, withdrawn DecCoins) - vd.UpdateTotalDelAccum(height, totalDelShares) - g = vd.TakeAccum(g, height, totalBonded, vdTokens) + vi.UpdateTotalDelAccum(height, totalDelShares) + g = vi.TakeAccum(g, height, totalBonded, vdTokens) - blocks = height - dd.WithdrawalHeight - dd.WithdrawalHeight = height + blocks = height - di.WithdrawalHeight + di.WithdrawalHeight = height accum = delegatorShares * blocks * (1 - commissionRate) - withdrawalTokens := vd.Pool * accum / vd.TotalDelAccum - vd.TotalDelAccum -= accum + withdrawalTokens := vi.Pool * accum / vi.TotalDelAccum + vi.TotalDelAccum -= accum - vd.Pool -= withdrawalTokens - vd.TotalDelAccum -= accum + vi.Pool -= withdrawalTokens + vi.TotalDelAccum -= accum return g, withdrawalTokens ``` @@ -163,21 +172,21 @@ Similar to a delegator's entitlement, but with recipient shares based on the commission portion of bonded tokens. ``` -func (vd ValidatorDist) WithdrawCommission(g Global, vd ValidatorDistribution, - height int64, totalBonded, vdTokens, totalDelShares, commissionRate Dec) (g Global, withdrawn DecCoins) +func (vi ValidatorDistInfo) WithdrawCommission(g Global, height int64, + totalBonded, vdTokens, totalDelShares, commissionRate Dec) (g Global, withdrawn DecCoins) - vd.UpdateTotalDelAccum(height, totalDelShares) - g = vd.TakeAccum(g, height, totalBonded, vdTokens) + vi.UpdateTotalDelAccum(height, totalDelShares) + g = vi.TakeAccum(g, height, totalBonded, vdTokens) - blocks = height - vd.CommissionWithdrawalHeight - vd.CommissionWithdrawalHeight = height + blocks = height - vi.CommissionWithdrawalHeight + vi.CommissionWithdrawalHeight = height accum = delegatorShares * blocks * (commissionRate) - withdrawalTokens := vd.Pool * accum / vd.TotalDelAccum - vd.TotalDelAccum -= accum + withdrawalTokens := vi.Pool * accum / vi.TotalDelAccum + vi.TotalDelAccum -= accum - vd.Pool -= withdrawalTokens - vd.TotalDelAccum -= accum + vi.Pool -= withdrawalTokens + vi.TotalDelAccum -= accum return g, withdrawalTokens ``` diff --git a/docs/spec/distribution/triggers.md b/docs/spec/distribution/triggers.md index 0e02f04312..2938e674f7 100644 --- a/docs/spec/distribution/triggers.md +++ b/docs/spec/distribution/triggers.md @@ -6,7 +6,7 @@ The pool of a new delegator bond will be 0 for the height at which the bond was added, or the withdrawal has taken place. This is achieved by setting -`DelegatorDist.WithdrawalHeight` to the height of the triggering transaction. +`DelegatorDistInfo.WithdrawalHeight` to the height of the triggering transaction. ## Commission rate change @@ -23,4 +23,4 @@ Additionally the change and associated height must be recorded in a Whenever a validator is slashed or enters/leaves the validator group all of the validator entitled reward tokens must be simultaniously withdrawn from -`Global.Pool` and added to `ValidatorDistribution.Pool` +`Global.Pool` and added to `ValidatorDistInfo.Pool` From 6e3e57e23e695680d8414509072c51abe1dccde9 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 20 Aug 2018 17:50:13 +0200 Subject: [PATCH 14/93] Typos; tiny wording changes --- docs/spec/distribution/overview.md | 36 ++++++++++++-------------- docs/spec/distribution/state.md | 2 +- docs/spec/distribution/transactions.md | 14 +++++----- docs/spec/distribution/triggers.md | 4 +-- 4 files changed, 26 insertions(+), 30 deletions(-) diff --git a/docs/spec/distribution/overview.md b/docs/spec/distribution/overview.md index 62cec2e768..7b912f2823 100644 --- a/docs/spec/distribution/overview.md +++ b/docs/spec/distribution/overview.md @@ -4,23 +4,23 @@ This _simple_ distribution mechanism describes a functional way to passively distribute rewards between validator and delegators. Note that this mechanism does -not distribute funds in as precisely as active reward distribution and will therefor +not distribute funds in as precisely as active reward distribution and will therefore be upgraded in the future. The mechanism operates as follows. Collected rewards are pooled globally and divided out passively to validators and delegators. Each validator has the opportunity to charge commission to the delegators on the rewards collected on -behalf of the delegators by the validators. Fees are paid directly into a +behalf of the delegators by the validators. Fees are paid directly into a global reward pool, and validator proposer-reward pool. Due to the nature of -passive accounting whenever changes to parameters which affect the rate of reward -distribution occurs, withdrawal of rewards must also occur when: - - - withdrawing one must withdrawal the maximum amount they are entitled - too, leaving nothing in the pool, - - bonding, unbonding, or re-delegating tokens to an existing account a +passive accounting, whenever changes to parameters which affect the rate of reward +distribution occurs, withdrawal of rewards must also occur. + + - Whenever withdrawing, one must withdraw the maximum amount they are entitled + too, leaving nothing in the pool. + - Whenever bonding, unbonding, or re-delegating tokens to an existing account, a full withdrawal of the rewards must occur (as the rules for lazy accounting - change), - - a validator chooses to change the commission on rewards, all accumulated + change). + - Whenever a validator chooses to change the commission on rewards, all accumulated commission rewards must be simultaneously withdrawn. The above scenarios are covered in `triggers.md`. @@ -33,10 +33,8 @@ following rewards between validators and associated delegators: - validator commission on all rewards earned by their delegators stake Fees are pooled within a global pool, as well as validator specific -proposer-reward pools. The mechanisms used allow for validators and delegators -to independently and lazily withdrawn their rewards. - -Within this spec +proposer-reward pools. The mechanisms used allow for validators and delegators +to independently and lazily withdraw their rewards. As a part of the lazy computations, each validator and delegator holds an accumulation term which is used to estimate what their approximate fair portion @@ -47,18 +45,16 @@ is not the case, the approximation of owed rewards will deviate from the active distribution based on fluctuations of incoming reward tokens as well as timing of reward withdrawal by other delegators and validators from the reward pool. - ## Affect on Staking Charging commission on Atom provisions while also allowing for Atom-provisions to be auto-bonded (distributed directly to the validators bonded stake) is -problematic within DPoS. Fundamentally these two mechnisms are mutually -exclusive. If there are atoms commissions and auto-bonding Atoms, the portion +problematic within DPoS. Fundamentally these two mechnisms are mutually +exclusive. If there are Atom commissions and auto-bonding Atoms, the portion of Atoms the reward distribution calculation would become very large as the Atom portion for each delegator would change each block making a withdrawal of rewards for a delegator require a calculation for every single block since the last -withdrawal. In conclusion we can only have atom commission and unbonded atoms -provisions, or bonded atom provisions with no Atom commission, and we elect to +withdrawal. In conclusion, we can only have Atom commission and unbonded atoms +provisions or bonded atom provisions with no Atom commission, and we elect to implement the former. Stakeholders wishing to rebond their provisions may elect to set up a script to periodically withdraw and rebond rewards. - diff --git a/docs/spec/distribution/state.md b/docs/spec/distribution/state.md index 83e82f494d..7dc011e957 100644 --- a/docs/spec/distribution/state.md +++ b/docs/spec/distribution/state.md @@ -33,7 +33,7 @@ type Global struct { ### Validator Distribution Validator distribution information for the relevant validator is updated each time: - 1. delegation amount to a validator are updated, + 1. delegation amount to a validator is updated, 2. a validator successfully proposes a block and receives a reward, 3. any delegator withdraws from a validator, or 4. the validator withdraws it's commission. diff --git a/docs/spec/distribution/transactions.md b/docs/spec/distribution/transactions.md index 364346ff48..82f9e84f76 100644 --- a/docs/spec/distribution/transactions.md +++ b/docs/spec/distribution/transactions.md @@ -53,7 +53,7 @@ func GetDelegatorAllWithdraws(delegatorAddr sdk.AccAddress, height int64) DecCoi ## TxWithdrawValidator When a validator wishes to withdraw their rewards it must send -`TxWithdrawDelegation`. Note that parts of this transaction logic is also +`TxWithdrawValidatorRewards`. Note that parts of this transaction logic are also triggered each with any change in individual delegations, such as an unbond, redelegation, or delegation of additional tokens to a specific validator. This transaction withdraws the validators commission fee, as well as any rewards @@ -61,7 +61,7 @@ earning on their self-delegation. ``` type TxWithdrawValidatorRewards struct { - operatorAddr sdk.AccAddress // validator address to withdraw from + operatorAddr sdk.AccAddress // validator address to withdraw from withdrawAddr sdk.AccAddress // address to make the withdrawal to } @@ -92,7 +92,7 @@ func WithdrawValidatorRewards(operatorAddr, withdrawAddr sdk.AccAddress) The total amount of validator accum must be calculated in order to determine the amount of pool tokens which a validator is entitled to at a particular block. The accum is always additive to the existing accum. This term is to be -updates each time rewards are withdrawn from the system. +updated each time rewards are withdrawn from the system. ``` func (g Global) UpdateTotalValAccum(height int64, totalBondedTokens Dec) @@ -118,8 +118,8 @@ func (vi ValidatorDistInfo) UpdateTotalDelAccum(height int64, totalDelShares Dec ### Global pool to validator pool -Every time a validator or delegator make a withdraw or the validator is the -proposer and receives new tokens - the relevant validator must move tokens from +Every time a validator or delegator executes a withdrawal or the validator is the +proposer and receives new tokens, the relevant validator must move tokens from the passive global pool to their own pool. ``` @@ -141,7 +141,7 @@ func (vi ValidatorDistInfo) TakeAccum(g Global, height int64, totalBonded, vdTok ``` -### Delegation's withdrawal +### Delegation reward withdrawal For delegations (including validator's self-delegation) all rewards from reward pool are subject to commission rate from the operator of the validator. @@ -166,7 +166,7 @@ func (di DelegatorDistInfo) WithdrawRewards(g Global, vi ValidatorDistInfo, ``` -### Validators's commission withdrawal +### Validator commission withdrawal Similar to a delegator's entitlement, but with recipient shares based on the commission portion of bonded tokens. diff --git a/docs/spec/distribution/triggers.md b/docs/spec/distribution/triggers.md index 2938e674f7..e3971ea99d 100644 --- a/docs/spec/distribution/triggers.md +++ b/docs/spec/distribution/triggers.md @@ -22,5 +22,5 @@ Additionally the change and associated height must be recorded in a - triggered-by: `stake.Slash`, `stake.UpdateValidator` Whenever a validator is slashed or enters/leaves the validator group all of the -validator entitled reward tokens must be simultaniously withdrawn from -`Global.Pool` and added to `ValidatorDistInfo.Pool` +validator entitled reward tokens must be simultaneously withdrawn from +`Global.Pool` and added to `ValidatorDistInfo.Pool`. From b32285ec3b11aea53beb79d5fcd4c2488881d038 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 23 Aug 2018 03:19:21 -0400 Subject: [PATCH 15/93] commission actively calculated, withdrawDelegationReward Tx --- docs/spec/distribution/end_block.md | 12 ++-- docs/spec/distribution/state.md | 25 +------ docs/spec/distribution/transactions.md | 92 +++++++++++++++----------- 3 files changed, 64 insertions(+), 65 deletions(-) diff --git a/docs/spec/distribution/end_block.md b/docs/spec/distribution/end_block.md index 19c9e83021..952d1832ac 100644 --- a/docs/spec/distribution/end_block.md +++ b/docs/spec/distribution/end_block.md @@ -1,6 +1,6 @@ # End Block -At each endblock, the fees received are sorted to the proposer, community fund, +At each endblock, the fees received are allocated to the proposer, community fund, and global pool. When the validator is the proposer of the round, that validator (and their delegators) receives between 1% and 5% of fee rewards, the reserve community tax is then charged, then the remainder is distributed @@ -15,13 +15,17 @@ pool which validator holds individually (`ValidatorDistribution.ProvisionsRewardPool`). ``` -func SortFees(feesCollected sdk.Coins, global Global, proposer ValidatorDistribution, - sumPowerPrecommitValidators, totalBondedTokens, communityTax sdk.Dec) +func AllocateFees(feesCollected sdk.Coins, global Global, proposer ValidatorDistribution, + sumPowerPrecommitValidators, totalBondedTokens, communityTax, + proposerCommissionRate sdk.Dec) feesCollectedDec = MakeDecCoins(feesCollected) proposerReward = feesCollectedDec * (0.01 + 0.04 * sumPowerPrecommitValidators / totalBondedTokens) - proposer.ProposerPool += proposerReward + + commission = proposerReward * proposerCommissionRate + proposer.PoolCommission += commission + proposer.Pool += proposerReward - commission communityFunding = feesCollectedDec * communityTax global.CommunityFund += communityFunding diff --git a/docs/spec/distribution/state.md b/docs/spec/distribution/state.md index 7dc011e957..3e3669789a 100644 --- a/docs/spec/distribution/state.md +++ b/docs/spec/distribution/state.md @@ -42,10 +42,9 @@ Validator distribution information for the relevant validator is updated each ti ```golang type ValidatorDistInfo struct { - CommissionWithdrawalHeight int64 // last height this validator withdrew commission - GlobalWithdrawalHeight int64 // last height this validator withdrew from the global pool - Pool DecCoins // reward pool collected held within this validator (includes proposer rewards) + Pool DecCoins // rewards owed to delegators, commission has already been charged (includes proposer reward) + PoolCommission DecCoins // commission collected by this validator (pending withdrawal) TotalDelAccumUpdateHeight int64 // last height which the total delegator accum was updated TotalDelAccum sdk.Dec // total proposer pool accumulation factor held by delegators @@ -67,23 +66,3 @@ type DelegatorDistInfo struct { WithdrawalHeight int64 // last time this delegation withdrew rewards } ``` - -### Validator Update - -Every instance that a validator: - - enters into the bonded state, - - leaves the bonded state, - - is slashed, or - - changes its commission rate, - -information about the state change to each validator must be recorded as a `ValidatorUpdate`. -Each power change is indexed by validator and its block height. - - - ValidatorUpdate: `0x03 | ValOperatorAddr | amino(Height) -> amino(ValidatorUpdate)` - -```golang -type ValidatorUpdate struct { - Height int64 // block height of update - OldCommissionRate sdk.Dec // commission rate at this height -} -``` diff --git a/docs/spec/distribution/transactions.md b/docs/spec/distribution/transactions.md index 82f9e84f76..2ed12d2c32 100644 --- a/docs/spec/distribution/transactions.md +++ b/docs/spec/distribution/transactions.md @@ -1,9 +1,9 @@ # Transactions -## TxWithdrawDelegation +## TxWithdrawDelegationRewards When a delegator wishes to withdraw their rewards it must send -`TxWithdrawDelegation`. Note that parts of this transaction logic are also +`TxWithdrawDelegationRewards`. Note that parts of this transaction logic are also triggered each with any change in individual delegations, such as an unbond, redelegation, or delegation of additional tokens to a specific validator. @@ -16,7 +16,7 @@ type TxWithdrawDelegationRewards struct { func WithdrawDelegationRewards(delegatorAddr, withdrawAddr sdk.AccAddress) height = GetHeight() withdraw = GetDelegatorAllWithdraws(delegatorAddr, height) - AddCoins(withdrawAddr, totalEntitlment.TruncateDecimal()) + AddCoins(withdrawAddr, withdraw.TruncateDecimal()) func GetDelegatorAllWithdraws(delegatorAddr sdk.AccAddress, height int64) DecCoins @@ -33,15 +33,6 @@ func GetDelegatorAllWithdraws(delegatorAddr sdk.AccAddress, height int64) DecCoi valInfo = GetValidatorDistInfo(delegation.ValidatorAddr) validator = GetValidator(delegation.ValidatorAddr) - // get all commission rate changes since last withdraw - vus = GetValidatorUpdates(delegation.ValidatorAddr, delInfo.WithdrawalHeight) - - for vu = range vus { - global, diWithdraw = delInfo.WithdrawRewards(global, valInfo, vu.Height, pool.BondedTokens, - validator.Tokens, validator.DelegatorShares, vu.OldCommissionRate) - withdraw += diWithdraw - } - global, diWithdraw = delInfo.WithdrawRewards(global, valInfo, height, pool.BondedTokens, validator.Tokens, validator.DelegatorShares, validator.Commission) withdraw += diWithdraw @@ -50,7 +41,38 @@ func GetDelegatorAllWithdraws(delegatorAddr sdk.AccAddress, height int64) DecCoi return withdraw ``` -## TxWithdrawValidator +## TxWithdrawDelegationReward + +under special circumstances a delegator may wish to withdraw rewards from only +a single validator. + +```golang +type TxWithdrawDelegationReward struct { + delegatorAddr sdk.AccAddress + validatorAddr sdk.AccAddress + withdrawAddr sdk.AccAddress // address to make the withdrawal to +} + +func WithdrawDelegationReward(delegatorAddr, validatorAddr, withdrawAddr sdk.AccAddress) + height = GetHeight() + + // get all distribution scenarios + pool = stake.GetPool() + global = GetGlobal() + delInfo = GetDelegationDistInfo(delegatorAddr, + validatorAddr) + valInfo = GetValidatorDistInfo(validatorAddr) + validator = GetValidator(validatorAddr) + + global, withdraw = delInfo.WithdrawRewards(global, valInfo, height, pool.BondedTokens, + validator.Tokens, validator.DelegatorShares, validator.Commission) + + SetGlobal(global) + AddCoins(withdrawAddr, withdraw.TruncateDecimal()) +``` + + +## TxWithdrawValidatorRewards When a validator wishes to withdraw their rewards it must send `TxWithdrawValidatorRewards`. Note that parts of this transaction logic are also @@ -78,11 +100,11 @@ func WithdrawValidatorRewards(operatorAddr, withdrawAddr sdk.AccAddress) // withdrawal validator commission rewards global, commission = valInfo.WithdrawCommission(global, valInfo, height, pool.BondedTokens, - validator.Tokens, validator.DelegatorShares, validator.Commission) + validator.Tokens, validator.Commission) withdraw += commission SetGlobal(global) - AddCoins(withdrawAddr, totalEntitlment.TruncateDecimal()) + AddCoins(withdrawAddr, withdraw.TruncateDecimal()) ``` ## Common calculations @@ -118,12 +140,13 @@ func (vi ValidatorDistInfo) UpdateTotalDelAccum(height int64, totalDelShares Dec ### Global pool to validator pool -Every time a validator or delegator executes a withdrawal or the validator is the -proposer and receives new tokens, the relevant validator must move tokens from -the passive global pool to their own pool. +Every time a validator or delegator executes a withdrawal or the validator is +the proposer and receives new tokens, the relevant validator must move tokens +from the passive global pool to their own pool. It is at this point that the +commission is withdrawn ``` -func (vi ValidatorDistInfo) TakeAccum(g Global, height int64, totalBonded, vdTokens Dec) g Global +func (vi ValidatorDistInfo) TakeAccum(g Global, height int64, totalBonded, vdTokens, commissionRate Dec) g Global g.UpdateTotalValAccum(height, totalBondedShares) g.UpdateValAccum(height, totalBondedShares) @@ -132,9 +155,11 @@ func (vi ValidatorDistInfo) TakeAccum(g Global, height int64, totalBonded, vdTok vi.GlobalWithdrawalHeight = height accum = blocks * vdTokens withdrawalTokens := g.Pool * accum / g.TotalValAccum + commission := withdrawalTokens * commissionRate g.TotalValAccum -= accumm - vi.Pool += withdrawalTokens + vi.PoolCommission += commission + vi.PoolCommissionFree += withdrawalTokens - commission g.Pool -= withdrawalTokens return g @@ -143,19 +168,19 @@ func (vi ValidatorDistInfo) TakeAccum(g Global, height int64, totalBonded, vdTok ### Delegation reward withdrawal -For delegations (including validator's self-delegation) all rewards from reward pool -are subject to commission rate from the operator of the validator. +For delegations (including validator's self-delegation) all rewards from reward +pool have already had the validator's commission taken away. ``` func (di DelegatorDistInfo) WithdrawRewards(g Global, vi ValidatorDistInfo, height int64, totalBonded, vdTokens, totalDelShares, commissionRate Dec) (g Global, withdrawn DecCoins) vi.UpdateTotalDelAccum(height, totalDelShares) - g = vi.TakeAccum(g, height, totalBonded, vdTokens) + g = vi.TakeAccum(g, height, totalBonded, vdTokens, commissionRate) blocks = height - di.WithdrawalHeight di.WithdrawalHeight = height - accum = delegatorShares * blocks * (1 - commissionRate) + accum = delegatorShares * blocks withdrawalTokens := vi.Pool * accum / vi.TotalDelAccum vi.TotalDelAccum -= accum @@ -168,25 +193,16 @@ func (di DelegatorDistInfo) WithdrawRewards(g Global, vi ValidatorDistInfo, ### Validator commission withdrawal -Similar to a delegator's entitlement, but with recipient shares based on the -commission portion of bonded tokens. +Commission is calculated each time rewards enter into the validator. ``` func (vi ValidatorDistInfo) WithdrawCommission(g Global, height int64, - totalBonded, vdTokens, totalDelShares, commissionRate Dec) (g Global, withdrawn DecCoins) + totalBonded, vdTokens, commissionRate Dec) (g Global, withdrawn DecCoins) - vi.UpdateTotalDelAccum(height, totalDelShares) - g = vi.TakeAccum(g, height, totalBonded, vdTokens) + g = vi.TakeAccum(g, height, totalBonded, vdTokens, commissionRate) - blocks = height - vi.CommissionWithdrawalHeight - vi.CommissionWithdrawalHeight = height - accum = delegatorShares * blocks * (commissionRate) - - withdrawalTokens := vi.Pool * accum / vi.TotalDelAccum - vi.TotalDelAccum -= accum - - vi.Pool -= withdrawalTokens - vi.TotalDelAccum -= accum + withdrawalTokens := vi.PoolCommission + vi.PoolCommission = 0 return g, withdrawalTokens ``` From cce4cbc9ec9bac54dc4d8b214b7efee585034ffc Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 23 Aug 2018 04:02:26 -0400 Subject: [PATCH 16/93] expand on shortcomings of the system --- docs/spec/distribution/overview.md | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/docs/spec/distribution/overview.md b/docs/spec/distribution/overview.md index 7b912f2823..e4308a21d8 100644 --- a/docs/spec/distribution/overview.md +++ b/docs/spec/distribution/overview.md @@ -36,20 +36,32 @@ Fees are pooled within a global pool, as well as validator specific proposer-reward pools. The mechanisms used allow for validators and delegators to independently and lazily withdraw their rewards. -As a part of the lazy computations, each validator and delegator holds an -accumulation term which is used to estimate what their approximate fair portion -of tokens held in the global pool is owed to them. This approximation of owed -rewards would be equivalent to the active distribution under the situation that -there was a constant flow of incoming reward tokens every block. Because this -is not the case, the approximation of owed rewards will deviate from the active -distribution based on fluctuations of incoming reward tokens as well as timing -of reward withdrawal by other delegators and validators from the reward pool. +## Shortcomings + +As a part of the lazy computations, each delegator holds an accumulation term +specific to each validator which is used to estimate what their approximate +fair portion of tokens held in the global pool is owed to them. + +``` +entitlement = delegator-accumulation / all-delegators-accumulation +``` + +Under the circumstance that there were constant and equal flow of incoming +reward tokens every block, this distribution mechanism would be equal to the +active distribution (distribute individually to all delegators each block). +However this is unrealistic so deviations from the active distribution will +occur based on fluctuations of incoming reward tokens as well as timing of +reward withdrawal by other delegators. + +If you happen to know that incoming rewards are about significantly move up, +you are incentivized to not withdraw until after this event, increasing the +worth of your existing _accum_. ## Affect on Staking Charging commission on Atom provisions while also allowing for Atom-provisions to be auto-bonded (distributed directly to the validators bonded stake) is -problematic within DPoS. Fundamentally these two mechnisms are mutually +problematic within DPoS. Fundamentally these two mechanisms are mutually exclusive. If there are Atom commissions and auto-bonding Atoms, the portion of Atoms the reward distribution calculation would become very large as the Atom portion for each delegator would change each block making a withdrawal of rewards From 222597165e5ae84936da4d3393a7a39d7845173d Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 28 Aug 2018 18:23:57 -0400 Subject: [PATCH 17/93] trigger -> hooks --- docs/spec/distribution/{triggers.md => hooks.md} | 2 +- docs/spec/distribution/overview.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename docs/spec/distribution/{triggers.md => hooks.md} (98%) diff --git a/docs/spec/distribution/triggers.md b/docs/spec/distribution/hooks.md similarity index 98% rename from docs/spec/distribution/triggers.md rename to docs/spec/distribution/hooks.md index e3971ea99d..e1a18ef593 100644 --- a/docs/spec/distribution/triggers.md +++ b/docs/spec/distribution/hooks.md @@ -1,4 +1,4 @@ -# Triggers +# Hooks ## Create or modify delegation distribution diff --git a/docs/spec/distribution/overview.md b/docs/spec/distribution/overview.md index e4308a21d8..13a4ea3f14 100644 --- a/docs/spec/distribution/overview.md +++ b/docs/spec/distribution/overview.md @@ -23,7 +23,7 @@ distribution occurs, withdrawal of rewards must also occur. - Whenever a validator chooses to change the commission on rewards, all accumulated commission rewards must be simultaneously withdrawn. -The above scenarios are covered in `triggers.md`. +The above scenarios are covered in `hooks.md`. The distribution mechanism outlines herein is used to lazily distribute the following rewards between validators and associated delegators: From 46bbada4eea507426a9909491279ceb5564522a5 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Wed, 29 Aug 2018 23:02:15 -0700 Subject: [PATCH 18/93] simulation: Add benchmarking --- PENDING.md | 1 + cmd/gaia/app/sim_test.go | 21 +++ x/bank/simulation/msgs.go | 18 +-- x/gov/simulation/msgs.go | 50 +++--- x/mock/simulation/random_simulate_blocks.go | 166 +++++++++++++++----- x/mock/simulation/types.go | 2 +- x/slashing/simulation/msgs.go | 8 +- x/stake/simulation/msgs.go | 44 ++++-- 8 files changed, 220 insertions(+), 90 deletions(-) diff --git a/PENDING.md b/PENDING.md index f45541ccdc..2e862ead6a 100644 --- a/PENDING.md +++ b/PENDING.md @@ -45,6 +45,7 @@ FEATURES * SDK * [querier] added custom querier functionality, so ABCI query requests can be handled by keepers * [simulation] \#1924 allow operations to specify future operations + * [simulation] Add benchmarking capabilities * Tendermint diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 0ca936bdbf..2bad6aba23 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -112,6 +112,27 @@ func invariants(app *GaiaApp) []simulation.Invariant { } } +// Profile with: +// /usr/local/go/bin/go test -benchmem -run=^$ github.com/cosmos/cosmos-sdk/cmd/gaia/app -bench ^BenchmarkFullGaiaSimulation$ -cpuprofile cpu.out +func BenchmarkFullGaiaSimulation(b *testing.B) { + // Setup Gaia application + var logger log.Logger + logger = log.NewNopLogger() + db := dbm.NewMemDB() + app := NewGaiaApp(logger, db, nil) + + // Run randomized simulation + // TODO parameterize numbers, save for a later PR + simulation.BenchmarkSimulationFromSeed( + b, app.BaseApp, appStateFn, seed, + testAndRunTxs(app), + []simulation.RandSetup{}, + 10, + 100, + false, + ) +} + func TestFullGaiaSimulation(t *testing.T) { if !enabled { t.Skip("Skipping Gaia simulation") diff --git a/x/bank/simulation/msgs.go b/x/bank/simulation/msgs.go index e3f3ab77b8..c53916a613 100644 --- a/x/bank/simulation/msgs.go +++ b/x/bank/simulation/msgs.go @@ -21,7 +21,7 @@ import ( // SimulateSingleInputMsgSend tests and runs a single msg send, with one input and one output, where both // accounts already exist. func SimulateSingleInputMsgSend(mapper auth.AccountMapper) simulation.Operation { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOps []simulation.FutureOperation, err sdk.Error) { + return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOps []simulation.FutureOperation, err sdk.Error) { fromKey := simulation.RandomKey(r, keys) fromAddr := sdk.AccAddress(fromKey.PubKey().Address()) toKey := simulation.RandomKey(r, keys) @@ -58,7 +58,7 @@ func SimulateSingleInputMsgSend(mapper auth.AccountMapper) simulation.Operation Inputs: []bank.Input{bank.NewInput(fromAddr, coins)}, Outputs: []bank.Output{bank.NewOutput(toAddr, coins)}, } - sendAndVerifyMsgSend(t, app, mapper, msg, ctx, log, []crypto.PrivKey{fromKey}) + sendAndVerifyMsgSend(tb, app, mapper, msg, ctx, log, []crypto.PrivKey{fromKey}) event("bank/sendAndVerifyMsgSend/ok") return action, nil, nil @@ -66,7 +66,7 @@ func SimulateSingleInputMsgSend(mapper auth.AccountMapper) simulation.Operation } // Sends and verifies the transition of a msg send. This fails if there are repeated inputs or outputs -func sendAndVerifyMsgSend(t *testing.T, app *baseapp.BaseApp, mapper auth.AccountMapper, msg bank.MsgSend, ctx sdk.Context, log string, privkeys []crypto.PrivKey) { +func sendAndVerifyMsgSend(tb testing.TB, app *baseapp.BaseApp, mapper auth.AccountMapper, msg bank.MsgSend, ctx sdk.Context, log string, privkeys []crypto.PrivKey) { initialInputAddrCoins := make([]sdk.Coins, len(msg.Inputs)) initialOutputAddrCoins := make([]sdk.Coins, len(msg.Outputs)) AccountNumbers := make([]int64, len(msg.Inputs)) @@ -91,12 +91,12 @@ func sendAndVerifyMsgSend(t *testing.T, app *baseapp.BaseApp, mapper auth.Accoun // TODO: Do this in a more 'canonical' way fmt.Println(res) fmt.Println(log) - t.FailNow() + tb.FailNow() } for i := 0; i < len(msg.Inputs); i++ { terminalInputCoins := mapper.GetAccount(ctx, msg.Inputs[i].Address).GetCoins() - require.Equal(t, + require.Equal(tb, initialInputAddrCoins[i].Minus(msg.Inputs[i].Coins), terminalInputCoins, fmt.Sprintf("Input #%d had an incorrect amount of coins\n%s", i, log), @@ -104,11 +104,9 @@ func sendAndVerifyMsgSend(t *testing.T, app *baseapp.BaseApp, mapper auth.Accoun } for i := 0; i < len(msg.Outputs); i++ { terminalOutputCoins := mapper.GetAccount(ctx, msg.Outputs[i].Address).GetCoins() - require.Equal(t, - initialOutputAddrCoins[i].Plus(msg.Outputs[i].Coins), - terminalOutputCoins, - fmt.Sprintf("Output #%d had an incorrect amount of coins\n%s", i, log), - ) + if !terminalOutputCoins.IsEqual(initialOutputAddrCoins[i].Plus(msg.Outputs[i].Coins)) { + tb.Fatalf("Output #%d had an incorrect amount of coins\n%s", i, log) + } } } diff --git a/x/gov/simulation/msgs.go b/x/gov/simulation/msgs.go index 0b1530138f..eca8accae0 100644 --- a/x/gov/simulation/msgs.go +++ b/x/gov/simulation/msgs.go @@ -5,8 +5,6 @@ import ( "math/rand" "testing" - "github.com/stretchr/testify/require" - "github.com/tendermint/tendermint/crypto" "github.com/cosmos/cosmos-sdk/baseapp" @@ -23,24 +21,15 @@ const ( // SimulateMsgSubmitProposal simulates a msg Submit Proposal // Note: Currently doesn't ensure that the proposal txt is in JSON form func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.Operation { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOps []simulation.FutureOperation, err sdk.Error) { - key := simulation.RandomKey(r, keys) - addr := sdk.AccAddress(key.PubKey().Address()) - deposit := randomDeposit(r) - msg := gov.NewMsgSubmitProposal( - simulation.RandStringOfLength(r, 5), - simulation.RandStringOfLength(r, 5), - gov.ProposalTypeText, - addr, - deposit, - ) - require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + handler := gov.NewHandler(k) + return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOps []simulation.FutureOperation, err sdk.Error) { + msg := simulationCreateMsgSubmitProposal(tb, r, keys, log) ctx, write := ctx.CacheContext() - result := gov.NewHandler(k)(ctx, msg) + result := handler(ctx, msg) if result.IsOK() { // Update pool to keep invariants pool := sk.GetPool(ctx) - pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewDecFromInt(deposit.AmountOf(denom))) + pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewDecFromInt(msg.InitialDeposit.AmountOf(denom))) sk.SetPool(ctx, pool) write() } @@ -50,9 +39,26 @@ func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.Operati } } +func simulationCreateMsgSubmitProposal(tb testing.TB, r *rand.Rand, keys []crypto.PrivKey, log string) gov.MsgSubmitProposal { + key := simulation.RandomKey(r, keys) + addr := sdk.AccAddress(key.PubKey().Address()) + deposit := randomDeposit(r) + msg := gov.NewMsgSubmitProposal( + simulation.RandStringOfLength(r, 5), + simulation.RandStringOfLength(r, 5), + gov.ProposalTypeText, + addr, + deposit, + ) + if msg.ValidateBasic() != nil { + tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) + } + return msg +} + // SimulateMsgDeposit func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { + return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { key := simulation.RandomKey(r, keys) addr := sdk.AccAddress(key.PubKey().Address()) proposalID, ok := randomProposalID(r, k, ctx) @@ -61,7 +67,9 @@ func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation { } deposit := randomDeposit(r) msg := gov.NewMsgDeposit(addr, proposalID, deposit) - require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + if msg.ValidateBasic() != nil { + tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) + } ctx, write := ctx.CacheContext() result := gov.NewHandler(k)(ctx, msg) if result.IsOK() { @@ -79,7 +87,7 @@ func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation { // SimulateMsgVote func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.Operation { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { + return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { key := simulation.RandomKey(r, keys) addr := sdk.AccAddress(key.PubKey().Address()) proposalID, ok := randomProposalID(r, k, ctx) @@ -88,7 +96,9 @@ func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.Operation { } option := randomVotingOption(r) msg := gov.NewMsgVote(addr, proposalID, option) - require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + if msg.ValidateBasic() != nil { + tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) + } ctx, write := ctx.CacheContext() result := gov.NewHandler(k)(ctx, msg) if result.IsOK() { diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index 995013ef8f..aa4df613dd 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -5,6 +5,7 @@ import ( "fmt" "math" "math/rand" + "os" "sort" "testing" "time" @@ -28,6 +29,26 @@ func Simulate( SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numBlocks, blockSize, commit) } +func initChain(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress, setups []RandSetup, app *baseapp.BaseApp, + appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage) (validators map[string]mockValidator) { + res := app.InitChain(abci.RequestInitChain{AppStateBytes: appStateFn(r, keys, accs)}) + validators = make(map[string]mockValidator) + for _, validator := range res.Validators { + validators[string(validator.Address)] = mockValidator{validator, GetMemberOfInitialState(r, initialLivenessWeightings)} + } + + for i := 0; i < len(setups); i++ { + setups[i](r, keys) + } + + return +} + +func randTimestamp(r *rand.Rand) time.Time { + unixTime := r.Int63n(int64(math.Pow(2, 40))) + return time.Unix(unixTime, 0) +} + // SimulateFromSeed tests an application by running the provided // operations, testing the provided invariants, but using the provided seed. func SimulateFromSeed( @@ -36,11 +57,7 @@ func SimulateFromSeed( ) { log := fmt.Sprintf("Starting SimulateFromSeed with randomness created with seed %d", int(seed)) r := rand.New(rand.NewSource(seed)) - - unixTime := r.Int63n(int64(math.Pow(2, 40))) - - // Set the timestamp for simulation - timestamp := time.Unix(unixTime, 0) + timestamp := randTimestamp(r) log = fmt.Sprintf("%s\nStarting the simulation from time %v, unixtime %v", log, timestamp.UTC().Format(time.UnixDate), timestamp.Unix()) fmt.Printf("%s\n", log) timeDiff := maxTimePerBlock - minTimePerBlock @@ -54,30 +71,18 @@ func SimulateFromSeed( events[what]++ } - res := app.InitChain(abci.RequestInitChain{AppStateBytes: appStateFn(r, keys, accs)}) - validators := make(map[string]mockValidator) - for _, validator := range res.Validators { - validators[string(validator.Address)] = mockValidator{validator, GetMemberOfInitialState(r, initialLivenessWeightings)} - } - - for i := 0; i < len(setups); i++ { - setups[i](r, keys) - } + validators := initChain(r, keys, accs, setups, app, appStateFn) header := abci.Header{Height: 0, Time: timestamp} opCount := 0 request := abci.RequestBeginBlock{Header: header} - var pastTimes []time.Time + var lastHeaderTime time.Time // These are operations which have been queued by previous operations operationQueue := make(map[int][]Operation) for i := 0; i < numBlocks; i++ { - - // Log the header time for future lookup - pastTimes = append(pastTimes, header.Time) - // Run the BeginBlock handler app.BeginBlock(request) @@ -88,16 +93,8 @@ func SimulateFromSeed( ctx := app.NewContext(false, header) - var thisBlockSize int - load := r.Float64() - switch { - case load < 0.33: - thisBlockSize = 0 - case load < 0.66: - thisBlockSize = r.Intn(blockSize * 2) - default: - thisBlockSize = r.Intn(blockSize * 4) - } + thisBlockSize := getBlockSize(r, blockSize) + // Run queued operations. Ignores blocksize if blocksize is too small log, numQueuedOpsRan := runQueuedOperations(operationQueue, int(header.Height), t, r, app, ctx, keys, log, event) opCount += numQueuedOpsRan @@ -119,6 +116,7 @@ func SimulateFromSeed( res := app.EndBlock(abci.RequestEndBlock{}) header.Height++ + lastHeaderTime = header.Time header.Time = header.Time.Add(time.Duration(minTimePerBlock) * time.Second).Add(time.Duration(int64(r.Intn(int(timeDiff)))) * time.Second) log += "\nEndBlock" @@ -131,7 +129,7 @@ func SimulateFromSeed( } // Generate a random RequestBeginBlock with the current validator set for the next block - request = RandomRequestBeginBlock(t, r, validators, livenessTransitionMatrix, evidenceFraction, pastTimes, event, header, log) + request = RandomRequestBeginBlock(r, validators, livenessTransitionMatrix, evidenceFraction, lastHeaderTime, event, header, log) // Update the validator set validators = updateValidators(t, r, validators, res.ValidatorUpdates, event) @@ -141,6 +139,84 @@ func SimulateFromSeed( DisplayEvents(events) } +func getBlockSize(r *rand.Rand, blockSize int) int { + load := r.Float64() + switch { + case load < 0.33: + return 0 + case load < 0.66: + return r.Intn(blockSize * 2) + default: + return r.Intn(blockSize * 4) + } +} + +// Simulate from seed, benchmarks +func BenchmarkSimulationFromSeed(b *testing.B, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, + seed int64, ops []Operation, setups []RandSetup, numBlocks int, blockSize int, commit bool) { + r := rand.New(rand.NewSource(seed)) + timestamp := randTimestamp(r) + timeDiff := maxTimePerBlock - minTimePerBlock + keys, accs := mock.GeneratePrivKeyAddressPairsFromRand(r, numKeys) + + // Setup event stats + events := make(map[string]uint) + event := func(what string) { + events[what]++ + } + + validators := initChain(r, keys, accs, setups, app, appStateFn) + + header := abci.Header{Height: 0, Time: timestamp} + opCount := 0 + + request := abci.RequestBeginBlock{Header: header} + + var lastHeaderTime time.Time + // These are operations which have been queued by previous operations + operationQueue := make(map[int][]Operation) + b.ResetTimer() + + for i := 0; i < numBlocks; i++ { + + // Run the BeginBlock handler + app.BeginBlock(request) + + ctx := app.NewContext(false, header) + + thisBlockSize := getBlockSize(r, blockSize) + + // Run queued operations. Ignores blocksize if blocksize is too small + log, numQueuedOpsRan := runQueuedOperations(operationQueue, int(header.Height), b, r, app, ctx, keys, "", event) + opCount += numQueuedOpsRan + thisBlockSize -= numQueuedOpsRan + for j := 0; j < thisBlockSize; j++ { + _, futureOps, err := ops[r.Intn(len(ops))](b, r, app, ctx, keys, "", event) + queueOperations(operationQueue, futureOps) + if err != nil { + b.Fatalf("error on operation %d, %v", opCount, err) + } + opCount++ + } + + res := app.EndBlock(abci.RequestEndBlock{}) + header.Height++ + lastHeaderTime = header.Time + header.Time = header.Time.Add(time.Duration(minTimePerBlock) * time.Second).Add(time.Duration(int64(r.Intn(int(timeDiff)))) * time.Second) + if commit { + app.Commit() + } + + // Generate a random RequestBeginBlock with the current validator set for the next block + request = RandomRequestBeginBlock(r, validators, livenessTransitionMatrix, evidenceFraction, lastHeaderTime, event, header, log) + + // Update the validator set + validators = updateValidators(b, r, validators, res.ValidatorUpdates, event) + } + DisplayEvents(events) + fmt.Printf("Benchmark simulation ran %d operations\n", opCount) +} + // adds all future operations into the operation queue. func queueOperations(queuedOperations map[int][]Operation, futureOperations []FutureOperation) { if futureOperations == nil { @@ -155,7 +231,7 @@ func queueOperations(queuedOperations map[int][]Operation, futureOperations []Fu } } -func runQueuedOperations(queueOperations map[int][]Operation, height int, t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, +func runQueuedOperations(queueOperations map[int][]Operation, height int, tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, privKeys []crypto.PrivKey, log string, event func(string)) (updatedLog string, numOpsRan int) { updatedLog = log if queuedOps, ok := queueOperations[height]; ok { @@ -164,9 +240,12 @@ func runQueuedOperations(queueOperations map[int][]Operation, height int, t *tes // For now, queued operations cannot queue more operations. // If a need arises for us to support queued messages to queue more messages, this can // be changed. - logUpdate, _, err := queuedOps[i](t, r, app, ctx, privKeys, updatedLog, event) - updatedLog += "\n" + logUpdate - require.Nil(t, err, updatedLog) + logUpdate, _, err := queuedOps[i](tb, r, app, ctx, privKeys, updatedLog, event) + updatedLog = fmt.Sprintf("%s\n%s", updatedLog, logUpdate) + if err != nil { + fmt.Fprint(os.Stderr, updatedLog) + tb.FailNow() + } } delete(queueOperations, height) return updatedLog, numOps @@ -186,8 +265,8 @@ func getKeys(validators map[string]mockValidator) []string { } // RandomRequestBeginBlock generates a list of signing validators according to the provided list of validators, signing fraction, and evidence fraction -func RandomRequestBeginBlock(t *testing.T, r *rand.Rand, validators map[string]mockValidator, livenessTransitions TransitionMatrix, evidenceFraction float64, - pastTimes []time.Time, event func(string), header abci.Header, log string) abci.RequestBeginBlock { +func RandomRequestBeginBlock(r *rand.Rand, validators map[string]mockValidator, livenessTransitions TransitionMatrix, evidenceFraction float64, + lastHeaderTime time.Time, event func(string), header abci.Header, log string) abci.RequestBeginBlock { if len(validators) == 0 { return abci.RequestBeginBlock{Header: header} } @@ -219,13 +298,14 @@ func RandomRequestBeginBlock(t *testing.T, r *rand.Rand, validators map[string]m } i++ } + // TODO: Determine capacity before allocation evidence := make([]abci.Evidence, 0) for r.Float64() < evidenceFraction { height := header.Height time := header.Time if r.Float64() < pastEvidenceFraction { height = int64(r.Intn(int(header.Height))) - time = pastTimes[height] + time = lastHeaderTime } validator := signingValidators[r.Intn(len(signingValidators))].Validator var currentTotalVotingPower int64 @@ -258,11 +338,19 @@ func AssertAllInvariants(t *testing.T, app *baseapp.BaseApp, tests []Invariant, } // updateValidators mimicks Tendermint's update logic -func updateValidators(t *testing.T, r *rand.Rand, current map[string]mockValidator, updates []abci.Validator, event func(string)) map[string]mockValidator { +func updateValidators(tb testing.TB, r *rand.Rand, current map[string]mockValidator, updates []abci.Validator, event func(string)) map[string]mockValidator { for _, update := range updates { switch { case update.Power == 0: - require.NotNil(t, current[string(update.PubKey.Data)], "tried to delete a nonexistent validator") + // // TEMPORARY DEBUG CODE TO PROVE THAT THE OLD METHOD WAS BROKEN + // // (i.e. didn't catch in the event of problem) + // if val, ok := tb.(*testing.T); ok { + // require.NotNil(val, current[string(update.PubKey.Data)]) + // } + // // CORRECT CHECK + // if _, ok := current[string(update.PubKey.Data)]; !ok { + // tb.Fatalf("tried to delete a nonexistent validator") + // } event("endblock/validatorupdates/kicked") delete(current, string(update.PubKey.Data)) default: diff --git a/x/mock/simulation/types.go b/x/mock/simulation/types.go index 2516e07ae5..2f91a4f263 100644 --- a/x/mock/simulation/types.go +++ b/x/mock/simulation/types.go @@ -23,7 +23,7 @@ type ( // Operations can optionally provide a list of "FutureOperations" to run later // These will be ran at the beginning of the corresponding block. Operation func( - t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, privKeys []crypto.PrivKey, log string, event func(string), ) (action string, futureOperations []FutureOperation, err sdk.Error) diff --git a/x/slashing/simulation/msgs.go b/x/slashing/simulation/msgs.go index e4900889e3..7b5490e423 100644 --- a/x/slashing/simulation/msgs.go +++ b/x/slashing/simulation/msgs.go @@ -5,8 +5,6 @@ import ( "math/rand" "testing" - "github.com/stretchr/testify/require" - "github.com/tendermint/tendermint/crypto" "github.com/cosmos/cosmos-sdk/baseapp" @@ -17,11 +15,13 @@ import ( // SimulateMsgUnjail func SimulateMsgUnjail(k slashing.Keeper) simulation.Operation { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { + return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { key := simulation.RandomKey(r, keys) address := sdk.AccAddress(key.PubKey().Address()) msg := slashing.NewMsgUnjail(address) - require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + if msg.ValidateBasic() != nil { + tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) + } ctx, write := ctx.CacheContext() result := slashing.NewHandler(k)(ctx, msg) if result.IsOK() { diff --git a/x/stake/simulation/msgs.go b/x/stake/simulation/msgs.go index 4280e70c13..bc1063494d 100644 --- a/x/stake/simulation/msgs.go +++ b/x/stake/simulation/msgs.go @@ -5,8 +5,6 @@ import ( "math/rand" "testing" - "github.com/stretchr/testify/require" - "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" @@ -19,7 +17,7 @@ import ( // SimulateMsgCreateValidator func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation.Operation { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { + return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { denom := k.GetParams(ctx).BondDenom description := stake.Description{ Moniker: simulation.RandStringOfLength(r, 10), @@ -41,7 +39,9 @@ func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation PubKey: pubkey, Delegation: sdk.NewCoin(denom, amount), } - require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + if msg.ValidateBasic() != nil { + tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) + } ctx, write := ctx.CacheContext() result := stake.NewHandler(k)(ctx, msg) if result.IsOK() { @@ -56,7 +56,7 @@ func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation // SimulateMsgEditValidator func SimulateMsgEditValidator(k stake.Keeper) simulation.Operation { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { + return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { description := stake.Description{ Moniker: simulation.RandStringOfLength(r, 10), Identity: simulation.RandStringOfLength(r, 10), @@ -70,7 +70,9 @@ func SimulateMsgEditValidator(k stake.Keeper) simulation.Operation { Description: description, ValidatorAddr: address, } - require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + if msg.ValidateBasic() != nil { + tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) + } ctx, write := ctx.CacheContext() result := stake.NewHandler(k)(ctx, msg) if result.IsOK() { @@ -84,7 +86,7 @@ func SimulateMsgEditValidator(k stake.Keeper) simulation.Operation { // SimulateMsgDelegate func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operation { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { + return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { denom := k.GetParams(ctx).BondDenom validatorKey := simulation.RandomKey(r, keys) validatorAddress := sdk.AccAddress(validatorKey.PubKey().Address()) @@ -102,7 +104,9 @@ func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operat ValidatorAddr: validatorAddress, Delegation: sdk.NewCoin(denom, amount), } - require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + if msg.ValidateBasic() != nil { + tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) + } ctx, write := ctx.CacheContext() result := stake.NewHandler(k)(ctx, msg) if result.IsOK() { @@ -116,7 +120,7 @@ func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operat // SimulateMsgBeginUnbonding func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation.Operation { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { + return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { denom := k.GetParams(ctx).BondDenom validatorKey := simulation.RandomKey(r, keys) validatorAddress := sdk.AccAddress(validatorKey.PubKey().Address()) @@ -134,7 +138,9 @@ func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation. ValidatorAddr: validatorAddress, SharesAmount: sdk.NewDecFromInt(amount), } - require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + if msg.ValidateBasic() != nil { + tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) + } ctx, write := ctx.CacheContext() result := stake.NewHandler(k)(ctx, msg) if result.IsOK() { @@ -148,7 +154,7 @@ func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation. // SimulateMsgCompleteUnbonding func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.Operation { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { + return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { validatorKey := simulation.RandomKey(r, keys) validatorAddress := sdk.AccAddress(validatorKey.PubKey().Address()) delegatorKey := simulation.RandomKey(r, keys) @@ -157,7 +163,9 @@ func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.Operation { DelegatorAddr: delegatorAddress, ValidatorAddr: validatorAddress, } - require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + if msg.ValidateBasic() != nil { + tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) + } ctx, write := ctx.CacheContext() result := stake.NewHandler(k)(ctx, msg) if result.IsOK() { @@ -171,7 +179,7 @@ func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.Operation { // SimulateMsgBeginRedelegate func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operation { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { + return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { denom := k.GetParams(ctx).BondDenom sourceValidatorKey := simulation.RandomKey(r, keys) sourceValidatorAddress := sdk.AccAddress(sourceValidatorKey.PubKey().Address()) @@ -193,7 +201,9 @@ func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation ValidatorDstAddr: destValidatorAddress, SharesAmount: sdk.NewDecFromInt(amount), } - require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + if msg.ValidateBasic() != nil { + tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) + } ctx, write := ctx.CacheContext() result := stake.NewHandler(k)(ctx, msg) if result.IsOK() { @@ -207,7 +217,7 @@ func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation // SimulateMsgCompleteRedelegate func SimulateMsgCompleteRedelegate(k stake.Keeper) simulation.Operation { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { + return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { validatorSrcKey := simulation.RandomKey(r, keys) validatorSrcAddress := sdk.AccAddress(validatorSrcKey.PubKey().Address()) validatorDstKey := simulation.RandomKey(r, keys) @@ -219,7 +229,9 @@ func SimulateMsgCompleteRedelegate(k stake.Keeper) simulation.Operation { ValidatorSrcAddr: validatorSrcAddress, ValidatorDstAddr: validatorDstAddress, } - require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + if msg.ValidateBasic() != nil { + tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) + } ctx, write := ctx.CacheContext() result := stake.NewHandler(k)(ctx, msg) if result.IsOK() { From 31ca2e058b9d666ac3ea60ad5b399f3f9da28da2 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Wed, 29 Aug 2018 23:11:14 -0700 Subject: [PATCH 19/93] Update PENDING --- PENDING.md | 2 +- x/mock/simulation/random_simulate_blocks.go | 10 ++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/PENDING.md b/PENDING.md index 2e862ead6a..53c7a6b343 100644 --- a/PENDING.md +++ b/PENDING.md @@ -45,7 +45,7 @@ FEATURES * SDK * [querier] added custom querier functionality, so ABCI query requests can be handled by keepers * [simulation] \#1924 allow operations to specify future operations - * [simulation] Add benchmarking capabilities + * [simulation] \#1924 Add benchmarking capabilities * Tendermint diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index aa4df613dd..ea0078853e 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -85,14 +85,12 @@ func SimulateFromSeed( for i := 0; i < numBlocks; i++ { // Run the BeginBlock handler app.BeginBlock(request) - log += "\nBeginBlock" // Make sure invariants hold at beginning of block AssertAllInvariants(t, app, invariants, log) ctx := app.NewContext(false, header) - thisBlockSize := getBlockSize(r, blockSize) // Run queued operations. Ignores blocksize if blocksize is too small @@ -102,9 +100,10 @@ func SimulateFromSeed( for j := 0; j < thisBlockSize; j++ { logUpdate, futureOps, err := ops[r.Intn(len(ops))](t, r, app, ctx, keys, log, event) log += "\n" + logUpdate + require.Nil(t, err, log) + queueOperations(operationQueue, futureOps) - require.Nil(t, err, log) if onOperation { AssertAllInvariants(t, app, invariants, log) } @@ -118,12 +117,10 @@ func SimulateFromSeed( header.Height++ lastHeaderTime = header.Time header.Time = header.Time.Add(time.Duration(minTimePerBlock) * time.Second).Add(time.Duration(int64(r.Intn(int(timeDiff)))) * time.Second) - log += "\nEndBlock" // Make sure invariants hold at end of block AssertAllInvariants(t, app, invariants, log) - if commit { app.Commit() } @@ -178,12 +175,9 @@ func BenchmarkSimulationFromSeed(b *testing.B, app *baseapp.BaseApp, appStateFn b.ResetTimer() for i := 0; i < numBlocks; i++ { - // Run the BeginBlock handler app.BeginBlock(request) - ctx := app.NewContext(false, header) - thisBlockSize := getBlockSize(r, blockSize) // Run queued operations. Ignores blocksize if blocksize is too small From 03d2f7331b418d68f0b3e4f5448754e4c27771f5 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Thu, 30 Aug 2018 00:13:31 -0700 Subject: [PATCH 20/93] Remove code duplication --- cmd/gaia/app/sim_test.go | 3 +- x/mock/simulation/random_simulate_blocks.go | 125 +++++++------------- x/stake/simulation/msgs.go | 21 ++-- 3 files changed, 61 insertions(+), 88 deletions(-) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 2bad6aba23..1fd07b3302 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -123,10 +123,11 @@ func BenchmarkFullGaiaSimulation(b *testing.B) { // Run randomized simulation // TODO parameterize numbers, save for a later PR - simulation.BenchmarkSimulationFromSeed( + simulation.SimulateFromSeed( b, app.BaseApp, appStateFn, seed, testAndRunTxs(app), []simulation.RandSetup{}, + invariants(app), // these shouldn't get ran 10, 100, false, diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index ea0078853e..6376d53dcb 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -17,7 +17,6 @@ import ( "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/mock" - "github.com/stretchr/testify/require" ) // Simulate tests application by sending random messages. @@ -52,13 +51,22 @@ func randTimestamp(r *rand.Rand) time.Time { // SimulateFromSeed tests an application by running the provided // operations, testing the provided invariants, but using the provided seed. func SimulateFromSeed( - t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, seed int64, ops []Operation, setups []RandSetup, + tb testing.TB, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, seed int64, ops []Operation, setups []RandSetup, invariants []Invariant, numBlocks int, blockSize int, commit bool, ) { + var t *testing.T + var b *testing.B + testingmode := false + if _t, ok := tb.(*testing.T); ok { + t = _t + testingmode = true + } else { + b = tb.(*testing.B) + } log := fmt.Sprintf("Starting SimulateFromSeed with randomness created with seed %d", int(seed)) r := rand.New(rand.NewSource(seed)) timestamp := randTimestamp(r) - log = fmt.Sprintf("%s\nStarting the simulation from time %v, unixtime %v", log, timestamp.UTC().Format(time.UnixDate), timestamp.Unix()) + log = updateLog(testingmode, log, "Starting the simulation from time %v, unixtime %v", timestamp.UTC().Format(time.UnixDate), timestamp.Unix()) fmt.Printf("%s\n", log) timeDiff := maxTimePerBlock - minTimePerBlock @@ -67,7 +75,7 @@ func SimulateFromSeed( // Setup event stats events := make(map[string]uint) event := func(what string) { - log += "\nevent - " + what + log = updateLog(testingmode, log, "event - "+what) events[what]++ } @@ -82,32 +90,40 @@ func SimulateFromSeed( // These are operations which have been queued by previous operations operationQueue := make(map[int][]Operation) + if !testingmode { + b.ResetTimer() + } + for i := 0; i < numBlocks; i++ { // Run the BeginBlock handler app.BeginBlock(request) - log += "\nBeginBlock" + log = updateLog(testingmode, log, "BeginBlock") - // Make sure invariants hold at beginning of block - AssertAllInvariants(t, app, invariants, log) + if testingmode { + // Make sure invariants hold at beginning of block + AssertAllInvariants(t, app, invariants, log) + } ctx := app.NewContext(false, header) thisBlockSize := getBlockSize(r, blockSize) // Run queued operations. Ignores blocksize if blocksize is too small - log, numQueuedOpsRan := runQueuedOperations(operationQueue, int(header.Height), t, r, app, ctx, keys, log, event) + log, numQueuedOpsRan := runQueuedOperations(operationQueue, int(header.Height), tb, r, app, ctx, keys, log, event) opCount += numQueuedOpsRan thisBlockSize -= numQueuedOpsRan for j := 0; j < thisBlockSize; j++ { - logUpdate, futureOps, err := ops[r.Intn(len(ops))](t, r, app, ctx, keys, log, event) - log += "\n" + logUpdate - require.Nil(t, err, log) + logUpdate, futureOps, err := ops[r.Intn(len(ops))](tb, r, app, ctx, keys, log, event) + log = updateLog(testingmode, log, logUpdate) + if err != nil { + tb.Fatalf("error on operation %d, %v", opCount, err) + } queueOperations(operationQueue, futureOps) - if onOperation { + if onOperation && testingmode { AssertAllInvariants(t, app, invariants, log) } - if opCount%200 == 0 { + if testingmode && opCount%200 == 0 { fmt.Printf("\rSimulating... block %d/%d, operation %d.", header.Height, numBlocks, opCount) } opCount++ @@ -119,8 +135,10 @@ func SimulateFromSeed( header.Time = header.Time.Add(time.Duration(minTimePerBlock) * time.Second).Add(time.Duration(int64(r.Intn(int(timeDiff)))) * time.Second) log += "\nEndBlock" - // Make sure invariants hold at end of block - AssertAllInvariants(t, app, invariants, log) + if testingmode { + // Make sure invariants hold at end of block + AssertAllInvariants(t, app, invariants, log) + } if commit { app.Commit() } @@ -129,13 +147,23 @@ func SimulateFromSeed( request = RandomRequestBeginBlock(r, validators, livenessTransitionMatrix, evidenceFraction, lastHeaderTime, event, header, log) // Update the validator set - validators = updateValidators(t, r, validators, res.ValidatorUpdates, event) + validators = updateValidators(tb, r, validators, res.ValidatorUpdates, event) } - fmt.Printf("\nSimulation complete. Final height (blocks): %d, final time (seconds): %v\n", header.Height, header.Time) + if testingmode { + fmt.Printf("\nSimulation complete. Final height (blocks): %d, final time (seconds): %v\n", header.Height, header.Time) + } DisplayEvents(events) } +func updateLog(testingmode bool, log string, update string, args ...interface{}) (updatedLog string) { + if testingmode == true { + update = fmt.Sprintf(update, args) + return fmt.Sprintf("%s\n%s", log, update) + } + return "" +} + func getBlockSize(r *rand.Rand, blockSize int) int { load := r.Float64() switch { @@ -148,69 +176,6 @@ func getBlockSize(r *rand.Rand, blockSize int) int { } } -// Simulate from seed, benchmarks -func BenchmarkSimulationFromSeed(b *testing.B, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, - seed int64, ops []Operation, setups []RandSetup, numBlocks int, blockSize int, commit bool) { - r := rand.New(rand.NewSource(seed)) - timestamp := randTimestamp(r) - timeDiff := maxTimePerBlock - minTimePerBlock - keys, accs := mock.GeneratePrivKeyAddressPairsFromRand(r, numKeys) - - // Setup event stats - events := make(map[string]uint) - event := func(what string) { - events[what]++ - } - - validators := initChain(r, keys, accs, setups, app, appStateFn) - - header := abci.Header{Height: 0, Time: timestamp} - opCount := 0 - - request := abci.RequestBeginBlock{Header: header} - - var lastHeaderTime time.Time - // These are operations which have been queued by previous operations - operationQueue := make(map[int][]Operation) - b.ResetTimer() - - for i := 0; i < numBlocks; i++ { - // Run the BeginBlock handler - app.BeginBlock(request) - ctx := app.NewContext(false, header) - thisBlockSize := getBlockSize(r, blockSize) - - // Run queued operations. Ignores blocksize if blocksize is too small - log, numQueuedOpsRan := runQueuedOperations(operationQueue, int(header.Height), b, r, app, ctx, keys, "", event) - opCount += numQueuedOpsRan - thisBlockSize -= numQueuedOpsRan - for j := 0; j < thisBlockSize; j++ { - _, futureOps, err := ops[r.Intn(len(ops))](b, r, app, ctx, keys, "", event) - queueOperations(operationQueue, futureOps) - if err != nil { - b.Fatalf("error on operation %d, %v", opCount, err) - } - opCount++ - } - - res := app.EndBlock(abci.RequestEndBlock{}) - header.Height++ - lastHeaderTime = header.Time - header.Time = header.Time.Add(time.Duration(minTimePerBlock) * time.Second).Add(time.Duration(int64(r.Intn(int(timeDiff)))) * time.Second) - if commit { - app.Commit() - } - - // Generate a random RequestBeginBlock with the current validator set for the next block - request = RandomRequestBeginBlock(r, validators, livenessTransitionMatrix, evidenceFraction, lastHeaderTime, event, header, log) - - // Update the validator set - validators = updateValidators(b, r, validators, res.ValidatorUpdates, event) - } - DisplayEvents(events) - fmt.Printf("Benchmark simulation ran %d operations\n", opCount) -} - // adds all future operations into the operation queue. func queueOperations(queuedOperations map[int][]Operation, futureOperations []FutureOperation) { if futureOperations == nil { diff --git a/x/stake/simulation/msgs.go b/x/stake/simulation/msgs.go index bc1063494d..033487254f 100644 --- a/x/stake/simulation/msgs.go +++ b/x/stake/simulation/msgs.go @@ -17,6 +17,7 @@ import ( // SimulateMsgCreateValidator func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation.Operation { + handler := stake.NewHandler(k) return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { denom := k.GetParams(ctx).BondDenom description := stake.Description{ @@ -43,7 +44,7 @@ func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) } ctx, write := ctx.CacheContext() - result := stake.NewHandler(k)(ctx, msg) + result := handler(ctx, msg) if result.IsOK() { write() } @@ -56,6 +57,7 @@ func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation // SimulateMsgEditValidator func SimulateMsgEditValidator(k stake.Keeper) simulation.Operation { + handler := stake.NewHandler(k) return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { description := stake.Description{ Moniker: simulation.RandStringOfLength(r, 10), @@ -74,7 +76,7 @@ func SimulateMsgEditValidator(k stake.Keeper) simulation.Operation { tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) } ctx, write := ctx.CacheContext() - result := stake.NewHandler(k)(ctx, msg) + result := handler(ctx, msg) if result.IsOK() { write() } @@ -86,6 +88,7 @@ func SimulateMsgEditValidator(k stake.Keeper) simulation.Operation { // SimulateMsgDelegate func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operation { + handler := stake.NewHandler(k) return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { denom := k.GetParams(ctx).BondDenom validatorKey := simulation.RandomKey(r, keys) @@ -108,7 +111,7 @@ func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operat tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) } ctx, write := ctx.CacheContext() - result := stake.NewHandler(k)(ctx, msg) + result := handler(ctx, msg) if result.IsOK() { write() } @@ -120,6 +123,7 @@ func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operat // SimulateMsgBeginUnbonding func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation.Operation { + handler := stake.NewHandler(k) return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { denom := k.GetParams(ctx).BondDenom validatorKey := simulation.RandomKey(r, keys) @@ -142,7 +146,7 @@ func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation. tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) } ctx, write := ctx.CacheContext() - result := stake.NewHandler(k)(ctx, msg) + result := handler(ctx, msg) if result.IsOK() { write() } @@ -154,6 +158,7 @@ func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation. // SimulateMsgCompleteUnbonding func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.Operation { + handler := stake.NewHandler(k) return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { validatorKey := simulation.RandomKey(r, keys) validatorAddress := sdk.AccAddress(validatorKey.PubKey().Address()) @@ -167,7 +172,7 @@ func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.Operation { tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) } ctx, write := ctx.CacheContext() - result := stake.NewHandler(k)(ctx, msg) + result := handler(ctx, msg) if result.IsOK() { write() } @@ -179,6 +184,7 @@ func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.Operation { // SimulateMsgBeginRedelegate func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operation { + handler := stake.NewHandler(k) return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { denom := k.GetParams(ctx).BondDenom sourceValidatorKey := simulation.RandomKey(r, keys) @@ -205,7 +211,7 @@ func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) } ctx, write := ctx.CacheContext() - result := stake.NewHandler(k)(ctx, msg) + result := handler(ctx, msg) if result.IsOK() { write() } @@ -217,6 +223,7 @@ func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation // SimulateMsgCompleteRedelegate func SimulateMsgCompleteRedelegate(k stake.Keeper) simulation.Operation { + handler := stake.NewHandler(k) return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { validatorSrcKey := simulation.RandomKey(r, keys) validatorSrcAddress := sdk.AccAddress(validatorSrcKey.PubKey().Address()) @@ -233,7 +240,7 @@ func SimulateMsgCompleteRedelegate(k stake.Keeper) simulation.Operation { tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) } ctx, write := ctx.CacheContext() - result := stake.NewHandler(k)(ctx, msg) + result := handler(ctx, msg) if result.IsOK() { write() } From b3d08bcb239198709191895ee15c86a09434ed08 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Thu, 30 Aug 2018 00:35:02 -0700 Subject: [PATCH 21/93] minor cleanup --- x/mock/simulation/random_simulate_blocks.go | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index 6376d53dcb..e609d3c5f9 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -75,7 +75,7 @@ func SimulateFromSeed( // Setup event stats events := make(map[string]uint) event := func(what string) { - log = updateLog(testingmode, log, "event - "+what) + log = updateLog(testingmode, log, "event - %s", what) events[what]++ } @@ -119,12 +119,13 @@ func SimulateFromSeed( } queueOperations(operationQueue, futureOps) - - if onOperation && testingmode { - AssertAllInvariants(t, app, invariants, log) - } - if testingmode && opCount%200 == 0 { - fmt.Printf("\rSimulating... block %d/%d, operation %d.", header.Height, numBlocks, opCount) + if testingmode { + if onOperation { + AssertAllInvariants(t, app, invariants, log) + } + if opCount%200 == 0 { + fmt.Printf("\rSimulating... block %d/%d, operation %d.", header.Height, numBlocks, opCount) + } } opCount++ } @@ -133,7 +134,7 @@ func SimulateFromSeed( header.Height++ lastHeaderTime = header.Time header.Time = header.Time.Add(time.Duration(minTimePerBlock) * time.Second).Add(time.Duration(int64(r.Intn(int(timeDiff)))) * time.Second) - log += "\nEndBlock" + log = updateLog(testingmode, log, "EndBlock") if testingmode { // Make sure invariants hold at end of block @@ -152,13 +153,15 @@ func SimulateFromSeed( if testingmode { fmt.Printf("\nSimulation complete. Final height (blocks): %d, final time (seconds): %v\n", header.Height, header.Time) + } else { + fmt.Printf("%d operations ran\n", opCount) } DisplayEvents(events) } func updateLog(testingmode bool, log string, update string, args ...interface{}) (updatedLog string) { if testingmode == true { - update = fmt.Sprintf(update, args) + update = fmt.Sprintf(update, args...) return fmt.Sprintf("%s\n%s", log, update) } return "" From d1a5808a7518f1244a1716877580c4df9c5ceb12 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Thu, 30 Aug 2018 09:32:15 -0700 Subject: [PATCH 22/93] Address Anton's comment --- x/mock/simulation/random_simulate_blocks.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index e609d3c5f9..e0ab9ba586 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -115,7 +115,7 @@ func SimulateFromSeed( logUpdate, futureOps, err := ops[r.Intn(len(ops))](tb, r, app, ctx, keys, log, event) log = updateLog(testingmode, log, logUpdate) if err != nil { - tb.Fatalf("error on operation %d, %v", opCount, err) + tb.Fatalf("error on operation %d, %v, log %s", opCount, err, log) } queueOperations(operationQueue, futureOps) @@ -160,7 +160,7 @@ func SimulateFromSeed( } func updateLog(testingmode bool, log string, update string, args ...interface{}) (updatedLog string) { - if testingmode == true { + if testingmode { update = fmt.Sprintf(update, args...) return fmt.Sprintf("%s\n%s", log, update) } From 4be69077fe262524527a1e265d4c1032877946ff Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Thu, 30 Aug 2018 11:43:56 -0700 Subject: [PATCH 23/93] Fix cyclomatic complexity, add ability to use GoLevelDB --- cmd/gaia/app/sim_test.go | 19 ++++-- server/export_test.go | 16 ++--- server/mock/app.go | 2 +- x/mock/simulation/random_simulate_blocks.go | 76 ++++++++++++--------- 4 files changed, 66 insertions(+), 47 deletions(-) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 1fd07b3302..6568f124b0 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -4,6 +4,7 @@ import ( "encoding/json" "flag" "math/rand" + "os" "testing" "github.com/stretchr/testify/require" @@ -23,11 +24,12 @@ import ( ) var ( - seed int64 - numBlocks int - blockSize int - enabled bool - verbose bool + seed int64 + numBlocks int + blockSize int + enabled bool + verbose bool + usegoleveldb bool ) func init() { @@ -36,6 +38,7 @@ func init() { flag.IntVar(&blockSize, "SimulationBlockSize", 200, "Operations per block") flag.BoolVar(&enabled, "SimulationEnabled", false, "Enable the simulation") flag.BoolVar(&verbose, "SimulationVerbose", false, "Verbose log output") + flag.BoolVar(&usegoleveldb, "SimulationGoLevelDB", false, "Use GoLevelDB instead of memdb") } func appStateFn(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage { @@ -118,7 +121,11 @@ func BenchmarkFullGaiaSimulation(b *testing.B) { // Setup Gaia application var logger log.Logger logger = log.NewNopLogger() - db := dbm.NewMemDB() + var db dbm.DB + db = dbm.NewMemDB() + if usegoleveldb { + db, _ = dbm.NewGoLevelDB("Simulation", os.TempDir()) + } app := NewGaiaApp(logger, db, nil) // Run randomized simulation diff --git a/server/export_test.go b/server/export_test.go index 358f72cf60..488c55bbf6 100644 --- a/server/export_test.go +++ b/server/export_test.go @@ -1,16 +1,16 @@ package server import ( - "testing" - "github.com/stretchr/testify/require" - "github.com/cosmos/cosmos-sdk/wire" - "github.com/tendermint/tendermint/libs/log" - tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" - "os" "bytes" + "github.com/cosmos/cosmos-sdk/server/mock" + "github.com/cosmos/cosmos-sdk/wire" + "github.com/stretchr/testify/require" + tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" + "github.com/tendermint/tendermint/libs/log" "io" - "github.com/cosmos/cosmos-sdk/server/mock" - ) + "os" + "testing" +) func TestEmptyState(t *testing.T) { defer setupViper(t)() diff --git a/server/mock/app.go b/server/mock/app.go index eb2dfc3cc3..3c6ad3ec27 100644 --- a/server/mock/app.go +++ b/server/mock/app.go @@ -129,7 +129,7 @@ func AppGenStateEmpty(_ *wire.Codec, _ []json.RawMessage) (appState json.RawMess // Return a validator, not much else func AppGenTx(_ *wire.Codec, pk crypto.PubKey, genTxConfig gc.GenTx) ( - appGenTx, cliPrint json.RawMessage, validator tmtypes.GenesisValidator, err error) { + appGenTx, cliPrint json.RawMessage, validator tmtypes.GenesisValidator, err error) { validator = tmtypes.GenesisValidator{ PubKey: pk, diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index e0ab9ba586..42a616331d 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -54,15 +54,7 @@ func SimulateFromSeed( tb testing.TB, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, seed int64, ops []Operation, setups []RandSetup, invariants []Invariant, numBlocks int, blockSize int, commit bool, ) { - var t *testing.T - var b *testing.B - testingmode := false - if _t, ok := tb.(*testing.T); ok { - t = _t - testingmode = true - } else { - b = tb.(*testing.B) - } + testingmode, t, b := getTestingMode(tb) log := fmt.Sprintf("Starting SimulateFromSeed with randomness created with seed %d", int(seed)) r := rand.New(rand.NewSource(seed)) timestamp := randTimestamp(r) @@ -93,6 +85,7 @@ func SimulateFromSeed( if !testingmode { b.ResetTimer() } + blockSimulator := createBlockSimulator(testingmode, tb, t, event, invariants, ops, operationQueue, numBlocks) for i := 0; i < numBlocks; i++ { // Run the BeginBlock handler @@ -111,24 +104,8 @@ func SimulateFromSeed( log, numQueuedOpsRan := runQueuedOperations(operationQueue, int(header.Height), tb, r, app, ctx, keys, log, event) opCount += numQueuedOpsRan thisBlockSize -= numQueuedOpsRan - for j := 0; j < thisBlockSize; j++ { - logUpdate, futureOps, err := ops[r.Intn(len(ops))](tb, r, app, ctx, keys, log, event) - log = updateLog(testingmode, log, logUpdate) - if err != nil { - tb.Fatalf("error on operation %d, %v, log %s", opCount, err, log) - } - - queueOperations(operationQueue, futureOps) - if testingmode { - if onOperation { - AssertAllInvariants(t, app, invariants, log) - } - if opCount%200 == 0 { - fmt.Printf("\rSimulating... block %d/%d, operation %d.", header.Height, numBlocks, opCount) - } - } - opCount++ - } + log, operations := blockSimulator(thisBlockSize, r, app, ctx, keys, log, header) + opCount += operations res := app.EndBlock(abci.RequestEndBlock{}) header.Height++ @@ -151,14 +128,49 @@ func SimulateFromSeed( validators = updateValidators(tb, r, validators, res.ValidatorUpdates, event) } - if testingmode { - fmt.Printf("\nSimulation complete. Final height (blocks): %d, final time (seconds): %v\n", header.Height, header.Time) - } else { - fmt.Printf("%d operations ran\n", opCount) - } + fmt.Printf("\nSimulation complete. Final height (blocks): %d, final time (seconds), : %v, operations ran %d\n", header.Height, header.Time, opCount) DisplayEvents(events) } +// Returns a function to simulate blocks. Written like this to avoid constant parameters being passed everytime, to minimize +// memory overhead +func createBlockSimulator(testingmode bool, tb testing.TB, t *testing.T, event func(string), invariants []Invariant, ops []Operation, operationQueue map[int][]Operation, totalNumBlocks int) func( + blocksize int, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, privKeys []crypto.PrivKey, log string, header abci.Header) (updatedLog string, opCount int) { + return func(blocksize int, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + keys []crypto.PrivKey, log string, header abci.Header) (updatedLog string, opCount int) { + for j := 0; j < blocksize; j++ { + logUpdate, futureOps, err := ops[r.Intn(len(ops))](tb, r, app, ctx, keys, log, event) + log = updateLog(testingmode, log, logUpdate) + if err != nil { + tb.Fatalf("error on operation %d within block %d, %v, log %s", header.Height, opCount, err, log) + } + + queueOperations(operationQueue, futureOps) + if testingmode { + if onOperation { + AssertAllInvariants(t, app, invariants, log) + } + if opCount%50 == 0 { + fmt.Printf("\rSimulating... block %d/%d, operation %d/%d.", header.Height, totalNumBlocks, opCount, blocksize) + } + } + opCount++ + } + return log, opCount + } +} + +func getTestingMode(tb testing.TB) (testingmode bool, t *testing.T, b *testing.B) { + testingmode = false + if _t, ok := tb.(*testing.T); ok { + t = _t + testingmode = true + } else { + b = tb.(*testing.B) + } + return +} + func updateLog(testingmode bool, log string, update string, args ...interface{}) (updatedLog string) { if testingmode { update = fmt.Sprintf(update, args...) From a69725d40d5ceaf2b27c0f5fba8e4e3c47029703 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Thu, 30 Aug 2018 11:47:32 -0700 Subject: [PATCH 24/93] Add method to benchmark with commits --- cmd/gaia/app/sim_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 6568f124b0..c7452ae533 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -30,6 +30,7 @@ var ( enabled bool verbose bool usegoleveldb bool + commit bool ) func init() { @@ -39,6 +40,7 @@ func init() { flag.BoolVar(&enabled, "SimulationEnabled", false, "Enable the simulation") flag.BoolVar(&verbose, "SimulationVerbose", false, "Verbose log output") flag.BoolVar(&usegoleveldb, "SimulationGoLevelDB", false, "Use GoLevelDB instead of memdb") + flag.BoolVar(&commit, "SimulationCommit", false, "Have the simulation commit") } func appStateFn(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage { @@ -137,7 +139,7 @@ func BenchmarkFullGaiaSimulation(b *testing.B) { invariants(app), // these shouldn't get ran 10, 100, - false, + commit, ) } @@ -165,7 +167,7 @@ func TestFullGaiaSimulation(t *testing.T) { invariants(app), numBlocks, blockSize, - false, + commit, ) } From e64c6da6f223019a5db6fbcb51c8d51745e42e44 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Thu, 30 Aug 2018 23:42:12 -0700 Subject: [PATCH 25/93] cleanup goleveldb dirs --- cmd/gaia/app/sim_test.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index c7452ae533..38dd352bde 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -124,10 +124,14 @@ func BenchmarkFullGaiaSimulation(b *testing.B) { var logger log.Logger logger = log.NewNopLogger() var db dbm.DB - db = dbm.NewMemDB() if usegoleveldb { - db, _ = dbm.NewGoLevelDB("Simulation", os.TempDir()) + dir := os.TempDir() + db, _ = dbm.NewGoLevelDB("Simulation", dir) + defer os.RemoveAll(dir) + } else { + db = dbm.NewMemDB() } + defer db.Close() app := NewGaiaApp(logger, db, nil) // Run randomized simulation From 75025720a3f63ae162ebe9ae48aa789b81287958 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Fri, 31 Aug 2018 21:57:33 -0700 Subject: [PATCH 26/93] simulation: Initialize governance properly --- cmd/gaia/app/sim_test.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 38dd352bde..be42511d05 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -16,6 +16,7 @@ import ( "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" banksim "github.com/cosmos/cosmos-sdk/x/bank/simulation" + "github.com/cosmos/cosmos-sdk/x/gov" govsim "github.com/cosmos/cosmos-sdk/x/gov/simulation" "github.com/cosmos/cosmos-sdk/x/mock/simulation" slashingsim "github.com/cosmos/cosmos-sdk/x/slashing/simulation" @@ -54,7 +55,7 @@ func appStateFn(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json Coins: coins, }) } - + govGenesis := gov.DefaultGenesisState() // Default genesis state stakeGenesis := stake.DefaultGenesisState() var validators []stake.Validator @@ -78,6 +79,7 @@ func appStateFn(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json genesis := GenesisState{ Accounts: genesisAccounts, StakeData: stakeGenesis, + GovData: govGenesis, } // Marshal genesis @@ -141,8 +143,8 @@ func BenchmarkFullGaiaSimulation(b *testing.B) { testAndRunTxs(app), []simulation.RandSetup{}, invariants(app), // these shouldn't get ran - 10, - 100, + 210, + blockSize, commit, ) } From 3c2100793eb8ba584a5dff16706acee39463b76b Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Sat, 1 Sep 2018 12:32:24 -0700 Subject: [PATCH 27/93] Address @cwgoes comments --- cmd/gaia/app/sim_test.go | 28 ++++++------- x/mock/simulation/random_simulate_blocks.go | 46 +++++++++++---------- 2 files changed, 36 insertions(+), 38 deletions(-) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index be42511d05..68f67709a3 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -25,13 +25,12 @@ import ( ) var ( - seed int64 - numBlocks int - blockSize int - enabled bool - verbose bool - usegoleveldb bool - commit bool + seed int64 + numBlocks int + blockSize int + enabled bool + verbose bool + commit bool ) func init() { @@ -40,7 +39,6 @@ func init() { flag.IntVar(&blockSize, "SimulationBlockSize", 200, "Operations per block") flag.BoolVar(&enabled, "SimulationEnabled", false, "Enable the simulation") flag.BoolVar(&verbose, "SimulationVerbose", false, "Verbose log output") - flag.BoolVar(&usegoleveldb, "SimulationGoLevelDB", false, "Use GoLevelDB instead of memdb") flag.BoolVar(&commit, "SimulationCommit", false, "Have the simulation commit") } @@ -126,14 +124,12 @@ func BenchmarkFullGaiaSimulation(b *testing.B) { var logger log.Logger logger = log.NewNopLogger() var db dbm.DB - if usegoleveldb { - dir := os.TempDir() - db, _ = dbm.NewGoLevelDB("Simulation", dir) - defer os.RemoveAll(dir) - } else { - db = dbm.NewMemDB() - } - defer db.Close() + dir := os.TempDir() + db, _ = dbm.NewGoLevelDB("Simulation", dir) + defer func() { + db.Close() + os.RemoveAll(dir) + }() app := NewGaiaApp(logger, db, nil) // Run randomized simulation diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index 42a616331d..be1963a9e8 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -54,11 +54,11 @@ func SimulateFromSeed( tb testing.TB, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, seed int64, ops []Operation, setups []RandSetup, invariants []Invariant, numBlocks int, blockSize int, commit bool, ) { - testingmode, t, b := getTestingMode(tb) + testingMode, t, b := getTestingMode(tb) log := fmt.Sprintf("Starting SimulateFromSeed with randomness created with seed %d", int(seed)) r := rand.New(rand.NewSource(seed)) timestamp := randTimestamp(r) - log = updateLog(testingmode, log, "Starting the simulation from time %v, unixtime %v", timestamp.UTC().Format(time.UnixDate), timestamp.Unix()) + log = updateLog(testingMode, log, "Starting the simulation from time %v, unixtime %v", timestamp.UTC().Format(time.UnixDate), timestamp.Unix()) fmt.Printf("%s\n", log) timeDiff := maxTimePerBlock - minTimePerBlock @@ -67,7 +67,7 @@ func SimulateFromSeed( // Setup event stats events := make(map[string]uint) event := func(what string) { - log = updateLog(testingmode, log, "event - %s", what) + log = updateLog(testingMode, log, "event - %s", what) events[what]++ } @@ -78,21 +78,24 @@ func SimulateFromSeed( request := abci.RequestBeginBlock{Header: header} - var lastHeaderTime time.Time + var pastTimes []time.Time // These are operations which have been queued by previous operations operationQueue := make(map[int][]Operation) - if !testingmode { + if !testingMode { b.ResetTimer() } - blockSimulator := createBlockSimulator(testingmode, tb, t, event, invariants, ops, operationQueue, numBlocks) + blockSimulator := createBlockSimulator(testingMode, tb, t, event, invariants, ops, operationQueue, numBlocks) for i := 0; i < numBlocks; i++ { + // Log the header time for future lookup + pastTimes = append(pastTimes, header.Time) + // Run the BeginBlock handler app.BeginBlock(request) - log = updateLog(testingmode, log, "BeginBlock") + log = updateLog(testingMode, log, "BeginBlock") - if testingmode { + if testingMode { // Make sure invariants hold at beginning of block AssertAllInvariants(t, app, invariants, log) } @@ -109,11 +112,10 @@ func SimulateFromSeed( res := app.EndBlock(abci.RequestEndBlock{}) header.Height++ - lastHeaderTime = header.Time header.Time = header.Time.Add(time.Duration(minTimePerBlock) * time.Second).Add(time.Duration(int64(r.Intn(int(timeDiff)))) * time.Second) - log = updateLog(testingmode, log, "EndBlock") + log = updateLog(testingMode, log, "EndBlock") - if testingmode { + if testingMode { // Make sure invariants hold at end of block AssertAllInvariants(t, app, invariants, log) } @@ -122,7 +124,7 @@ func SimulateFromSeed( } // Generate a random RequestBeginBlock with the current validator set for the next block - request = RandomRequestBeginBlock(r, validators, livenessTransitionMatrix, evidenceFraction, lastHeaderTime, event, header, log) + request = RandomRequestBeginBlock(r, validators, livenessTransitionMatrix, evidenceFraction, pastTimes, event, header, log) // Update the validator set validators = updateValidators(tb, r, validators, res.ValidatorUpdates, event) @@ -134,19 +136,19 @@ func SimulateFromSeed( // Returns a function to simulate blocks. Written like this to avoid constant parameters being passed everytime, to minimize // memory overhead -func createBlockSimulator(testingmode bool, tb testing.TB, t *testing.T, event func(string), invariants []Invariant, ops []Operation, operationQueue map[int][]Operation, totalNumBlocks int) func( +func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, event func(string), invariants []Invariant, ops []Operation, operationQueue map[int][]Operation, totalNumBlocks int) func( blocksize int, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, privKeys []crypto.PrivKey, log string, header abci.Header) (updatedLog string, opCount int) { return func(blocksize int, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, header abci.Header) (updatedLog string, opCount int) { for j := 0; j < blocksize; j++ { logUpdate, futureOps, err := ops[r.Intn(len(ops))](tb, r, app, ctx, keys, log, event) - log = updateLog(testingmode, log, logUpdate) + log = updateLog(testingMode, log, logUpdate) if err != nil { tb.Fatalf("error on operation %d within block %d, %v, log %s", header.Height, opCount, err, log) } queueOperations(operationQueue, futureOps) - if testingmode { + if testingMode { if onOperation { AssertAllInvariants(t, app, invariants, log) } @@ -160,19 +162,19 @@ func createBlockSimulator(testingmode bool, tb testing.TB, t *testing.T, event f } } -func getTestingMode(tb testing.TB) (testingmode bool, t *testing.T, b *testing.B) { - testingmode = false +func getTestingMode(tb testing.TB) (testingMode bool, t *testing.T, b *testing.B) { + testingMode = false if _t, ok := tb.(*testing.T); ok { t = _t - testingmode = true + testingMode = true } else { b = tb.(*testing.B) } return } -func updateLog(testingmode bool, log string, update string, args ...interface{}) (updatedLog string) { - if testingmode { +func updateLog(testingMode bool, log string, update string, args ...interface{}) (updatedLog string) { + if testingMode { update = fmt.Sprintf(update, args...) return fmt.Sprintf("%s\n%s", log, update) } @@ -240,7 +242,7 @@ func getKeys(validators map[string]mockValidator) []string { // RandomRequestBeginBlock generates a list of signing validators according to the provided list of validators, signing fraction, and evidence fraction func RandomRequestBeginBlock(r *rand.Rand, validators map[string]mockValidator, livenessTransitions TransitionMatrix, evidenceFraction float64, - lastHeaderTime time.Time, event func(string), header abci.Header, log string) abci.RequestBeginBlock { + pastTimes []time.Time, event func(string), header abci.Header, log string) abci.RequestBeginBlock { if len(validators) == 0 { return abci.RequestBeginBlock{Header: header} } @@ -279,7 +281,7 @@ func RandomRequestBeginBlock(r *rand.Rand, validators map[string]mockValidator, time := header.Time if r.Float64() < pastEvidenceFraction { height = int64(r.Intn(int(header.Height))) - time = lastHeaderTime + time = pastTimes[height] } validator := signingValidators[r.Intn(len(signingValidators))].Validator var currentTotalVotingPower int64 From a991a2e1c4b328cb70af86fb5b794a1967813c5a Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Fri, 31 Aug 2018 00:37:25 -0700 Subject: [PATCH 28/93] Improve GetValidator speed In simulation, this was shown to cause a 4x speedup. There are no safety concerns here, as amino encoding is deterministic. --- PENDING.md | 2 +- x/stake/keeper/validator.go | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/PENDING.md b/PENDING.md index 0aef9fd193..5557a8771e 100644 --- a/PENDING.md +++ b/PENDING.md @@ -78,7 +78,7 @@ IMPROVEMENTS * [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. * [x/auth] Signature verification's gas cost now accounts for pubkey type. [#2046](https://github.com/tendermint/tendermint/pull/2046) * [x/stake] [x/slashing] Ensure delegation invariants to jailed validators [#1883](https://github.com/cosmos/cosmos-sdk/issues/1883). - + * [x/stake] Improve speed of GetValidator, which was shown to be a performance bottleneck. [#2046](https://github.com/tendermint/tendermint/pull/2200) * SDK * [tools] Make get_vendor_deps deletes `.vendor-new` directories, in case scratch files are present. * [cli] \#1632 Add integration tests to ensure `basecoind init && basecoind` start sequences run successfully for both `democoin` and `basecoin` examples. diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 0ea24e6396..5dc075742e 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -2,6 +2,7 @@ package keeper import ( "bytes" + "container/list" "fmt" abci "github.com/tendermint/tendermint/abci/types" @@ -11,6 +12,14 @@ import ( "github.com/cosmos/cosmos-sdk/x/stake/types" ) +type cachedValidator struct { + val types.Validator + marshalled string +} + +var validatorCache = make(map[string]cachedValidator, 1000) +var validatorCacheList = list.New() + // get a single validator func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator types.Validator, found bool) { store := ctx.KVStore(k.storeKey) @@ -18,6 +27,23 @@ func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator ty if value == nil { return validator, false } + // return cached validator + strValue := string(value) + if val, ok := validatorCache[strValue]; ok { + valToReturn := val.val + // Doesn't mutate the cache's value + valToReturn.Operator = addr + return valToReturn, true + } else { // get validator from cache + validator = types.MustUnmarshalValidator(k.cdc, addr, value) + cachedVal := cachedValidator{validator, strValue} + validatorCache[strValue] = cachedValidator{validator, strValue} + validatorCacheList.PushBack(cachedVal) + if validatorCacheList.Len() > 500 { + valToRemove := validatorCacheList.Remove(validatorCacheList.Front()).(cachedValidator) + delete(validatorCache, valToRemove.marshalled) + } + } validator = types.MustUnmarshalValidator(k.cdc, addr, value) return validator, true } From 3b4caa5dd2bf218f24fd53616a41aefea79c9f20 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Fri, 31 Aug 2018 08:29:32 -0700 Subject: [PATCH 29/93] fix lint --- x/stake/keeper/validator.go | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 5dc075742e..a12801dc9e 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -34,16 +34,17 @@ func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator ty // Doesn't mutate the cache's value valToReturn.Operator = addr return valToReturn, true - } else { // get validator from cache - validator = types.MustUnmarshalValidator(k.cdc, addr, value) - cachedVal := cachedValidator{validator, strValue} - validatorCache[strValue] = cachedValidator{validator, strValue} - validatorCacheList.PushBack(cachedVal) - if validatorCacheList.Len() > 500 { - valToRemove := validatorCacheList.Remove(validatorCacheList.Front()).(cachedValidator) - delete(validatorCache, valToRemove.marshalled) - } } + // get validator from cache + validator = types.MustUnmarshalValidator(k.cdc, addr, value) + cachedVal := cachedValidator{validator, strValue} + validatorCache[strValue] = cachedValidator{validator, strValue} + validatorCacheList.PushBack(cachedVal) + if validatorCacheList.Len() > 500 { + valToRemove := validatorCacheList.Remove(validatorCacheList.Front()).(cachedValidator) + delete(validatorCache, valToRemove.marshalled) + } + validator = types.MustUnmarshalValidator(k.cdc, addr, value) return validator, true } From f29fdcafddd84e1faf290305b840aca1cddd7ec2 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Sat, 1 Sep 2018 13:21:42 -0700 Subject: [PATCH 30/93] Add comments --- x/stake/keeper/validator.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index a12801dc9e..d5fba14337 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -12,12 +12,16 @@ import ( "github.com/cosmos/cosmos-sdk/x/stake/types" ) +// Cache the amino decoding of validators, as it can be the case that repeated slashing calls +// cause many calls to GetValidator, which were shown to throttle the state machine in our +// simulation. Note this is quite biased though, as the simulator does more slashes than a +// live chain should, however we require the slashing to be fast as noone pays gas for it. type cachedValidator struct { val types.Validator marshalled string } -var validatorCache = make(map[string]cachedValidator, 1000) +var validatorCache = make(map[string]cachedValidator, 500) var validatorCacheList = list.New() // get a single validator @@ -27,7 +31,7 @@ func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator ty if value == nil { return validator, false } - // return cached validator + // If these amino encoded bytes are in the cache, return the cached validator strValue := string(value) if val, ok := validatorCache[strValue]; ok { valToReturn := val.val @@ -35,11 +39,12 @@ func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator ty valToReturn.Operator = addr return valToReturn, true } - // get validator from cache + // amino bytes weren't found in cache, so amino unmarshal and add it to the cache validator = types.MustUnmarshalValidator(k.cdc, addr, value) cachedVal := cachedValidator{validator, strValue} validatorCache[strValue] = cachedValidator{validator, strValue} validatorCacheList.PushBack(cachedVal) + // if the cache is too big, pop off the last element from it if validatorCacheList.Len() > 500 { valToRemove := validatorCacheList.Remove(validatorCacheList.Front()).(cachedValidator) delete(validatorCache, valToRemove.marshalled) From 8a452b940a38c799ebb432361a0daeeec833fe63 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Sat, 1 Sep 2018 19:04:44 -0700 Subject: [PATCH 31/93] simulation: display db size at end of simulation, add makefile entries --- Makefile | 11 +++++++++++ PENDING.md | 2 +- cmd/gaia/app/sim_test.go | 14 +++++++++++--- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 983234dbc3..e363891e2a 100644 --- a/Makefile +++ b/Makefile @@ -163,6 +163,17 @@ test_sim_gaia_slow: @echo "Running full Gaia simulation. This may take awhile!" @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=1000 -SimulationVerbose=true -v -timeout 24h +SIM_NUM_BLOCKS ?= 210 +SIM_BLOCK_SIZE ?= 200 +SIM_COMMIT ?= true +test_sim_gaia_benchmark: + @echo "Running Gaia benchmark for numBlocks=$(SIM_NUM_BLOCKS), blockSize=$(SIM_BLOCK_SIZE). This may take awhile!" + @go test -benchmem -run=^$$ github.com/cosmos/cosmos-sdk/cmd/gaia/app -bench ^BenchmarkFullGaiaSimulation$$ -SimulationEnabled=true -SimulationNumBlocks=$(SIM_NUM_BLOCKS) -SimulationBlockSize=$(SIM_BLOCK_SIZE) -SimulationCommit=$(SIM_COMMIT) -timeout 24h + +test_sim_gaia_profile: + @echo "Running Gaia benchmark for numBlocks=$(SIM_NUM_BLOCKS), blockSize=$(SIM_BLOCK_SIZE). This may take awhile!" + @go test -benchmem -run=^$$ github.com/cosmos/cosmos-sdk/cmd/gaia/app -bench ^BenchmarkFullGaiaSimulation$$ -SimulationEnabled=true -SimulationNumBlocks=$(SIM_NUM_BLOCKS) -SimulationBlockSize=$(SIM_BLOCK_SIZE) -SimulationCommit=$(SIM_COMMIT) -timeout 24h -cpuprofile cpu.out -memprofile mem.out + test_cover: @bash tests/test_cover.sh diff --git a/PENDING.md b/PENDING.md index 5557a8771e..34e202999d 100644 --- a/PENDING.md +++ b/PENDING.md @@ -58,7 +58,7 @@ FEATURES * SDK * [querier] added custom querier functionality, so ABCI query requests can be handled by keepers * [simulation] \#1924 allow operations to specify future operations - * [simulation] \#1924 Add benchmarking capabilities + * [simulation] \#1924 Add benchmarking capabilities, with makefile commands "test_sim_gaia_benchmark, test_sim_gaia_profile" * Tendermint diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 58d7ca18d3..3878166b3a 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -3,6 +3,7 @@ package app import ( "encoding/json" "flag" + "fmt" "math/rand" "os" "testing" @@ -118,7 +119,7 @@ func invariants(app *GaiaApp) []simulation.Invariant { } // Profile with: -// /usr/local/go/bin/go test -benchmem -run=^$ github.com/cosmos/cosmos-sdk/cmd/gaia/app -bench ^BenchmarkFullGaiaSimulation$ -cpuprofile cpu.out +// /usr/local/go/bin/go test -benchmem -run=^$ github.com/cosmos/cosmos-sdk/cmd/gaia/app -bench ^BenchmarkFullGaiaSimulation$ -SimulationCommit=true -cpuprofile cpu.out func BenchmarkFullGaiaSimulation(b *testing.B) { // Setup Gaia application var logger log.Logger @@ -139,10 +140,15 @@ func BenchmarkFullGaiaSimulation(b *testing.B) { testAndRunTxs(app), []simulation.RandSetup{}, invariants(app), // these shouldn't get ran - 210, + numBlocks, blockSize, commit, ) + if commit { + fmt.Println("GoLevelDB Stats") + fmt.Println(db.Stats()["leveldb.stats"]) + fmt.Println("GoLevelDB cached block size", db.Stats()["leveldb.cachedblock"]) + } } func TestFullGaiaSimulation(t *testing.T) { @@ -171,7 +177,9 @@ func TestFullGaiaSimulation(t *testing.T) { blockSize, commit, ) - + if commit { + fmt.Println("Database Size", db.Stats()["database.size"]) + } } // TODO: Make another test for the fuzzer itself, which just has noOp txs From 2c66ba0bd4e47a4692f55105b0c405a63b004875 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Sun, 2 Sep 2018 15:42:25 -0400 Subject: [PATCH 32/93] extra comment on cache key usage --- x/stake/keeper/validator.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index d5fba14337..2d8f947fc0 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -18,9 +18,10 @@ import ( // live chain should, however we require the slashing to be fast as noone pays gas for it. type cachedValidator struct { val types.Validator - marshalled string + marshalled string // marshalled amino bytes for the validator object (not operator address) } +// validatorCache-key: validator amino bytes var validatorCache = make(map[string]cachedValidator, 500) var validatorCacheList = list.New() @@ -31,6 +32,7 @@ func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator ty if value == nil { return validator, false } + // If these amino encoded bytes are in the cache, return the cached validator strValue := string(value) if val, ok := validatorCache[strValue]; ok { @@ -39,11 +41,13 @@ func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator ty valToReturn.Operator = addr return valToReturn, true } + // amino bytes weren't found in cache, so amino unmarshal and add it to the cache validator = types.MustUnmarshalValidator(k.cdc, addr, value) cachedVal := cachedValidator{validator, strValue} validatorCache[strValue] = cachedValidator{validator, strValue} validatorCacheList.PushBack(cachedVal) + // if the cache is too big, pop off the last element from it if validatorCacheList.Len() > 500 { valToRemove := validatorCacheList.Remove(validatorCacheList.Front()).(cachedValidator) From 3a62c838734a38712ed1455a26f828685bfef1cf Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Fri, 31 Aug 2018 22:10:05 -0700 Subject: [PATCH 33/93] asdf --- x/gov/genesis.go | 6 ++++-- x/gov/handler.go | 8 ++++---- x/gov/keeper.go | 19 +++++++++---------- x/gov/procedures.go | 8 +++++--- x/gov/proposals.go | 27 ++++++++++++++------------- 5 files changed, 36 insertions(+), 32 deletions(-) diff --git a/x/gov/genesis.go b/x/gov/genesis.go index 15f952c000..58273c8e84 100644 --- a/x/gov/genesis.go +++ b/x/gov/genesis.go @@ -1,6 +1,8 @@ package gov import ( + "time" + sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -27,10 +29,10 @@ func DefaultGenesisState() GenesisState { StartingProposalID: 1, DepositProcedure: DepositProcedure{ MinDeposit: sdk.Coins{sdk.NewInt64Coin("steak", 10)}, - MaxDepositPeriod: 200, + MaxDepositPeriod: time.Duration(172800) * time.Second, }, VotingProcedure: VotingProcedure{ - VotingPeriod: 200, + VotingPeriod: time.Duration(172800) * time.Second, }, TallyingProcedure: TallyingProcedure{ Threshold: sdk.NewDecWithPrec(5, 1), diff --git a/x/gov/handler.go b/x/gov/handler.go index 6424bb0a10..59e47a14ec 100644 --- a/x/gov/handler.go +++ b/x/gov/handler.go @@ -122,9 +122,9 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) { for shouldPopActiveProposalQueue(ctx, keeper) { activeProposal := keeper.ActiveProposalQueuePop(ctx) - proposalStartBlock := activeProposal.GetVotingStartBlock() + proposalStartTime := activeProposal.GetVotingStartTime() votingPeriod := keeper.GetVotingProcedure(ctx).VotingPeriod - if ctx.BlockHeight() < proposalStartBlock+votingPeriod { + if ctx.BlockHeader().Time.Before(proposalStartTime.Add(votingPeriod)) { continue } @@ -172,7 +172,7 @@ func shouldPopInactiveProposalQueue(ctx sdk.Context, keeper Keeper) bool { return false } else if peekProposal.GetStatus() != StatusDepositPeriod { return true - } else if ctx.BlockHeight() >= peekProposal.GetSubmitBlock()+depositProcedure.MaxDepositPeriod { + } else if !ctx.BlockHeader().Time.Before(peekProposal.GetSubmitTime().Add(depositProcedure.MaxDepositPeriod)) { return true } return false @@ -184,7 +184,7 @@ func shouldPopActiveProposalQueue(ctx sdk.Context, keeper Keeper) bool { if peekProposal == nil { return false - } else if ctx.BlockHeight() >= peekProposal.GetVotingStartBlock()+votingProcedure.VotingPeriod { + } else if !ctx.BlockHeader().Time.Before(peekProposal.GetVotingStartTime().Add(votingProcedure.VotingPeriod)) { return true } return false diff --git a/x/gov/keeper.go b/x/gov/keeper.go index e8dbbc4a7f..b7b666c90d 100644 --- a/x/gov/keeper.go +++ b/x/gov/keeper.go @@ -66,15 +66,14 @@ func (keeper Keeper) NewTextProposal(ctx sdk.Context, title string, description return nil } var proposal Proposal = &TextProposal{ - ProposalID: proposalID, - Title: title, - Description: description, - ProposalType: proposalType, - Status: StatusDepositPeriod, - TallyResult: EmptyTallyResult(), - TotalDeposit: sdk.Coins{}, - SubmitBlock: ctx.BlockHeight(), - VotingStartBlock: -1, // TODO: Make Time + ProposalID: proposalID, + Title: title, + Description: description, + ProposalType: proposalType, + Status: StatusDepositPeriod, + TallyResult: EmptyTallyResult(), + TotalDeposit: sdk.Coins{}, + SubmitTime: ctx.BlockHeader().Time, } keeper.SetProposal(ctx, proposal) keeper.InactiveProposalQueuePush(ctx, proposal) @@ -200,7 +199,7 @@ func (keeper Keeper) peekCurrentProposalID(ctx sdk.Context) (proposalID int64, e } func (keeper Keeper) activateVotingPeriod(ctx sdk.Context, proposal Proposal) { - proposal.SetVotingStartBlock(ctx.BlockHeight()) + proposal.SetVotingStartTime(ctx.BlockHeader().Time) proposal.SetStatus(StatusVotingPeriod) keeper.SetProposal(ctx, proposal) keeper.ActiveProposalQueuePush(ctx, proposal) diff --git a/x/gov/procedures.go b/x/gov/procedures.go index f74091c74f..e453add791 100644 --- a/x/gov/procedures.go +++ b/x/gov/procedures.go @@ -1,13 +1,15 @@ package gov import ( + "time" + sdk "github.com/cosmos/cosmos-sdk/types" ) // Procedure around Deposits for governance type DepositProcedure struct { - MinDeposit sdk.Coins `json:"min_deposit"` // Minimum deposit for a proposal to enter voting period. - MaxDepositPeriod int64 `json:"max_deposit_period"` // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months + MinDeposit sdk.Coins `json:"min_deposit"` // Minimum deposit for a proposal to enter voting period. + MaxDepositPeriod time.Duration `json:"max_deposit_period"` // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months } // Procedure around Tallying votes in governance @@ -19,5 +21,5 @@ type TallyingProcedure struct { // Procedure around Voting in governance type VotingProcedure struct { - VotingPeriod int64 `json:"voting_period"` // Length of the voting period. + VotingPeriod time.Duration `json:"voting_period"` // Length of the voting period. } diff --git a/x/gov/proposals.go b/x/gov/proposals.go index c52ab1e875..80539b3097 100644 --- a/x/gov/proposals.go +++ b/x/gov/proposals.go @@ -3,6 +3,7 @@ package gov import ( "encoding/json" "fmt" + "time" "github.com/pkg/errors" @@ -30,14 +31,14 @@ type Proposal interface { GetTallyResult() TallyResult SetTallyResult(TallyResult) - GetSubmitBlock() int64 - SetSubmitBlock(int64) + GetSubmitTime() time.Time + SetSubmitTime(time.Time) GetTotalDeposit() sdk.Coins SetTotalDeposit(sdk.Coins) - GetVotingStartBlock() int64 - SetVotingStartBlock(int64) + GetVotingStartTime() time.Time + SetVotingStartTime(time.Time) } // checks if two proposals are equal @@ -48,9 +49,9 @@ func ProposalEqual(proposalA Proposal, proposalB Proposal) bool { proposalA.GetProposalType() == proposalB.GetProposalType() && proposalA.GetStatus() == proposalB.GetStatus() && proposalA.GetTallyResult().Equals(proposalB.GetTallyResult()) && - proposalA.GetSubmitBlock() == proposalB.GetSubmitBlock() && + proposalA.GetSubmitTime().Equal(proposalB.GetSubmitTime()) && proposalA.GetTotalDeposit().IsEqual(proposalB.GetTotalDeposit()) && - proposalA.GetVotingStartBlock() == proposalB.GetVotingStartBlock() { + proposalA.GetVotingStartTime().Equal(proposalB.GetVotingStartTime()) { return true } return false @@ -67,10 +68,10 @@ type TextProposal struct { Status ProposalStatus `json:"proposal_status"` // Status of the Proposal {Pending, Active, Passed, Rejected} TallyResult TallyResult `json:"tally_result"` // Result of Tallys - SubmitBlock int64 `json:"submit_block"` // Height of the block where TxGovSubmitProposal was included + SubmitTime time.Time `json:"submit_block"` // Height of the block where TxGovSubmitProposal was included TotalDeposit sdk.Coins `json:"total_deposit"` // Current deposit on this proposal. Initial value is set at InitialDeposit - VotingStartBlock int64 `json:"voting_start_block"` // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached + VotingStartTime time.Time `json:"voting_start_block"` // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached } // Implements Proposal Interface @@ -89,13 +90,13 @@ func (tp TextProposal) GetStatus() ProposalStatus { return tp.S func (tp *TextProposal) SetStatus(status ProposalStatus) { tp.Status = status } func (tp TextProposal) GetTallyResult() TallyResult { return tp.TallyResult } func (tp *TextProposal) SetTallyResult(tallyResult TallyResult) { tp.TallyResult = tallyResult } -func (tp TextProposal) GetSubmitBlock() int64 { return tp.SubmitBlock } -func (tp *TextProposal) SetSubmitBlock(submitBlock int64) { tp.SubmitBlock = submitBlock } +func (tp TextProposal) GetSubmitTime() time.Time { return tp.SubmitTime } +func (tp *TextProposal) SetSubmitTime(submitTime time.Time) { tp.SubmitTime = submitTime } func (tp TextProposal) GetTotalDeposit() sdk.Coins { return tp.TotalDeposit } func (tp *TextProposal) SetTotalDeposit(totalDeposit sdk.Coins) { tp.TotalDeposit = totalDeposit } -func (tp TextProposal) GetVotingStartBlock() int64 { return tp.VotingStartBlock } -func (tp *TextProposal) SetVotingStartBlock(votingStartBlock int64) { - tp.VotingStartBlock = votingStartBlock +func (tp TextProposal) GetVotingStartTime() time.Time { return tp.VotingStartTime } +func (tp *TextProposal) SetVotingStartTime(votingStartTime time.Time) { + tp.VotingStartTime = votingStartTime } //----------------------------------------------------------- From aafa0d92dd7ae6ceda0f6d843ad6744014dbc715 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Sun, 2 Sep 2018 23:51:48 -0700 Subject: [PATCH 34/93] BFT Time --- x/gov/endblocker_test.go | 51 ++++++++++++++++++++++++++++++++-------- x/gov/keeper_test.go | 9 +++---- 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/x/gov/endblocker_test.go b/x/gov/endblocker_test.go index 710ecb1dba..4cbd1d7588 100644 --- a/x/gov/endblocker_test.go +++ b/x/gov/endblocker_test.go @@ -2,6 +2,7 @@ package gov import ( "testing" + "time" "github.com/stretchr/testify/require" @@ -28,12 +29,18 @@ func TestTickExpiredDepositPeriod(t *testing.T) { require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - ctx = ctx.WithBlockHeight(10) + newHeader := ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second) + ctx = ctx.WithBlockHeader(newHeader) + EndBlocker(ctx, keeper) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - ctx = ctx.WithBlockHeight(250) + newHeader = ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod) + ctx = ctx.WithBlockHeader(newHeader) + require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.True(t, shouldPopInactiveProposalQueue(ctx, keeper)) EndBlocker(ctx, keeper) @@ -59,7 +66,10 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) { require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - ctx = ctx.WithBlockHeight(10) + newHeader := ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(2) * time.Second) + ctx = ctx.WithBlockHeader(newHeader) + EndBlocker(ctx, keeper) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) @@ -68,14 +78,20 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) { res = govHandler(ctx, newProposalMsg2) require.True(t, res.IsOK()) - ctx = ctx.WithBlockHeight(205) + newHeader = ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod).Add(time.Duration(-1) * time.Second) + ctx = ctx.WithBlockHeader(newHeader) + require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.True(t, shouldPopInactiveProposalQueue(ctx, keeper)) EndBlocker(ctx, keeper) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - ctx = ctx.WithBlockHeight(215) + newHeader = ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(5) * time.Second) + ctx = ctx.WithBlockHeader(newHeader) + require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.True(t, shouldPopInactiveProposalQueue(ctx, keeper)) EndBlocker(ctx, keeper) @@ -105,7 +121,10 @@ func TestTickPassedDepositPeriod(t *testing.T) { require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - ctx = ctx.WithBlockHeight(10) + newHeader := ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second) + ctx = ctx.WithBlockHeader(newHeader) + EndBlocker(ctx, keeper) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) @@ -146,14 +165,20 @@ func TestTickPassedVotingPeriod(t *testing.T) { var proposalID int64 keeper.cdc.UnmarshalBinaryBare(res.Data, &proposalID) - ctx = ctx.WithBlockHeight(10) + newHeader := ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second) + ctx = ctx.WithBlockHeader(newHeader) + newDepositMsg := NewMsgDeposit(addrs[1], proposalID, sdk.Coins{sdk.NewInt64Coin("steak", 5)}) res = govHandler(ctx, newDepositMsg) require.True(t, res.IsOK()) EndBlocker(ctx, keeper) - ctx = ctx.WithBlockHeight(215) + newHeader = ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod).Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod) + ctx = ctx.WithBlockHeader(newHeader) + require.True(t, shouldPopActiveProposalQueue(ctx, keeper)) depositsIterator := keeper.GetDeposits(ctx, proposalID) require.True(t, depositsIterator.Valid()) @@ -197,7 +222,10 @@ func TestSlashing(t *testing.T) { var proposalID int64 keeper.cdc.UnmarshalBinaryBare(res.Data, &proposalID) - ctx = ctx.WithBlockHeight(10) + newHeader := ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second) + ctx = ctx.WithBlockHeader(newHeader) + require.Equal(t, StatusVotingPeriod, keeper.GetProposal(ctx, proposalID).GetStatus()) newVoteMsg := NewMsgVote(addrs[0], proposalID, OptionYes) @@ -206,7 +234,10 @@ func TestSlashing(t *testing.T) { EndBlocker(ctx, keeper) - ctx = ctx.WithBlockHeight(215) + newHeader = ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod).Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod) + ctx = ctx.WithBlockHeader(newHeader) + require.Equal(t, StatusVotingPeriod, keeper.GetProposal(ctx, proposalID).GetStatus()) EndBlocker(ctx, keeper) diff --git a/x/gov/keeper_test.go b/x/gov/keeper_test.go index a61292b93e..91c41d7d7d 100644 --- a/x/gov/keeper_test.go +++ b/x/gov/keeper_test.go @@ -2,6 +2,7 @@ package gov import ( "testing" + "time" "github.com/stretchr/testify/require" @@ -45,12 +46,12 @@ func TestActivateVotingPeriod(t *testing.T) { proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText) - require.Equal(t, int64(-1), proposal.GetVotingStartBlock()) + require.True(t, proposal.GetVotingStartTime().Equal(time.Time{})) require.Nil(t, keeper.ActiveProposalQueuePeek(ctx)) keeper.activateVotingPeriod(ctx, proposal) - require.Equal(t, proposal.GetVotingStartBlock(), ctx.BlockHeight()) + require.True(t, proposal.GetVotingStartTime().Equal(ctx.BlockHeader().Time)) require.Equal(t, proposal.GetProposalID(), keeper.ActiveProposalQueuePeek(ctx).GetProposalID()) } @@ -77,7 +78,7 @@ func TestDeposits(t *testing.T) { // Check no deposits at beginning deposit, found := keeper.GetDeposit(ctx, proposalID, addrs[1]) require.False(t, found) - require.Equal(t, keeper.GetProposal(ctx, proposalID).GetVotingStartBlock(), int64(-1)) + require.True(t, keeper.GetProposal(ctx, proposalID).GetVotingStartTime().Equal(time.Time{})) require.Nil(t, keeper.ActiveProposalQueuePeek(ctx)) // Check first deposit @@ -114,7 +115,7 @@ func TestDeposits(t *testing.T) { require.Equal(t, addr1Initial.Minus(fourSteak), keeper.ck.GetCoins(ctx, addrs[1])) // Check that proposal moved to voting period - require.Equal(t, ctx.BlockHeight(), keeper.GetProposal(ctx, proposalID).GetVotingStartBlock()) + require.True(t, keeper.GetProposal(ctx, proposalID).GetVotingStartTime().Equal(ctx.BlockHeader().Time)) require.NotNil(t, keeper.ActiveProposalQueuePeek(ctx)) require.Equal(t, proposalID, keeper.ActiveProposalQueuePeek(ctx).GetProposalID()) From a3bbf3a55b313be47b0b8d762d84c57f1bc8d7ee Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Mon, 3 Sep 2018 00:08:49 -0700 Subject: [PATCH 35/93] PENDING --- PENDING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PENDING.md b/PENDING.md index 7eb324a23d..f15e68bd6e 100644 --- a/PENDING.md +++ b/PENDING.md @@ -28,6 +28,7 @@ BREAKING CHANGES * [x/stake] \#2040 Validator operator type has now changed to `sdk.ValAddress` * A new bech32 prefix has been introduced for Tendermint signing keys and addresses, `cosmosconspub` and `cosmoscons` respectively. + * [x/gov] \#2195 Made governance use BFT Time instead of Block Heights for deposit and voting periods. * SDK * [core] \#1807 Switch from use of rational to decimal From 92eef7a4fadc9041768df4981dc41b4d7bf081e9 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Mon, 3 Sep 2018 00:16:38 -0700 Subject: [PATCH 36/93] docs --- docs/spec/governance/state.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/spec/governance/state.md b/docs/spec/governance/state.md index 728ded3713..0d2927d7a5 100644 --- a/docs/spec/governance/state.md +++ b/docs/spec/governance/state.md @@ -13,13 +13,13 @@ has to be created and the previous one rendered inactive. ```go type DepositProcedure struct { MinDeposit sdk.Coins // Minimum deposit for a proposal to enter voting period. - MaxDepositPeriod int64 // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months + MaxDepositPeriod time.Time // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months } ``` ```go type VotingProcedure struct { - VotingPeriod int64 // Length of the voting period. Initial value: 2 weeks + VotingPeriod time.Time // Length of the voting period. Initial value: 2 weeks } ``` @@ -28,7 +28,7 @@ type TallyingProcedure struct { 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 + GracePeriod time.Time // If validator entered validator set in this period of blocks before vote ended, governance penalty does not apply } ``` @@ -97,10 +97,10 @@ type Proposal struct { Type ProposalType // Type of proposal. Initial set {PlainTextProposal, SoftwareUpgradeProposal} TotalDeposit sdk.Coins // Current deposit on this proposal. Initial value is set at InitialDeposit Deposits []Deposit // List of deposits on the proposal - SubmitBlock int64 // Height of the block where TxGovSubmitProposal was included + SubmitTime time.Time // Time of the block where TxGovSubmitProposal was included Submitter sdk.Address // Address of the submitter - VotingStartBlock int64 // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached + VotingStartTime time.Time // Time of the block where MinDeposit was reached. time.Time{} if MinDeposit is not reached CurrentStatus ProposalStatus // Current status of the proposal YesVotes sdk.Dec @@ -137,7 +137,7 @@ For pseudocode purposes, here are the two function we will use to read or write * `ProposalProcessingQueue`: A queue `queue[proposalID]` containing all the `ProposalIDs` of proposals that reached `MinDeposit`. Each round, the oldest element of `ProposalProcessingQueue` is checked during `BeginBlock` to see if - `CurrentBlock == VotingStartBlock + activeProcedure.VotingPeriod`. If it is, + `CurrentTime == VotingStartTime + activeProcedure.VotingPeriod`. If it is, then the application tallies the votes, compute the votes of each validator and checks if every validator in the valdiator set have voted and, if not, applies `GovernancePenalty`. If the proposal is accepted, deposits are refunded. After that proposal is ejected from `ProposalProcessingQueue` and the next element of the queue is evaluated. @@ -159,7 +159,7 @@ And the pseudocode for the `ProposalProcessingQueue`: proposal = load(Governance, ) // proposal is a const key votingProcedure = load(GlobalParams, 'VotingProcedure') - if (CurrentBlock == proposal.VotingStartBlock + votingProcedure.VotingPeriod && proposal.CurrentStatus == ProposalStatusActive) + if (CurrentTime == proposal.VotingStartTime + votingProcedure.VotingPeriod && proposal.CurrentStatus == ProposalStatusActive) // End of voting period, tally @@ -194,7 +194,7 @@ And the pseudocode for the `ProposalProcessingQueue`: // Slash validators that did not vote, or update tally if they voted for each validator in validators - if (validator.bondHeight < CurrentBlock - tallyingProcedure.GracePeriod) + if (validator.bondTime < CurrentTime - tallyingProcedure.GracePeriod) // only slash if validator entered validator set before grace period if (!tmpValMap(validator).HasVoted) slash validator by tallyingProcedure.GovernancePenalty From b72f87a0270cf6b234f5e4d15855c032cf5a1d6e Mon Sep 17 00:00:00 2001 From: Jeremiah Andrews Date: Fri, 3 Aug 2018 16:24:03 -0700 Subject: [PATCH 37/93] Update IAVL dependency for v0.10.0 --- Gopkg.lock | 8 ++++---- Gopkg.toml | 2 +- store/iavlstore.go | 16 ++++++++-------- store/iavlstore_test.go | 12 ++++++------ store/prefixstore_test.go | 2 +- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 5e40c17e6c..5edc19816d 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -415,12 +415,12 @@ version = "v0.12.0-rc0" [[projects]] - digest = "1:d4a15d404afbf591e8be16fcda7f5ac87948d5c7531f9d909fd84cc730ab16e2" + digest = "1:e99ef92d64f2391efbbfb15310df635f96247532bbac2676ea43e466d706401d" name = "github.com/tendermint/iavl" packages = ["."] pruneopts = "UT" - revision = "35f66e53d9b01e83b30de68b931f54b2477a94c9" - version = "v0.9.2" + revision = "e5726c0066ccdd299a2ec9262f93c7896cdfcd87" + version = "v0.10.0" [[projects]] digest = "1:4f15e95fe3888cc75dd34f407d6394cbc7fd3ff24920851b92b295f6a8b556e6" @@ -579,7 +579,7 @@ [[projects]] branch = "master" - digest = "1:077c1c599507b3b3e9156d17d36e1e61928ee9b53a5b420f10f28ebd4a0b275c" + digest = "1:601e63e7d4577f907118bec825902505291918859d223bce015539e79f1160e3" name = "google.golang.org/genproto" packages = ["googleapis/rpc/status"] pruneopts = "UT" diff --git a/Gopkg.toml b/Gopkg.toml index 4368699b6b..f8194ccd01 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -53,7 +53,7 @@ [[override]] name = "github.com/tendermint/iavl" - version = "=v0.9.2" + version = "=v0.10.0" [[override]] name = "github.com/tendermint/tendermint" diff --git a/store/iavlstore.go b/store/iavlstore.go index daffa7dd55..57c1032384 100644 --- a/store/iavlstore.go +++ b/store/iavlstore.go @@ -20,7 +20,7 @@ const ( // load the iavl store func LoadIAVLStore(db dbm.DB, id CommitID, pruning sdk.PruningStrategy) (CommitStore, error) { - tree := iavl.NewVersionedTree(db, defaultIAVLCacheSize) + tree := iavl.NewMutableTree(db, defaultIAVLCacheSize) _, err := tree.LoadVersion(id.Version) if err != nil { return nil, err @@ -40,7 +40,7 @@ var _ Queryable = (*iavlStore)(nil) type iavlStore struct { // The underlying tree. - tree *iavl.VersionedTree + tree *iavl.MutableTree // How many old versions we hold onto. // A value of 0 means keep no recent states. @@ -56,7 +56,7 @@ type iavlStore struct { } // CONTRACT: tree should be fully loaded. -func newIAVLStore(tree *iavl.VersionedTree, numRecent int64, storeEvery int64) *iavlStore { +func newIAVLStore(tree *iavl.MutableTree, numRecent int64, storeEvery int64) *iavlStore { st := &iavlStore{ tree: tree, numRecent: numRecent, @@ -167,16 +167,16 @@ func (st *iavlStore) Gas(meter GasMeter, config GasConfig) KVStore { // Implements KVStore. func (st *iavlStore) Iterator(start, end []byte) Iterator { - return newIAVLIterator(st.tree.Tree(), start, end, true) + return newIAVLIterator(st.tree.ImmutableTree, start, end, true) } // Implements KVStore. func (st *iavlStore) ReverseIterator(start, end []byte) Iterator { - return newIAVLIterator(st.tree.Tree(), start, end, false) + return newIAVLIterator(st.tree.ImmutableTree, start, end, false) } // Handle gatest the latest height, if height is 0 -func getHeight(tree *iavl.VersionedTree, req abci.RequestQuery) int64 { +func getHeight(tree *iavl.MutableTree, req abci.RequestQuery) int64 { height := req.Height if height == 0 { latest := tree.Version64() @@ -255,7 +255,7 @@ func (st *iavlStore) Query(req abci.RequestQuery) (res abci.ResponseQuery) { // Implements Iterator. type iavlIterator struct { // Underlying store - tree *iavl.Tree + tree *iavl.ImmutableTree // Domain start, end []byte @@ -286,7 +286,7 @@ var _ Iterator = (*iavlIterator)(nil) // newIAVLIterator will create a new iavlIterator. // CONTRACT: Caller must release the iavlIterator, as each one creates a new // goroutine. -func newIAVLIterator(tree *iavl.Tree, start, end []byte, ascending bool) *iavlIterator { +func newIAVLIterator(tree *iavl.ImmutableTree, start, end []byte, ascending bool) *iavlIterator { iter := &iavlIterator{ tree: tree, start: cp(start), diff --git a/store/iavlstore_test.go b/store/iavlstore_test.go index 793089a26e..c200a63d4a 100644 --- a/store/iavlstore_test.go +++ b/store/iavlstore_test.go @@ -29,8 +29,8 @@ var ( ) // make a tree and save it -func newTree(t *testing.T, db dbm.DB) (*iavl.VersionedTree, CommitID) { - tree := iavl.NewVersionedTree(db, cacheSize) +func newTree(t *testing.T, db dbm.DB) (*iavl.MutableTree, CommitID) { + tree := iavl.NewMutableTree(db, cacheSize) for k, v := range treeData { tree.Set([]byte(k), []byte(v)) } @@ -325,7 +325,7 @@ type pruneState struct { func testPruning(t *testing.T, numRecent int64, storeEvery int64, states []pruneState) { db := dbm.NewMemDB() - tree := iavl.NewVersionedTree(db, cacheSize) + tree := iavl.NewMutableTree(db, cacheSize) iavlStore := newIAVLStore(tree, numRecent, storeEvery) for step, state := range states { for _, ver := range state.stored { @@ -344,7 +344,7 @@ func testPruning(t *testing.T, numRecent int64, storeEvery int64, states []prune func TestIAVLNoPrune(t *testing.T) { db := dbm.NewMemDB() - tree := iavl.NewVersionedTree(db, cacheSize) + tree := iavl.NewMutableTree(db, cacheSize) iavlStore := newIAVLStore(tree, numRecent, int64(1)) nextVersion(iavlStore) for i := 1; i < 100; i++ { @@ -359,7 +359,7 @@ func TestIAVLNoPrune(t *testing.T) { func TestIAVLPruneEverything(t *testing.T) { db := dbm.NewMemDB() - tree := iavl.NewVersionedTree(db, cacheSize) + tree := iavl.NewMutableTree(db, cacheSize) iavlStore := newIAVLStore(tree, int64(0), int64(0)) nextVersion(iavlStore) for i := 1; i < 100; i++ { @@ -377,7 +377,7 @@ func TestIAVLPruneEverything(t *testing.T) { func TestIAVLStoreQuery(t *testing.T) { db := dbm.NewMemDB() - tree := iavl.NewVersionedTree(db, cacheSize) + tree := iavl.NewMutableTree(db, cacheSize) iavlStore := newIAVLStore(tree, numRecent, storeEvery) k1, v1 := []byte("key1"), []byte("val1") diff --git a/store/prefixstore_test.go b/store/prefixstore_test.go index ff37b27d47..49bc68037a 100644 --- a/store/prefixstore_test.go +++ b/store/prefixstore_test.go @@ -66,7 +66,7 @@ func testPrefixStore(t *testing.T, baseStore KVStore, prefix []byte) { func TestIAVLStorePrefix(t *testing.T) { db := dbm.NewMemDB() - tree := iavl.NewVersionedTree(db, cacheSize) + tree := iavl.NewMutableTree(db, cacheSize) iavlStore := newIAVLStore(tree, numRecent, storeEvery) testPrefixStore(t, iavlStore, []byte("test")) From b83e6e8b1aa21422a27533da949bed6b587809e9 Mon Sep 17 00:00:00 2001 From: Jeremiah Andrews Date: Mon, 20 Aug 2018 22:15:58 -0700 Subject: [PATCH 38/93] Add to pending changelog --- PENDING.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/PENDING.md b/PENDING.md index 17616ced1a..00e609039f 100644 --- a/PENDING.md +++ b/PENDING.md @@ -1,4 +1,17 @@ -## PENDING +## v0.24.1 PENDING + +BREAKING CHANGES + +FEATURES + +IMPROVEMENTS + +* [store] \#1952 Update IAVL dependency to v0.10.0 + +BUG FIXES + +## v0.24.0 PENDING +^--- PENDING wasn't purged on sdk v0.23.0 release. BREAKING CHANGES From bd227ec6dbca3623a72f382ffe9053b80ab325cb Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Tue, 21 Aug 2018 15:53:44 +0200 Subject: [PATCH 39/93] dep ensure -v -update --- Gopkg.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 5edc19816d..2245223419 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -552,7 +552,7 @@ "unix", ] pruneopts = "UT" - revision = "11551d06cbcc94edc80a0facaccbda56473c19c1" + revision = "4ea2f632f6e912459fe60b26b1749377f0d889d5" [[projects]] digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" @@ -579,7 +579,7 @@ [[projects]] branch = "master" - digest = "1:601e63e7d4577f907118bec825902505291918859d223bce015539e79f1160e3" + digest = "1:077c1c599507b3b3e9156d17d36e1e61928ee9b53a5b420f10f28ebd4a0b275c" name = "google.golang.org/genproto" packages = ["googleapis/rpc/status"] pruneopts = "UT" From 3ac55b589dfd7b5b22135451c41b2fa84017f016 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 29 Aug 2018 15:08:04 +0200 Subject: [PATCH 40/93] Update testcase from merge --- store/iavlstore_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store/iavlstore_test.go b/store/iavlstore_test.go index c200a63d4a..49793d3766 100644 --- a/store/iavlstore_test.go +++ b/store/iavlstore_test.go @@ -468,7 +468,7 @@ func TestIAVLStoreQuery(t *testing.T) { func BenchmarkIAVLIteratorNext(b *testing.B) { db := dbm.NewMemDB() treeSize := 1000 - tree := iavl.NewVersionedTree(db, cacheSize) + tree := iavl.NewMutableTree(db, cacheSize) for i := 0; i < treeSize; i++ { key := cmn.RandBytes(4) value := cmn.RandBytes(50) From 2378e3431c050d4763a7d362a71f07b98ce1d532 Mon Sep 17 00:00:00 2001 From: Jeremiah Andrews Date: Fri, 31 Aug 2018 15:22:37 -0700 Subject: [PATCH 41/93] Fix linter errors --- baseapp/baseapp.go | 1 + baseapp/baseapp_test.go | 4 ++-- client/context/query.go | 4 +++- cmd/cosmos-sdk-cli/cmd/init.go | 3 +++ examples/democoin/x/assoc/validator_set.go | 3 +++ server/init.go | 1 + server/start.go | 1 + store/iavlstore.go | 1 + store/multistoreproof_test.go | 8 +++++--- store/tracekvstore.go | 1 + store/tracekvstore_test.go | 8 ++++---- tests/gobash.go | 1 + types/account.go | 3 +++ types/context.go | 1 + types/errors.go | 1 + x/auth/client/cli/account.go | 1 + x/gov/depositsvotes.go | 1 + x/gov/keeper.go | 6 ++++++ x/gov/proposals.go | 2 ++ x/gov/queryable.go | 7 +++++++ x/gov/simulation/msgs.go | 1 + x/ibc/client/cli/relay.go | 1 + x/mock/app.go | 2 ++ x/mock/simulation/random_simulate_blocks.go | 1 + x/params/keeper.go | 1 + x/params/msg_status.go | 1 + x/slashing/client/rest/query.go | 1 + x/slashing/keeper_test.go | 10 +++++----- x/stake/client/rest/utils.go | 1 + x/stake/handler_test.go | 2 +- x/stake/keeper/key.go | 1 + x/stake/keeper/slash.go | 1 + x/stake/keeper/validator.go | 2 ++ x/stake/simulation/invariants.go | 1 + x/stake/simulation/msgs.go | 1 + x/stake/types/delegation_test.go | 4 ++-- 36 files changed, 71 insertions(+), 18 deletions(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 60c694ff76..5552ff7847 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -345,6 +345,7 @@ func handleQueryStore(app *BaseApp, path []string, req abci.RequestQuery) (res a return queryable.Query(req) } +// nolint: unparam func handleQueryP2P(app *BaseApp, path []string, req abci.RequestQuery) (res abci.ResponseQuery) { // "/p2p" prefix for p2p queries if len(path) >= 4 { diff --git a/baseapp/baseapp_test.go b/baseapp/baseapp_test.go index 04e47214dd..b871627862 100644 --- a/baseapp/baseapp_test.go +++ b/baseapp/baseapp_test.go @@ -626,12 +626,12 @@ func TestSimulateTx(t *testing.T) { // simulate a message, check gas reported result := app.Simulate(tx) require.True(t, result.IsOK(), result.Log) - require.Equal(t, int64(gasConsumed), result.GasUsed) + require.Equal(t, gasConsumed, result.GasUsed) // simulate again, same result result = app.Simulate(tx) require.True(t, result.IsOK(), result.Log) - require.Equal(t, int64(gasConsumed), result.GasUsed) + require.Equal(t, gasConsumed, result.GasUsed) // simulate by calling Query with encoded tx txBytes, err := codec.MarshalBinary(tx) diff --git a/client/context/query.go b/client/context/query.go index 4c1cad8777..33610bc15b 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -10,6 +10,8 @@ import ( "github.com/pkg/errors" + "strings" + "github.com/cosmos/cosmos-sdk/store" "github.com/cosmos/cosmos-sdk/wire" abci "github.com/tendermint/tendermint/abci/types" @@ -17,7 +19,6 @@ import ( tmliteProxy "github.com/tendermint/tendermint/lite/proxy" rpcclient "github.com/tendermint/tendermint/rpc/client" ctypes "github.com/tendermint/tendermint/rpc/core/types" - "strings" ) // GetNode returns an RPC client. If the context's client is not defined, an @@ -323,6 +324,7 @@ func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, err erro } // verifyProof perform response proof verification +// nolint: unparam func (ctx CLIContext) verifyProof(path string, resp abci.ResponseQuery) error { if ctx.Certifier == nil { diff --git a/cmd/cosmos-sdk-cli/cmd/init.go b/cmd/cosmos-sdk-cli/cmd/init.go index 8cebc48f29..e9e9cd8a92 100644 --- a/cmd/cosmos-sdk-cli/cmd/init.go +++ b/cmd/cosmos-sdk-cli/cmd/init.go @@ -60,6 +60,7 @@ func resolveProjectPath(remoteProjectPath string) string { return gopath + string(os.PathSeparator) + "src" + string(os.PathSeparator) + remoteProjectPath } +// nolint: unparam, errcheck func copyBasecoinTemplate(projectName string, projectPath string, remoteProjectPath string) { basecoinProjectPath := resolveProjectPath(remoteBasecoinPath) filepath.Walk(basecoinProjectPath, func(path string, f os.FileInfo, err error) error { @@ -88,6 +89,7 @@ func copyBasecoinTemplate(projectName string, projectPath string, remoteProjectP }) } +// nolint: errcheck func createGopkg(projectPath string) { // Create gopkg.toml file dependencies := map[string]string{ @@ -111,6 +113,7 @@ func createGopkg(projectPath string) { ioutil.WriteFile(projectPath+"/Gopkg.toml", []byte(contents), os.ModePerm) } +// nolint: errcheck func createMakefile(projectPath string) { // Create makefile // TODO: Should we use tools/ directory as in Cosmos-SDK to get tools for linting etc. diff --git a/examples/democoin/x/assoc/validator_set.go b/examples/democoin/x/assoc/validator_set.go index 8a954c7203..7515e1ad60 100644 --- a/examples/democoin/x/assoc/validator_set.go +++ b/examples/democoin/x/assoc/validator_set.go @@ -62,6 +62,7 @@ func GetAssocKey(base sdk.ValAddress, assoc sdk.ValAddress) []byte { } // Associate associates new address with validator address +// nolint: unparam func (valset ValidatorSet) Associate(ctx sdk.Context, base sdk.ValAddress, assoc sdk.ValAddress) bool { if len(base) != valset.addrLen || len(assoc) != valset.addrLen { return false @@ -76,6 +77,7 @@ func (valset ValidatorSet) Associate(ctx sdk.Context, base sdk.ValAddress, assoc } // Dissociate removes association between addresses +// nolint: unparam func (valset ValidatorSet) Dissociate(ctx sdk.Context, base sdk.ValAddress, assoc sdk.ValAddress) bool { if len(base) != valset.addrLen || len(assoc) != valset.addrLen { return false @@ -90,6 +92,7 @@ func (valset ValidatorSet) Dissociate(ctx sdk.Context, base sdk.ValAddress, asso } // Associations returns all associated addresses with a validator +// nolint: unparam func (valset ValidatorSet) Associations(ctx sdk.Context, base sdk.ValAddress) (res []sdk.ValAddress) { res = make([]sdk.ValAddress, valset.maxAssoc) iter := sdk.KVStorePrefixIterator(valset.store, GetAssocPrefix(base)) diff --git a/server/init.go b/server/init.go index 105325e0d5..ffe2b6eddc 100644 --- a/server/init.go +++ b/server/init.go @@ -344,6 +344,7 @@ func readOrCreatePrivValidator(tmConfig *cfg.Config) crypto.PubKey { // writeGenesisFile creates and writes the genesis configuration to disk. An // error is returned if building or writing the configuration to file fails. +// nolint: unparam func writeGenesisFile(cdc *wire.Codec, genesisFile, chainID string, validators []tmtypes.GenesisValidator, appState json.RawMessage) error { genDoc := tmtypes.GenesisDoc{ ChainID: chainID, diff --git a/server/start.go b/server/start.go index 8f369d517f..829e393639 100644 --- a/server/start.go +++ b/server/start.go @@ -84,6 +84,7 @@ func startStandAlone(ctx *Context, appCreator AppCreator) error { return nil } +// nolint: unparam func startInProcess(ctx *Context, appCreator AppCreator) (*node.Node, error) { cfg := ctx.Config home := cfg.RootDir diff --git a/store/iavlstore.go b/store/iavlstore.go index 57c1032384..61bdc56307 100644 --- a/store/iavlstore.go +++ b/store/iavlstore.go @@ -56,6 +56,7 @@ type iavlStore struct { } // CONTRACT: tree should be fully loaded. +// nolint: unparam func newIAVLStore(tree *iavl.MutableTree, numRecent int64, storeEvery int64) *iavlStore { st := &iavlStore{ tree: tree, diff --git a/store/multistoreproof_test.go b/store/multistoreproof_test.go index b4e8a84b16..790588fb29 100644 --- a/store/multistoreproof_test.go +++ b/store/multistoreproof_test.go @@ -2,10 +2,12 @@ package store import ( "encoding/hex" + "testing" + "github.com/stretchr/testify/assert" "github.com/tendermint/iavl" cmn "github.com/tendermint/tendermint/libs/common" - "testing" + "github.com/tendermint/tendermint/libs/db" ) func TestVerifyMultiStoreCommitInfo(t *testing.T) { @@ -91,7 +93,7 @@ func TestVerifyMultiStoreCommitInfo(t *testing.T) { } func TestVerifyRangeProof(t *testing.T) { - tree := iavl.NewTree(nil, 0) + tree := iavl.NewMutableTree(db.NewMemDB(), 0) rand := cmn.NewRand() rand.Seed(0) // for determinism @@ -100,7 +102,7 @@ func TestVerifyRangeProof(t *testing.T) { tree.Set(key, []byte(rand.Str(8))) } - root := tree.Hash() + root := tree.WorkingHash() key := []byte{0x32} val, proof, err := tree.GetWithProof(key) diff --git a/store/tracekvstore.go b/store/tracekvstore.go index 0224e8c123..d8c34c3545 100644 --- a/store/tracekvstore.go +++ b/store/tracekvstore.go @@ -179,6 +179,7 @@ func (tkv *TraceKVStore) CacheWrapWithTrace(_ io.Writer, _ TraceContext) CacheWr // writeOperation writes a KVStore operation to the underlying io.Writer as // JSON-encoded data where the key/value pair is base64 encoded. +// nolint: errcheck func writeOperation(w io.Writer, op operation, tc TraceContext, key, value []byte) { traceOp := traceOperation{ Operation: op, diff --git a/store/tracekvstore_test.go b/store/tracekvstore_test.go index 2182c52886..887fcf96e5 100644 --- a/store/tracekvstore_test.go +++ b/store/tracekvstore_test.go @@ -156,8 +156,8 @@ func TestTestTraceKVStoreIterator(t *testing.T) { iterator := store.Iterator(nil, nil) s, e := iterator.Domain() - require.Equal(t, []uint8([]byte(nil)), s) - require.Equal(t, []uint8([]byte(nil)), e) + require.Equal(t, []byte(nil), s) + require.Equal(t, []byte(nil), e) testCases := []struct { expectedKey []byte @@ -212,8 +212,8 @@ func TestTestTraceKVStoreReverseIterator(t *testing.T) { iterator := store.ReverseIterator(nil, nil) s, e := iterator.Domain() - require.Equal(t, []uint8([]byte(nil)), s) - require.Equal(t, []uint8([]byte(nil)), e) + require.Equal(t, []byte(nil), s) + require.Equal(t, []byte(nil), e) testCases := []struct { expectedKey []byte diff --git a/tests/gobash.go b/tests/gobash.go index 11f4407f23..6282f2fda4 100644 --- a/tests/gobash.go +++ b/tests/gobash.go @@ -13,6 +13,7 @@ import ( // ExecuteT executes the command, pipes any input to STDIN and return STDOUT, // logging STDOUT/STDERR to t. +// nolint: errcheck func ExecuteT(t *testing.T, cmd, input string) (out string) { t.Log("Running", cmn.Cyan(cmd)) diff --git a/types/account.go b/types/account.go index 429cbf2857..943867d79b 100644 --- a/types/account.go +++ b/types/account.go @@ -133,6 +133,7 @@ func (aa AccAddress) String() string { } // Format implements the fmt.Formatter interface. +// nolint: errcheck func (aa AccAddress) Format(s fmt.State, verb rune) { switch verb { case 's': @@ -247,6 +248,7 @@ func (va ValAddress) String() string { } // Format implements the fmt.Formatter interface. +// nolint: errcheck func (va ValAddress) Format(s fmt.State, verb rune) { switch verb { case 's': @@ -361,6 +363,7 @@ func (ca ConsAddress) String() string { } // Format implements the fmt.Formatter interface. +// nolint: errcheck func (ca ConsAddress) Format(s fmt.State, verb rune) { switch verb { case 's': diff --git a/types/context.go b/types/context.go index 44b0474e8b..85fb16a7ff 100644 --- a/types/context.go +++ b/types/context.go @@ -30,6 +30,7 @@ type Context struct { } // create a new context +// nolint: unparam func NewContext(ms MultiStore, header abci.Header, isCheckTx bool, logger log.Logger) Context { c := Context{ Context: context.Background(), diff --git a/types/errors.go b/types/errors.go index 45ef79f56a..c72933d605 100644 --- a/types/errors.go +++ b/types/errors.go @@ -219,6 +219,7 @@ func (err *sdkError) WithDefaultCodespace(cs CodespaceType) Error { } // Implements ABCIError. +// nolint: errcheck func (err *sdkError) TraceSDK(format string, args ...interface{}) Error { err.Trace(1, format, args...) return err diff --git a/x/auth/client/cli/account.go b/x/auth/client/cli/account.go index 3b93798a0d..6f63592882 100644 --- a/x/auth/client/cli/account.go +++ b/x/auth/client/cli/account.go @@ -30,6 +30,7 @@ func GetAccountDecoder(cdc *wire.Codec) auth.AccountDecoder { // GetAccountCmd returns a query account that will display the state of the // account at a given address. +// nolint: unparam func GetAccountCmd(storeName string, cdc *wire.Codec, decoder auth.AccountDecoder) *cobra.Command { return &cobra.Command{ Use: "account [address]", diff --git a/x/gov/depositsvotes.go b/x/gov/depositsvotes.go index b5c65931fc..d1179023fa 100644 --- a/x/gov/depositsvotes.go +++ b/x/gov/depositsvotes.go @@ -132,6 +132,7 @@ func (vo VoteOption) String() string { } // For Printf / Sprintf, returns bech32 when using %s +// nolint: errcheck func (vo VoteOption) Format(s fmt.State, verb rune) { switch verb { case 's': diff --git a/x/gov/keeper.go b/x/gov/keeper.go index e8dbbc4a7f..576d2cc22f 100644 --- a/x/gov/keeper.go +++ b/x/gov/keeper.go @@ -210,6 +210,7 @@ func (keeper Keeper) activateVotingPeriod(ctx sdk.Context, proposal Proposal) { // Procedures // Returns the current Deposit Procedure from the global param store +// nolint: errcheck func (keeper Keeper) GetDepositProcedure(ctx sdk.Context) DepositProcedure { var depositProcedure DepositProcedure keeper.ps.Get(ctx, ParamStoreKeyDepositProcedure, &depositProcedure) @@ -217,6 +218,7 @@ func (keeper Keeper) GetDepositProcedure(ctx sdk.Context) DepositProcedure { } // Returns the current Voting Procedure from the global param store +// nolint: errcheck func (keeper Keeper) GetVotingProcedure(ctx sdk.Context) VotingProcedure { var votingProcedure VotingProcedure keeper.ps.Get(ctx, ParamStoreKeyVotingProcedure, &votingProcedure) @@ -224,20 +226,24 @@ func (keeper Keeper) GetVotingProcedure(ctx sdk.Context) VotingProcedure { } // Returns the current Tallying Procedure from the global param store +// nolint: errcheck func (keeper Keeper) GetTallyingProcedure(ctx sdk.Context) TallyingProcedure { var tallyingProcedure TallyingProcedure keeper.ps.Get(ctx, ParamStoreKeyTallyingProcedure, &tallyingProcedure) return tallyingProcedure } +// nolint: errcheck func (keeper Keeper) setDepositProcedure(ctx sdk.Context, depositProcedure DepositProcedure) { keeper.ps.Set(ctx, ParamStoreKeyDepositProcedure, &depositProcedure) } +// nolint: errcheck func (keeper Keeper) setVotingProcedure(ctx sdk.Context, votingProcedure VotingProcedure) { keeper.ps.Set(ctx, ParamStoreKeyVotingProcedure, &votingProcedure) } +// nolint: errcheck func (keeper Keeper) setTallyingProcedure(ctx sdk.Context, tallyingProcedure TallyingProcedure) { keeper.ps.Set(ctx, ParamStoreKeyTallyingProcedure, &tallyingProcedure) } diff --git a/x/gov/proposals.go b/x/gov/proposals.go index c52ab1e875..b4c6783673 100644 --- a/x/gov/proposals.go +++ b/x/gov/proposals.go @@ -187,6 +187,7 @@ func (pt ProposalKind) String() string { } // For Printf / Sprintf, returns bech32 when using %s +// nolint: errcheck func (pt ProposalKind) Format(s fmt.State, verb rune) { switch verb { case 's': @@ -289,6 +290,7 @@ func (status ProposalStatus) String() string { } // For Printf / Sprintf, returns bech32 when using %s +// nolint: errcheck func (status ProposalStatus) Format(s fmt.State, verb rune) { switch verb { case 's': diff --git a/x/gov/queryable.go b/x/gov/queryable.go index e64d506d1e..090b9a9145 100644 --- a/x/gov/queryable.go +++ b/x/gov/queryable.go @@ -36,6 +36,7 @@ type QueryProposalParams struct { ProposalID int64 } +// nolint: unparam func queryProposal(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) { var params QueryProposalParams err2 := keeper.cdc.UnmarshalJSON(req.Data, ¶ms) @@ -61,6 +62,7 @@ type QueryDepositParams struct { Depositer sdk.AccAddress } +// nolint: unparam func queryDeposit(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) { var params QueryDepositParams err2 := keeper.cdc.UnmarshalJSON(req.Data, ¶ms) @@ -82,6 +84,7 @@ type QueryVoteParams struct { Voter sdk.AccAddress } +// nolint: unparam func queryVote(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) { var params QueryVoteParams err2 := keeper.cdc.UnmarshalJSON(req.Data, ¶ms) @@ -102,6 +105,7 @@ type QueryDepositsParams struct { ProposalID int64 } +// nolint: unparam func queryDeposits(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) { var params QueryDepositParams err2 := keeper.cdc.UnmarshalJSON(req.Data, ¶ms) @@ -129,6 +133,7 @@ type QueryVotesParams struct { ProposalID int64 } +// nolint: unparam func queryVotes(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) { var params QueryVotesParams err2 := keeper.cdc.UnmarshalJSON(req.Data, ¶ms) @@ -160,6 +165,7 @@ type QueryProposalsParams struct { NumLatestProposals int64 } +// nolint: unparam func queryProposals(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) { var params QueryProposalsParams err2 := keeper.cdc.UnmarshalJSON(req.Data, ¶ms) @@ -181,6 +187,7 @@ type QueryTallyParams struct { ProposalID int64 } +// nolint: unparam func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) { // TODO: Dependant on #1914 diff --git a/x/gov/simulation/msgs.go b/x/gov/simulation/msgs.go index eca8accae0..13e537efad 100644 --- a/x/gov/simulation/msgs.go +++ b/x/gov/simulation/msgs.go @@ -86,6 +86,7 @@ func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation { } // SimulateMsgVote +// nolint: unparam func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.Operation { return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { key := simulation.RandomKey(r, keys) diff --git a/x/ibc/client/cli/relay.go b/x/ibc/client/cli/relay.go index 92b03a66fc..37479980c5 100644 --- a/x/ibc/client/cli/relay.go +++ b/x/ibc/client/cli/relay.go @@ -163,6 +163,7 @@ func query(node string, key []byte, storeName string) (res []byte, err error) { return context.NewCLIContext().WithNodeURI(node).QueryStore(key, storeName) } +// nolint: unparam func (c relayCommander) broadcastTx(seq int64, node string, tx []byte) error { _, err := context.NewCLIContext().WithNodeURI(node).BroadcastTx(tx) return err diff --git a/x/mock/app.go b/x/mock/app.go index f472c5531c..97068a3a51 100644 --- a/x/mock/app.go +++ b/x/mock/app.go @@ -86,6 +86,7 @@ func (app *App) CompleteSetup(newKeys []*sdk.KVStoreKey) error { } // InitChainer performs custom logic for initialization. +// nolint: errcheck func (app *App) InitChainer(ctx sdk.Context, _ abci.RequestInitChain) abci.ResponseInitChain { // Load the genesis accounts for _, genacc := range app.GenesisAccounts { @@ -207,6 +208,7 @@ func GeneratePrivKeyAddressPairsFromRand(rand *rand.Rand, n int) (keys []crypto. // RandomSetGenesis set genesis accounts with random coin values using the // provided addresses and coin denominations. +// nolint: errcheck func RandomSetGenesis(r *rand.Rand, app *App, addrs []sdk.AccAddress, denoms []string) { accts := make([]auth.Account, len(addrs), len(addrs)) randCoinIntervals := []BigInterval{ diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index fc7543280a..11c3dbd6a3 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -243,6 +243,7 @@ func getKeys(validators map[string]mockValidator) []string { } // RandomRequestBeginBlock generates a list of signing validators according to the provided list of validators, signing fraction, and evidence fraction +// nolint: unparam func RandomRequestBeginBlock(r *rand.Rand, validators map[string]mockValidator, livenessTransitions TransitionMatrix, evidenceFraction float64, pastTimes []time.Time, pastSigningValidators [][]abci.SigningValidator, event func(string), header abci.Header, log string) abci.RequestBeginBlock { if len(validators) == 0 { diff --git a/x/params/keeper.go b/x/params/keeper.go index 69bcc05ea8..7fd9bb3c9c 100644 --- a/x/params/keeper.go +++ b/x/params/keeper.go @@ -23,6 +23,7 @@ func NewKeeper(cdc *wire.Codec, key sdk.StoreKey) Keeper { } // InitKeeper constructs a new Keeper with initial parameters +// nolint: errcheck func InitKeeper(ctx sdk.Context, cdc *wire.Codec, key sdk.StoreKey, params ...interface{}) Keeper { if len(params)%2 != 0 { panic("Odd params list length for InitKeeper") diff --git a/x/params/msg_status.go b/x/params/msg_status.go index 7f9197c5c1..a8516a85b7 100644 --- a/x/params/msg_status.go +++ b/x/params/msg_status.go @@ -15,6 +15,7 @@ func ActivatedParamKey(ty string) string { } // InitGenesis stores activated type to param store +// nolint: errcheck func InitGenesis(ctx sdk.Context, k Keeper, data GenesisState) { for _, ty := range data.ActivatedTypes { k.set(ctx, ActivatedParamKey(ty), true) diff --git a/x/slashing/client/rest/query.go b/x/slashing/client/rest/query.go index 78c4a2d2f8..0ebe13250f 100644 --- a/x/slashing/client/rest/query.go +++ b/x/slashing/client/rest/query.go @@ -19,6 +19,7 @@ func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *wire.Cod } // http request handler to query signing info +// nolint: unparam func signingInfoHandlerFn(cliCtx context.CLIContext, storeName string, cdc *wire.Codec) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index c0932acf42..0eb67bfb6b 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -165,7 +165,7 @@ func TestHandleAbsentValidator(t *testing.T) { validator, _ := sk.GetValidatorByPubKey(ctx, val) require.Equal(t, sdk.Bonded, validator.GetStatus()) pool := sk.GetPool(ctx) - require.Equal(t, int64(amtInt), pool.BondedTokens.RoundInt64()) + require.Equal(t, amtInt, pool.BondedTokens.RoundInt64()) // 501st block missed ctx = ctx.WithBlockHeight(height) @@ -195,7 +195,7 @@ func TestHandleAbsentValidator(t *testing.T) { // validator should have been slashed pool = sk.GetPool(ctx) slashAmt := sdk.NewDec(amtInt).Mul(keeper.SlashFractionDowntime(ctx)).RoundInt64() - require.Equal(t, int64(amtInt)-slashAmt, pool.BondedTokens.RoundInt64()) + require.Equal(t, amtInt-slashAmt, pool.BondedTokens.RoundInt64()) // validator start height should have been changed info, found = keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) @@ -252,7 +252,7 @@ func TestHandleNewValidator(t *testing.T) { info, found := keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) require.True(t, found) - require.Equal(t, int64(keeper.SignedBlocksWindow(ctx)+1), info.StartHeight) + require.Equal(t, keeper.SignedBlocksWindow(ctx)+1, info.StartHeight) require.Equal(t, int64(2), info.IndexOffset) require.Equal(t, int64(1), info.SignedBlocksCounter) require.Equal(t, time.Unix(0, 0).UTC(), info.JailedUntil) @@ -296,7 +296,7 @@ func TestHandleAlreadyJailed(t *testing.T) { require.Equal(t, sdk.Unbonding, validator.GetStatus()) // validator should have been slashed - require.Equal(t, int64(amtInt-1), validator.GetTokens().RoundInt64()) + require.Equal(t, amtInt-1, validator.GetTokens().RoundInt64()) // another block missed ctx = ctx.WithBlockHeight(height) @@ -304,6 +304,6 @@ func TestHandleAlreadyJailed(t *testing.T) { // validator should not have been slashed twice validator, _ = sk.GetValidatorByPubKey(ctx, val) - require.Equal(t, int64(amtInt-1), validator.GetTokens().RoundInt64()) + require.Equal(t, amtInt-1, validator.GetTokens().RoundInt64()) } diff --git a/x/stake/client/rest/utils.go b/x/stake/client/rest/utils.go index 171ded2b35..d8ad5fec55 100644 --- a/x/stake/client/rest/utils.go +++ b/x/stake/client/rest/utils.go @@ -163,6 +163,7 @@ func getValidators(validatorKVs []sdk.KVPair, cdc *wire.Codec) ([]types.BechVali } // gets all Bech32 validators from a key +// nolint: unparam func getBech32Validators(storeName string, cliCtx context.CLIContext, cdc *wire.Codec) ( validators []types.BechValidator, httpStatusCode int, errMsg string, err error) { diff --git a/x/stake/handler_test.go b/x/stake/handler_test.go index 68c342fd87..a733b7f156 100644 --- a/x/stake/handler_test.go +++ b/x/stake/handler_test.go @@ -430,7 +430,7 @@ func TestIncrementsMsgUnbond(t *testing.T) { initBond, } for _, c := range errorCases { - unbondShares := sdk.NewDec(int64(c)) + unbondShares := sdk.NewDec(c) msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) require.False(t, got.IsOK(), "expected unbond msg to fail") diff --git a/x/stake/keeper/key.go b/x/stake/keeper/key.go index d539c35d05..f3e2967c81 100644 --- a/x/stake/keeper/key.go +++ b/x/stake/keeper/key.go @@ -68,6 +68,7 @@ func GetValidatorsByPowerIndexKey(validator types.Validator, pool types.Pool) [] // get the power ranking of a validator // NOTE the larger values are of higher value +// nolint: unparam func getValidatorPowerRank(validator types.Validator, pool types.Pool) []byte { potentialPower := validator.Tokens diff --git a/x/stake/keeper/slash.go b/x/stake/keeper/slash.go index be26d1a232..e077accb71 100644 --- a/x/stake/keeper/slash.go +++ b/x/stake/keeper/slash.go @@ -203,6 +203,7 @@ func (k Keeper) slashUnbondingDelegation(ctx sdk.Context, unbondingDelegation ty // the unbonding delegation had enough stake to slash // (the amount actually slashed may be less if there's // insufficient stake remaining) +// nolint: unparam func (k Keeper) slashRedelegation(ctx sdk.Context, validator types.Validator, redelegation types.Redelegation, infractionHeight int64, slashFactor sdk.Dec) (slashAmount sdk.Dec) { diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 47a5d5f66f..96719d8607 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -372,6 +372,7 @@ func (k Keeper) updateForJailing(ctx sdk.Context, oldFound bool, oldValidator, n return newValidator } +// nolint: unparam func (k Keeper) getPowerIncreasing(ctx sdk.Context, oldFound bool, oldValidator, newValidator types.Validator) bool { if oldFound && oldValidator.BondedTokens().LT(newValidator.BondedTokens()) { return true @@ -380,6 +381,7 @@ func (k Keeper) getPowerIncreasing(ctx sdk.Context, oldFound bool, oldValidator, } // get the bond height and incremented intra-tx counter +// nolint: unparam func (k Keeper) bondIncrement(ctx sdk.Context, oldFound bool, oldValidator, newValidator types.Validator) (height int64, intraTxCounter int16) { diff --git a/x/stake/simulation/invariants.go b/x/stake/simulation/invariants.go index 859bb05915..8f218f45be 100644 --- a/x/stake/simulation/invariants.go +++ b/x/stake/simulation/invariants.go @@ -25,6 +25,7 @@ func AllInvariants(ck bank.Keeper, k stake.Keeper, am auth.AccountMapper) simula } // SupplyInvariants checks that the total supply reflects all held loose tokens, bonded tokens, and unbonding delegations +// nolint: unparam func SupplyInvariants(ck bank.Keeper, k stake.Keeper, am auth.AccountMapper) simulation.Invariant { return func(t *testing.T, app *baseapp.BaseApp, log string) { ctx := app.NewContext(false, abci.Header{}) diff --git a/x/stake/simulation/msgs.go b/x/stake/simulation/msgs.go index af42dba490..2644601324 100644 --- a/x/stake/simulation/msgs.go +++ b/x/stake/simulation/msgs.go @@ -258,6 +258,7 @@ func SimulateMsgCompleteRedelegate(k stake.Keeper) simulation.Operation { } // Setup +// nolint: errcheck func Setup(mapp *mock.App, k stake.Keeper) simulation.RandSetup { return func(r *rand.Rand, privKeys []crypto.PrivKey) { ctx := mapp.NewContext(false, abci.Header{}) diff --git a/x/stake/types/delegation_test.go b/x/stake/types/delegation_test.go index 8e0dda7e24..e752122571 100644 --- a/x/stake/types/delegation_test.go +++ b/x/stake/types/delegation_test.go @@ -23,7 +23,7 @@ func TestDelegationEqual(t *testing.T) { ok := d1.Equal(d2) require.True(t, ok) - d2.ValidatorAddr = sdk.ValAddress(addr3) + d2.ValidatorAddr = addr3 d2.Shares = sdk.NewDec(200) ok = d1.Equal(d2) @@ -57,7 +57,7 @@ func TestUnbondingDelegationEqual(t *testing.T) { ok := ud1.Equal(ud2) require.True(t, ok) - ud2.ValidatorAddr = sdk.ValAddress(addr3) + ud2.ValidatorAddr = addr3 ud2.MinTime = time.Unix(20*20*2, 0) ok = ud1.Equal(ud2) From 01da56a020dd091c9af8599e52777120989c468b Mon Sep 17 00:00:00 2001 From: Jeremiah Andrews Date: Mon, 3 Sep 2018 08:00:41 -0700 Subject: [PATCH 42/93] Fix pending changelog --- PENDING.md | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/PENDING.md b/PENDING.md index 00e609039f..5e253df300 100644 --- a/PENDING.md +++ b/PENDING.md @@ -1,17 +1,4 @@ -## v0.24.1 PENDING - -BREAKING CHANGES - -FEATURES - -IMPROVEMENTS - -* [store] \#1952 Update IAVL dependency to v0.10.0 - -BUG FIXES - -## v0.24.0 PENDING -^--- PENDING wasn't purged on sdk v0.23.0 release. +## PENDING BREAKING CHANGES @@ -98,6 +85,7 @@ IMPROVEMENTS * [tools] Make get_vendor_deps deletes `.vendor-new` directories, in case scratch files are present. * [cli] \#1632 Add integration tests to ensure `basecoind init && basecoind` start sequences run successfully for both `democoin` and `basecoin` examples. * [store] Speedup IAVL iteration, and consequently everything that requires IAVL iteration. [#2143](https://github.com/cosmos/cosmos-sdk/issues/2143) + * [store] \#1952 Update IAVL dependency to v0.10.0 * [simulation] Make timestamps randomized [#2153](https://github.com/cosmos/cosmos-sdk/pull/2153) * Tendermint From 20f5325f479ca513538dec1ec240379b6f89fbe3 Mon Sep 17 00:00:00 2001 From: Jeremiah Andrews Date: Mon, 3 Sep 2018 09:47:24 -0700 Subject: [PATCH 43/93] Fix more linter errors --- x/mock/simulation/random_simulate_blocks.go | 2 ++ x/slashing/handler_test.go | 8 +++---- x/slashing/keeper_test.go | 24 ++++++++++----------- x/slashing/tick_test.go | 4 ++-- 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index 11c3dbd6a3..00b7a7365f 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -209,6 +209,7 @@ func queueOperations(queuedOperations map[int][]Operation, futureOperations []Fu } } +// nolint: errcheck func runQueuedOperations(queueOperations map[int][]Operation, height int, tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, privKeys []crypto.PrivKey, log string, event func(string)) (updatedLog string, numOpsRan int) { updatedLog = log @@ -321,6 +322,7 @@ func AssertAllInvariants(t *testing.T, app *baseapp.BaseApp, tests []Invariant, } // updateValidators mimicks Tendermint's update logic +// nolint: unparam func updateValidators(tb testing.TB, r *rand.Rand, current map[string]mockValidator, updates []abci.Validator, event func(string)) map[string]mockValidator { for _, update := range updates { switch { diff --git a/x/slashing/handler_test.go b/x/slashing/handler_test.go index c5afb87389..9cdcd05334 100644 --- a/x/slashing/handler_test.go +++ b/x/slashing/handler_test.go @@ -16,15 +16,15 @@ func TestCannotUnjailUnlessJailed(t *testing.T) { slh := NewHandler(keeper) amtInt := int64(100) addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) - msg := newTestMsgCreateValidator(sdk.ValAddress(addr), val, amt) + msg := newTestMsgCreateValidator(addr, val, amt) got := stake.NewHandler(sk)(ctx, msg) require.True(t, got.IsOK()) stake.EndBlocker(ctx, sk) require.Equal(t, ck.GetCoins(ctx, sdk.AccAddress(addr)), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}}) - require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, sdk.ValAddress(addr)).GetPower())) + require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower())) // assert non-jailed validator can't be unjailed - got = slh(ctx, NewMsgUnjail(sdk.ValAddress(addr))) + got = slh(ctx, NewMsgUnjail(addr)) require.False(t, got.IsOK(), "allowed unjail of non-jailed validator") require.Equal(t, sdk.ToABCICode(DefaultCodespace, CodeValidatorNotJailed), got.Code) } @@ -39,7 +39,7 @@ func TestJailedValidatorDelegations(t *testing.T) { // create a validator amount := int64(10) valPubKey, bondAmount := pks[0], sdk.NewInt(amount) - valAddr, consAddr := sdk.ValAddress(addrs[1]), sdk.ConsAddress(addrs[0]) + valAddr, consAddr := addrs[1], sdk.ConsAddress(addrs[0]) msgCreateVal := newTestMsgCreateValidator(valAddr, valPubKey, bondAmount) got := stake.NewHandler(stakeKeeper)(ctx, msgCreateVal) diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index 0eb67bfb6b..ff50a594ea 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -27,12 +27,12 @@ func TestHandleDoubleSign(t *testing.T) { sk = sk.WithValidatorHooks(keeper.ValidatorHooks()) amtInt := int64(100) addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) - got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(sdk.ValAddress(addr), val, amt)) + got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt)) require.True(t, got.IsOK()) validatorUpdates := stake.EndBlocker(ctx, sk) keeper.AddValidators(ctx, validatorUpdates) require.Equal(t, ck.GetCoins(ctx, sdk.AccAddress(addr)), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}}) - require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, sdk.ValAddress(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) @@ -41,13 +41,13 @@ func TestHandleDoubleSign(t *testing.T) { keeper.handleDoubleSign(ctx, val.Address(), 0, time.Unix(0, 0), amtInt) // should be jailed - require.True(t, sk.Validator(ctx, sdk.ValAddress(addr)).GetJailed()) + require.True(t, sk.Validator(ctx, addr).GetJailed()) // unjail to measure power sk.Unjail(ctx, val) // power should be reduced require.Equal( t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))), - sk.Validator(ctx, sdk.ValAddress(addr)).GetPower(), + sk.Validator(ctx, addr).GetPower(), ) ctx = ctx.WithBlockHeader(abci.Header{Time: time.Unix(1, 0).Add(keeper.MaxEvidenceAge(ctx))}) @@ -55,7 +55,7 @@ func TestHandleDoubleSign(t *testing.T) { keeper.handleDoubleSign(ctx, val.Address(), 0, time.Unix(0, 0), amtInt) require.Equal( t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))), - sk.Validator(ctx, sdk.ValAddress(addr)).GetPower(), + sk.Validator(ctx, addr).GetPower(), ) } @@ -125,12 +125,12 @@ func TestHandleAbsentValidator(t *testing.T) { addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) sh := stake.NewHandler(sk) slh := NewHandler(keeper) - got := sh(ctx, newTestMsgCreateValidator(sdk.ValAddress(addr), val, amt)) + got := sh(ctx, newTestMsgCreateValidator(addr, val, amt)) require.True(t, got.IsOK()) validatorUpdates := stake.EndBlocker(ctx, sk) keeper.AddValidators(ctx, validatorUpdates) require.Equal(t, ck.GetCoins(ctx, sdk.AccAddress(addr)), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}}) - require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, sdk.ValAddress(addr)).GetPower())) + require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower())) info, found := keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) require.False(t, found) require.Equal(t, int64(0), info.StartHeight) @@ -180,12 +180,12 @@ func TestHandleAbsentValidator(t *testing.T) { require.Equal(t, sdk.Unbonding, validator.GetStatus()) // unrevocation should fail prior to jail expiration - got = slh(ctx, NewMsgUnjail(sdk.ValAddress(addr))) + got = slh(ctx, NewMsgUnjail(addr)) require.False(t, got.IsOK()) // unrevocation should succeed after jail expiration ctx = ctx.WithBlockHeader(abci.Header{Time: time.Unix(1, 0).Add(keeper.DowntimeUnbondDuration(ctx))}) - got = slh(ctx, NewMsgUnjail(sdk.ValAddress(addr))) + got = slh(ctx, NewMsgUnjail(addr)) require.True(t, got.IsOK()) // validator should be rebonded now @@ -235,12 +235,12 @@ func TestHandleNewValidator(t *testing.T) { ctx, ck, sk, _, keeper := createTestInput(t) addr, val, amt := addrs[0], pks[0], int64(100) sh := stake.NewHandler(sk) - got := sh(ctx, newTestMsgCreateValidator(sdk.ValAddress(addr), val, sdk.NewInt(amt))) + got := sh(ctx, newTestMsgCreateValidator(addr, val, sdk.NewInt(amt))) require.True(t, got.IsOK()) validatorUpdates := stake.EndBlocker(ctx, sk) keeper.AddValidators(ctx, validatorUpdates) require.Equal(t, ck.GetCoins(ctx, sdk.AccAddress(addr)), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.SubRaw(amt)}}) - require.Equal(t, sdk.NewDec(amt), sk.Validator(ctx, sdk.ValAddress(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) @@ -273,7 +273,7 @@ func TestHandleAlreadyJailed(t *testing.T) { amtInt := int64(100) addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) sh := stake.NewHandler(sk) - got := sh(ctx, newTestMsgCreateValidator(sdk.ValAddress(addr), val, amt)) + got := sh(ctx, newTestMsgCreateValidator(addr, val, amt)) require.True(t, got.IsOK()) validatorUpdates := stake.EndBlocker(ctx, sk) keeper.AddValidators(ctx, validatorUpdates) diff --git a/x/slashing/tick_test.go b/x/slashing/tick_test.go index 25167578d1..81003a968a 100644 --- a/x/slashing/tick_test.go +++ b/x/slashing/tick_test.go @@ -17,12 +17,12 @@ func TestBeginBlocker(t *testing.T) { addr, pk, amt := addrs[2], pks[2], sdk.NewInt(100) // bond the validator - got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(sdk.ValAddress(addr), pk, amt)) + got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, pk, amt)) require.True(t, got.IsOK()) validatorUpdates := stake.EndBlocker(ctx, sk) keeper.AddValidators(ctx, validatorUpdates) require.Equal(t, ck.GetCoins(ctx, sdk.AccAddress(addr)), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}}) - require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, sdk.ValAddress(addr)).GetPower())) + require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower())) val := abci.Validator{ Address: pk.Address(), From 5c600f2e2b66884723892ba53a0d6f780e2364fe Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 3 Sep 2018 15:49:36 -0400 Subject: [PATCH 44/93] jae comments --- docs/spec/distribution/transactions.md | 45 ++++++++++++++------------ 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/docs/spec/distribution/transactions.md b/docs/spec/distribution/transactions.md index 2ed12d2c32..0b89ae44ee 100644 --- a/docs/spec/distribution/transactions.md +++ b/docs/spec/distribution/transactions.md @@ -1,24 +1,24 @@ # Transactions -## TxWithdrawDelegationRewards +## TxWithdrawDelegationRewardsAll When a delegator wishes to withdraw their rewards it must send -`TxWithdrawDelegationRewards`. Note that parts of this transaction logic are also +`TxWithdrawDelegationRewardsAll`. Note that parts of this transaction logic are also triggered each with any change in individual delegations, such as an unbond, redelegation, or delegation of additional tokens to a specific validator. ```golang -type TxWithdrawDelegationRewards struct { +type TxWithdrawDelegationRewardsAll struct { delegatorAddr sdk.AccAddress withdrawAddr sdk.AccAddress // address to make the withdrawal to } -func WithdrawDelegationRewards(delegatorAddr, withdrawAddr sdk.AccAddress) +func WithdrawDelegationRewardsAll(delegatorAddr, withdrawAddr sdk.AccAddress) height = GetHeight() - withdraw = GetDelegatorAllWithdraws(delegatorAddr, height) + withdraw = GetDelegatorRewardsAll(delegatorAddr, height) AddCoins(withdrawAddr, withdraw.TruncateDecimal()) -func GetDelegatorAllWithdraws(delegatorAddr sdk.AccAddress, height int64) DecCoins +func GetDelegatorRewardsAll(delegatorAddr sdk.AccAddress, height int64) DecCoins // get all distribution scenarios delegations = GetDelegations(delegatorAddr) @@ -72,22 +72,22 @@ func WithdrawDelegationReward(delegatorAddr, validatorAddr, withdrawAddr sdk.Acc ``` -## TxWithdrawValidatorRewards +## TxWithdrawValidatorRewardsAll When a validator wishes to withdraw their rewards it must send -`TxWithdrawValidatorRewards`. Note that parts of this transaction logic are also +`TxWithdrawValidatorRewardsAll`. Note that parts of this transaction logic are also triggered each with any change in individual delegations, such as an unbond, redelegation, or delegation of additional tokens to a specific validator. This transaction withdraws the validators commission fee, as well as any rewards earning on their self-delegation. ``` -type TxWithdrawValidatorRewards struct { +type TxWithdrawValidatorRewardsAll struct { operatorAddr sdk.AccAddress // validator address to withdraw from withdrawAddr sdk.AccAddress // address to make the withdrawal to } -func WithdrawValidatorRewards(operatorAddr, withdrawAddr sdk.AccAddress) +func WithdrawValidatorRewardsAll(operatorAddr, withdrawAddr sdk.AccAddress) height = GetHeight() global = GetGlobal() @@ -96,7 +96,7 @@ func WithdrawValidatorRewards(operatorAddr, withdrawAddr sdk.AccAddress) validator = GetValidator(delegation.ValidatorAddr) // withdraw self-delegation - withdraw = GetDelegatorAllWithdraws(validator.OperatorAddr, height) + withdraw = GetDelegatorRewardsAll(validator.OperatorAddr, height) // withdrawal validator commission rewards global, commission = valInfo.WithdrawCommission(global, valInfo, height, pool.BondedTokens, @@ -117,10 +117,11 @@ block. The accum is always additive to the existing accum. This term is to be updated each time rewards are withdrawn from the system. ``` -func (g Global) UpdateTotalValAccum(height int64, totalBondedTokens Dec) +func (g Global) UpdateTotalValAccum(height int64, totalBondedTokens Dec) Global blocks = height - g.TotalValAccumUpdateHeight g.TotalValAccum += totalDelShares * blocks g.TotalValAccumUpdateHeight = height + return g ``` ### Update validator's accums @@ -132,10 +133,11 @@ the existing accum. This term is to be updated each time a withdrawal is made from a validator. ``` -func (vi ValidatorDistInfo) UpdateTotalDelAccum(height int64, totalDelShares Dec) +func (vi ValidatorDistInfo) UpdateTotalDelAccum(height int64, totalDelShares Dec) ValidatorDistInfo blocks = height - vi.TotalDelAccumUpdateHeight vi.TotalDelAccum += totalDelShares * blocks vi.TotalDelAccumUpdateHeight = height + return vi ``` ### Global pool to validator pool @@ -146,9 +148,10 @@ from the passive global pool to their own pool. It is at this point that the commission is withdrawn ``` -func (vi ValidatorDistInfo) TakeAccum(g Global, height int64, totalBonded, vdTokens, commissionRate Dec) g Global +func (vi ValidatorDistInfo) TakeAccum(g Global, height int64, totalBonded, vdTokens, commissionRate Dec) ( + vi ValidatorDistInfo, g Global) + g.UpdateTotalValAccum(height, totalBondedShares) - g.UpdateValAccum(height, totalBondedShares) // update the validators pool blocks = height - vi.GlobalWithdrawalHeight @@ -162,7 +165,7 @@ func (vi ValidatorDistInfo) TakeAccum(g Global, height int64, totalBonded, vdTok vi.PoolCommissionFree += withdrawalTokens - commission g.Pool -= withdrawalTokens - return g + return vi, g ``` @@ -173,7 +176,8 @@ pool have already had the validator's commission taken away. ``` func (di DelegatorDistInfo) WithdrawRewards(g Global, vi ValidatorDistInfo, - height int64, totalBonded, vdTokens, totalDelShares, commissionRate Dec) (g Global, withdrawn DecCoins) + height int64, totalBonded, vdTokens, totalDelShares, commissionRate Dec) ( + di DelegatorDistInfo, g Global, withdrawn DecCoins) vi.UpdateTotalDelAccum(height, totalDelShares) g = vi.TakeAccum(g, height, totalBonded, vdTokens, commissionRate) @@ -187,7 +191,7 @@ func (di DelegatorDistInfo) WithdrawRewards(g Global, vi ValidatorDistInfo, vi.Pool -= withdrawalTokens vi.TotalDelAccum -= accum - return g, withdrawalTokens + return di, g, withdrawalTokens ``` @@ -197,12 +201,13 @@ Commission is calculated each time rewards enter into the validator. ``` func (vi ValidatorDistInfo) WithdrawCommission(g Global, height int64, - totalBonded, vdTokens, commissionRate Dec) (g Global, withdrawn DecCoins) + totalBonded, vdTokens, commissionRate Dec) ( + vi ValidatorDistInfo, g Global, withdrawn DecCoins) g = vi.TakeAccum(g, height, totalBonded, vdTokens, commissionRate) withdrawalTokens := vi.PoolCommission vi.PoolCommission = 0 - return g, withdrawalTokens + return vi, g, withdrawalTokens ``` From 86395809cbcbe99ba7da9a6f4b3103eee8c0cd05 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Sun, 2 Sep 2018 20:20:14 +0200 Subject: [PATCH 45/93] Implement generate-only option for commands that create txs The new CLI flag builds an unsigned transaction and writes it to STDOUT. Likewise, REST clients can now append generate_only=true to a request's query arguments list and expect a JSON response carrying the unsigned transaction. Closes: #966 --- PENDING.md | 1 + client/context/context.go | 5 +- client/flags.go | 2 + client/lcd/lcd_test.go | 15 ++++++ client/utils/rest.go | 33 +++++++++++-- client/utils/utils.go | 37 +++++++++++++- cmd/gaia/cli_test/cli_test.go | 91 ++++++++++++++++++++++++++++++++++- crypto/keys/keybase.go | 4 +- docs/sdk/clients.md | 11 +++++ x/auth/stdtx.go | 12 ++--- x/bank/client/cli/sendtx.go | 3 ++ x/bank/client/rest/sendtx.go | 5 ++ x/gov/client/cli/tx.go | 11 ++++- x/gov/client/rest/util.go | 6 +++ x/gov/msgs.go | 10 ++-- x/ibc/client/cli/ibctx.go | 3 ++ x/ibc/client/rest/transfer.go | 5 ++ x/ibc/types.go | 10 ++-- x/slashing/client/cli/tx.go | 4 +- x/slashing/client/rest/tx.go | 5 ++ x/stake/client/cli/tx.go | 22 ++++++++- x/stake/client/rest/tx.go | 5 ++ 22 files changed, 270 insertions(+), 30 deletions(-) diff --git a/PENDING.md b/PENDING.md index 17616ced1a..7289cd23f6 100644 --- a/PENDING.md +++ b/PENDING.md @@ -53,6 +53,7 @@ FEATURES * [cli] \#2047 Setting the --gas flag value to 0 triggers a simulation of the tx before the actual execution. The gas estimate obtained via the simulation will be used as gas limit in the actual execution. * [cli] \#2047 The --gas-adjustment flag can be used to adjust the estimate obtained via the simulation triggered by --gas=0. * [cli] \#2110 Add --dry-run flag to perform a simulation of a transaction without broadcasting it. The --gas flag is ignored as gas would be automatically estimated. + * [cli] \#966 Add --generate-only flag to build an unsigned transaction and write it to STDOUT. * Gaia * [cli] #2170 added ability to show the node's address via `gaiad tendermint show-address` diff --git a/client/context/context.go b/client/context/context.go index 8e56cfa1ae..a4d4afd3b3 100644 --- a/client/context/context.go +++ b/client/context/context.go @@ -3,10 +3,11 @@ package context import ( "bytes" "fmt" + "io" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/x/auth" - "io" "github.com/spf13/viper" @@ -38,6 +39,7 @@ type CLIContext struct { PrintResponse bool Certifier tmlite.Certifier DryRun bool + GenerateOnly bool } // NewCLIContext returns a new initialized CLIContext with parameters from the @@ -65,6 +67,7 @@ func NewCLIContext() CLIContext { PrintResponse: viper.GetBool(client.FlagPrintResponse), Certifier: createCertifier(), DryRun: viper.GetBool(client.FlagDryRun), + GenerateOnly: viper.GetBool(client.FlagGenerateOnly), } } diff --git a/client/flags.go b/client/flags.go index a1d3c6e178..97fce42a58 100644 --- a/client/flags.go +++ b/client/flags.go @@ -27,6 +27,7 @@ const ( FlagJson = "json" FlagPrintResponse = "print-response" FlagDryRun = "dry-run" + FlagGenerateOnly = "generate-only" ) // LineBreak can be included in a command list to provide a blank line @@ -64,6 +65,7 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command { c.Flags().Bool(FlagPrintResponse, true, "return tx response (only works with async = false)") c.Flags().Bool(FlagTrustNode, true, "Don't verify proofs for query responses") c.Flags().Bool(FlagDryRun, false, "ignore the --gas flag and perform a simulation of a transaction, but don't broadcast it") + c.Flags().Bool(FlagGenerateOnly, false, "build an unsigned transaction and write it to STDOUT") } return cmds } diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index 707cc21f7a..7eb592a70c 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -313,6 +313,21 @@ func TestIBCTransfer(t *testing.T) { // TODO: query ibc egress packet state } +func TestCoinSendGenerateOnly(t *testing.T) { + name, password := "test", "1234567890" + addr, seed := CreateAddr(t, "test", password, GetKeyBase(t)) + cleanup, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}) + defer cleanup() + // create TX + res, body, _ := doSendWithGas(t, port, seed, name, password, addr, 0, 0, "?generate_only=true") + require.Equal(t, http.StatusOK, res.StatusCode, body) + var msg auth.StdTx + require.Nil(t, cdc.UnmarshalJSON([]byte(body), &msg)) + require.Equal(t, len(msg.Msgs), 1) + require.Equal(t, msg.Msgs[0].Type(), "bank") + require.Equal(t, msg.Msgs[0].GetSigners(), []sdk.AccAddress{addr}) +} + func TestTxs(t *testing.T) { name, password := "test", "1234567890" addr, seed := CreateAddr(t, "test", password, GetKeyBase(t)) diff --git a/client/utils/rest.go b/client/utils/rest.go index 25e1c23d85..b6cee6c1f3 100644 --- a/client/utils/rest.go +++ b/client/utils/rest.go @@ -3,11 +3,17 @@ package utils import ( "fmt" "net/http" + "net/url" "strconv" + + sdk "github.com/cosmos/cosmos-sdk/types" + auth "github.com/cosmos/cosmos-sdk/x/auth" + authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context" ) const ( - queryArgDryRun = "simulate" + queryArgDryRun = "simulate" + queryArgGenerateOnly = "generate_only" ) // WriteErrorResponse prepares and writes a HTTP error @@ -26,9 +32,10 @@ func WriteSimulationResponse(w http.ResponseWriter, gas int64) { // HasDryRunArg returns true if the request's URL query contains // the dry run argument and its value is set to "true". -func HasDryRunArg(r *http.Request) bool { - return r.URL.Query().Get(queryArgDryRun) == "true" -} +func HasDryRunArg(r *http.Request) bool { return urlQueryHasArg(r.URL, queryArgDryRun) } + +// HasGenerateOnlyArg returns whether a URL's query "generate-only" parameter is set to "true". +func HasGenerateOnlyArg(r *http.Request) bool { return urlQueryHasArg(r.URL, queryArgGenerateOnly) } // ParseFloat64OrReturnBadRequest converts s to a float64 value. It returns a default // value if the string is empty. Write @@ -43,3 +50,21 @@ func ParseFloat64OrReturnBadRequest(w http.ResponseWriter, s string, defaultIfEm } return n, true } + +// WriteGenerateStdTxResponse writes response for the generate_only mode. +func WriteGenerateStdTxResponse(w http.ResponseWriter, txCtx authctx.TxContext, msgs []sdk.Msg) { + stdMsg, err := txCtx.Build(msgs) + if err != nil { + WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + output, err := txCtx.Codec.MarshalJSON(auth.NewStdTx(stdMsg.Msgs, stdMsg.Fee, nil, stdMsg.Memo)) + if err != nil { + WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + w.Write(output) + return +} + +func urlQueryHasArg(url *url.URL, arg string) bool { return url.Query().Get(arg) == "true" } diff --git a/client/utils/utils.go b/client/utils/utils.go index 20b1c6bc54..fa5bcf817d 100644 --- a/client/utils/utils.go +++ b/client/utils/utils.go @@ -7,6 +7,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/keys" sdk "github.com/cosmos/cosmos-sdk/types" + auth "github.com/cosmos/cosmos-sdk/x/auth" authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context" amino "github.com/tendermint/go-amino" "github.com/tendermint/tendermint/libs/common" @@ -28,7 +29,7 @@ func SendTx(txCtx authctx.TxContext, cliCtx context.CLIContext, msgs []sdk.Msg) if err != nil { return err } - fmt.Fprintf(os.Stdout, "estimated gas = %v\n", txCtx.Gas) + fmt.Fprintf(os.Stderr, "estimated gas = %v\n", txCtx.Gas) } if cliCtx.DryRun { return nil @@ -85,6 +86,19 @@ func CalculateGas(queryFunc func(string, common.HexBytes) ([]byte, error), cdc * return } +// PrintUnsignedStdTx builds an unsigned StdTx and prints it to os.Stdout. +func PrintUnsignedStdTx(txCtx authctx.TxContext, cliCtx context.CLIContext, msgs []sdk.Msg) (err error) { + stdTx, err := buildUnsignedStdTx(txCtx, cliCtx, msgs) + if err != nil { + return + } + json, err := txCtx.Codec.MarshalJSON(stdTx) + if err == nil { + fmt.Printf("%s\n", json) + } + return +} + func adjustGasEstimate(estimate int64, adjustment float64) int64 { return int64(adjustment * float64(estimate)) } @@ -128,3 +142,24 @@ func prepareTxContext(txCtx authctx.TxContext, cliCtx context.CLIContext) (authc } return txCtx, nil } + +// buildUnsignedStdTx builds a StdTx as per the parameters passed in the +// contexts. Gas is automatically estimated if gas wanted is set to 0. +func buildUnsignedStdTx(txCtx authctx.TxContext, cliCtx context.CLIContext, msgs []sdk.Msg) (stdTx auth.StdTx, err error) { + txCtx, err = prepareTxContext(txCtx, cliCtx) + if err != nil { + return + } + if txCtx.Gas == 0 { + txCtx, err = EnrichCtxWithGas(txCtx, cliCtx, cliCtx.FromAddressName, msgs) + if err != nil { + return + } + fmt.Fprintf(os.Stderr, "estimated gas = %v\n", txCtx.Gas) + } + stdSignMsg, err := txCtx.Build(msgs) + if err != nil { + return + } + return auth.NewStdTx(stdSignMsg.Msgs, stdSignMsg.Fee, nil, stdSignMsg.Memo), nil +} diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 696c0fc6ab..473a3bb3bd 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -13,6 +13,7 @@ import ( "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tendermint/libs/common" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/cmd/gaia/app" "github.com/cosmos/cosmos-sdk/server" @@ -155,8 +156,17 @@ func TestGaiaCLICreateValidator(t *testing.T) { initialPool.BondedTokens = initialPool.BondedTokens.Add(sdk.NewDec(1)) + // Test --generate-only + success, stdout, stderr := executeWriteRetStdStreams(t, cvStr+" --generate-only", app.DefaultKeyPass) + require.True(t, success) + require.True(t, success) + require.Empty(t, stderr) + msg := unmarshalStdTx(t, stdout) + require.NotZero(t, msg.Fee.Gas) + require.Equal(t, len(msg.Msgs), 1) + // Test --dry-run - success := executeWrite(t, cvStr+" --dry-run", app.DefaultKeyPass) + success = executeWrite(t, cvStr+" --dry-run", app.DefaultKeyPass) require.True(t, success) executeWrite(t, cvStr, app.DefaultKeyPass) @@ -222,8 +232,17 @@ func TestGaiaCLISubmitProposal(t *testing.T) { spStr += fmt.Sprintf(" --title=%s", "Test") spStr += fmt.Sprintf(" --description=%s", "test") + // Test generate only + success, stdout, stderr := executeWriteRetStdStreams(t, spStr+" --generate-only", app.DefaultKeyPass) + require.True(t, success) + require.True(t, success) + require.Empty(t, stderr) + msg := unmarshalStdTx(t, stdout) + require.NotZero(t, msg.Fee.Gas) + require.Equal(t, len(msg.Msgs), 1) + // Test --dry-run - success := executeWrite(t, spStr+" --dry-run", app.DefaultKeyPass) + success = executeWrite(t, spStr+" --dry-run", app.DefaultKeyPass) require.True(t, success) executeWrite(t, spStr, app.DefaultKeyPass) @@ -244,6 +263,15 @@ func TestGaiaCLISubmitProposal(t *testing.T) { depositStr += fmt.Sprintf(" --deposit=%s", "10steak") depositStr += fmt.Sprintf(" --proposal-id=%s", "1") + // Test generate only + success, stdout, stderr = executeWriteRetStdStreams(t, depositStr+" --generate-only", app.DefaultKeyPass) + require.True(t, success) + require.True(t, success) + require.Empty(t, stderr) + msg = unmarshalStdTx(t, stdout) + require.NotZero(t, msg.Fee.Gas) + require.Equal(t, len(msg.Msgs), 1) + executeWrite(t, depositStr, app.DefaultKeyPass) tests.WaitForNextNBlocksTM(2, port) @@ -258,6 +286,15 @@ func TestGaiaCLISubmitProposal(t *testing.T) { voteStr += fmt.Sprintf(" --proposal-id=%s", "1") voteStr += fmt.Sprintf(" --option=%s", "Yes") + // Test generate only + success, stdout, stderr = executeWriteRetStdStreams(t, voteStr+" --generate-only", app.DefaultKeyPass) + require.True(t, success) + require.True(t, success) + require.Empty(t, stderr) + msg = unmarshalStdTx(t, stdout) + require.NotZero(t, msg.Fee.Gas) + require.Equal(t, len(msg.Msgs), 1) + executeWrite(t, voteStr, app.DefaultKeyPass) tests.WaitForNextNBlocksTM(2, port) @@ -291,6 +328,50 @@ func TestGaiaCLISubmitProposal(t *testing.T) { require.Equal(t, " 2 - Apples", proposalsQuery) } +func TestGaiaCLISendGenerateOnly(t *testing.T) { + chainID, servAddr, port := initializeFixtures(t) + flags := fmt.Sprintf("--home=%s --node=%v --chain-id=%v", gaiacliHome, servAddr, chainID) + + // start gaiad server + proc := tests.GoExecuteTWithStdout(t, fmt.Sprintf("gaiad start --home=%s --rpc.laddr=%v", gaiadHome, servAddr)) + + defer proc.Stop(false) + tests.WaitForTMStart(port) + tests.WaitForNextNBlocksTM(2, port) + + barAddr, _ := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show bar --output=json --home=%s", gaiacliHome)) + + // Test generate sendTx with default gas + success, stdout, stderr := executeWriteRetStdStreams(t, fmt.Sprintf( + "gaiacli send %v --amount=10steak --to=%s --from=foo --generate-only", + flags, barAddr), []string{}...) + require.True(t, success) + require.Empty(t, stderr) + msg := unmarshalStdTx(t, stdout) + require.Equal(t, msg.Fee.Gas, int64(client.DefaultGasLimit)) + require.Equal(t, len(msg.Msgs), 1) + + // Test generate sendTx, estimate gas + success, stdout, stderr = executeWriteRetStdStreams(t, fmt.Sprintf( + "gaiacli send %v --amount=10steak --to=%s --from=foo --gas=0 --generate-only", + flags, barAddr), []string{}...) + require.True(t, success) + require.NotEmpty(t, stderr) + msg = unmarshalStdTx(t, stdout) + require.NotZero(t, msg.Fee.Gas) + require.Equal(t, len(msg.Msgs), 1) + + // Test generate sendTx with --gas=$amount + success, stdout, stderr = executeWriteRetStdStreams(t, fmt.Sprintf( + "gaiacli send %v --amount=10steak --to=%s --from=foo --gas=100 --generate-only", + flags, barAddr), []string{}...) + require.True(t, success) + require.Empty(t, stderr) + msg = unmarshalStdTx(t, stdout) + require.Equal(t, msg.Fee.Gas, int64(100)) + require.Equal(t, len(msg.Msgs), 1) +} + //___________________________________________________________________________________ // helper methods @@ -315,6 +396,12 @@ func initializeFixtures(t *testing.T) (chainID, servAddr, port string) { return } +func unmarshalStdTx(t *testing.T, s string) (stdTx auth.StdTx) { + cdc := app.MakeCodec() + require.Nil(t, cdc.UnmarshalJSON([]byte(s), &stdTx)) + return +} + //___________________________________________________________________________________ // executors diff --git a/crypto/keys/keybase.go b/crypto/keys/keybase.go index ae036362e3..ec5b7b0fda 100644 --- a/crypto/keys/keybase.go +++ b/crypto/keys/keybase.go @@ -224,9 +224,9 @@ func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig []byte, pub t } case offlineInfo: linfo := info.(offlineInfo) - fmt.Printf("Bytes to sign:\n%s", msg) + fmt.Fprintf(os.Stderr, "Bytes to sign:\n%s", msg) buf := bufio.NewReader(os.Stdin) - fmt.Printf("\nEnter Amino-encoded signature:\n") + fmt.Fprintf(os.Stderr, "\nEnter Amino-encoded signature:\n") // Will block until user inputs the signature signed, err := buf.ReadString('\n') if err != nil { diff --git a/docs/sdk/clients.md b/docs/sdk/clients.md index 62d79bbacd..fdfbca7bd2 100644 --- a/docs/sdk/clients.md +++ b/docs/sdk/clients.md @@ -139,6 +139,17 @@ gaiacli send \ --dry-run ``` +Furthermore, you can build a transaction and print its JSON format to STDOUT by appending `--generate-only` to the list of the command line arguments: + +```bash +gaiacli send \ + --amount=10faucetToken \ + --chain-id= \ + --name= \ + --to= \ + --generate-only +``` + ### Staking #### Set up a Validator diff --git a/x/auth/stdtx.go b/x/auth/stdtx.go index c6e280157b..69627b31a3 100644 --- a/x/auth/stdtx.go +++ b/x/auth/stdtx.go @@ -143,12 +143,12 @@ func StdSignBytes(chainID string, accnum int64, sequence int64, fee StdFee, msgs // a Msg with the other requirements for a StdSignDoc before // it is signed. For use in the CLI. type StdSignMsg struct { - ChainID string - AccountNumber int64 - Sequence int64 - Fee StdFee - Msgs []sdk.Msg - Memo string + ChainID string `json:"chain_id"` + AccountNumber int64 `json:"account_number"` + Sequence int64 `json:"sequence"` + Fee StdFee `json:"fee"` + Msgs []sdk.Msg `json:"msgs"` + Memo string `json:"memo"` } // get message bytes diff --git a/x/bank/client/cli/sendtx.go b/x/bank/client/cli/sendtx.go index 92ac37c1e9..08210569e0 100644 --- a/x/bank/client/cli/sendtx.go +++ b/x/bank/client/cli/sendtx.go @@ -68,6 +68,9 @@ func SendTxCmd(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint msg := client.BuildMsg(from, to, coins) + if cliCtx.GenerateOnly { + return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + } return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) }, diff --git a/x/bank/client/rest/sendtx.go b/x/bank/client/rest/sendtx.go index 23506e0fec..1c09943d07 100644 --- a/x/bank/client/rest/sendtx.go +++ b/x/bank/client/rest/sendtx.go @@ -107,6 +107,11 @@ func SendRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLICo txCtx = newCtx } + if utils.HasGenerateOnlyArg(r) { + utils.WriteGenerateStdTxResponse(w, txCtx, []sdk.Msg{msg}) + return + } + txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error()) diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index 65c922c6c1..b0fa4d6beb 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -99,6 +99,9 @@ $ gaiacli gov submit-proposal --title="Test Proposal" --description="My awesome } msg := gov.NewMsgSubmitProposal(proposal.Title, proposal.Description, proposalType, fromAddr, amount) + if cliCtx.GenerateOnly { + return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + } err = msg.ValidateBasic() if err != nil { @@ -177,7 +180,9 @@ func GetCmdDeposit(cdc *wire.Codec) *cobra.Command { } msg := gov.NewMsgDeposit(depositerAddr, proposalID, amount) - + if cliCtx.GenerateOnly { + return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + } err = msg.ValidateBasic() if err != nil { return err @@ -221,7 +226,9 @@ func GetCmdVote(cdc *wire.Codec) *cobra.Command { } msg := gov.NewMsgVote(voterAddr, proposalID, byteVoteOption) - + if cliCtx.GenerateOnly { + return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + } err = msg.ValidateBasic() if err != nil { return err diff --git a/x/gov/client/rest/util.go b/x/gov/client/rest/util.go index a5fae3c3fa..7ba23befaa 100644 --- a/x/gov/client/rest/util.go +++ b/x/gov/client/rest/util.go @@ -96,6 +96,12 @@ func signAndBuild(w http.ResponseWriter, r *http.Request, cliCtx context.CLICont } txCtx = newCtx } + + if utils.HasGenerateOnlyArg(r) { + utils.WriteGenerateStdTxResponse(w, txCtx, []sdk.Msg{msg}) + return + } + txBytes, err := txCtx.BuildAndSign(baseReq.Name, baseReq.Password, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error()) diff --git a/x/gov/msgs.go b/x/gov/msgs.go index 5d85f689e5..dcd7112aa1 100644 --- a/x/gov/msgs.go +++ b/x/gov/msgs.go @@ -12,11 +12,11 @@ const MsgType = "gov" //----------------------------------------------------------- // MsgSubmitProposal type MsgSubmitProposal struct { - Title string // Title of the proposal - Description string // Description of the proposal - ProposalType ProposalKind // Type of proposal. Initial set {PlainTextProposal, SoftwareUpgradeProposal} - Proposer sdk.AccAddress // Address of the proposer - InitialDeposit sdk.Coins // Initial deposit paid by sender. Must be strictly positive. + Title string `json:"title"` // Title of the proposal + Description string `json:"description"` // Description of the proposal + ProposalType ProposalKind `json:"proposal_type"` // Type of proposal. Initial set {PlainTextProposal, SoftwareUpgradeProposal} + Proposer sdk.AccAddress `json:"proposer"` // Address of the proposer + InitialDeposit sdk.Coins `json:"initial_deposit"` // Initial deposit paid by sender. Must be strictly positive. } func NewMsgSubmitProposal(title string, description string, proposalType ProposalKind, proposer sdk.AccAddress, initialDeposit sdk.Coins) MsgSubmitProposal { diff --git a/x/ibc/client/cli/ibctx.go b/x/ibc/client/cli/ibctx.go index f44c736d89..37cf7ce91e 100644 --- a/x/ibc/client/cli/ibctx.go +++ b/x/ibc/client/cli/ibctx.go @@ -43,6 +43,9 @@ func IBCTransferCmd(cdc *wire.Codec) *cobra.Command { if err != nil { return err } + if cliCtx.GenerateOnly { + return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + } return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) }, diff --git a/x/ibc/client/rest/transfer.go b/x/ibc/client/rest/transfer.go index 0580ff4062..7f5595dd7c 100644 --- a/x/ibc/client/rest/transfer.go +++ b/x/ibc/client/rest/transfer.go @@ -98,6 +98,11 @@ func TransferRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.C txCtx = newCtx } + if utils.HasGenerateOnlyArg(r) { + utils.WriteGenerateStdTxResponse(w, txCtx, []sdk.Msg{msg}) + return + } + txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error()) diff --git a/x/ibc/types.go b/x/ibc/types.go index 5f9ee611bb..b3fe6fc392 100644 --- a/x/ibc/types.go +++ b/x/ibc/types.go @@ -22,11 +22,11 @@ func init() { // IBCPacket defines a piece of data that can be send between two separate // blockchains. type IBCPacket struct { - SrcAddr sdk.AccAddress - DestAddr sdk.AccAddress - Coins sdk.Coins - SrcChain string - DestChain string + SrcAddr sdk.AccAddress `json:"src_addr"` + DestAddr sdk.AccAddress `json:"dest_addr"` + Coins sdk.Coins `json:"coins"` + SrcChain string `json:"src_chain"` + DestChain string `json:"dest_chain"` } func NewIBCPacket(srcAddr sdk.AccAddress, destAddr sdk.AccAddress, coins sdk.Coins, diff --git a/x/slashing/client/cli/tx.go b/x/slashing/client/cli/tx.go index 4234e52ce8..d69a9e1583 100644 --- a/x/slashing/client/cli/tx.go +++ b/x/slashing/client/cli/tx.go @@ -33,7 +33,9 @@ func GetCmdUnjail(cdc *wire.Codec) *cobra.Command { } msg := slashing.NewMsgUnjail(sdk.ValAddress(valAddr)) - + if cliCtx.GenerateOnly { + return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + } return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) }, } diff --git a/x/slashing/client/rest/tx.go b/x/slashing/client/rest/tx.go index faf0341ce5..bbed6ed9ab 100644 --- a/x/slashing/client/rest/tx.go +++ b/x/slashing/client/rest/tx.go @@ -99,6 +99,11 @@ func unjailRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLI txCtx = newCtx } + if utils.HasGenerateOnlyArg(r) { + utils.WriteGenerateStdTxResponse(w, txCtx, []sdk.Msg{msg}) + return + } + txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusUnauthorized, "Must use own validator address") diff --git a/x/stake/client/cli/tx.go b/x/stake/client/cli/tx.go index defc2b1e23..bd38e7b5b5 100644 --- a/x/stake/client/cli/tx.go +++ b/x/stake/client/cli/tx.go @@ -77,7 +77,9 @@ func GetCmdCreateValidator(cdc *wire.Codec) *cobra.Command { } else { msg = stake.NewMsgCreateValidator(sdk.ValAddress(valAddr), pk, amount, description) } - + if cliCtx.GenerateOnly { + return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + } // build and sign the transaction, then broadcast to Tendermint return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) }, @@ -117,6 +119,9 @@ func GetCmdEditValidator(cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgEditValidator(sdk.ValAddress(valAddr), description) + if cliCtx.GenerateOnly { + return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + } // build and sign the transaction, then broadcast to Tendermint return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) }, @@ -156,6 +161,9 @@ func GetCmdDelegate(cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgDelegate(delAddr, valAddr, amount) + if cliCtx.GenerateOnly { + return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + } // build and sign the transaction, then broadcast to Tendermint return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) }, @@ -225,6 +233,9 @@ func GetCmdBeginRedelegate(storeName string, cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgBeginRedelegate(delAddr, valSrcAddr, valDstAddr, sharesAmount) + if cliCtx.GenerateOnly { + return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + } // build and sign the transaction, then broadcast to Tendermint return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) }, @@ -313,6 +324,9 @@ func GetCmdCompleteRedelegate(cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgCompleteRedelegate(delAddr, valSrcAddr, valDstAddr) + if cliCtx.GenerateOnly { + return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + } // build and sign the transaction, then broadcast to Tendermint return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) }, @@ -374,6 +388,9 @@ func GetCmdBeginUnbonding(storeName string, cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgBeginUnbonding(delAddr, valAddr, sharesAmount) + if cliCtx.GenerateOnly { + return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + } // build and sign the transaction, then broadcast to Tendermint return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) }, @@ -409,6 +426,9 @@ func GetCmdCompleteUnbonding(cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgCompleteUnbonding(delAddr, valAddr) + if cliCtx.GenerateOnly { + return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + } // build and sign the transaction, then broadcast to Tendermint return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) }, diff --git a/x/stake/client/rest/tx.go b/x/stake/client/rest/tx.go index 9925b6b1ce..4bb6d0f7e5 100644 --- a/x/stake/client/rest/tx.go +++ b/x/stake/client/rest/tx.go @@ -297,6 +297,11 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex txCtx = newCtx } + if utils.HasGenerateOnlyArg(r) { + utils.WriteGenerateStdTxResponse(w, txCtx, []sdk.Msg{msg}) + return + } + txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error()) From 753e58bac047f15e05777b2b879ca8ef5ee34f48 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Mon, 3 Sep 2018 17:40:02 -0700 Subject: [PATCH 46/93] simulation: Make governance simulation use future operations to schedule votes. In a future PR, functionality to test that slashing occured properly should be added. --- cmd/gaia/app/sim_test.go | 3 +- x/gov/simulation/msgs.go | 109 ++++++++++++++++++++++++++++------- x/gov/simulation/sim_test.go | 15 +++++ 3 files changed, 105 insertions(+), 22 deletions(-) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 3878166b3a..73e3e2e4a5 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -93,9 +93,8 @@ func appStateFn(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json func testAndRunTxs(app *GaiaApp) []simulation.Operation { return []simulation.Operation{ banksim.SimulateSingleInputMsgSend(app.accountMapper), - govsim.SimulateMsgSubmitProposal(app.govKeeper, app.stakeKeeper), + govsim.SimulateSubmittingVotingAndSlashingForProposal(app.govKeeper, app.stakeKeeper), govsim.SimulateMsgDeposit(app.govKeeper, app.stakeKeeper), - govsim.SimulateMsgVote(app.govKeeper, app.stakeKeeper), stakesim.SimulateMsgCreateValidator(app.accountMapper, app.stakeKeeper), stakesim.SimulateMsgEditValidator(app.stakeKeeper), stakesim.SimulateMsgDelegate(app.accountMapper, app.stakeKeeper), diff --git a/x/gov/simulation/msgs.go b/x/gov/simulation/msgs.go index eca8accae0..e89a040d1e 100644 --- a/x/gov/simulation/msgs.go +++ b/x/gov/simulation/msgs.go @@ -2,6 +2,7 @@ package simulation import ( "fmt" + "math" "math/rand" "testing" @@ -18,30 +19,89 @@ const ( denom = "steak" ) +// SimulateSubmittingVotingAndSlashingForProposal simulates creating a msg Submit Proposal +// voting on the proposal, and subsequently slashing the proposal. It is implemented using +// future operations. +// TODO: Vote more intelligently, so we can actually do some checks regarding votes passing or failing +// TODO: Actually check that validator slashings happened +func SimulateSubmittingVotingAndSlashingForProposal(k gov.Keeper, sk stake.Keeper) simulation.Operation { + handler := gov.NewHandler(k) + // The states are: + // column 1: All validators vote + // column 2: 90% vote + // column 3: 75% vote + // column 4: 40% vote + // column 5: 15% vote + // column 6: noone votes + // All columns sum to 100 for simplicity, values chosen by @valardragon semi-arbitrarily, + // feel free to change. + numVotesTransitionMatrix, _ := simulation.CreateTransitionMatrix([][]int{ + {20, 10, 0, 0, 0, 0}, + {55, 50, 20, 10, 0, 0}, + {25, 25, 30, 25, 30, 15}, + {0, 15, 30, 25, 30, 30}, + {0, 0, 20, 30, 30, 30}, + {0, 0, 0, 10, 10, 25}, + }) + statePercentageArray := []float64{1, .9, .75, .4, .15, 0} + curNumVotesState := 1 + return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOps []simulation.FutureOperation, err sdk.Error) { + // 1) submit proposal now + sender := simulation.RandomKey(r, keys) + msg := simulationCreateMsgSubmitProposal(tb, r, sender, log) + action = simulateHandleMsgSubmitProposal(msg, sk, handler, ctx, event) + proposalID := k.GetLastProposalID(ctx) + // 2) Schedule operations for votes + // 2.1) first pick a number of people to vote. + curNumVotesState = numVotesTransitionMatrix.NextState(r, curNumVotesState) + numVotes := int(math.Ceil(float64(len(keys)) * statePercentageArray[curNumVotesState])) + // 2.2) select who votes and when + whoVotes := r.Perm(len(keys)) + // didntVote := whoVotes[numVotes:] + whoVotes = whoVotes[:numVotes] + votingPeriod := k.GetVotingProcedure(ctx).VotingPeriod + fops := make([]simulation.FutureOperation, numVotes+1) + for i := 0; i < numVotes; i++ { + whenVote := ctx.BlockHeight() + r.Int63n(votingPeriod) + fops[i] = simulation.FutureOperation{int(whenVote), operationSimulateMsgVote(k, sk, keys[whoVotes[i]], proposalID)} + } + // 3) Make an operation to ensure slashes were done correctly. (Really should be a future invariant) + // TODO: Find a way to check if a validator was slashed other than just checking their balance a block + // before and after. + + return action, fops, nil + } +} + // SimulateMsgSubmitProposal simulates a msg Submit Proposal // Note: Currently doesn't ensure that the proposal txt is in JSON form func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.Operation { handler := gov.NewHandler(k) return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOps []simulation.FutureOperation, err sdk.Error) { - msg := simulationCreateMsgSubmitProposal(tb, r, keys, log) - ctx, write := ctx.CacheContext() - result := handler(ctx, msg) - if result.IsOK() { - // Update pool to keep invariants - pool := sk.GetPool(ctx) - pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewDecFromInt(msg.InitialDeposit.AmountOf(denom))) - sk.SetPool(ctx, pool) - write() - } - event(fmt.Sprintf("gov/MsgSubmitProposal/%v", result.IsOK())) - action = fmt.Sprintf("TestMsgSubmitProposal: ok %v, msg %s", result.IsOK(), msg.GetSignBytes()) + sender := simulation.RandomKey(r, keys) + msg := simulationCreateMsgSubmitProposal(tb, r, sender, log) + action = simulateHandleMsgSubmitProposal(msg, sk, handler, ctx, event) return action, nil, nil } } -func simulationCreateMsgSubmitProposal(tb testing.TB, r *rand.Rand, keys []crypto.PrivKey, log string) gov.MsgSubmitProposal { - key := simulation.RandomKey(r, keys) - addr := sdk.AccAddress(key.PubKey().Address()) +func simulateHandleMsgSubmitProposal(msg gov.MsgSubmitProposal, sk stake.Keeper, handler sdk.Handler, ctx sdk.Context, event func(string)) (action string) { + ctx, write := ctx.CacheContext() + result := handler(ctx, msg) + if result.IsOK() { + // Update pool to keep invariants + pool := sk.GetPool(ctx) + pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewDecFromInt(msg.InitialDeposit.AmountOf(denom))) + sk.SetPool(ctx, pool) + write() + } + event(fmt.Sprintf("gov/MsgSubmitProposal/%v", result.IsOK())) + action = fmt.Sprintf("TestMsgSubmitProposal: ok %v, msg %s", result.IsOK(), msg.GetSignBytes()) + return action +} + +func simulationCreateMsgSubmitProposal(tb testing.TB, r *rand.Rand, sender crypto.PrivKey, log string) gov.MsgSubmitProposal { + addr := sdk.AccAddress(sender.PubKey().Address()) deposit := randomDeposit(r) msg := gov.NewMsgSubmitProposal( simulation.RandStringOfLength(r, 5), @@ -87,13 +147,22 @@ func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation { // SimulateMsgVote func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.Operation { + return operationSimulateMsgVote(k, sk, nil, -1) +} + +func operationSimulateMsgVote(k gov.Keeper, sk stake.Keeper, key crypto.PrivKey, proposalID int64) simulation.Operation { return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { - key := simulation.RandomKey(r, keys) - addr := sdk.AccAddress(key.PubKey().Address()) - proposalID, ok := randomProposalID(r, k, ctx) - if !ok { - return "no-operation", nil, nil + if key == nil { + key = simulation.RandomKey(r, keys) } + var ok bool + if proposalID < 0 { + proposalID, ok = randomProposalID(r, k, ctx) + if !ok { + return "no-operation", nil, nil + } + } + addr := sdk.AccAddress(key.PubKey().Address()) option := randomVotingOption(r) msg := gov.NewMsgVote(addr, proposalID, option) if msg.ValidateBasic() != nil { diff --git a/x/gov/simulation/sim_test.go b/x/gov/simulation/sim_test.go index 6f0f9830cd..540dcb4473 100644 --- a/x/gov/simulation/sim_test.go +++ b/x/gov/simulation/sim_test.go @@ -53,6 +53,7 @@ func TestGovWithRandomMessages(t *testing.T) { gov.InitGenesis(ctx, govKeeper, gov.DefaultGenesisState()) } + // Test with unscheduled votes simulation.Simulate( t, mapp.BaseApp, appStateFn, []simulation.Operation{ @@ -66,4 +67,18 @@ func TestGovWithRandomMessages(t *testing.T) { }, 10, 100, false, ) + + // Test with scheduled votes + simulation.Simulate( + t, mapp.BaseApp, appStateFn, + []simulation.Operation{ + SimulateSubmittingVotingAndSlashingForProposal(govKeeper, stakeKeeper), + SimulateMsgDeposit(govKeeper, stakeKeeper), + }, []simulation.RandSetup{ + setup, + }, []simulation.Invariant{ + AllInvariants(), + }, 10, 100, + false, + ) } From 5ed24e44d2b84c2d433bbcc1be3f02f4345cac43 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Mon, 3 Sep 2018 19:13:08 -0700 Subject: [PATCH 47/93] simulation: Minor changes Now that we properly initialize governance, a ton of governance slashing doesn't happen in the first few blocks. Because of this, we can run through blocks in the range (0,200) quite rapidly. This PR acknowledges that and increases many of the default block heights. --- Makefile | 2 +- cmd/gaia/app/sim_test.go | 9 +++++---- x/mock/simulation/random_simulate_blocks.go | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index e363891e2a..2f23fd54fe 100644 --- a/Makefile +++ b/Makefile @@ -157,7 +157,7 @@ test_sim_gaia_nondeterminism: test_sim_gaia_fast: @echo "Running quick Gaia simulation. This may take several minutes..." - @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=50 -v -timeout 24h + @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=150 -v -timeout 24h test_sim_gaia_slow: @echo "Running full Gaia simulation. This may take awhile!" diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 3878166b3a..61affb261d 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -189,7 +189,7 @@ func TestAppStateDeterminism(t *testing.T) { t.Skip("Skipping Gaia simulation") } - numSeeds := 5 + numSeeds := 3 numTimesToRunPerSeed := 5 appHashList := make([]json.RawMessage, numTimesToRunPerSeed) @@ -206,10 +206,11 @@ func TestAppStateDeterminism(t *testing.T) { testAndRunTxs(app), []simulation.RandSetup{}, []simulation.Invariant{}, - 20, - 20, - true, + 50, + 100, + false, ) + app.Commit() appHash := app.LastCommitID().Hash appHashList[j] = appHash } diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index fc7543280a..14ca6c2166 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -155,7 +155,7 @@ func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, event f AssertAllInvariants(t, app, invariants, log) } if opCount%50 == 0 { - fmt.Printf("\rSimulating... block %d/%d, operation %d/%d.", header.Height, totalNumBlocks, opCount, blocksize) + fmt.Printf("\rSimulating... block %d/%d, operation %d/%d. ", header.Height, totalNumBlocks, opCount, blocksize) } } opCount++ From 9b26ccfa76e1a100ba5cb12f46ed48ae03a78881 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Mon, 3 Sep 2018 21:29:59 -0700 Subject: [PATCH 48/93] tools: Remove gocyclo We can investigate re-introducing our own fork #postlaunch. Closes #2211 --- PENDING.md | 1 + tools/Makefile | 18 +++++++++--------- tools/gometalinter.json | 2 +- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/PENDING.md b/PENDING.md index 17616ced1a..dd663564a8 100644 --- a/PENDING.md +++ b/PENDING.md @@ -35,6 +35,7 @@ BREAKING CHANGES * [x/slashing] [#2122](https://github.com/cosmos/cosmos-sdk/pull/2122) - Implement slashing period * [types] \#2119 Parsed error messages and ABCI log errors to make them more human readable. * [simulation] Rename TestAndRunTx to Operation [#2153](https://github.com/cosmos/cosmos-sdk/pull/2153) + * [tools] Removed golint [#2211](https://github.com/cosmos/cosmos-sdk/issues/2211) * Tendermint diff --git a/tools/Makefile b/tools/Makefile index a11f2ec70d..87544107c5 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -22,7 +22,7 @@ INEFFASSIGN_CHECK := $(shell command -v ineffassign 2> /dev/null) MISSPELL_CHECK := $(shell command -v misspell 2> /dev/null) ERRCHECK_CHECK := $(shell command -v errcheck 2> /dev/null) UNPARAM_CHECK := $(shell command -v unparam 2> /dev/null) -GOCYCLO_CHECK := $(shell command -v gocyclo 2> /dev/null) +# GOCYCLO_CHECK := $(shell command -v gocyclo 2> /dev/null) check_tools: ifndef DEP_CHECK @@ -126,12 +126,12 @@ else @echo "Installing unparam" go get -v $(UNPARAM) endif -ifdef GOCYCLO_CHECK - @echo "gocyclo is already installed. Run 'make update_tools' to update." -else - @echo "Installing gocyclo" - go get -v $(GOCYCLO) -endif +# ifdef GOCYCLO_CHECK +# @echo "gocyclo is already installed. Run 'make update_tools' to update." +# else +# @echo "Installing gocyclo" +# go get -v $(GOCYCLO) +# endif update_tools: @echo "Updating dep" @@ -153,8 +153,8 @@ update_dev_tools: go get -u -v $(ERRCHECK) @echo "Updating unparam" go get -u -v $(UNPARAM) - @echo "Updating goyclo" - go get -u -v $(GOCYCLO) + # @echo "Updating goyclo" + # go get -u -v $(GOCYCLO) # To avoid unintended conflicts with file names, always add to .PHONY # unless there is a reason not to. diff --git a/tools/gometalinter.json b/tools/gometalinter.json index 124e28c147..42788714bf 100644 --- a/tools/gometalinter.json +++ b/tools/gometalinter.json @@ -2,7 +2,7 @@ "Linters": { "vet": "go tool vet -composites=false :PATH:LINE:MESSAGE" }, - "Enable": ["golint", "vet", "ineffassign", "unparam", "unconvert", "misspell", "gocyclo"], + "Enable": ["golint", "vet", "ineffassign", "unparam", "unconvert", "misspell"], "Deadline": "500s", "Vendor": true, "Cyclo": 11 From ea01b91958766075b5461a5017a53ab681f33e42 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Mon, 3 Sep 2018 22:53:07 -0700 Subject: [PATCH 49/93] baseapp: Remove baseapp.SetTxDecoder() Closes #1441 --- PENDING.md | 1 + baseapp/setters.go | 6 ------ 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/PENDING.md b/PENDING.md index 17616ced1a..3fcf0b3b38 100644 --- a/PENDING.md +++ b/PENDING.md @@ -35,6 +35,7 @@ BREAKING CHANGES * [x/slashing] [#2122](https://github.com/cosmos/cosmos-sdk/pull/2122) - Implement slashing period * [types] \#2119 Parsed error messages and ABCI log errors to make them more human readable. * [simulation] Rename TestAndRunTx to Operation [#2153](https://github.com/cosmos/cosmos-sdk/pull/2153) + * [baseapp] Remove `SetTxDecoder` in favor of requiring the decoder be set in baseapp initialization. [#1441](https://github.com/cosmos/cosmos-sdk/issues/1441) * Tendermint diff --git a/baseapp/setters.go b/baseapp/setters.go index a8b1591a73..28782c96de 100644 --- a/baseapp/setters.go +++ b/baseapp/setters.go @@ -26,12 +26,6 @@ func (app *BaseApp) SetCMS(cms store.CommitMultiStore) { } app.cms = cms } -func (app *BaseApp) SetTxDecoder(txDecoder sdk.TxDecoder) { - if app.sealed { - panic("SetTxDecoder() on sealed BaseApp") - } - app.txDecoder = txDecoder -} func (app *BaseApp) SetInitChainer(initChainer sdk.InitChainer) { if app.sealed { panic("SetInitChainer() on sealed BaseApp") From 8c32a8f2295dd9ce93b7dea6194b4910a37dbe62 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Tue, 4 Sep 2018 14:57:40 +0200 Subject: [PATCH 50/93] Check generate_only's output is actually unsigned --- client/lcd/lcd_test.go | 1 + cmd/gaia/cli_test/cli_test.go | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index 7eb592a70c..656362bcd6 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -326,6 +326,7 @@ func TestCoinSendGenerateOnly(t *testing.T) { require.Equal(t, len(msg.Msgs), 1) require.Equal(t, msg.Msgs[0].Type(), "bank") require.Equal(t, msg.Msgs[0].GetSigners(), []sdk.AccAddress{addr}) + require.Equal(t, 0, len(msg.Signatures)) } func TestTxs(t *testing.T) { diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 473a3bb3bd..8b66ab4a1d 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -164,6 +164,7 @@ func TestGaiaCLICreateValidator(t *testing.T) { msg := unmarshalStdTx(t, stdout) require.NotZero(t, msg.Fee.Gas) require.Equal(t, len(msg.Msgs), 1) + require.Equal(t, 0, len(msg.GetSignatures())) // Test --dry-run success = executeWrite(t, cvStr+" --dry-run", app.DefaultKeyPass) @@ -240,6 +241,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) { msg := unmarshalStdTx(t, stdout) require.NotZero(t, msg.Fee.Gas) require.Equal(t, len(msg.Msgs), 1) + require.Equal(t, 0, len(msg.GetSignatures())) // Test --dry-run success = executeWrite(t, spStr+" --dry-run", app.DefaultKeyPass) @@ -271,6 +273,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) { msg = unmarshalStdTx(t, stdout) require.NotZero(t, msg.Fee.Gas) require.Equal(t, len(msg.Msgs), 1) + require.Equal(t, 0, len(msg.GetSignatures())) executeWrite(t, depositStr, app.DefaultKeyPass) tests.WaitForNextNBlocksTM(2, port) @@ -294,6 +297,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) { msg = unmarshalStdTx(t, stdout) require.NotZero(t, msg.Fee.Gas) require.Equal(t, len(msg.Msgs), 1) + require.Equal(t, 0, len(msg.GetSignatures())) executeWrite(t, voteStr, app.DefaultKeyPass) tests.WaitForNextNBlocksTM(2, port) @@ -350,6 +354,7 @@ func TestGaiaCLISendGenerateOnly(t *testing.T) { msg := unmarshalStdTx(t, stdout) require.Equal(t, msg.Fee.Gas, int64(client.DefaultGasLimit)) require.Equal(t, len(msg.Msgs), 1) + require.Equal(t, 0, len(msg.GetSignatures())) // Test generate sendTx, estimate gas success, stdout, stderr = executeWriteRetStdStreams(t, fmt.Sprintf( @@ -370,6 +375,7 @@ func TestGaiaCLISendGenerateOnly(t *testing.T) { msg = unmarshalStdTx(t, stdout) require.Equal(t, msg.Fee.Gas, int64(100)) require.Equal(t, len(msg.Msgs), 1) + require.Equal(t, 0, len(msg.GetSignatures())) } //___________________________________________________________________________________ From 89b3ab9e515c8992a210a7462930905d80465ed1 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Tue, 4 Sep 2018 17:29:33 +0200 Subject: [PATCH 51/93] Don't skip basic validation --- x/gov/client/cli/tx.go | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index b0fa4d6beb..e9a55c5577 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -99,15 +99,15 @@ $ gaiacli gov submit-proposal --title="Test Proposal" --description="My awesome } msg := gov.NewMsgSubmitProposal(proposal.Title, proposal.Description, proposalType, fromAddr, amount) - if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) - } - err = msg.ValidateBasic() if err != nil { return err } + if cliCtx.GenerateOnly { + return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + } + // Build and sign the transaction, then broadcast to Tendermint // proposalID must be returned, and it is a part of response. cliCtx.PrintResponse = true @@ -180,14 +180,15 @@ func GetCmdDeposit(cdc *wire.Codec) *cobra.Command { } msg := gov.NewMsgDeposit(depositerAddr, proposalID, amount) - if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) - } err = msg.ValidateBasic() if err != nil { return err } + if cliCtx.GenerateOnly { + return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + } + // Build and sign the transaction, then broadcast to a Tendermint // node. return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) @@ -226,14 +227,15 @@ func GetCmdVote(cdc *wire.Codec) *cobra.Command { } msg := gov.NewMsgVote(voterAddr, proposalID, byteVoteOption) - if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) - } err = msg.ValidateBasic() if err != nil { return err } + if cliCtx.GenerateOnly { + return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + } + fmt.Printf("Vote[Voter:%s,ProposalID:%d,Option:%s]", voterAddr.String(), msg.ProposalID, msg.Option.String(), ) From 8378f3ea86cc1db946987e3856be4f2bede943e2 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Tue, 4 Sep 2018 17:35:35 +0200 Subject: [PATCH 52/93] Drop note in PENDING.md about generate_only=true query arg --- PENDING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PENDING.md b/PENDING.md index 7289cd23f6..e3be5b6b10 100644 --- a/PENDING.md +++ b/PENDING.md @@ -44,6 +44,7 @@ FEATURES * Gaia REST API (`gaiacli advanced rest-server`) * [lcd] Endpoints to query staking pool and params * [lcd] \#2110 Add support for `simulate=true` requests query argument to endpoints that send txs to run simulations of transactions + * [lcd] \#966 Add support for `generate_only=true` query argument to generate offline unsigned transactions * Gaia CLI (`gaiacli`) * [cli] Cmds to query staking pool and params From e9e83f0b6df672f7fe8e286e538ee51ee89eaf08 Mon Sep 17 00:00:00 2001 From: Rigel Date: Wed, 5 Sep 2018 13:59:37 -0400 Subject: [PATCH 53/93] Merge PR #2237: move WIP-lamborghini-distribution --- .../WIP-lamborghini-distribution/README.md | 0 .../WIP-lamborghini-distribution/end_block.md | 0 .../example_sheet/distribution.xlsx | Bin .../future_improvements.md | 0 .../WIP-lamborghini-distribution/overview.md | 0 .../WIP-lamborghini-distribution/state.md | 0 .../WIP-lamborghini-distribution/transactions.md | 0 .../WIP-lamborghini-distribution/triggers.md | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename docs/{spec/distribution => _attic}/WIP-lamborghini-distribution/README.md (100%) rename docs/{spec/distribution => _attic}/WIP-lamborghini-distribution/end_block.md (100%) rename docs/{spec/distribution => _attic}/WIP-lamborghini-distribution/example_sheet/distribution.xlsx (100%) rename docs/{spec/distribution => _attic}/WIP-lamborghini-distribution/future_improvements.md (100%) rename docs/{spec/distribution => _attic}/WIP-lamborghini-distribution/overview.md (100%) rename docs/{spec/distribution => _attic}/WIP-lamborghini-distribution/state.md (100%) rename docs/{spec/distribution => _attic}/WIP-lamborghini-distribution/transactions.md (100%) rename docs/{spec/distribution => _attic}/WIP-lamborghini-distribution/triggers.md (100%) diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/README.md b/docs/_attic/WIP-lamborghini-distribution/README.md similarity index 100% rename from docs/spec/distribution/WIP-lamborghini-distribution/README.md rename to docs/_attic/WIP-lamborghini-distribution/README.md diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/end_block.md b/docs/_attic/WIP-lamborghini-distribution/end_block.md similarity index 100% rename from docs/spec/distribution/WIP-lamborghini-distribution/end_block.md rename to docs/_attic/WIP-lamborghini-distribution/end_block.md diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/example_sheet/distribution.xlsx b/docs/_attic/WIP-lamborghini-distribution/example_sheet/distribution.xlsx similarity index 100% rename from docs/spec/distribution/WIP-lamborghini-distribution/example_sheet/distribution.xlsx rename to docs/_attic/WIP-lamborghini-distribution/example_sheet/distribution.xlsx diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/future_improvements.md b/docs/_attic/WIP-lamborghini-distribution/future_improvements.md similarity index 100% rename from docs/spec/distribution/WIP-lamborghini-distribution/future_improvements.md rename to docs/_attic/WIP-lamborghini-distribution/future_improvements.md diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/overview.md b/docs/_attic/WIP-lamborghini-distribution/overview.md similarity index 100% rename from docs/spec/distribution/WIP-lamborghini-distribution/overview.md rename to docs/_attic/WIP-lamborghini-distribution/overview.md diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/state.md b/docs/_attic/WIP-lamborghini-distribution/state.md similarity index 100% rename from docs/spec/distribution/WIP-lamborghini-distribution/state.md rename to docs/_attic/WIP-lamborghini-distribution/state.md diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/transactions.md b/docs/_attic/WIP-lamborghini-distribution/transactions.md similarity index 100% rename from docs/spec/distribution/WIP-lamborghini-distribution/transactions.md rename to docs/_attic/WIP-lamborghini-distribution/transactions.md diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/triggers.md b/docs/_attic/WIP-lamborghini-distribution/triggers.md similarity index 100% rename from docs/spec/distribution/WIP-lamborghini-distribution/triggers.md rename to docs/_attic/WIP-lamborghini-distribution/triggers.md From 51d3a39b39a32c66a3c57309f2e90f71d4dbe6ac Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 5 Sep 2018 18:47:21 -0400 Subject: [PATCH 54/93] move types/account -> address --- types/{account.go => address.go} | 0 types/{account_test.go => address_test.go} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename types/{account.go => address.go} (100%) rename types/{account_test.go => address_test.go} (100%) diff --git a/types/account.go b/types/address.go similarity index 100% rename from types/account.go rename to types/address.go diff --git a/types/account_test.go b/types/address_test.go similarity index 100% rename from types/account_test.go rename to types/address_test.go From 693aea8985b28835be8ee4cf79f0312ccc1027ae Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 7 Sep 2018 01:03:52 +0200 Subject: [PATCH 55/93] Suggest opening pending PR back to develop --- docs/RELEASE_PROCESS.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/RELEASE_PROCESS.md b/docs/RELEASE_PROCESS.md index 8ff722b335..c8968486a4 100644 --- a/docs/RELEASE_PROCESS.md +++ b/docs/RELEASE_PROCESS.md @@ -5,7 +5,8 @@ - [ ] 3. Merge items in `PENDING.md` into the `CHANGELOG.md`. While doing this make sure that each entry contains links to issues/PRs for each item - [ ] 4. Summarize breaking API changes section under “Breaking Changes” section to the `CHANGELOG.md` to bring attention to any breaking API changes that affect RPC consumers. - [ ] 5. Tag the commit `{ .Release.Name }-rcN` -- [ ] 6. Kick off 1 day of automated fuzz testing -- [ ] 7. Release Lead assigns 2 people to perform [buddy testing script](/docs/RELEASE_TEST_SCRIPT.md) and update the relevant documentation -- [ ] 8. If errors are found in either #6 or #7 go back to #2 (*NOTE*: be sure to increment the `rcN`) -- [ ] 9. After #6 and #7 have successfully completed then merge the release PR and push the final release tag +- [ ] 6. Open a branch & PR to merge the pending release back into `develop`. If any changes are made to the release branch, they must also be made to the pending develop merge, and both must pass tests. +- [ ] 7. Kick off 1 day of automated fuzz testing +- [ ] 8. Release Lead assigns 2 people to perform [buddy testing script](/docs/RELEASE_TEST_SCRIPT.md) and update the relevant documentation +- [ ] 9. If errors are found in either #6 or #7 go back to #2 (*NOTE*: be sure to increment the `rcN`) +- [ ] 10. After #6 and #7 have successfully completed then merge the release PR and push the final release tag From a94219e062d585d396ed8cf242675d58bbd6f737 Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Thu, 6 Sep 2018 21:54:59 -0700 Subject: [PATCH 56/93] Merge PR #2246: add script to make changelog links actual links --- PENDING.md | 56 ++++++++++++++++++------------------ scripts/linkify_changelog.py | 13 +++++++++ 2 files changed, 41 insertions(+), 28 deletions(-) create mode 100644 scripts/linkify_changelog.py diff --git a/PENDING.md b/PENDING.md index 6ccd96be36..e5ea9884a5 100644 --- a/PENDING.md +++ b/PENDING.md @@ -8,32 +8,32 @@ BREAKING CHANGES * Gaia CLI (`gaiacli`) * [x/stake] Validator.Owner renamed to Validator.Operator * [cli] unsafe_reset_all, show_validator, and show_node_id have been renamed to unsafe-reset-all, show-validator, and show-node-id - * [cli] \#1983 --print-response now defaults to true in commands that create and send a transaction - * [cli] \#1983 you can now pass --pubkey or --address to gaiacli keys show to return a plaintext representation of the key's address or public key for use with other commands - * [cli] \#2061 changed proposalID in governance REST endpoints to proposal-id - * [cli] \#2014 `gaiacli advanced` no longer exists - to access `ibc`, `rest-server`, and `validator-set` commands use `gaiacli ibc`, `gaiacli rest-server`, and `gaiacli tendermint`, respectively + * [cli] [\#1983](https://github.com/cosmos/cosmos-sdk/issues/1983) --print-response now defaults to true in commands that create and send a transaction + * [cli] [\#1983](https://github.com/cosmos/cosmos-sdk/issues/1983) you can now pass --pubkey or --address to gaiacli keys show to return a plaintext representation of the key's address or public key for use with other commands + * [cli] [\#2061](https://github.com/cosmos/cosmos-sdk/issues/2061) changed proposalID in governance REST endpoints to proposal-id + * [cli] [\#2014](https://github.com/cosmos/cosmos-sdk/issues/2014) `gaiacli advanced` no longer exists - to access `ibc`, `rest-server`, and `validator-set` commands use `gaiacli ibc`, `gaiacli rest-server`, and `gaiacli tendermint`, respectively * [makefile] `get_vendor_deps` no longer updates lock file it just updates vendor directory. Use `update_vendor_deps` to update the lock file. [#2152](https://github.com/cosmos/cosmos-sdk/pull/2152) - * [cli] \#2190 `gaiacli init --gen-txs` is now `gaiacli init --with-txs` to reduce confusion - * \#2040 All commands that utilize a validator's address must now use the new + * [cli] [\#2190](https://github.com/cosmos/cosmos-sdk/issues/2190) `gaiacli init --gen-txs` is now `gaiacli init --with-txs` to reduce confusion + * [\#2040](https://github.com/cosmos/cosmos-sdk/issues/2040) All commands that utilize a validator's address must now use the new bech32 prefix, `cosmosval`. A validator's Tendermint signing key and address now use a new bech32 prefix, `cosmoscons`. * Gaia * Make the transient store key use a distinct store key. [#2013](https://github.com/cosmos/cosmos-sdk/pull/2013) - * [x/stake] \#1901 Validator type's Owner field renamed to Operator; Validator's GetOwner() renamed accordingly to comply with the SDK's Validator interface. + * [x/stake] [\#1901](https://github.com/cosmos/cosmos-sdk/issues/1901) Validator type's Owner field renamed to Operator; Validator's GetOwner() renamed accordingly to comply with the SDK's Validator interface. * [docs] [#2001](https://github.com/cosmos/cosmos-sdk/pull/2001) Update slashing spec for slashing period * [x/stake, x/slashing] [#1305](https://github.com/cosmos/cosmos-sdk/issues/1305) - Rename "revoked" to "jailed" * [x/stake] [#1676] Revoked and jailed validators put into the unbonding state * [x/stake] [#1877] Redelegations/unbonding-delegation from unbonding validator have reduced time - * [x/stake] \#2040 Validator operator type has now changed to `sdk.ValAddress` + * [x/stake] [\#2040](https://github.com/cosmos/cosmos-sdk/issues/2040) Validator operator type has now changed to `sdk.ValAddress` * A new bech32 prefix has been introduced for Tendermint signing keys and addresses, `cosmosconspub` and `cosmoscons` respectively. - + * SDK - * [core] \#1807 Switch from use of rational to decimal - * [types] \#1901 Validator interface's GetOwner() renamed to GetOperator() + * [core] [\#1807](https://github.com/cosmos/cosmos-sdk/issues/1807) Switch from use of rational to decimal + * [types] [\#1901](https://github.com/cosmos/cosmos-sdk/issues/1901) Validator interface's GetOwner() renamed to GetOperator() * [x/slashing] [#2122](https://github.com/cosmos/cosmos-sdk/pull/2122) - Implement slashing period - * [types] \#2119 Parsed error messages and ABCI log errors to make them more human readable. + * [types] [\#2119](https://github.com/cosmos/cosmos-sdk/issues/2119) Parsed error messages and ABCI log errors to make them more human readable. * [simulation] Rename TestAndRunTx to Operation [#2153](https://github.com/cosmos/cosmos-sdk/pull/2153) * [tools] Removed gocyclo [#2211](https://github.com/cosmos/cosmos-sdk/issues/2211) * [baseapp] Remove `SetTxDecoder` in favor of requiring the decoder be set in baseapp initialization. [#1441](https://github.com/cosmos/cosmos-sdk/issues/1441) @@ -45,26 +45,26 @@ FEATURES * Gaia REST API (`gaiacli advanced rest-server`) * [lcd] Endpoints to query staking pool and params - * [lcd] \#2110 Add support for `simulate=true` requests query argument to endpoints that send txs to run simulations of transactions - * [lcd] \#966 Add support for `generate_only=true` query argument to generate offline unsigned transactions + * [lcd] [\#2110](https://github.com/cosmos/cosmos-sdk/issues/2110) Add support for `simulate=true` requests query argument to endpoints that send txs to run simulations of transactions + * [lcd] [\#966](https://github.com/cosmos/cosmos-sdk/issues/966) Add support for `generate_only=true` query argument to generate offline unsigned transactions * Gaia CLI (`gaiacli`) * [cli] Cmds to query staking pool and params * [gov][cli] #2062 added `--proposal` flag to `submit-proposal` that allows a JSON file containing a proposal to be passed in - * \#2040 Add `--bech` to `gaiacli keys show` and respective REST endpoint to + * [\#2040](https://github.com/cosmos/cosmos-sdk/issues/2040) Add `--bech` to `gaiacli keys show` and respective REST endpoint to provide desired Bech32 prefix encoding - * [cli] \#2047 Setting the --gas flag value to 0 triggers a simulation of the tx before the actual execution. The gas estimate obtained via the simulation will be used as gas limit in the actual execution. - * [cli] \#2047 The --gas-adjustment flag can be used to adjust the estimate obtained via the simulation triggered by --gas=0. - * [cli] \#2110 Add --dry-run flag to perform a simulation of a transaction without broadcasting it. The --gas flag is ignored as gas would be automatically estimated. - * [cli] \#966 Add --generate-only flag to build an unsigned transaction and write it to STDOUT. + * [cli] [\#2047](https://github.com/cosmos/cosmos-sdk/issues/2047) Setting the --gas flag value to 0 triggers a simulation of the tx before the actual execution. The gas estimate obtained via the simulation will be used as gas limit in the actual execution. + * [cli] [\#2047](https://github.com/cosmos/cosmos-sdk/issues/2047) The --gas-adjustment flag can be used to adjust the estimate obtained via the simulation triggered by --gas=0. + * [cli] [\#2110](https://github.com/cosmos/cosmos-sdk/issues/2110) Add --dry-run flag to perform a simulation of a transaction without broadcasting it. The --gas flag is ignored as gas would be automatically estimated. + * [cli] [\#966](https://github.com/cosmos/cosmos-sdk/issues/966) Add --generate-only flag to build an unsigned transaction and write it to STDOUT. * Gaia * [cli] #2170 added ability to show the node's address via `gaiad tendermint show-address` * SDK * [querier] added custom querier functionality, so ABCI query requests can be handled by keepers - * [simulation] \#1924 allow operations to specify future operations - * [simulation] \#1924 Add benchmarking capabilities, with makefile commands "test_sim_gaia_benchmark, test_sim_gaia_profile" + * [simulation] [\#1924](https://github.com/cosmos/cosmos-sdk/issues/1924) allow operations to specify future operations + * [simulation] [\#1924](https://github.com/cosmos/cosmos-sdk/issues/1924) Add benchmarking capabilities, with makefile commands "test_sim_gaia_benchmark, test_sim_gaia_profile" * Tendermint @@ -74,7 +74,7 @@ IMPROVEMENTS * [tools] Added ansible script to enable process core dumps * Gaia REST API (`gaiacli advanced rest-server`) - * [x/stake] \#2000 Added tests for new staking endpoints + * [x/stake] [\#2000](https://github.com/cosmos/cosmos-sdk/issues/2000) Added tests for new staking endpoints * Gaia CLI (`gaiacli`) * [cli] #2060 removed `--select` from `block` command @@ -88,7 +88,7 @@ IMPROVEMENTS * SDK * [tools] Make get_vendor_deps deletes `.vendor-new` directories, in case scratch files are present. * [spec] Added simple piggy bank distribution spec - * [cli] \#1632 Add integration tests to ensure `basecoind init && basecoind` start sequences run successfully for both `democoin` and `basecoin` examples. + * [cli] [\#1632](https://github.com/cosmos/cosmos-sdk/issues/1632) Add integration tests to ensure `basecoind init && basecoind` start sequences run successfully for both `democoin` and `basecoin` examples. * [store] Speedup IAVL iteration, and consequently everything that requires IAVL iteration. [#2143](https://github.com/cosmos/cosmos-sdk/issues/2143) * [store] \#1952 Update IAVL dependency to v0.10.0 * [simulation] Make timestamps randomized [#2153](https://github.com/cosmos/cosmos-sdk/pull/2153) @@ -100,15 +100,15 @@ BUG FIXES * Gaia REST API (`gaiacli advanced rest-server`) * Gaia CLI (`gaiacli`) - * [cli] \#1997 Handle panics gracefully when `gaiacli stake {delegation,unbond}` fail to unmarshal delegation. + * [cli] [\#1997](https://github.com/cosmos/cosmos-sdk/issues/1997) Handle panics gracefully when `gaiacli stake {delegation,unbond}` fail to unmarshal delegation. * Gaia * SDK - * \#1988 Make us compile on OpenBSD (disable ledger) [#1988] (https://github.com/cosmos/cosmos-sdk/issues/1988) - * \#2105 Fix DB Iterator leak, which may leak a go routine. - * [ledger] \#2064 Fix inability to sign and send transactions via the LCD by + * [\#1988](https://github.com/cosmos/cosmos-sdk/issues/1988) Make us compile on OpenBSD (disable ledger) [#1988] (https://github.com/cosmos/cosmos-sdk/issues/1988) + * [\#2105](https://github.com/cosmos/cosmos-sdk/issues/2105) Fix DB Iterator leak, which may leak a go routine. + * [ledger] [\#2064](https://github.com/cosmos/cosmos-sdk/issues/2064) Fix inability to sign and send transactions via the LCD by loading a Ledger device at runtime. - * \#2158 Fix non-deterministic ordering of validator iteration when slashing in `gov EndBlocker` + * [\#2158](https://github.com/cosmos/cosmos-sdk/issues/2158) Fix non-deterministic ordering of validator iteration when slashing in `gov EndBlocker` * Tendermint diff --git a/scripts/linkify_changelog.py b/scripts/linkify_changelog.py new file mode 100644 index 0000000000..3423506e7e --- /dev/null +++ b/scripts/linkify_changelog.py @@ -0,0 +1,13 @@ +import fileinput +import re + +# This script goes through the provided file, and replaces any " \#", +# with the valid mark down formatted link to it. e.g. +# " [\#number](https://github.com/cosmos/cosmos-sdk/issues/) +# Note that if the number is for a PR, github will auto-redirect you when you click the link. +# It is safe to run the script multiple times in succession. +# +# Example usage $ python3 linkify_changelog.py ../PENDING.md +for line in fileinput.input(inplace=1): + line = re.sub(r"\s\\#([0-9]*)", r" [\\#\1](https://github.com/cosmos/cosmos-sdk/issues/\1)", line.rstrip()) + print(line) \ No newline at end of file From 74d8999b99940e8f556842592a54557857027f0e Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Fri, 7 Sep 2018 14:22:32 +0800 Subject: [PATCH 57/93] checked error on Fprintf --- crypto/keys/keybase.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crypto/keys/keybase.go b/crypto/keys/keybase.go index ec5b7b0fda..0bf7ad9903 100644 --- a/crypto/keys/keybase.go +++ b/crypto/keys/keybase.go @@ -224,9 +224,15 @@ func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig []byte, pub t } case offlineInfo: linfo := info.(offlineInfo) - fmt.Fprintf(os.Stderr, "Bytes to sign:\n%s", msg) + _, err := fmt.Fprintf(os.Stderr, "Bytes to sign:\n%s", msg) + if err != nil { + return nil, nil, err + } buf := bufio.NewReader(os.Stdin) - fmt.Fprintf(os.Stderr, "\nEnter Amino-encoded signature:\n") + _, err = fmt.Fprintf(os.Stderr, "\nEnter Amino-encoded signature:\n") + if err != nil { + return nil, nil, err + } // Will block until user inputs the signature signed, err := buf.ReadString('\n') if err != nil { From e6a8a4df559c9474e753eab19b54a0354e60b059 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 7 Sep 2018 11:59:16 +0100 Subject: [PATCH 58/93] Implement command/REST endpoint for offline tx sign off #1953 * Add sign CLI command to sign transactions generated with the --generate-only flag. * Add /sign REST endpoint for Voyager support. Redirect password prompt to STDERR to avoid messing up cli commands output. As a rule of thumb, program's output should always go to STDOUT, whilst errors&diagnostics go to STDERR as per POSIX's philosophy and specs. --- Makefile | 2 +- PENDING.md | 7 ++- client/input.go | 2 +- client/lcd/lcd_test.go | 30 ++++++++++- client/utils/utils.go | 53 +++++++++++++++++++ cmd/gaia/cli_test/cli_test.go | 42 ++++++++++++++- cmd/gaia/cmd/gaiacli/main.go | 1 + docs/light/api.md | 69 ++++++++++++++++++++++++ docs/sdk/clients.md | 11 +++- x/auth/client/cli/sign.go | 91 ++++++++++++++++++++++++++++++++ x/auth/client/context/context.go | 60 +++++++++++++++------ x/auth/client/rest/query.go | 4 ++ x/auth/client/rest/sign.go | 60 +++++++++++++++++++++ 13 files changed, 409 insertions(+), 23 deletions(-) create mode 100644 x/auth/client/cli/sign.go create mode 100644 x/auth/client/rest/sign.go diff --git a/Makefile b/Makefile index 2f23fd54fe..78fc864c9e 100644 --- a/Makefile +++ b/Makefile @@ -179,7 +179,7 @@ test_cover: test_lint: gometalinter.v2 --config=tools/gometalinter.json ./... - !(gometalinter.v2 --disable-all --enable='errcheck' --vendor ./... | grep -v "client/") + !(gometalinter.v2 --disable-all --enable='errcheck' --vendor ./... | grep -v -e "client/" -e "fmt\.Fprintf") find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" | xargs gofmt -d -s dep status >> /dev/null !(grep -n branch Gopkg.toml) diff --git a/PENDING.md b/PENDING.md index d23a372a30..bfcbcd9781 100644 --- a/PENDING.md +++ b/PENDING.md @@ -29,7 +29,7 @@ BREAKING CHANGES * A new bech32 prefix has been introduced for Tendermint signing keys and addresses, `cosmosconspub` and `cosmoscons` respectively. * [x/gov] \#2195 Made governance use BFT Time instead of Block Heights for deposit and voting periods. - + * SDK * [core] [\#1807](https://github.com/cosmos/cosmos-sdk/issues/1807) Switch from use of rational to decimal * [types] [\#1901](https://github.com/cosmos/cosmos-sdk/issues/1901) Validator interface's GetOwner() renamed to GetOperator() @@ -48,6 +48,7 @@ FEATURES * [lcd] Endpoints to query staking pool and params * [lcd] [\#2110](https://github.com/cosmos/cosmos-sdk/issues/2110) Add support for `simulate=true` requests query argument to endpoints that send txs to run simulations of transactions * [lcd] [\#966](https://github.com/cosmos/cosmos-sdk/issues/966) Add support for `generate_only=true` query argument to generate offline unsigned transactions + * [lcd] [\#1953](https://github.com/cosmos/cosmos-sdk/issues/1953) Add /sign endpoint to sign transactions generated with `generate_only=true`. * Gaia CLI (`gaiacli`) * [cli] Cmds to query staking pool and params @@ -57,7 +58,9 @@ FEATURES * [cli] [\#2047](https://github.com/cosmos/cosmos-sdk/issues/2047) Setting the --gas flag value to 0 triggers a simulation of the tx before the actual execution. The gas estimate obtained via the simulation will be used as gas limit in the actual execution. * [cli] [\#2047](https://github.com/cosmos/cosmos-sdk/issues/2047) The --gas-adjustment flag can be used to adjust the estimate obtained via the simulation triggered by --gas=0. * [cli] [\#2110](https://github.com/cosmos/cosmos-sdk/issues/2110) Add --dry-run flag to perform a simulation of a transaction without broadcasting it. The --gas flag is ignored as gas would be automatically estimated. - * [cli] [\#966](https://github.com/cosmos/cosmos-sdk/issues/966) Add --generate-only flag to build an unsigned transaction and write it to STDOUT. + * [cli] [\#2204](https://github.com/cosmos/cosmos-sdk/issues/2204) Support generating and broadcasting messages with multiple signatures via command line: + * [\#966](https://github.com/cosmos/cosmos-sdk/issues/966) Add --generate-only flag to build an unsigned transaction and write it to STDOUT. + * [\#1953](https://github.com/cosmos/cosmos-sdk/issues/1953) New `sign` command to sign transactions generated with the --generate-only flag. * Gaia * [cli] #2170 added ability to show the node's address via `gaiad tendermint show-address` diff --git a/client/input.go b/client/input.go index e7d13f3bfd..b10f65ce62 100644 --- a/client/input.go +++ b/client/input.go @@ -24,7 +24,7 @@ func BufferStdin() *bufio.Reader { // It enforces the password length func GetPassword(prompt string, buf *bufio.Reader) (pass string, err error) { if inputIsTty() { - pass, err = speakeasy.Ask(prompt) + pass, err = speakeasy.FAsk(os.Stderr, prompt) } else { pass, err = readLineFromBuf(buf) } diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index 656362bcd6..8b4e318684 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -26,6 +26,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/x/auth" + authrest "github.com/cosmos/cosmos-sdk/x/auth/client/rest" "github.com/cosmos/cosmos-sdk/x/gov" "github.com/cosmos/cosmos-sdk/x/slashing" "github.com/cosmos/cosmos-sdk/x/stake" @@ -313,12 +314,13 @@ func TestIBCTransfer(t *testing.T) { // TODO: query ibc egress packet state } -func TestCoinSendGenerateOnly(t *testing.T) { +func TestCoinSendGenerateAndSign(t *testing.T) { name, password := "test", "1234567890" addr, seed := CreateAddr(t, "test", password, GetKeyBase(t)) cleanup, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}) defer cleanup() - // create TX + + // generate TX res, body, _ := doSendWithGas(t, port, seed, name, password, addr, 0, 0, "?generate_only=true") require.Equal(t, http.StatusOK, res.StatusCode, body) var msg auth.StdTx @@ -327,6 +329,30 @@ func TestCoinSendGenerateOnly(t *testing.T) { require.Equal(t, msg.Msgs[0].Type(), "bank") require.Equal(t, msg.Msgs[0].GetSigners(), []sdk.AccAddress{addr}) require.Equal(t, 0, len(msg.Signatures)) + + // sign tx + var signedMsg auth.StdTx + acc := getAccount(t, port, addr) + accnum := acc.GetAccountNumber() + sequence := acc.GetSequence() + + payload := authrest.SignBody{ + Tx: msg, + LocalAccountName: name, + Password: password, + ChainID: viper.GetString(client.FlagChainID), + AccountNumber: accnum, + Sequence: sequence, + } + json, err := cdc.MarshalJSON(payload) + require.Nil(t, err) + res, body = Request(t, port, "POST", "/sign", json) + require.Equal(t, http.StatusOK, res.StatusCode, body) + require.Nil(t, cdc.UnmarshalJSON([]byte(body), &signedMsg)) + require.Equal(t, len(msg.Msgs), len(signedMsg.Msgs)) + require.Equal(t, msg.Msgs[0].Type(), signedMsg.Msgs[0].Type()) + require.Equal(t, msg.Msgs[0].GetSigners(), signedMsg.Msgs[0].GetSigners()) + require.Equal(t, 1, len(signedMsg.Signatures)) } func TestTxs(t *testing.T) { diff --git a/client/utils/utils.go b/client/utils/utils.go index fa5bcf817d..554406b4aa 100644 --- a/client/utils/utils.go +++ b/client/utils/utils.go @@ -1,6 +1,7 @@ package utils import ( + "bytes" "fmt" "os" @@ -99,6 +100,49 @@ func PrintUnsignedStdTx(txCtx authctx.TxContext, cliCtx context.CLIContext, msgs return } +// SignStdTx appends a signature to a StdTx and returns a copy of a it. If appendSig +// is false, it replaces the signatures already attached with the new signature. +func SignStdTx(txCtx authctx.TxContext, cliCtx context.CLIContext, name string, stdTx auth.StdTx, appendSig bool) (auth.StdTx, error) { + var signedStdTx auth.StdTx + + keybase, err := keys.GetKeyBase() + if err != nil { + return signedStdTx, err + } + info, err := keybase.Get(name) + if err != nil { + return signedStdTx, err + } + addr := info.GetPubKey().Address() + + // Check whether the address is a signer + if !isTxSigner(sdk.AccAddress(addr), stdTx.GetSigners()) { + fmt.Fprintf(os.Stderr, "WARNING: The generated transaction's intended signer does not match the given signer: '%v'", name) + } + + if txCtx.AccountNumber == 0 { + accNum, err := cliCtx.GetAccountNumber(addr) + if err != nil { + return signedStdTx, err + } + txCtx = txCtx.WithAccountNumber(accNum) + } + + if txCtx.Sequence == 0 { + accSeq, err := cliCtx.GetAccountSequence(addr) + if err != nil { + return signedStdTx, err + } + txCtx = txCtx.WithSequence(accSeq) + } + + passphrase, err := keys.GetPassphrase(name) + if err != nil { + return signedStdTx, err + } + return txCtx.SignStdTx(name, passphrase, stdTx, appendSig) +} + func adjustGasEstimate(estimate int64, adjustment float64) int64 { return int64(adjustment * float64(estimate)) } @@ -163,3 +207,12 @@ func buildUnsignedStdTx(txCtx authctx.TxContext, cliCtx context.CLIContext, msgs } return auth.NewStdTx(stdSignMsg.Msgs, stdSignMsg.Fee, nil, stdSignMsg.Memo), nil } + +func isTxSigner(user sdk.AccAddress, signers []sdk.AccAddress) bool { + for _, s := range signers { + if bytes.Equal(user.Bytes(), s.Bytes()) { + return true + } + } + return false +} diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 8b66ab4a1d..e67ac30822 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -5,6 +5,7 @@ package clitest import ( "encoding/json" "fmt" + "io/ioutil" "os" "testing" @@ -332,7 +333,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) { require.Equal(t, " 2 - Apples", proposalsQuery) } -func TestGaiaCLISendGenerateOnly(t *testing.T) { +func TestGaiaCLISendGenerateAndSign(t *testing.T) { chainID, servAddr, port := initializeFixtures(t) flags := fmt.Sprintf("--home=%s --node=%v --chain-id=%v", gaiacliHome, servAddr, chainID) @@ -343,6 +344,7 @@ func TestGaiaCLISendGenerateOnly(t *testing.T) { tests.WaitForTMStart(port) tests.WaitForNextNBlocksTM(2, port) + fooAddr, _ := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show foo --output=json --home=%s", gaiacliHome)) barAddr, _ := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show bar --output=json --home=%s", gaiacliHome)) // Test generate sendTx with default gas @@ -376,6 +378,35 @@ func TestGaiaCLISendGenerateOnly(t *testing.T) { require.Equal(t, msg.Fee.Gas, int64(100)) require.Equal(t, len(msg.Msgs), 1) require.Equal(t, 0, len(msg.GetSignatures())) + + // Write the output to disk + unsignedTxFile := writeToNewTempFile(t, stdout) + defer os.Remove(unsignedTxFile.Name()) + + // Test sign --print-sigs + success, stdout, _ = executeWriteRetStdStreams(t, fmt.Sprintf( + "gaiacli sign %v --print-sigs %v", flags, unsignedTxFile.Name())) + require.True(t, success) + require.Equal(t, fmt.Sprintf("Signers:\n 0: %v\n\nSignatures:\n", fooAddr.String()), stdout) + + // Test sign + success, stdout, _ = executeWriteRetStdStreams(t, fmt.Sprintf( + "gaiacli sign %v --name=foo %v", flags, unsignedTxFile.Name()), app.DefaultKeyPass) + require.True(t, success) + msg = unmarshalStdTx(t, stdout) + require.Equal(t, len(msg.Msgs), 1) + require.Equal(t, 1, len(msg.GetSignatures())) + require.Equal(t, fooAddr.String(), msg.GetSigners()[0].String()) + + // Write the output to disk + signedTxFile := writeToNewTempFile(t, stdout) + defer os.Remove(signedTxFile.Name()) + + // Test sign --print-signatures + success, stdout, _ = executeWriteRetStdStreams(t, fmt.Sprintf( + "gaiacli sign %v --print-sigs %v", flags, signedTxFile.Name())) + require.True(t, success) + require.Equal(t, fmt.Sprintf("Signers:\n 0: %v\n\nSignatures:\n 0: %v\n", fooAddr.String(), fooAddr.String()), stdout) } //___________________________________________________________________________________ @@ -408,6 +439,15 @@ func unmarshalStdTx(t *testing.T, s string) (stdTx auth.StdTx) { return } +func writeToNewTempFile(t *testing.T, s string) *os.File { + fp, err := ioutil.TempFile(os.TempDir(), "cosmos_cli_test_") + require.Nil(t, err) + // defer os.Remove(signedTxFile.Name()) + _, err = fp.WriteString(s) + require.Nil(t, err) + return fp +} + //___________________________________________________________________________________ // executors diff --git a/cmd/gaia/cmd/gaiacli/main.go b/cmd/gaia/cmd/gaiacli/main.go index df0fd3c113..7a1af62214 100644 --- a/cmd/gaia/cmd/gaiacli/main.go +++ b/cmd/gaia/cmd/gaiacli/main.go @@ -127,6 +127,7 @@ func main() { rootCmd.AddCommand( client.GetCommands( authcmd.GetAccountCmd("acc", cdc, authcmd.GetAccountDecoder(cdc)), + authcmd.GetSignCommand(cdc, authcmd.GetAccountDecoder(cdc)), )...) rootCmd.AddCommand( client.PostCommands( diff --git a/docs/light/api.md b/docs/light/api.md index 7168cf9d74..293b023cd0 100644 --- a/docs/light/api.md +++ b/docs/light/api.md @@ -229,6 +229,75 @@ Returns on success: } ``` +### POST /auth/accounts/sign + +- **URL**: `/auth/sign` +- **Functionality**: Sign a transaction without broadcasting it. +- Returns on success: + +```json +{ + "rest api": "1.0", + "code": 200, + "error": "", + "result": { + "type": "auth/StdTx", + "value": { + "msg": [ + { + "type": "cosmos-sdk/Send", + "value": { + "inputs": [ + { + "address": "cosmos1ql4ekxkujf3xllk8h5ldhhgh4ylpu7kwec6q3d", + "coins": [ + { + "denom": "steak", + "amount": "1" + } + ] + } + ], + "outputs": [ + { + "address": "cosmos1dhyqhg4px33ed3erqymls0hc7q2lxw9hhfwklj", + "coins": [ + { + "denom": "steak", + "amount": "1" + } + ] + } + ] + } + } + ], + "fee": { + "amount": [ + { + "denom": "", + "amount": "0" + } + ], + "gas": "2742" + }, + "signatures": [ + { + "pub_key": { + "type": "tendermint/PubKeySecp256k1", + "value": "A2A/f2IYnrPUMTMqhwN81oas9jurtfcsvxdeLlNw3gGy" + }, + "signature": "MEQCIGVn73y9QLwBa3vmsAD1bs3ygX75Wo+lAFSAUDs431ZPAiBWAf2amyqTCDXE9J87rL9QF9sd5JvVMt7goGSuamPJwg==", + "account_number": "1", + "sequence": "0" + } + ], + "memo": "" + } + } +} +``` + ## ICS20 - TokenAPI The TokenAPI exposes all functionality needed to query account balances and send transactions. diff --git a/docs/sdk/clients.md b/docs/sdk/clients.md index fdfbca7bd2..0cc87cf215 100644 --- a/docs/sdk/clients.md +++ b/docs/sdk/clients.md @@ -147,7 +147,16 @@ gaiacli send \ --chain-id= \ --name= \ --to= \ - --generate-only + --generate-only > unsignedSendTx.json +``` + +You can now sign the transaction file generated through the `--generate-only` flag by providing your key to the following command: + +```bash +gaiacli sign \ + --chain-id= \ + --name= + unsignedSendTx.json > signedSendTx.json ``` ### Staking diff --git a/x/auth/client/cli/sign.go b/x/auth/client/cli/sign.go new file mode 100644 index 0000000000..e5cd412356 --- /dev/null +++ b/x/auth/client/cli/sign.go @@ -0,0 +1,91 @@ +package cli + +import ( + "fmt" + "io/ioutil" + + "github.com/spf13/viper" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/utils" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" + authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context" + "github.com/spf13/cobra" + amino "github.com/tendermint/go-amino" +) + +const ( + flagAppend = "append" + flagPrintSigs = "print-sigs" +) + +// GetSignCommand returns the sign command +func GetSignCommand(codec *amino.Codec, decoder auth.AccountDecoder) *cobra.Command { + cmd := &cobra.Command{ + Use: "sign ", + Short: "Sign transactions", + Long: `Sign transactions created with the --generate-only flag. +Read a transaction from , sign it, and print its JSON encoding.`, + RunE: makeSignCmd(codec, decoder), + Args: cobra.ExactArgs(1), + } + cmd.Flags().String(client.FlagName, "", "Name of private key with which to sign") + cmd.Flags().Bool(flagAppend, true, "Append the signature to the existing ones. If disabled, old signatures would be overwritten") + cmd.Flags().Bool(flagPrintSigs, false, "Print the addresses that must sign the transaction and those who have already signed it, then exit") + return cmd +} + +func makeSignCmd(cdc *amino.Codec, decoder auth.AccountDecoder) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) (err error) { + stdTx, err := readAndUnmarshalStdTx(cdc, args[0]) + if err != nil { + return + } + + if viper.GetBool(flagPrintSigs) { + printSignatures(stdTx) + return nil + } + + name := viper.GetString(client.FlagName) + cliCtx := context.NewCLIContext().WithCodec(cdc).WithAccountDecoder(decoder) + txCtx := authctx.NewTxContextFromCLI() + + newTx, err := utils.SignStdTx(txCtx, cliCtx, name, stdTx, viper.GetBool(flagAppend)) + if err != nil { + return err + } + json, err := cdc.MarshalJSON(newTx) + if err != nil { + return err + } + fmt.Printf("%s\n", json) + return + } +} + +func printSignatures(stdTx auth.StdTx) { + fmt.Println("Signers:") + for i, signer := range stdTx.GetSigners() { + fmt.Printf(" %v: %v\n", i, signer.String()) + } + fmt.Println("") + fmt.Println("Signatures:") + for i, sig := range stdTx.GetSignatures() { + fmt.Printf(" %v: %v\n", i, sdk.AccAddress(sig.Address()).String()) + } + return +} + +func readAndUnmarshalStdTx(cdc *amino.Codec, filename string) (stdTx auth.StdTx, err error) { + var bytes []byte + if bytes, err = ioutil.ReadFile(filename); err != nil { + return + } + if err = cdc.UnmarshalJSON(bytes, &stdTx); err != nil { + return + } + return +} diff --git a/x/auth/client/context/context.go b/x/auth/client/context/context.go index 5e55696b83..fe030449b2 100644 --- a/x/auth/client/context/context.go +++ b/x/auth/client/context/context.go @@ -117,24 +117,11 @@ func (ctx TxContext) Build(msgs []sdk.Msg) (auth.StdSignMsg, error) { // Sign signs a transaction given a name, passphrase, and a single message to // signed. An error is returned if signing fails. func (ctx TxContext) Sign(name, passphrase string, msg auth.StdSignMsg) ([]byte, error) { - keybase, err := keys.GetKeyBase() + sig, err := MakeSignature(name, passphrase, msg) if err != nil { return nil, err } - - sig, pubkey, err := keybase.Sign(name, passphrase, msg.Bytes()) - if err != nil { - return nil, err - } - - sigs := []auth.StdSignature{{ - AccountNumber: msg.AccountNumber, - Sequence: msg.Sequence, - PubKey: pubkey, - Signature: sig, - }} - - return ctx.Codec.MarshalBinary(auth.NewStdTx(msg.Msgs, msg.Fee, sigs, msg.Memo)) + return ctx.Codec.MarshalBinary(auth.NewStdTx(msg.Msgs, msg.Fee, []auth.StdSignature{sig}, msg.Memo)) } // BuildAndSign builds a single message to be signed, and signs a transaction @@ -177,3 +164,46 @@ func (ctx TxContext) BuildWithPubKey(name string, msgs []sdk.Msg) ([]byte, error return ctx.Codec.MarshalBinary(auth.NewStdTx(msg.Msgs, msg.Fee, sigs, msg.Memo)) } + +// SignStdTx appends a signature to a StdTx and returns a copy of a it. If append +// is false, it replaces the signatures already attached with the new signature. +func (ctx TxContext) SignStdTx(name, passphrase string, stdTx auth.StdTx, appendSig bool) (signedStdTx auth.StdTx, err error) { + stdSignature, err := MakeSignature(name, passphrase, auth.StdSignMsg{ + ChainID: ctx.ChainID, + AccountNumber: ctx.AccountNumber, + Sequence: ctx.Sequence, + Fee: stdTx.Fee, + Msgs: stdTx.GetMsgs(), + Memo: stdTx.GetMemo(), + }) + if err != nil { + return + } + + sigs := stdTx.GetSignatures() + if len(sigs) == 0 || !appendSig { + sigs = []auth.StdSignature{stdSignature} + } else { + sigs = append(sigs, stdSignature) + } + signedStdTx = auth.NewStdTx(stdTx.GetMsgs(), stdTx.Fee, sigs, stdTx.GetMemo()) + return +} + +// MakeSignature builds a StdSignature given key name, passphrase, and a StdSignMsg. +func MakeSignature(name, passphrase string, msg auth.StdSignMsg) (sig auth.StdSignature, err error) { + keybase, err := keys.GetKeyBase() + if err != nil { + return + } + sigBytes, pubkey, err := keybase.Sign(name, passphrase, msg.Bytes()) + if err != nil { + return + } + return auth.StdSignature{ + AccountNumber: msg.AccountNumber, + Sequence: msg.Sequence, + PubKey: pubkey, + Signature: sigBytes, + }, nil +} diff --git a/x/auth/client/rest/query.go b/x/auth/client/rest/query.go index 6ad50a14dd..3a5ab756d1 100644 --- a/x/auth/client/rest/query.go +++ b/x/auth/client/rest/query.go @@ -20,6 +20,10 @@ func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *wire.Codec, s "/accounts/{address}", QueryAccountRequestHandlerFn(storeName, cdc, authcmd.GetAccountDecoder(cdc), cliCtx), ).Methods("GET") + r.HandleFunc( + "/sign", + SignTxRequestHandlerFn(cdc, cliCtx), + ).Methods("POST") } // query accountREST Handler diff --git a/x/auth/client/rest/sign.go b/x/auth/client/rest/sign.go new file mode 100644 index 0000000000..bbbf7f26ce --- /dev/null +++ b/x/auth/client/rest/sign.go @@ -0,0 +1,60 @@ +package rest + +import ( + "io/ioutil" + "net/http" + + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/utils" + "github.com/cosmos/cosmos-sdk/wire" + "github.com/cosmos/cosmos-sdk/x/auth" + authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context" +) + +// SignBody defines the properties of a sign request's body. +type SignBody struct { + Tx auth.StdTx `json:"tx"` + LocalAccountName string `json:"name"` + Password string `json:"password"` + ChainID string `json:"chain_id"` + AccountNumber int64 `json:"account_number"` + Sequence int64 `json:"sequence"` +} + +// sign tx REST handler +func SignTxRequestHandlerFn(cdc *wire.Codec, cliCtx context.CLIContext) http.HandlerFunc { + + return func(w http.ResponseWriter, r *http.Request) { + var m SignBody + + body, err := ioutil.ReadAll(r.Body) + if err != nil { + utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + err = cdc.UnmarshalJSON(body, &m) + if err != nil { + utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + txCtx := authctx.TxContext{ + ChainID: m.ChainID, + AccountNumber: m.AccountNumber, + Sequence: m.Sequence, + } + + signedTx, err := txCtx.SignStdTx(m.LocalAccountName, m.Password, m.Tx, false) + if err != nil { + utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + + output, err := wire.MarshalJSONIndent(cdc, signedTx) + if err != nil { + utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + w.Write(output) + } +} From a450bf7ae4728b5003c6952d3fc7739922cbeba7 Mon Sep 17 00:00:00 2001 From: Juan Leni Date: Fri, 7 Sep 2018 15:33:24 +0200 Subject: [PATCH 59/93] Upgrading ledger-goclient --- .gitignore | 1 + Gopkg.lock | 21 +++++++++++---------- Gopkg.toml | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index eb10faca73..8498547cc2 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ # Build vendor +.vendor-new build tools/bin/* examples/build/* diff --git a/Gopkg.lock b/Gopkg.lock index 2245223419..f5221a4e50 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1,6 +1,14 @@ # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. +[[projects]] + branch = "master" + digest = "1:7736fc6da04620727f8f3aa2ced8d77be8e074a302820937aa5993848c769b27" + name = "github.com/ZondaX/hid-go" + packages = ["."] + pruneopts = "UT" + revision = "48b08affede2cea076a3cf13b2e3f72ed262b743" + [[projects]] digest = "1:09a7f74eb6bb3c0f14d8926610c87f569c5cff68e978d30e9a3540aeb626fdf0" name = "github.com/bartekn/go-bip39" @@ -24,14 +32,6 @@ revision = "4aabc24848ce5fd31929f7d1e4ea74d3709c14cd" version = "v0.1.0" -[[projects]] - branch = "master" - digest = "1:70f6b224a59b2fa453debffa85c77f71063d8754b90c8c4fbad5794e2c382b0f" - name = "github.com/brejski/hid" - packages = ["."] - pruneopts = "UT" - revision = "06112dcfcc50a7e0e4fd06e17f9791e788fdaafc" - [[projects]] branch = "master" digest = "1:2c00f064ba355903866cbfbf3f7f4c0fe64af6638cc7d1b8bdcf3181bc67f1d8" @@ -498,11 +498,12 @@ version = "v0.9.0" [[projects]] - digest = "1:4dcb0dd65feecb068ce23a234d1a07c7868a1e39f52a6defcae0bb371d03abf6" + digest = "1:7886f86064faff6f8d08a3eb0e8c773648ff5a2e27730831e2bfbf07467f6666" name = "github.com/zondax/ledger-goclient" packages = ["."] pruneopts = "UT" - revision = "4296ee5701e945f9b3a7dbe51f402e0b9be57259" + revision = "58598458c11bc0ad1c1b8dac3dc3e11eaf270b79" + version = "v0.1.0" [[projects]] branch = "master" diff --git a/Gopkg.toml b/Gopkg.toml index f8194ccd01..1b440891de 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -65,7 +65,7 @@ [[constraint]] name = "github.com/zondax/ledger-goclient" - revision = "4296ee5701e945f9b3a7dbe51f402e0b9be57259" + version = "=v0.1.0" [prune] go-tests = true From 3b6da7af18e90da05b123f26cfbdb8e3156a3cbe Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 7 Sep 2018 14:36:21 +0100 Subject: [PATCH 60/93] TxContext -> TxBuilder --- client/utils/rest.go | 2 +- client/utils/utils.go | 16 ++-- examples/democoin/x/cool/client/cli/tx.go | 4 +- examples/democoin/x/pow/client/cli/tx.go | 2 +- .../x/simplestake/client/cli/commands.go | 4 +- x/auth/client/context/context.go | 90 +++++++++---------- x/bank/client/cli/sendtx.go | 2 +- x/bank/client/rest/sendtx.go | 2 +- x/gov/client/cli/tx.go | 6 +- x/gov/client/rest/util.go | 2 +- x/ibc/client/cli/ibctx.go | 2 +- x/ibc/client/cli/relay.go | 2 +- x/ibc/client/rest/transfer.go | 2 +- x/slashing/client/cli/tx.go | 2 +- x/slashing/client/rest/tx.go | 2 +- x/stake/client/cli/tx.go | 14 +-- x/stake/client/rest/tx.go | 2 +- 17 files changed, 78 insertions(+), 78 deletions(-) diff --git a/client/utils/rest.go b/client/utils/rest.go index b6cee6c1f3..8bcb1173d5 100644 --- a/client/utils/rest.go +++ b/client/utils/rest.go @@ -52,7 +52,7 @@ func ParseFloat64OrReturnBadRequest(w http.ResponseWriter, s string, defaultIfEm } // WriteGenerateStdTxResponse writes response for the generate_only mode. -func WriteGenerateStdTxResponse(w http.ResponseWriter, txCtx authctx.TxContext, msgs []sdk.Msg) { +func WriteGenerateStdTxResponse(w http.ResponseWriter, txCtx authctx.TxBuilder, msgs []sdk.Msg) { stdMsg, err := txCtx.Build(msgs) if err != nil { WriteErrorResponse(w, http.StatusBadRequest, err.Error()) diff --git a/client/utils/utils.go b/client/utils/utils.go index fa5bcf817d..c0188e5c96 100644 --- a/client/utils/utils.go +++ b/client/utils/utils.go @@ -14,11 +14,11 @@ import ( ) // SendTx implements a auxiliary handler that facilitates sending a series of -// messages in a signed transaction given a TxContext and a QueryContext. It +// messages in a signed transaction given a TxBuilder and a QueryContext. It // ensures that the account exists, has a proper number and sequence set. In // addition, it builds and signs a transaction with the supplied messages. // Finally, it broadcasts the signed transaction to a node. -func SendTx(txCtx authctx.TxContext, cliCtx context.CLIContext, msgs []sdk.Msg) error { +func SendTx(txCtx authctx.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) error { txCtx, err := prepareTxContext(txCtx, cliCtx) if err != nil { return err @@ -50,7 +50,7 @@ func SendTx(txCtx authctx.TxContext, cliCtx context.CLIContext, msgs []sdk.Msg) } // SimulateMsgs simulates the transaction and returns the gas estimate and the adjusted value. -func SimulateMsgs(txCtx authctx.TxContext, cliCtx context.CLIContext, name string, msgs []sdk.Msg, gas int64) (estimated, adjusted int64, err error) { +func SimulateMsgs(txCtx authctx.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg, gas int64) (estimated, adjusted int64, err error) { txBytes, err := txCtx.WithGas(gas).BuildWithPubKey(name, msgs) if err != nil { return @@ -61,7 +61,7 @@ func SimulateMsgs(txCtx authctx.TxContext, cliCtx context.CLIContext, name strin // EnrichCtxWithGas calculates the gas estimate that would be consumed by the // transaction and set the transaction's respective value accordingly. -func EnrichCtxWithGas(txCtx authctx.TxContext, cliCtx context.CLIContext, name string, msgs []sdk.Msg) (authctx.TxContext, error) { +func EnrichCtxWithGas(txCtx authctx.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg) (authctx.TxBuilder, error) { _, adjusted, err := SimulateMsgs(txCtx, cliCtx, name, msgs, 0) if err != nil { return txCtx, err @@ -73,7 +73,7 @@ func EnrichCtxWithGas(txCtx authctx.TxContext, cliCtx context.CLIContext, name s // both the estimate obtained by the query and the adjusted amount. func CalculateGas(queryFunc func(string, common.HexBytes) ([]byte, error), cdc *amino.Codec, txBytes []byte, adjustment float64) (estimate, adjusted int64, err error) { // run a simulation (via /app/simulate query) to - // estimate gas and update TxContext accordingly + // estimate gas and update TxBuilder accordingly rawRes, err := queryFunc("/app/simulate", txBytes) if err != nil { return @@ -87,7 +87,7 @@ func CalculateGas(queryFunc func(string, common.HexBytes) ([]byte, error), cdc * } // PrintUnsignedStdTx builds an unsigned StdTx and prints it to os.Stdout. -func PrintUnsignedStdTx(txCtx authctx.TxContext, cliCtx context.CLIContext, msgs []sdk.Msg) (err error) { +func PrintUnsignedStdTx(txCtx authctx.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) (err error) { stdTx, err := buildUnsignedStdTx(txCtx, cliCtx, msgs) if err != nil { return @@ -111,7 +111,7 @@ func parseQueryResponse(cdc *amino.Codec, rawRes []byte) (int64, error) { return simulationResult.GasUsed, nil } -func prepareTxContext(txCtx authctx.TxContext, cliCtx context.CLIContext) (authctx.TxContext, error) { +func prepareTxContext(txCtx authctx.TxBuilder, cliCtx context.CLIContext) (authctx.TxBuilder, error) { if err := cliCtx.EnsureAccountExists(); err != nil { return txCtx, err } @@ -145,7 +145,7 @@ func prepareTxContext(txCtx authctx.TxContext, cliCtx context.CLIContext) (authc // buildUnsignedStdTx builds a StdTx as per the parameters passed in the // contexts. Gas is automatically estimated if gas wanted is set to 0. -func buildUnsignedStdTx(txCtx authctx.TxContext, cliCtx context.CLIContext, msgs []sdk.Msg) (stdTx auth.StdTx, err error) { +func buildUnsignedStdTx(txCtx authctx.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) (stdTx auth.StdTx, err error) { txCtx, err = prepareTxContext(txCtx, cliCtx) if err != nil { return diff --git a/examples/democoin/x/cool/client/cli/tx.go b/examples/democoin/x/cool/client/cli/tx.go index 82b46be738..84ebffba41 100644 --- a/examples/democoin/x/cool/client/cli/tx.go +++ b/examples/democoin/x/cool/client/cli/tx.go @@ -21,7 +21,7 @@ func QuizTxCmd(cdc *wire.Codec) *cobra.Command { Short: "What's cooler than being cool?", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) + txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -46,7 +46,7 @@ func SetTrendTxCmd(cdc *wire.Codec) *cobra.Command { Short: "You're so cool, tell us what is cool!", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) + txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). diff --git a/examples/democoin/x/pow/client/cli/tx.go b/examples/democoin/x/pow/client/cli/tx.go index af1a8a060b..ef62618ea7 100644 --- a/examples/democoin/x/pow/client/cli/tx.go +++ b/examples/democoin/x/pow/client/cli/tx.go @@ -22,7 +22,7 @@ func MineCmd(cdc *wire.Codec) *cobra.Command { Short: "Mine some coins with proof-of-work!", Args: cobra.ExactArgs(4), RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) + txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). diff --git a/examples/democoin/x/simplestake/client/cli/commands.go b/examples/democoin/x/simplestake/client/cli/commands.go index a387dcac3f..9e9a9004e1 100644 --- a/examples/democoin/x/simplestake/client/cli/commands.go +++ b/examples/democoin/x/simplestake/client/cli/commands.go @@ -30,7 +30,7 @@ func BondTxCmd(cdc *wire.Codec) *cobra.Command { Use: "bond", Short: "Bond to a validator", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) + txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -84,7 +84,7 @@ func UnbondTxCmd(cdc *wire.Codec) *cobra.Command { Use: "unbond", Short: "Unbond from a validator", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) + txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout) diff --git a/x/auth/client/context/context.go b/x/auth/client/context/context.go index 5e55696b83..41b8018051 100644 --- a/x/auth/client/context/context.go +++ b/x/auth/client/context/context.go @@ -11,8 +11,8 @@ import ( "github.com/spf13/viper" ) -// TxContext implements a transaction context created in SDK modules. -type TxContext struct { +// TxBuilder implements a transaction context created in SDK modules. +type TxBuilder struct { Codec *wire.Codec AccountNumber int64 Sequence int64 @@ -22,9 +22,9 @@ type TxContext struct { Fee string } -// NewTxContextFromCLI returns a new initialized TxContext with parameters from +// NewTxBuilderFromCLI returns a new initialized TxBuilder with parameters from // the command line using Viper. -func NewTxContextFromCLI() TxContext { +func NewTxBuilderFromCLI() TxBuilder { // if chain ID is not specified manually, read default chain ID chainID := viper.GetString(client.FlagChainID) if chainID == "" { @@ -34,7 +34,7 @@ func NewTxContextFromCLI() TxContext { } } - return TxContext{ + return TxBuilder{ ChainID: chainID, Gas: viper.GetInt64(client.FlagGas), AccountNumber: viper.GetInt64(client.FlagAccountNumber), @@ -45,58 +45,58 @@ func NewTxContextFromCLI() TxContext { } // WithCodec returns a copy of the context with an updated codec. -func (ctx TxContext) WithCodec(cdc *wire.Codec) TxContext { - ctx.Codec = cdc - return ctx +func (bld TxBuilder) WithCodec(cdc *wire.Codec) TxBuilder { + bld.Codec = cdc + return bld } // WithChainID returns a copy of the context with an updated chainID. -func (ctx TxContext) WithChainID(chainID string) TxContext { - ctx.ChainID = chainID - return ctx +func (bld TxBuilder) WithChainID(chainID string) TxBuilder { + bld.ChainID = chainID + return bld } // WithGas returns a copy of the context with an updated gas. -func (ctx TxContext) WithGas(gas int64) TxContext { - ctx.Gas = gas - return ctx +func (bld TxBuilder) WithGas(gas int64) TxBuilder { + bld.Gas = gas + return bld } // WithFee returns a copy of the context with an updated fee. -func (ctx TxContext) WithFee(fee string) TxContext { - ctx.Fee = fee - return ctx +func (bld TxBuilder) WithFee(fee string) TxBuilder { + bld.Fee = fee + return bld } // WithSequence returns a copy of the context with an updated sequence number. -func (ctx TxContext) WithSequence(sequence int64) TxContext { - ctx.Sequence = sequence - return ctx +func (bld TxBuilder) WithSequence(sequence int64) TxBuilder { + bld.Sequence = sequence + return bld } // WithMemo returns a copy of the context with an updated memo. -func (ctx TxContext) WithMemo(memo string) TxContext { - ctx.Memo = memo - return ctx +func (bld TxBuilder) WithMemo(memo string) TxBuilder { + bld.Memo = memo + return bld } // WithAccountNumber returns a copy of the context with an account number. -func (ctx TxContext) WithAccountNumber(accnum int64) TxContext { - ctx.AccountNumber = accnum - return ctx +func (bld TxBuilder) WithAccountNumber(accnum int64) TxBuilder { + bld.AccountNumber = accnum + return bld } -// Build builds a single message to be signed from a TxContext given a set of +// Build builds a single message to be signed from a TxBuilder given a set of // messages. It returns an error if a fee is supplied but cannot be parsed. -func (ctx TxContext) Build(msgs []sdk.Msg) (auth.StdSignMsg, error) { - chainID := ctx.ChainID +func (bld TxBuilder) Build(msgs []sdk.Msg) (auth.StdSignMsg, error) { + chainID := bld.ChainID if chainID == "" { return auth.StdSignMsg{}, errors.Errorf("chain ID required but not specified") } fee := sdk.Coin{} - if ctx.Fee != "" { - parsedFee, err := sdk.ParseCoin(ctx.Fee) + if bld.Fee != "" { + parsedFee, err := sdk.ParseCoin(bld.Fee) if err != nil { return auth.StdSignMsg{}, err } @@ -105,18 +105,18 @@ func (ctx TxContext) Build(msgs []sdk.Msg) (auth.StdSignMsg, error) { } return auth.StdSignMsg{ - ChainID: ctx.ChainID, - AccountNumber: ctx.AccountNumber, - Sequence: ctx.Sequence, - Memo: ctx.Memo, + ChainID: bld.ChainID, + AccountNumber: bld.AccountNumber, + Sequence: bld.Sequence, + Memo: bld.Memo, Msgs: msgs, - Fee: auth.NewStdFee(ctx.Gas, fee), + Fee: auth.NewStdFee(bld.Gas, fee), }, nil } // Sign signs a transaction given a name, passphrase, and a single message to // signed. An error is returned if signing fails. -func (ctx TxContext) Sign(name, passphrase string, msg auth.StdSignMsg) ([]byte, error) { +func (bld TxBuilder) Sign(name, passphrase string, msg auth.StdSignMsg) ([]byte, error) { keybase, err := keys.GetKeyBase() if err != nil { return nil, err @@ -134,27 +134,27 @@ func (ctx TxContext) Sign(name, passphrase string, msg auth.StdSignMsg) ([]byte, Signature: sig, }} - return ctx.Codec.MarshalBinary(auth.NewStdTx(msg.Msgs, msg.Fee, sigs, msg.Memo)) + return bld.Codec.MarshalBinary(auth.NewStdTx(msg.Msgs, msg.Fee, sigs, msg.Memo)) } // BuildAndSign builds a single message to be signed, and signs a transaction // with the built message given a name, passphrase, and a set of // messages. -func (ctx TxContext) BuildAndSign(name, passphrase string, msgs []sdk.Msg) ([]byte, error) { - msg, err := ctx.Build(msgs) +func (bld TxBuilder) BuildAndSign(name, passphrase string, msgs []sdk.Msg) ([]byte, error) { + msg, err := bld.Build(msgs) if err != nil { return nil, err } - return ctx.Sign(name, passphrase, msg) + return bld.Sign(name, passphrase, msg) } -// BuildWithPubKey builds a single message to be signed from a TxContext given a set of +// BuildWithPubKey builds a single message to be signed from a TxBuilder given a set of // messages and attach the public key associated to the given name. // It returns an error if a fee is supplied but cannot be parsed or the key cannot be // retrieved. -func (ctx TxContext) BuildWithPubKey(name string, msgs []sdk.Msg) ([]byte, error) { - msg, err := ctx.Build(msgs) +func (bld TxBuilder) BuildWithPubKey(name string, msgs []sdk.Msg) ([]byte, error) { + msg, err := bld.Build(msgs) if err != nil { return nil, err } @@ -175,5 +175,5 @@ func (ctx TxContext) BuildWithPubKey(name string, msgs []sdk.Msg) ([]byte, error PubKey: info.GetPubKey(), }} - return ctx.Codec.MarshalBinary(auth.NewStdTx(msg.Msgs, msg.Fee, sigs, msg.Memo)) + return bld.Codec.MarshalBinary(auth.NewStdTx(msg.Msgs, msg.Fee, sigs, msg.Memo)) } diff --git a/x/bank/client/cli/sendtx.go b/x/bank/client/cli/sendtx.go index 08210569e0..9d812bfb0a 100644 --- a/x/bank/client/cli/sendtx.go +++ b/x/bank/client/cli/sendtx.go @@ -27,7 +27,7 @@ func SendTxCmd(cdc *wire.Codec) *cobra.Command { Use: "send", Short: "Create and sign a send tx", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) + txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). diff --git a/x/bank/client/rest/sendtx.go b/x/bank/client/rest/sendtx.go index 1c09943d07..1c104cee02 100644 --- a/x/bank/client/rest/sendtx.go +++ b/x/bank/client/rest/sendtx.go @@ -80,7 +80,7 @@ func SendRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLICo return } - txCtx := authctx.TxContext{ + txCtx := authctx.TxBuilder{ Codec: cdc, Gas: m.Gas, ChainID: m.ChainID, diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index e9a55c5577..516753a619 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -77,7 +77,7 @@ $ gaiacli gov submit-proposal --title="Test Proposal" --description="My awesome return err } - txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) + txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -161,7 +161,7 @@ func GetCmdDeposit(cdc *wire.Codec) *cobra.Command { Use: "deposit", Short: "deposit tokens for activing proposal", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) + txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -207,7 +207,7 @@ func GetCmdVote(cdc *wire.Codec) *cobra.Command { Use: "vote", Short: "vote for an active proposal, options: Yes/No/NoWithVeto/Abstain", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) + txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). diff --git a/x/gov/client/rest/util.go b/x/gov/client/rest/util.go index 7ba23befaa..d10ca48b7c 100644 --- a/x/gov/client/rest/util.go +++ b/x/gov/client/rest/util.go @@ -70,7 +70,7 @@ func (req baseReq) baseReqValidate(w http.ResponseWriter) bool { // (probably should live in client/lcd). func signAndBuild(w http.ResponseWriter, r *http.Request, cliCtx context.CLIContext, baseReq baseReq, msg sdk.Msg, cdc *wire.Codec) { var err error - txCtx := authctx.TxContext{ + txCtx := authctx.TxBuilder{ Codec: cdc, AccountNumber: baseReq.AccountNumber, Sequence: baseReq.Sequence, diff --git a/x/ibc/client/cli/ibctx.go b/x/ibc/client/cli/ibctx.go index 37cf7ce91e..bf5d551e59 100644 --- a/x/ibc/client/cli/ibctx.go +++ b/x/ibc/client/cli/ibctx.go @@ -28,7 +28,7 @@ func IBCTransferCmd(cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "transfer", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) + txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). diff --git a/x/ibc/client/cli/relay.go b/x/ibc/client/cli/relay.go index 37479980c5..deeb4d2d17 100644 --- a/x/ibc/client/cli/relay.go +++ b/x/ibc/client/cli/relay.go @@ -199,7 +199,7 @@ func (c relayCommander) refine(bz []byte, sequence int64, passphrase string) []b Sequence: sequence, } - txCtx := authctx.NewTxContextFromCLI().WithSequence(sequence).WithCodec(c.cdc) + txCtx := authctx.NewTxBuilderFromCLI().WithSequence(sequence).WithCodec(c.cdc) cliCtx := context.NewCLIContext() res, err := txCtx.BuildAndSign(cliCtx.FromAddressName, passphrase, []sdk.Msg{msg}) diff --git a/x/ibc/client/rest/transfer.go b/x/ibc/client/rest/transfer.go index 7f5595dd7c..1bd0cb84b2 100644 --- a/x/ibc/client/rest/transfer.go +++ b/x/ibc/client/rest/transfer.go @@ -71,7 +71,7 @@ func TransferRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.C packet := ibc.NewIBCPacket(sdk.AccAddress(info.GetPubKey().Address()), to, m.Amount, m.SrcChainID, destChainID) msg := ibc.IBCTransferMsg{packet} - txCtx := authctx.TxContext{ + txCtx := authctx.TxBuilder{ Codec: cdc, ChainID: m.SrcChainID, AccountNumber: m.AccountNumber, diff --git a/x/slashing/client/cli/tx.go b/x/slashing/client/cli/tx.go index d69a9e1583..777d1542ce 100644 --- a/x/slashing/client/cli/tx.go +++ b/x/slashing/client/cli/tx.go @@ -21,7 +21,7 @@ func GetCmdUnjail(cdc *wire.Codec) *cobra.Command { Args: cobra.NoArgs, Short: "unjail validator previously jailed for downtime", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) + txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). diff --git a/x/slashing/client/rest/tx.go b/x/slashing/client/rest/tx.go index bbed6ed9ab..2b9c901959 100644 --- a/x/slashing/client/rest/tx.go +++ b/x/slashing/client/rest/tx.go @@ -70,7 +70,7 @@ func unjailRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLI return } - txCtx := authctx.TxContext{ + txCtx := authctx.TxBuilder{ Codec: cdc, ChainID: m.ChainID, AccountNumber: m.AccountNumber, diff --git a/x/stake/client/cli/tx.go b/x/stake/client/cli/tx.go index bd38e7b5b5..2e5e227557 100644 --- a/x/stake/client/cli/tx.go +++ b/x/stake/client/cli/tx.go @@ -25,7 +25,7 @@ func GetCmdCreateValidator(cdc *wire.Codec) *cobra.Command { Use: "create-validator", Short: "create new validator initialized with a self-delegation to it", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) + txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -99,7 +99,7 @@ func GetCmdEditValidator(cdc *wire.Codec) *cobra.Command { Use: "edit-validator", Short: "edit and existing validator account", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) + txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -138,7 +138,7 @@ func GetCmdDelegate(cdc *wire.Codec) *cobra.Command { Use: "delegate", Short: "delegate liquid tokens to an validator", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) + txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -197,7 +197,7 @@ func GetCmdBeginRedelegate(storeName string, cdc *wire.Codec) *cobra.Command { Use: "begin", Short: "begin redelegation", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) + txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -301,7 +301,7 @@ func GetCmdCompleteRedelegate(cdc *wire.Codec) *cobra.Command { Use: "complete", Short: "complete redelegation", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) + txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -359,7 +359,7 @@ func GetCmdBeginUnbonding(storeName string, cdc *wire.Codec) *cobra.Command { Use: "begin", Short: "begin unbonding", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) + txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -408,7 +408,7 @@ func GetCmdCompleteUnbonding(cdc *wire.Codec) *cobra.Command { Use: "complete", Short: "complete unbonding", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) + txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). diff --git a/x/stake/client/rest/tx.go b/x/stake/client/rest/tx.go index 4bb6d0f7e5..dd478487b3 100644 --- a/x/stake/client/rest/tx.go +++ b/x/stake/client/rest/tx.go @@ -263,7 +263,7 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex i++ } - txCtx := authcliCtx.TxContext{ + txCtx := authcliCtx.TxBuilder{ Codec: cdc, ChainID: m.ChainID, Gas: m.Gas, From 54b3b5c028cf42e559981f8109d263734576136b Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 7 Sep 2018 14:39:23 +0100 Subject: [PATCH 61/93] sed -i 's/txCtx/txBld/g' --- client/utils/rest.go | 6 +- client/utils/utils.go | 60 +++++++++---------- examples/democoin/x/cool/client/cli/tx.go | 8 +-- examples/democoin/x/pow/client/cli/tx.go | 4 +- .../x/simplestake/client/cli/commands.go | 8 +-- x/bank/client/cli/sendtx.go | 6 +- x/bank/client/rest/sendtx.go | 12 ++-- x/gov/client/cli/tx.go | 18 +++--- x/gov/client/rest/util.go | 12 ++-- x/ibc/client/cli/ibctx.go | 6 +- x/ibc/client/cli/relay.go | 4 +- x/ibc/client/rest/transfer.go | 12 ++-- x/slashing/client/cli/tx.go | 6 +- x/slashing/client/rest/tx.go | 12 ++-- x/stake/client/cli/tx.go | 42 ++++++------- x/stake/client/rest/tx.go | 16 ++--- 16 files changed, 116 insertions(+), 116 deletions(-) diff --git a/client/utils/rest.go b/client/utils/rest.go index 8bcb1173d5..6446fb1337 100644 --- a/client/utils/rest.go +++ b/client/utils/rest.go @@ -52,13 +52,13 @@ func ParseFloat64OrReturnBadRequest(w http.ResponseWriter, s string, defaultIfEm } // WriteGenerateStdTxResponse writes response for the generate_only mode. -func WriteGenerateStdTxResponse(w http.ResponseWriter, txCtx authctx.TxBuilder, msgs []sdk.Msg) { - stdMsg, err := txCtx.Build(msgs) +func WriteGenerateStdTxResponse(w http.ResponseWriter, txBld authctx.TxBuilder, msgs []sdk.Msg) { + stdMsg, err := txBld.Build(msgs) if err != nil { WriteErrorResponse(w, http.StatusBadRequest, err.Error()) return } - output, err := txCtx.Codec.MarshalJSON(auth.NewStdTx(stdMsg.Msgs, stdMsg.Fee, nil, stdMsg.Memo)) + output, err := txBld.Codec.MarshalJSON(auth.NewStdTx(stdMsg.Msgs, stdMsg.Fee, nil, stdMsg.Memo)) if err != nil { WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return diff --git a/client/utils/utils.go b/client/utils/utils.go index c0188e5c96..32cc810006 100644 --- a/client/utils/utils.go +++ b/client/utils/utils.go @@ -18,18 +18,18 @@ import ( // ensures that the account exists, has a proper number and sequence set. In // addition, it builds and signs a transaction with the supplied messages. // Finally, it broadcasts the signed transaction to a node. -func SendTx(txCtx authctx.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) error { - txCtx, err := prepareTxContext(txCtx, cliCtx) +func SendTx(txBld authctx.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) error { + txBld, err := prepareTxContext(txBld, cliCtx) if err != nil { return err } autogas := cliCtx.DryRun || (cliCtx.Gas == 0) if autogas { - txCtx, err = EnrichCtxWithGas(txCtx, cliCtx, cliCtx.FromAddressName, msgs) + txBld, err = EnrichCtxWithGas(txBld, cliCtx, cliCtx.FromAddressName, msgs) if err != nil { return err } - fmt.Fprintf(os.Stderr, "estimated gas = %v\n", txCtx.Gas) + fmt.Fprintf(os.Stderr, "estimated gas = %v\n", txBld.Gas) } if cliCtx.DryRun { return nil @@ -41,7 +41,7 @@ func SendTx(txCtx authctx.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) } // build and sign the transaction - txBytes, err := txCtx.BuildAndSign(cliCtx.FromAddressName, passphrase, msgs) + txBytes, err := txBld.BuildAndSign(cliCtx.FromAddressName, passphrase, msgs) if err != nil { return err } @@ -50,8 +50,8 @@ func SendTx(txCtx authctx.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) } // SimulateMsgs simulates the transaction and returns the gas estimate and the adjusted value. -func SimulateMsgs(txCtx authctx.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg, gas int64) (estimated, adjusted int64, err error) { - txBytes, err := txCtx.WithGas(gas).BuildWithPubKey(name, msgs) +func SimulateMsgs(txBld authctx.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg, gas int64) (estimated, adjusted int64, err error) { + txBytes, err := txBld.WithGas(gas).BuildWithPubKey(name, msgs) if err != nil { return } @@ -61,12 +61,12 @@ func SimulateMsgs(txCtx authctx.TxBuilder, cliCtx context.CLIContext, name strin // EnrichCtxWithGas calculates the gas estimate that would be consumed by the // transaction and set the transaction's respective value accordingly. -func EnrichCtxWithGas(txCtx authctx.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg) (authctx.TxBuilder, error) { - _, adjusted, err := SimulateMsgs(txCtx, cliCtx, name, msgs, 0) +func EnrichCtxWithGas(txBld authctx.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg) (authctx.TxBuilder, error) { + _, adjusted, err := SimulateMsgs(txBld, cliCtx, name, msgs, 0) if err != nil { - return txCtx, err + return txBld, err } - return txCtx.WithGas(adjusted), nil + return txBld.WithGas(adjusted), nil } // CalculateGas simulates the execution of a transaction and returns @@ -87,12 +87,12 @@ func CalculateGas(queryFunc func(string, common.HexBytes) ([]byte, error), cdc * } // PrintUnsignedStdTx builds an unsigned StdTx and prints it to os.Stdout. -func PrintUnsignedStdTx(txCtx authctx.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) (err error) { - stdTx, err := buildUnsignedStdTx(txCtx, cliCtx, msgs) +func PrintUnsignedStdTx(txBld authctx.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) (err error) { + stdTx, err := buildUnsignedStdTx(txBld, cliCtx, msgs) if err != nil { return } - json, err := txCtx.Codec.MarshalJSON(stdTx) + json, err := txBld.Codec.MarshalJSON(stdTx) if err == nil { fmt.Printf("%s\n", json) } @@ -111,53 +111,53 @@ func parseQueryResponse(cdc *amino.Codec, rawRes []byte) (int64, error) { return simulationResult.GasUsed, nil } -func prepareTxContext(txCtx authctx.TxBuilder, cliCtx context.CLIContext) (authctx.TxBuilder, error) { +func prepareTxContext(txBld authctx.TxBuilder, cliCtx context.CLIContext) (authctx.TxBuilder, error) { if err := cliCtx.EnsureAccountExists(); err != nil { - return txCtx, err + return txBld, err } from, err := cliCtx.GetFromAddress() if err != nil { - return txCtx, err + return txBld, err } // TODO: (ref #1903) Allow for user supplied account number without // automatically doing a manual lookup. - if txCtx.AccountNumber == 0 { + if txBld.AccountNumber == 0 { accNum, err := cliCtx.GetAccountNumber(from) if err != nil { - return txCtx, err + return txBld, err } - txCtx = txCtx.WithAccountNumber(accNum) + txBld = txBld.WithAccountNumber(accNum) } // TODO: (ref #1903) Allow for user supplied account sequence without // automatically doing a manual lookup. - if txCtx.Sequence == 0 { + if txBld.Sequence == 0 { accSeq, err := cliCtx.GetAccountSequence(from) if err != nil { - return txCtx, err + return txBld, err } - txCtx = txCtx.WithSequence(accSeq) + txBld = txBld.WithSequence(accSeq) } - return txCtx, nil + return txBld, nil } // buildUnsignedStdTx builds a StdTx as per the parameters passed in the // contexts. Gas is automatically estimated if gas wanted is set to 0. -func buildUnsignedStdTx(txCtx authctx.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) (stdTx auth.StdTx, err error) { - txCtx, err = prepareTxContext(txCtx, cliCtx) +func buildUnsignedStdTx(txBld authctx.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) (stdTx auth.StdTx, err error) { + txBld, err = prepareTxContext(txBld, cliCtx) if err != nil { return } - if txCtx.Gas == 0 { - txCtx, err = EnrichCtxWithGas(txCtx, cliCtx, cliCtx.FromAddressName, msgs) + if txBld.Gas == 0 { + txBld, err = EnrichCtxWithGas(txBld, cliCtx, cliCtx.FromAddressName, msgs) if err != nil { return } - fmt.Fprintf(os.Stderr, "estimated gas = %v\n", txCtx.Gas) + fmt.Fprintf(os.Stderr, "estimated gas = %v\n", txBld.Gas) } - stdSignMsg, err := txCtx.Build(msgs) + stdSignMsg, err := txBld.Build(msgs) if err != nil { return } diff --git a/examples/democoin/x/cool/client/cli/tx.go b/examples/democoin/x/cool/client/cli/tx.go index 84ebffba41..0134a1ea62 100644 --- a/examples/democoin/x/cool/client/cli/tx.go +++ b/examples/democoin/x/cool/client/cli/tx.go @@ -21,7 +21,7 @@ func QuizTxCmd(cdc *wire.Codec) *cobra.Command { Short: "What's cooler than being cool?", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -34,7 +34,7 @@ func QuizTxCmd(cdc *wire.Codec) *cobra.Command { msg := cool.NewMsgQuiz(from, args[0]) - return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) }, } } @@ -46,7 +46,7 @@ func SetTrendTxCmd(cdc *wire.Codec) *cobra.Command { Short: "You're so cool, tell us what is cool!", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -59,7 +59,7 @@ func SetTrendTxCmd(cdc *wire.Codec) *cobra.Command { msg := cool.NewMsgSetTrend(from, args[0]) - return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) }, } } diff --git a/examples/democoin/x/pow/client/cli/tx.go b/examples/democoin/x/pow/client/cli/tx.go index ef62618ea7..820dd105c6 100644 --- a/examples/democoin/x/pow/client/cli/tx.go +++ b/examples/democoin/x/pow/client/cli/tx.go @@ -22,7 +22,7 @@ func MineCmd(cdc *wire.Codec) *cobra.Command { Short: "Mine some coins with proof-of-work!", Args: cobra.ExactArgs(4), RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -53,7 +53,7 @@ func MineCmd(cdc *wire.Codec) *cobra.Command { // Build and sign the transaction, then broadcast to a Tendermint // node. - return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) }, } } diff --git a/examples/democoin/x/simplestake/client/cli/commands.go b/examples/democoin/x/simplestake/client/cli/commands.go index 9e9a9004e1..f8bd075de4 100644 --- a/examples/democoin/x/simplestake/client/cli/commands.go +++ b/examples/democoin/x/simplestake/client/cli/commands.go @@ -30,7 +30,7 @@ func BondTxCmd(cdc *wire.Codec) *cobra.Command { Use: "bond", Short: "Bond to a validator", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -68,7 +68,7 @@ func BondTxCmd(cdc *wire.Codec) *cobra.Command { // Build and sign the transaction, then broadcast to a Tendermint // node. - return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) }, } @@ -84,7 +84,7 @@ func UnbondTxCmd(cdc *wire.Codec) *cobra.Command { Use: "unbond", Short: "Unbond from a validator", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout) @@ -98,7 +98,7 @@ func UnbondTxCmd(cdc *wire.Codec) *cobra.Command { // Build and sign the transaction, then broadcast to a Tendermint // node. - return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) }, } diff --git a/x/bank/client/cli/sendtx.go b/x/bank/client/cli/sendtx.go index 9d812bfb0a..98fb3e9843 100644 --- a/x/bank/client/cli/sendtx.go +++ b/x/bank/client/cli/sendtx.go @@ -27,7 +27,7 @@ func SendTxCmd(cdc *wire.Codec) *cobra.Command { Use: "send", Short: "Create and sign a send tx", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -69,10 +69,10 @@ func SendTxCmd(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint msg := client.BuildMsg(from, to, coins) if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) } - return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) }, } diff --git a/x/bank/client/rest/sendtx.go b/x/bank/client/rest/sendtx.go index 1c104cee02..f0d2d6308d 100644 --- a/x/bank/client/rest/sendtx.go +++ b/x/bank/client/rest/sendtx.go @@ -80,7 +80,7 @@ func SendRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLICo return } - txCtx := authctx.TxBuilder{ + txBld := authctx.TxBuilder{ Codec: cdc, Gas: m.Gas, ChainID: m.ChainID, @@ -95,24 +95,24 @@ func SendRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLICo cliCtx = cliCtx.WithGasAdjustment(adjustment) if utils.HasDryRunArg(r) || m.Gas == 0 { - newCtx, err := utils.EnrichCtxWithGas(txCtx, cliCtx, m.LocalAccountName, []sdk.Msg{msg}) + newCtx, err := utils.EnrichCtxWithGas(txBld, cliCtx, m.LocalAccountName, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } if utils.HasDryRunArg(r) { - utils.WriteSimulationResponse(w, txCtx.Gas) + utils.WriteSimulationResponse(w, txBld.Gas) return } - txCtx = newCtx + txBld = newCtx } if utils.HasGenerateOnlyArg(r) { - utils.WriteGenerateStdTxResponse(w, txCtx, []sdk.Msg{msg}) + utils.WriteGenerateStdTxResponse(w, txBld, []sdk.Msg{msg}) return } - txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) + txBytes, err := txBld.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error()) return diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index 516753a619..da828e513a 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -77,7 +77,7 @@ $ gaiacli gov submit-proposal --title="Test Proposal" --description="My awesome return err } - txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -105,13 +105,13 @@ $ gaiacli gov submit-proposal --title="Test Proposal" --description="My awesome } if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) } // Build and sign the transaction, then broadcast to Tendermint // proposalID must be returned, and it is a part of response. cliCtx.PrintResponse = true - return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) }, } @@ -161,7 +161,7 @@ func GetCmdDeposit(cdc *wire.Codec) *cobra.Command { Use: "deposit", Short: "deposit tokens for activing proposal", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -186,12 +186,12 @@ func GetCmdDeposit(cdc *wire.Codec) *cobra.Command { } if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) } // Build and sign the transaction, then broadcast to a Tendermint // node. - return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) }, } @@ -207,7 +207,7 @@ func GetCmdVote(cdc *wire.Codec) *cobra.Command { Use: "vote", Short: "vote for an active proposal, options: Yes/No/NoWithVeto/Abstain", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -233,7 +233,7 @@ func GetCmdVote(cdc *wire.Codec) *cobra.Command { } if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) } fmt.Printf("Vote[Voter:%s,ProposalID:%d,Option:%s]", @@ -242,7 +242,7 @@ func GetCmdVote(cdc *wire.Codec) *cobra.Command { // Build and sign the transaction, then broadcast to a Tendermint // node. - return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) }, } diff --git a/x/gov/client/rest/util.go b/x/gov/client/rest/util.go index d10ca48b7c..f8152042e3 100644 --- a/x/gov/client/rest/util.go +++ b/x/gov/client/rest/util.go @@ -70,7 +70,7 @@ func (req baseReq) baseReqValidate(w http.ResponseWriter) bool { // (probably should live in client/lcd). func signAndBuild(w http.ResponseWriter, r *http.Request, cliCtx context.CLIContext, baseReq baseReq, msg sdk.Msg, cdc *wire.Codec) { var err error - txCtx := authctx.TxBuilder{ + txBld := authctx.TxBuilder{ Codec: cdc, AccountNumber: baseReq.AccountNumber, Sequence: baseReq.Sequence, @@ -85,24 +85,24 @@ func signAndBuild(w http.ResponseWriter, r *http.Request, cliCtx context.CLICont cliCtx = cliCtx.WithGasAdjustment(adjustment) if utils.HasDryRunArg(r) || baseReq.Gas == 0 { - newCtx, err := utils.EnrichCtxWithGas(txCtx, cliCtx, baseReq.Name, []sdk.Msg{msg}) + newCtx, err := utils.EnrichCtxWithGas(txBld, cliCtx, baseReq.Name, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } if utils.HasDryRunArg(r) { - utils.WriteSimulationResponse(w, txCtx.Gas) + utils.WriteSimulationResponse(w, txBld.Gas) return } - txCtx = newCtx + txBld = newCtx } if utils.HasGenerateOnlyArg(r) { - utils.WriteGenerateStdTxResponse(w, txCtx, []sdk.Msg{msg}) + utils.WriteGenerateStdTxResponse(w, txBld, []sdk.Msg{msg}) return } - txBytes, err := txCtx.BuildAndSign(baseReq.Name, baseReq.Password, []sdk.Msg{msg}) + txBytes, err := txBld.BuildAndSign(baseReq.Name, baseReq.Password, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error()) return diff --git a/x/ibc/client/cli/ibctx.go b/x/ibc/client/cli/ibctx.go index bf5d551e59..9c20a44f71 100644 --- a/x/ibc/client/cli/ibctx.go +++ b/x/ibc/client/cli/ibctx.go @@ -28,7 +28,7 @@ func IBCTransferCmd(cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "transfer", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -44,10 +44,10 @@ func IBCTransferCmd(cdc *wire.Codec) *cobra.Command { return err } if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) } - return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) }, } diff --git a/x/ibc/client/cli/relay.go b/x/ibc/client/cli/relay.go index deeb4d2d17..1bb679987b 100644 --- a/x/ibc/client/cli/relay.go +++ b/x/ibc/client/cli/relay.go @@ -199,10 +199,10 @@ func (c relayCommander) refine(bz []byte, sequence int64, passphrase string) []b Sequence: sequence, } - txCtx := authctx.NewTxBuilderFromCLI().WithSequence(sequence).WithCodec(c.cdc) + txBld := authctx.NewTxBuilderFromCLI().WithSequence(sequence).WithCodec(c.cdc) cliCtx := context.NewCLIContext() - res, err := txCtx.BuildAndSign(cliCtx.FromAddressName, passphrase, []sdk.Msg{msg}) + res, err := txBld.BuildAndSign(cliCtx.FromAddressName, passphrase, []sdk.Msg{msg}) if err != nil { panic(err) } diff --git a/x/ibc/client/rest/transfer.go b/x/ibc/client/rest/transfer.go index 1bd0cb84b2..c071e48d14 100644 --- a/x/ibc/client/rest/transfer.go +++ b/x/ibc/client/rest/transfer.go @@ -71,7 +71,7 @@ func TransferRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.C packet := ibc.NewIBCPacket(sdk.AccAddress(info.GetPubKey().Address()), to, m.Amount, m.SrcChainID, destChainID) msg := ibc.IBCTransferMsg{packet} - txCtx := authctx.TxBuilder{ + txBld := authctx.TxBuilder{ Codec: cdc, ChainID: m.SrcChainID, AccountNumber: m.AccountNumber, @@ -86,24 +86,24 @@ func TransferRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.C cliCtx = cliCtx.WithGasAdjustment(adjustment) if utils.HasDryRunArg(r) || m.Gas == 0 { - newCtx, err := utils.EnrichCtxWithGas(txCtx, cliCtx, m.LocalAccountName, []sdk.Msg{msg}) + newCtx, err := utils.EnrichCtxWithGas(txBld, cliCtx, m.LocalAccountName, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } if utils.HasDryRunArg(r) { - utils.WriteSimulationResponse(w, txCtx.Gas) + utils.WriteSimulationResponse(w, txBld.Gas) return } - txCtx = newCtx + txBld = newCtx } if utils.HasGenerateOnlyArg(r) { - utils.WriteGenerateStdTxResponse(w, txCtx, []sdk.Msg{msg}) + utils.WriteGenerateStdTxResponse(w, txBld, []sdk.Msg{msg}) return } - txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) + txBytes, err := txBld.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error()) return diff --git a/x/slashing/client/cli/tx.go b/x/slashing/client/cli/tx.go index 777d1542ce..60c89a2cb0 100644 --- a/x/slashing/client/cli/tx.go +++ b/x/slashing/client/cli/tx.go @@ -21,7 +21,7 @@ func GetCmdUnjail(cdc *wire.Codec) *cobra.Command { Args: cobra.NoArgs, Short: "unjail validator previously jailed for downtime", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -34,9 +34,9 @@ func GetCmdUnjail(cdc *wire.Codec) *cobra.Command { msg := slashing.NewMsgUnjail(sdk.ValAddress(valAddr)) if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) } - return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) }, } diff --git a/x/slashing/client/rest/tx.go b/x/slashing/client/rest/tx.go index 2b9c901959..4c07515cbd 100644 --- a/x/slashing/client/rest/tx.go +++ b/x/slashing/client/rest/tx.go @@ -70,7 +70,7 @@ func unjailRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLI return } - txCtx := authctx.TxBuilder{ + txBld := authctx.TxBuilder{ Codec: cdc, ChainID: m.ChainID, AccountNumber: m.AccountNumber, @@ -87,24 +87,24 @@ func unjailRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLI cliCtx = cliCtx.WithGasAdjustment(adjustment) if utils.HasDryRunArg(r) || m.Gas == 0 { - newCtx, err := utils.EnrichCtxWithGas(txCtx, cliCtx, m.LocalAccountName, []sdk.Msg{msg}) + newCtx, err := utils.EnrichCtxWithGas(txBld, cliCtx, m.LocalAccountName, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } if utils.HasDryRunArg(r) { - utils.WriteSimulationResponse(w, txCtx.Gas) + utils.WriteSimulationResponse(w, txBld.Gas) return } - txCtx = newCtx + txBld = newCtx } if utils.HasGenerateOnlyArg(r) { - utils.WriteGenerateStdTxResponse(w, txCtx, []sdk.Msg{msg}) + utils.WriteGenerateStdTxResponse(w, txBld, []sdk.Msg{msg}) return } - txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) + txBytes, err := txBld.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusUnauthorized, "Must use own validator address") return diff --git a/x/stake/client/cli/tx.go b/x/stake/client/cli/tx.go index 2e5e227557..a103932c36 100644 --- a/x/stake/client/cli/tx.go +++ b/x/stake/client/cli/tx.go @@ -25,7 +25,7 @@ func GetCmdCreateValidator(cdc *wire.Codec) *cobra.Command { Use: "create-validator", Short: "create new validator initialized with a self-delegation to it", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -78,10 +78,10 @@ func GetCmdCreateValidator(cdc *wire.Codec) *cobra.Command { msg = stake.NewMsgCreateValidator(sdk.ValAddress(valAddr), pk, amount, description) } if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) } // build and sign the transaction, then broadcast to Tendermint - return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) }, } @@ -99,7 +99,7 @@ func GetCmdEditValidator(cdc *wire.Codec) *cobra.Command { Use: "edit-validator", Short: "edit and existing validator account", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -120,10 +120,10 @@ func GetCmdEditValidator(cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgEditValidator(sdk.ValAddress(valAddr), description) if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) } // build and sign the transaction, then broadcast to Tendermint - return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) }, } @@ -138,7 +138,7 @@ func GetCmdDelegate(cdc *wire.Codec) *cobra.Command { Use: "delegate", Short: "delegate liquid tokens to an validator", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -162,10 +162,10 @@ func GetCmdDelegate(cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgDelegate(delAddr, valAddr, amount) if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) } // build and sign the transaction, then broadcast to Tendermint - return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) }, } @@ -197,7 +197,7 @@ func GetCmdBeginRedelegate(storeName string, cdc *wire.Codec) *cobra.Command { Use: "begin", Short: "begin redelegation", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -234,10 +234,10 @@ func GetCmdBeginRedelegate(storeName string, cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgBeginRedelegate(delAddr, valSrcAddr, valDstAddr, sharesAmount) if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) } // build and sign the transaction, then broadcast to Tendermint - return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) }, } @@ -301,7 +301,7 @@ func GetCmdCompleteRedelegate(cdc *wire.Codec) *cobra.Command { Use: "complete", Short: "complete redelegation", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -325,10 +325,10 @@ func GetCmdCompleteRedelegate(cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgCompleteRedelegate(delAddr, valSrcAddr, valDstAddr) if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) } // build and sign the transaction, then broadcast to Tendermint - return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) }, } @@ -359,7 +359,7 @@ func GetCmdBeginUnbonding(storeName string, cdc *wire.Codec) *cobra.Command { Use: "begin", Short: "begin unbonding", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -389,10 +389,10 @@ func GetCmdBeginUnbonding(storeName string, cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgBeginUnbonding(delAddr, valAddr, sharesAmount) if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) } // build and sign the transaction, then broadcast to Tendermint - return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) }, } @@ -408,7 +408,7 @@ func GetCmdCompleteUnbonding(cdc *wire.Codec) *cobra.Command { Use: "complete", Short: "complete unbonding", RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -427,10 +427,10 @@ func GetCmdCompleteUnbonding(cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgCompleteUnbonding(delAddr, valAddr) if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) } // build and sign the transaction, then broadcast to Tendermint - return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) }, } diff --git a/x/stake/client/rest/tx.go b/x/stake/client/rest/tx.go index dd478487b3..f43e837496 100644 --- a/x/stake/client/rest/tx.go +++ b/x/stake/client/rest/tx.go @@ -263,7 +263,7 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex i++ } - txCtx := authcliCtx.TxBuilder{ + txBld := authcliCtx.TxBuilder{ Codec: cdc, ChainID: m.ChainID, Gas: m.Gas, @@ -273,8 +273,8 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex signedTxs := make([][]byte, len(messages[:])) for i, msg := range messages { // increment sequence for each message - txCtx = txCtx.WithAccountNumber(m.AccountNumber) - txCtx = txCtx.WithSequence(m.Sequence) + txBld = txBld.WithAccountNumber(m.AccountNumber) + txBld = txBld.WithSequence(m.Sequence) m.Sequence++ @@ -285,24 +285,24 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex cliCtx = cliCtx.WithGasAdjustment(adjustment) if utils.HasDryRunArg(r) || m.Gas == 0 { - newCtx, err := utils.EnrichCtxWithGas(txCtx, cliCtx, m.LocalAccountName, []sdk.Msg{msg}) + newCtx, err := utils.EnrichCtxWithGas(txBld, cliCtx, m.LocalAccountName, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } if utils.HasDryRunArg(r) { - utils.WriteSimulationResponse(w, txCtx.Gas) + utils.WriteSimulationResponse(w, txBld.Gas) return } - txCtx = newCtx + txBld = newCtx } if utils.HasGenerateOnlyArg(r) { - utils.WriteGenerateStdTxResponse(w, txCtx, []sdk.Msg{msg}) + utils.WriteGenerateStdTxResponse(w, txBld, []sdk.Msg{msg}) return } - txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) + txBytes, err := txBld.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error()) return From f5a7f2524f328e2e2e4923293e5d8db1932cc0a2 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 7 Sep 2018 15:25:20 +0100 Subject: [PATCH 62/93] ACK and incorporate @cwgoes comments --- Makefile | 2 +- cmd/gaia/cli_test/cli_test.go | 1 - x/auth/client/rest/sign.go | 3 ++- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 78fc864c9e..2f23fd54fe 100644 --- a/Makefile +++ b/Makefile @@ -179,7 +179,7 @@ test_cover: test_lint: gometalinter.v2 --config=tools/gometalinter.json ./... - !(gometalinter.v2 --disable-all --enable='errcheck' --vendor ./... | grep -v -e "client/" -e "fmt\.Fprintf") + !(gometalinter.v2 --disable-all --enable='errcheck' --vendor ./... | grep -v "client/") find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" | xargs gofmt -d -s dep status >> /dev/null !(grep -n branch Gopkg.toml) diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index e67ac30822..d8d242e5b7 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -442,7 +442,6 @@ func unmarshalStdTx(t *testing.T, s string) (stdTx auth.StdTx) { func writeToNewTempFile(t *testing.T, s string) *os.File { fp, err := ioutil.TempFile(os.TempDir(), "cosmos_cli_test_") require.Nil(t, err) - // defer os.Remove(signedTxFile.Name()) _, err = fp.WriteString(s) require.Nil(t, err) return fp diff --git a/x/auth/client/rest/sign.go b/x/auth/client/rest/sign.go index bbbf7f26ce..7ec7038841 100644 --- a/x/auth/client/rest/sign.go +++ b/x/auth/client/rest/sign.go @@ -19,6 +19,7 @@ type SignBody struct { ChainID string `json:"chain_id"` AccountNumber int64 `json:"account_number"` Sequence int64 `json:"sequence"` + AppendSig bool `json:"append_sig"` } // sign tx REST handler @@ -44,7 +45,7 @@ func SignTxRequestHandlerFn(cdc *wire.Codec, cliCtx context.CLIContext) http.Han Sequence: m.Sequence, } - signedTx, err := txCtx.SignStdTx(m.LocalAccountName, m.Password, m.Tx, false) + signedTx, err := txCtx.SignStdTx(m.LocalAccountName, m.Password, m.Tx, m.AppendSig) if err != nil { utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return From 72e9664ce10d30f97fc4e6eab603981ff1ccfa0a Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 7 Sep 2018 17:00:57 +0200 Subject: [PATCH 63/93] Revert "Merge PR #2217: Governance BFT Time" This reverts commit 94b86f85c193c11bcc42c6c99619fad20103bb6b, reversing changes made to 2a4edcca48e0a81226b231508349f1d060b09cc5. --- PENDING.md | 3 +-- docs/spec/governance/state.md | 16 +++++------ x/gov/endblocker_test.go | 51 +++++++---------------------------- x/gov/genesis.go | 6 ++--- x/gov/handler.go | 8 +++--- x/gov/keeper.go | 19 ++++++------- x/gov/keeper_test.go | 9 +++---- x/gov/procedures.go | 8 +++--- x/gov/proposals.go | 27 +++++++++---------- 9 files changed, 55 insertions(+), 92 deletions(-) diff --git a/PENDING.md b/PENDING.md index d23a372a30..e5ea9884a5 100644 --- a/PENDING.md +++ b/PENDING.md @@ -28,8 +28,7 @@ BREAKING CHANGES * [x/stake] [\#2040](https://github.com/cosmos/cosmos-sdk/issues/2040) Validator operator type has now changed to `sdk.ValAddress` * A new bech32 prefix has been introduced for Tendermint signing keys and addresses, `cosmosconspub` and `cosmoscons` respectively. - * [x/gov] \#2195 Made governance use BFT Time instead of Block Heights for deposit and voting periods. - + * SDK * [core] [\#1807](https://github.com/cosmos/cosmos-sdk/issues/1807) Switch from use of rational to decimal * [types] [\#1901](https://github.com/cosmos/cosmos-sdk/issues/1901) Validator interface's GetOwner() renamed to GetOperator() diff --git a/docs/spec/governance/state.md b/docs/spec/governance/state.md index 0d2927d7a5..728ded3713 100644 --- a/docs/spec/governance/state.md +++ b/docs/spec/governance/state.md @@ -13,13 +13,13 @@ has to be created and the previous one rendered inactive. ```go type DepositProcedure struct { MinDeposit sdk.Coins // Minimum deposit for a proposal to enter voting period. - MaxDepositPeriod time.Time // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months + MaxDepositPeriod int64 // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months } ``` ```go type VotingProcedure struct { - VotingPeriod time.Time // Length of the voting period. Initial value: 2 weeks + VotingPeriod int64 // Length of the voting period. Initial value: 2 weeks } ``` @@ -28,7 +28,7 @@ type TallyingProcedure struct { 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 time.Time // If validator entered validator set in this period of blocks before vote ended, governance penalty does not apply + GracePeriod int64 // If validator entered validator set in this period of blocks before vote ended, governance penalty does not apply } ``` @@ -97,10 +97,10 @@ type Proposal struct { Type ProposalType // Type of proposal. Initial set {PlainTextProposal, SoftwareUpgradeProposal} TotalDeposit sdk.Coins // Current deposit on this proposal. Initial value is set at InitialDeposit Deposits []Deposit // List of deposits on the proposal - SubmitTime time.Time // Time of the block where TxGovSubmitProposal was included + SubmitBlock int64 // Height of the block where TxGovSubmitProposal was included Submitter sdk.Address // Address of the submitter - VotingStartTime time.Time // Time of the block where MinDeposit was reached. time.Time{} if MinDeposit is not reached + 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.Dec @@ -137,7 +137,7 @@ For pseudocode purposes, here are the two function we will use to read or write * `ProposalProcessingQueue`: A queue `queue[proposalID]` containing all the `ProposalIDs` of proposals that reached `MinDeposit`. Each round, the oldest element of `ProposalProcessingQueue` is checked during `BeginBlock` to see if - `CurrentTime == VotingStartTime + activeProcedure.VotingPeriod`. If it is, + `CurrentBlock == VotingStartBlock + activeProcedure.VotingPeriod`. If it is, then the application tallies the votes, compute the votes of each validator and checks if every validator in the valdiator set have voted and, if not, applies `GovernancePenalty`. If the proposal is accepted, deposits are refunded. After that proposal is ejected from `ProposalProcessingQueue` and the next element of the queue is evaluated. @@ -159,7 +159,7 @@ And the pseudocode for the `ProposalProcessingQueue`: proposal = load(Governance, ) // proposal is a const key votingProcedure = load(GlobalParams, 'VotingProcedure') - if (CurrentTime == proposal.VotingStartTime + votingProcedure.VotingPeriod && proposal.CurrentStatus == ProposalStatusActive) + if (CurrentBlock == proposal.VotingStartBlock + votingProcedure.VotingPeriod && proposal.CurrentStatus == ProposalStatusActive) // End of voting period, tally @@ -194,7 +194,7 @@ And the pseudocode for the `ProposalProcessingQueue`: // Slash validators that did not vote, or update tally if they voted for each validator in validators - if (validator.bondTime < CurrentTime - tallyingProcedure.GracePeriod) + if (validator.bondHeight < CurrentBlock - tallyingProcedure.GracePeriod) // only slash if validator entered validator set before grace period if (!tmpValMap(validator).HasVoted) slash validator by tallyingProcedure.GovernancePenalty diff --git a/x/gov/endblocker_test.go b/x/gov/endblocker_test.go index 4cbd1d7588..710ecb1dba 100644 --- a/x/gov/endblocker_test.go +++ b/x/gov/endblocker_test.go @@ -2,7 +2,6 @@ package gov import ( "testing" - "time" "github.com/stretchr/testify/require" @@ -29,18 +28,12 @@ func TestTickExpiredDepositPeriod(t *testing.T) { require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - newHeader := ctx.BlockHeader() - newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second) - ctx = ctx.WithBlockHeader(newHeader) - + ctx = ctx.WithBlockHeight(10) EndBlocker(ctx, keeper) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - newHeader = ctx.BlockHeader() - newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod) - ctx = ctx.WithBlockHeader(newHeader) - + ctx = ctx.WithBlockHeight(250) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.True(t, shouldPopInactiveProposalQueue(ctx, keeper)) EndBlocker(ctx, keeper) @@ -66,10 +59,7 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) { require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - newHeader := ctx.BlockHeader() - newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(2) * time.Second) - ctx = ctx.WithBlockHeader(newHeader) - + ctx = ctx.WithBlockHeight(10) EndBlocker(ctx, keeper) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) @@ -78,20 +68,14 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) { res = govHandler(ctx, newProposalMsg2) require.True(t, res.IsOK()) - newHeader = ctx.BlockHeader() - newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod).Add(time.Duration(-1) * time.Second) - ctx = ctx.WithBlockHeader(newHeader) - + ctx = ctx.WithBlockHeight(205) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.True(t, shouldPopInactiveProposalQueue(ctx, keeper)) EndBlocker(ctx, keeper) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - newHeader = ctx.BlockHeader() - newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(5) * time.Second) - ctx = ctx.WithBlockHeader(newHeader) - + ctx = ctx.WithBlockHeight(215) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.True(t, shouldPopInactiveProposalQueue(ctx, keeper)) EndBlocker(ctx, keeper) @@ -121,10 +105,7 @@ func TestTickPassedDepositPeriod(t *testing.T) { require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - newHeader := ctx.BlockHeader() - newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second) - ctx = ctx.WithBlockHeader(newHeader) - + ctx = ctx.WithBlockHeight(10) EndBlocker(ctx, keeper) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) @@ -165,20 +146,14 @@ func TestTickPassedVotingPeriod(t *testing.T) { var proposalID int64 keeper.cdc.UnmarshalBinaryBare(res.Data, &proposalID) - newHeader := ctx.BlockHeader() - newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second) - ctx = ctx.WithBlockHeader(newHeader) - + ctx = ctx.WithBlockHeight(10) newDepositMsg := NewMsgDeposit(addrs[1], proposalID, sdk.Coins{sdk.NewInt64Coin("steak", 5)}) res = govHandler(ctx, newDepositMsg) require.True(t, res.IsOK()) EndBlocker(ctx, keeper) - newHeader = ctx.BlockHeader() - newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod).Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod) - ctx = ctx.WithBlockHeader(newHeader) - + ctx = ctx.WithBlockHeight(215) require.True(t, shouldPopActiveProposalQueue(ctx, keeper)) depositsIterator := keeper.GetDeposits(ctx, proposalID) require.True(t, depositsIterator.Valid()) @@ -222,10 +197,7 @@ func TestSlashing(t *testing.T) { var proposalID int64 keeper.cdc.UnmarshalBinaryBare(res.Data, &proposalID) - newHeader := ctx.BlockHeader() - newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second) - ctx = ctx.WithBlockHeader(newHeader) - + ctx = ctx.WithBlockHeight(10) require.Equal(t, StatusVotingPeriod, keeper.GetProposal(ctx, proposalID).GetStatus()) newVoteMsg := NewMsgVote(addrs[0], proposalID, OptionYes) @@ -234,10 +206,7 @@ func TestSlashing(t *testing.T) { EndBlocker(ctx, keeper) - newHeader = ctx.BlockHeader() - newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod).Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod) - ctx = ctx.WithBlockHeader(newHeader) - + ctx = ctx.WithBlockHeight(215) require.Equal(t, StatusVotingPeriod, keeper.GetProposal(ctx, proposalID).GetStatus()) EndBlocker(ctx, keeper) diff --git a/x/gov/genesis.go b/x/gov/genesis.go index 58273c8e84..15f952c000 100644 --- a/x/gov/genesis.go +++ b/x/gov/genesis.go @@ -1,8 +1,6 @@ package gov import ( - "time" - sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -29,10 +27,10 @@ func DefaultGenesisState() GenesisState { StartingProposalID: 1, DepositProcedure: DepositProcedure{ MinDeposit: sdk.Coins{sdk.NewInt64Coin("steak", 10)}, - MaxDepositPeriod: time.Duration(172800) * time.Second, + MaxDepositPeriod: 200, }, VotingProcedure: VotingProcedure{ - VotingPeriod: time.Duration(172800) * time.Second, + VotingPeriod: 200, }, TallyingProcedure: TallyingProcedure{ Threshold: sdk.NewDecWithPrec(5, 1), diff --git a/x/gov/handler.go b/x/gov/handler.go index 59e47a14ec..6424bb0a10 100644 --- a/x/gov/handler.go +++ b/x/gov/handler.go @@ -122,9 +122,9 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) { for shouldPopActiveProposalQueue(ctx, keeper) { activeProposal := keeper.ActiveProposalQueuePop(ctx) - proposalStartTime := activeProposal.GetVotingStartTime() + proposalStartBlock := activeProposal.GetVotingStartBlock() votingPeriod := keeper.GetVotingProcedure(ctx).VotingPeriod - if ctx.BlockHeader().Time.Before(proposalStartTime.Add(votingPeriod)) { + if ctx.BlockHeight() < proposalStartBlock+votingPeriod { continue } @@ -172,7 +172,7 @@ func shouldPopInactiveProposalQueue(ctx sdk.Context, keeper Keeper) bool { return false } else if peekProposal.GetStatus() != StatusDepositPeriod { return true - } else if !ctx.BlockHeader().Time.Before(peekProposal.GetSubmitTime().Add(depositProcedure.MaxDepositPeriod)) { + } else if ctx.BlockHeight() >= peekProposal.GetSubmitBlock()+depositProcedure.MaxDepositPeriod { return true } return false @@ -184,7 +184,7 @@ func shouldPopActiveProposalQueue(ctx sdk.Context, keeper Keeper) bool { if peekProposal == nil { return false - } else if !ctx.BlockHeader().Time.Before(peekProposal.GetVotingStartTime().Add(votingProcedure.VotingPeriod)) { + } else if ctx.BlockHeight() >= peekProposal.GetVotingStartBlock()+votingProcedure.VotingPeriod { return true } return false diff --git a/x/gov/keeper.go b/x/gov/keeper.go index 3b9d8a7ff3..576d2cc22f 100644 --- a/x/gov/keeper.go +++ b/x/gov/keeper.go @@ -66,14 +66,15 @@ func (keeper Keeper) NewTextProposal(ctx sdk.Context, title string, description return nil } var proposal Proposal = &TextProposal{ - ProposalID: proposalID, - Title: title, - Description: description, - ProposalType: proposalType, - Status: StatusDepositPeriod, - TallyResult: EmptyTallyResult(), - TotalDeposit: sdk.Coins{}, - SubmitTime: ctx.BlockHeader().Time, + ProposalID: proposalID, + Title: title, + Description: description, + ProposalType: proposalType, + Status: StatusDepositPeriod, + TallyResult: EmptyTallyResult(), + TotalDeposit: sdk.Coins{}, + SubmitBlock: ctx.BlockHeight(), + VotingStartBlock: -1, // TODO: Make Time } keeper.SetProposal(ctx, proposal) keeper.InactiveProposalQueuePush(ctx, proposal) @@ -199,7 +200,7 @@ func (keeper Keeper) peekCurrentProposalID(ctx sdk.Context) (proposalID int64, e } func (keeper Keeper) activateVotingPeriod(ctx sdk.Context, proposal Proposal) { - proposal.SetVotingStartTime(ctx.BlockHeader().Time) + proposal.SetVotingStartBlock(ctx.BlockHeight()) proposal.SetStatus(StatusVotingPeriod) keeper.SetProposal(ctx, proposal) keeper.ActiveProposalQueuePush(ctx, proposal) diff --git a/x/gov/keeper_test.go b/x/gov/keeper_test.go index 91c41d7d7d..a61292b93e 100644 --- a/x/gov/keeper_test.go +++ b/x/gov/keeper_test.go @@ -2,7 +2,6 @@ package gov import ( "testing" - "time" "github.com/stretchr/testify/require" @@ -46,12 +45,12 @@ func TestActivateVotingPeriod(t *testing.T) { proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText) - require.True(t, proposal.GetVotingStartTime().Equal(time.Time{})) + require.Equal(t, int64(-1), proposal.GetVotingStartBlock()) require.Nil(t, keeper.ActiveProposalQueuePeek(ctx)) keeper.activateVotingPeriod(ctx, proposal) - require.True(t, proposal.GetVotingStartTime().Equal(ctx.BlockHeader().Time)) + require.Equal(t, proposal.GetVotingStartBlock(), ctx.BlockHeight()) require.Equal(t, proposal.GetProposalID(), keeper.ActiveProposalQueuePeek(ctx).GetProposalID()) } @@ -78,7 +77,7 @@ func TestDeposits(t *testing.T) { // Check no deposits at beginning deposit, found := keeper.GetDeposit(ctx, proposalID, addrs[1]) require.False(t, found) - require.True(t, keeper.GetProposal(ctx, proposalID).GetVotingStartTime().Equal(time.Time{})) + require.Equal(t, keeper.GetProposal(ctx, proposalID).GetVotingStartBlock(), int64(-1)) require.Nil(t, keeper.ActiveProposalQueuePeek(ctx)) // Check first deposit @@ -115,7 +114,7 @@ func TestDeposits(t *testing.T) { require.Equal(t, addr1Initial.Minus(fourSteak), keeper.ck.GetCoins(ctx, addrs[1])) // Check that proposal moved to voting period - require.True(t, keeper.GetProposal(ctx, proposalID).GetVotingStartTime().Equal(ctx.BlockHeader().Time)) + require.Equal(t, ctx.BlockHeight(), keeper.GetProposal(ctx, proposalID).GetVotingStartBlock()) require.NotNil(t, keeper.ActiveProposalQueuePeek(ctx)) require.Equal(t, proposalID, keeper.ActiveProposalQueuePeek(ctx).GetProposalID()) diff --git a/x/gov/procedures.go b/x/gov/procedures.go index e453add791..f74091c74f 100644 --- a/x/gov/procedures.go +++ b/x/gov/procedures.go @@ -1,15 +1,13 @@ package gov import ( - "time" - sdk "github.com/cosmos/cosmos-sdk/types" ) // Procedure around Deposits for governance type DepositProcedure struct { - MinDeposit sdk.Coins `json:"min_deposit"` // Minimum deposit for a proposal to enter voting period. - MaxDepositPeriod time.Duration `json:"max_deposit_period"` // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months + MinDeposit sdk.Coins `json:"min_deposit"` // Minimum deposit for a proposal to enter voting period. + MaxDepositPeriod int64 `json:"max_deposit_period"` // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months } // Procedure around Tallying votes in governance @@ -21,5 +19,5 @@ type TallyingProcedure struct { // Procedure around Voting in governance type VotingProcedure struct { - VotingPeriod time.Duration `json:"voting_period"` // Length of the voting period. + VotingPeriod int64 `json:"voting_period"` // Length of the voting period. } diff --git a/x/gov/proposals.go b/x/gov/proposals.go index e680699575..b4c6783673 100644 --- a/x/gov/proposals.go +++ b/x/gov/proposals.go @@ -3,7 +3,6 @@ package gov import ( "encoding/json" "fmt" - "time" "github.com/pkg/errors" @@ -31,14 +30,14 @@ type Proposal interface { GetTallyResult() TallyResult SetTallyResult(TallyResult) - GetSubmitTime() time.Time - SetSubmitTime(time.Time) + GetSubmitBlock() int64 + SetSubmitBlock(int64) GetTotalDeposit() sdk.Coins SetTotalDeposit(sdk.Coins) - GetVotingStartTime() time.Time - SetVotingStartTime(time.Time) + GetVotingStartBlock() int64 + SetVotingStartBlock(int64) } // checks if two proposals are equal @@ -49,9 +48,9 @@ func ProposalEqual(proposalA Proposal, proposalB Proposal) bool { proposalA.GetProposalType() == proposalB.GetProposalType() && proposalA.GetStatus() == proposalB.GetStatus() && proposalA.GetTallyResult().Equals(proposalB.GetTallyResult()) && - proposalA.GetSubmitTime().Equal(proposalB.GetSubmitTime()) && + proposalA.GetSubmitBlock() == proposalB.GetSubmitBlock() && proposalA.GetTotalDeposit().IsEqual(proposalB.GetTotalDeposit()) && - proposalA.GetVotingStartTime().Equal(proposalB.GetVotingStartTime()) { + proposalA.GetVotingStartBlock() == proposalB.GetVotingStartBlock() { return true } return false @@ -68,10 +67,10 @@ type TextProposal struct { Status ProposalStatus `json:"proposal_status"` // Status of the Proposal {Pending, Active, Passed, Rejected} TallyResult TallyResult `json:"tally_result"` // Result of Tallys - SubmitTime time.Time `json:"submit_block"` // Height of the block where TxGovSubmitProposal was included + SubmitBlock int64 `json:"submit_block"` // Height of the block where TxGovSubmitProposal was included TotalDeposit sdk.Coins `json:"total_deposit"` // Current deposit on this proposal. Initial value is set at InitialDeposit - VotingStartTime time.Time `json:"voting_start_block"` // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached + VotingStartBlock int64 `json:"voting_start_block"` // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached } // Implements Proposal Interface @@ -90,13 +89,13 @@ func (tp TextProposal) GetStatus() ProposalStatus { return tp.S func (tp *TextProposal) SetStatus(status ProposalStatus) { tp.Status = status } func (tp TextProposal) GetTallyResult() TallyResult { return tp.TallyResult } func (tp *TextProposal) SetTallyResult(tallyResult TallyResult) { tp.TallyResult = tallyResult } -func (tp TextProposal) GetSubmitTime() time.Time { return tp.SubmitTime } -func (tp *TextProposal) SetSubmitTime(submitTime time.Time) { tp.SubmitTime = submitTime } +func (tp TextProposal) GetSubmitBlock() int64 { return tp.SubmitBlock } +func (tp *TextProposal) SetSubmitBlock(submitBlock int64) { tp.SubmitBlock = submitBlock } func (tp TextProposal) GetTotalDeposit() sdk.Coins { return tp.TotalDeposit } func (tp *TextProposal) SetTotalDeposit(totalDeposit sdk.Coins) { tp.TotalDeposit = totalDeposit } -func (tp TextProposal) GetVotingStartTime() time.Time { return tp.VotingStartTime } -func (tp *TextProposal) SetVotingStartTime(votingStartTime time.Time) { - tp.VotingStartTime = votingStartTime +func (tp TextProposal) GetVotingStartBlock() int64 { return tp.VotingStartBlock } +func (tp *TextProposal) SetVotingStartBlock(votingStartBlock int64) { + tp.VotingStartBlock = votingStartBlock } //----------------------------------------------------------- From acd125029d8a4d8c61e9f9a56921513fa401732f Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 7 Sep 2018 10:04:58 -0700 Subject: [PATCH 64/93] x/auth/client/context -> x/auth/client/txbuilder --- client/utils/rest.go | 4 ++-- client/utils/utils.go | 14 +++++++------- examples/democoin/x/cool/client/cli/tx.go | 6 +++--- examples/democoin/x/pow/client/cli/tx.go | 4 ++-- .../x/simplestake/client/cli/commands.go | 6 +++--- .../context.go => txbuilder/txbuilder.go} | 0 x/auth/client/{context => txbuilder}/utils.go | 0 x/bank/client/cli/sendtx.go | 4 ++-- x/bank/client/rest/sendtx.go | 4 ++-- x/gov/client/cli/tx.go | 8 ++++---- x/gov/client/rest/util.go | 4 ++-- x/ibc/client/cli/ibctx.go | 4 ++-- x/ibc/client/cli/relay.go | 4 ++-- x/ibc/client/rest/transfer.go | 4 ++-- x/slashing/client/cli/tx.go | 4 ++-- x/slashing/client/rest/tx.go | 4 ++-- x/stake/client/cli/tx.go | 16 ++++++++-------- x/stake/client/rest/tx.go | 4 ++-- 18 files changed, 47 insertions(+), 47 deletions(-) rename x/auth/client/{context/context.go => txbuilder/txbuilder.go} (100%) rename x/auth/client/{context => txbuilder}/utils.go (100%) diff --git a/client/utils/rest.go b/client/utils/rest.go index 6446fb1337..ea85dfa74c 100644 --- a/client/utils/rest.go +++ b/client/utils/rest.go @@ -8,7 +8,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" auth "github.com/cosmos/cosmos-sdk/x/auth" - authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context" + authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" ) const ( @@ -52,7 +52,7 @@ func ParseFloat64OrReturnBadRequest(w http.ResponseWriter, s string, defaultIfEm } // WriteGenerateStdTxResponse writes response for the generate_only mode. -func WriteGenerateStdTxResponse(w http.ResponseWriter, txBld authctx.TxBuilder, msgs []sdk.Msg) { +func WriteGenerateStdTxResponse(w http.ResponseWriter, txBld authtxb.TxBuilder, msgs []sdk.Msg) { stdMsg, err := txBld.Build(msgs) if err != nil { WriteErrorResponse(w, http.StatusBadRequest, err.Error()) diff --git a/client/utils/utils.go b/client/utils/utils.go index 32cc810006..341bba9a5d 100644 --- a/client/utils/utils.go +++ b/client/utils/utils.go @@ -8,7 +8,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/keys" sdk "github.com/cosmos/cosmos-sdk/types" auth "github.com/cosmos/cosmos-sdk/x/auth" - authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context" + authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" amino "github.com/tendermint/go-amino" "github.com/tendermint/tendermint/libs/common" ) @@ -18,7 +18,7 @@ import ( // ensures that the account exists, has a proper number and sequence set. In // addition, it builds and signs a transaction with the supplied messages. // Finally, it broadcasts the signed transaction to a node. -func SendTx(txBld authctx.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) error { +func SendTx(txBld authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) error { txBld, err := prepareTxContext(txBld, cliCtx) if err != nil { return err @@ -50,7 +50,7 @@ func SendTx(txBld authctx.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) } // SimulateMsgs simulates the transaction and returns the gas estimate and the adjusted value. -func SimulateMsgs(txBld authctx.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg, gas int64) (estimated, adjusted int64, err error) { +func SimulateMsgs(txBld authtxb.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg, gas int64) (estimated, adjusted int64, err error) { txBytes, err := txBld.WithGas(gas).BuildWithPubKey(name, msgs) if err != nil { return @@ -61,7 +61,7 @@ func SimulateMsgs(txBld authctx.TxBuilder, cliCtx context.CLIContext, name strin // EnrichCtxWithGas calculates the gas estimate that would be consumed by the // transaction and set the transaction's respective value accordingly. -func EnrichCtxWithGas(txBld authctx.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg) (authctx.TxBuilder, error) { +func EnrichCtxWithGas(txBld authtxb.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg) (authtxb.TxBuilder, error) { _, adjusted, err := SimulateMsgs(txBld, cliCtx, name, msgs, 0) if err != nil { return txBld, err @@ -87,7 +87,7 @@ func CalculateGas(queryFunc func(string, common.HexBytes) ([]byte, error), cdc * } // PrintUnsignedStdTx builds an unsigned StdTx and prints it to os.Stdout. -func PrintUnsignedStdTx(txBld authctx.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) (err error) { +func PrintUnsignedStdTx(txBld authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) (err error) { stdTx, err := buildUnsignedStdTx(txBld, cliCtx, msgs) if err != nil { return @@ -111,7 +111,7 @@ func parseQueryResponse(cdc *amino.Codec, rawRes []byte) (int64, error) { return simulationResult.GasUsed, nil } -func prepareTxContext(txBld authctx.TxBuilder, cliCtx context.CLIContext) (authctx.TxBuilder, error) { +func prepareTxContext(txBld authtxb.TxBuilder, cliCtx context.CLIContext) (authtxb.TxBuilder, error) { if err := cliCtx.EnsureAccountExists(); err != nil { return txBld, err } @@ -145,7 +145,7 @@ func prepareTxContext(txBld authctx.TxBuilder, cliCtx context.CLIContext) (authc // buildUnsignedStdTx builds a StdTx as per the parameters passed in the // contexts. Gas is automatically estimated if gas wanted is set to 0. -func buildUnsignedStdTx(txBld authctx.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) (stdTx auth.StdTx, err error) { +func buildUnsignedStdTx(txBld authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) (stdTx auth.StdTx, err error) { txBld, err = prepareTxContext(txBld, cliCtx) if err != nil { return diff --git a/examples/democoin/x/cool/client/cli/tx.go b/examples/democoin/x/cool/client/cli/tx.go index 0134a1ea62..abdfcb2401 100644 --- a/examples/democoin/x/cool/client/cli/tx.go +++ b/examples/democoin/x/cool/client/cli/tx.go @@ -11,7 +11,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" - authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context" + authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" ) // QuizTxCmd invokes the coolness quiz transaction. @@ -21,7 +21,7 @@ func QuizTxCmd(cdc *wire.Codec) *cobra.Command { Short: "What's cooler than being cool?", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -46,7 +46,7 @@ func SetTrendTxCmd(cdc *wire.Codec) *cobra.Command { Short: "You're so cool, tell us what is cool!", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). diff --git a/examples/democoin/x/pow/client/cli/tx.go b/examples/democoin/x/pow/client/cli/tx.go index 820dd105c6..3b576da880 100644 --- a/examples/democoin/x/pow/client/cli/tx.go +++ b/examples/democoin/x/pow/client/cli/tx.go @@ -10,7 +10,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" - authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context" + authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" "github.com/spf13/cobra" ) @@ -22,7 +22,7 @@ func MineCmd(cdc *wire.Codec) *cobra.Command { Short: "Mine some coins with proof-of-work!", Args: cobra.ExactArgs(4), RunE: func(cmd *cobra.Command, args []string) error { - txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). diff --git a/examples/democoin/x/simplestake/client/cli/commands.go b/examples/democoin/x/simplestake/client/cli/commands.go index f8bd075de4..75a5cacc8c 100644 --- a/examples/democoin/x/simplestake/client/cli/commands.go +++ b/examples/democoin/x/simplestake/client/cli/commands.go @@ -11,7 +11,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" - authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context" + authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -30,7 +30,7 @@ func BondTxCmd(cdc *wire.Codec) *cobra.Command { Use: "bond", Short: "Bond to a validator", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -84,7 +84,7 @@ func UnbondTxCmd(cdc *wire.Codec) *cobra.Command { Use: "unbond", Short: "Unbond from a validator", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout) diff --git a/x/auth/client/context/context.go b/x/auth/client/txbuilder/txbuilder.go similarity index 100% rename from x/auth/client/context/context.go rename to x/auth/client/txbuilder/txbuilder.go diff --git a/x/auth/client/context/utils.go b/x/auth/client/txbuilder/utils.go similarity index 100% rename from x/auth/client/context/utils.go rename to x/auth/client/txbuilder/utils.go diff --git a/x/bank/client/cli/sendtx.go b/x/bank/client/cli/sendtx.go index 98fb3e9843..1ea3a27ef9 100644 --- a/x/bank/client/cli/sendtx.go +++ b/x/bank/client/cli/sendtx.go @@ -8,7 +8,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" - authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context" + authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" "github.com/cosmos/cosmos-sdk/x/bank/client" "github.com/pkg/errors" @@ -27,7 +27,7 @@ func SendTxCmd(cdc *wire.Codec) *cobra.Command { Use: "send", Short: "Create and sign a send tx", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). diff --git a/x/bank/client/rest/sendtx.go b/x/bank/client/rest/sendtx.go index f0d2d6308d..436803c628 100644 --- a/x/bank/client/rest/sendtx.go +++ b/x/bank/client/rest/sendtx.go @@ -10,7 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" - authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context" + authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" "github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/x/bank/client" @@ -80,7 +80,7 @@ func SendRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLICo return } - txBld := authctx.TxBuilder{ + txBld := authtxb.TxBuilder{ Codec: cdc, Gas: m.Gas, ChainID: m.ChainID, diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index da828e513a..6eb7a30582 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -9,7 +9,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" - authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context" + authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" "github.com/cosmos/cosmos-sdk/x/gov" "encoding/json" @@ -77,7 +77,7 @@ $ gaiacli gov submit-proposal --title="Test Proposal" --description="My awesome return err } - txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -161,7 +161,7 @@ func GetCmdDeposit(cdc *wire.Codec) *cobra.Command { Use: "deposit", Short: "deposit tokens for activing proposal", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -207,7 +207,7 @@ func GetCmdVote(cdc *wire.Codec) *cobra.Command { Use: "vote", Short: "vote for an active proposal, options: Yes/No/NoWithVeto/Abstain", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). diff --git a/x/gov/client/rest/util.go b/x/gov/client/rest/util.go index f8152042e3..83160ecd0e 100644 --- a/x/gov/client/rest/util.go +++ b/x/gov/client/rest/util.go @@ -11,7 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/utils" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" - authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context" + authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" ) type baseReq struct { @@ -70,7 +70,7 @@ func (req baseReq) baseReqValidate(w http.ResponseWriter) bool { // (probably should live in client/lcd). func signAndBuild(w http.ResponseWriter, r *http.Request, cliCtx context.CLIContext, baseReq baseReq, msg sdk.Msg, cdc *wire.Codec) { var err error - txBld := authctx.TxBuilder{ + txBld := authtxb.TxBuilder{ Codec: cdc, AccountNumber: baseReq.AccountNumber, Sequence: baseReq.Sequence, diff --git a/x/ibc/client/cli/ibctx.go b/x/ibc/client/cli/ibctx.go index 9c20a44f71..a8b90a6713 100644 --- a/x/ibc/client/cli/ibctx.go +++ b/x/ibc/client/cli/ibctx.go @@ -10,7 +10,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" wire "github.com/cosmos/cosmos-sdk/wire" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" - authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context" + authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" "github.com/cosmos/cosmos-sdk/x/ibc" "github.com/spf13/cobra" @@ -28,7 +28,7 @@ func IBCTransferCmd(cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "transfer", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). diff --git a/x/ibc/client/cli/relay.go b/x/ibc/client/cli/relay.go index 1bb679987b..d274edd49a 100644 --- a/x/ibc/client/cli/relay.go +++ b/x/ibc/client/cli/relay.go @@ -10,7 +10,7 @@ import ( wire "github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/x/auth" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" - authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context" + authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" "github.com/cosmos/cosmos-sdk/x/ibc" "github.com/spf13/cobra" @@ -199,7 +199,7 @@ func (c relayCommander) refine(bz []byte, sequence int64, passphrase string) []b Sequence: sequence, } - txBld := authctx.NewTxBuilderFromCLI().WithSequence(sequence).WithCodec(c.cdc) + txBld := authtxb.NewTxBuilderFromCLI().WithSequence(sequence).WithCodec(c.cdc) cliCtx := context.NewCLIContext() res, err := txBld.BuildAndSign(cliCtx.FromAddressName, passphrase, []sdk.Msg{msg}) diff --git a/x/ibc/client/rest/transfer.go b/x/ibc/client/rest/transfer.go index c071e48d14..5367bc88b3 100644 --- a/x/ibc/client/rest/transfer.go +++ b/x/ibc/client/rest/transfer.go @@ -10,7 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" - authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context" + authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" "github.com/cosmos/cosmos-sdk/x/ibc" "github.com/gorilla/mux" @@ -71,7 +71,7 @@ func TransferRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.C packet := ibc.NewIBCPacket(sdk.AccAddress(info.GetPubKey().Address()), to, m.Amount, m.SrcChainID, destChainID) msg := ibc.IBCTransferMsg{packet} - txBld := authctx.TxBuilder{ + txBld := authtxb.TxBuilder{ Codec: cdc, ChainID: m.SrcChainID, AccountNumber: m.AccountNumber, diff --git a/x/slashing/client/cli/tx.go b/x/slashing/client/cli/tx.go index 60c89a2cb0..86abdeade7 100644 --- a/x/slashing/client/cli/tx.go +++ b/x/slashing/client/cli/tx.go @@ -8,7 +8,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" - authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context" + authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" "github.com/cosmos/cosmos-sdk/x/slashing" "github.com/spf13/cobra" @@ -21,7 +21,7 @@ func GetCmdUnjail(cdc *wire.Codec) *cobra.Command { Args: cobra.NoArgs, Short: "unjail validator previously jailed for downtime", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). diff --git a/x/slashing/client/rest/tx.go b/x/slashing/client/rest/tx.go index 4c07515cbd..b8e4c46547 100644 --- a/x/slashing/client/rest/tx.go +++ b/x/slashing/client/rest/tx.go @@ -13,7 +13,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" - authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context" + authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" "github.com/cosmos/cosmos-sdk/x/slashing" "github.com/gorilla/mux" @@ -70,7 +70,7 @@ func unjailRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLI return } - txBld := authctx.TxBuilder{ + txBld := authtxb.TxBuilder{ Codec: cdc, ChainID: m.ChainID, AccountNumber: m.AccountNumber, diff --git a/x/stake/client/cli/tx.go b/x/stake/client/cli/tx.go index a103932c36..b93fdb1f46 100644 --- a/x/stake/client/cli/tx.go +++ b/x/stake/client/cli/tx.go @@ -10,7 +10,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" - authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context" + authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" "github.com/cosmos/cosmos-sdk/x/stake" "github.com/cosmos/cosmos-sdk/x/stake/types" @@ -25,7 +25,7 @@ func GetCmdCreateValidator(cdc *wire.Codec) *cobra.Command { Use: "create-validator", Short: "create new validator initialized with a self-delegation to it", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -99,7 +99,7 @@ func GetCmdEditValidator(cdc *wire.Codec) *cobra.Command { Use: "edit-validator", Short: "edit and existing validator account", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -138,7 +138,7 @@ func GetCmdDelegate(cdc *wire.Codec) *cobra.Command { Use: "delegate", Short: "delegate liquid tokens to an validator", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -197,7 +197,7 @@ func GetCmdBeginRedelegate(storeName string, cdc *wire.Codec) *cobra.Command { Use: "begin", Short: "begin redelegation", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -301,7 +301,7 @@ func GetCmdCompleteRedelegate(cdc *wire.Codec) *cobra.Command { Use: "complete", Short: "complete redelegation", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -359,7 +359,7 @@ func GetCmdBeginUnbonding(storeName string, cdc *wire.Codec) *cobra.Command { Use: "begin", Short: "begin unbonding", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -408,7 +408,7 @@ func GetCmdCompleteUnbonding(cdc *wire.Codec) *cobra.Command { Use: "complete", Short: "complete unbonding", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authctx.NewTxBuilderFromCLI().WithCodec(cdc) + txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). diff --git a/x/stake/client/rest/tx.go b/x/stake/client/rest/tx.go index f43e837496..c506935a50 100644 --- a/x/stake/client/rest/tx.go +++ b/x/stake/client/rest/tx.go @@ -12,7 +12,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" - authcliCtx "github.com/cosmos/cosmos-sdk/x/auth/client/context" + authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" "github.com/cosmos/cosmos-sdk/x/stake" "github.com/gorilla/mux" @@ -263,7 +263,7 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex i++ } - txBld := authcliCtx.TxBuilder{ + txBld := authtxb.TxBuilder{ Codec: cdc, ChainID: m.ChainID, Gas: m.Gas, From 632544186105cdbcf0b068fc105ee46b8dd80129 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 7 Sep 2018 10:15:49 -0700 Subject: [PATCH 65/93] txBld -> txBldr --- client/utils/rest.go | 6 +- client/utils/utils.go | 60 +++++++++---------- examples/democoin/x/cool/client/cli/tx.go | 8 +-- examples/democoin/x/pow/client/cli/tx.go | 4 +- .../x/simplestake/client/cli/commands.go | 8 +-- x/bank/client/cli/sendtx.go | 6 +- x/bank/client/rest/sendtx.go | 12 ++-- x/gov/client/cli/tx.go | 18 +++--- x/gov/client/rest/util.go | 12 ++-- x/ibc/client/cli/ibctx.go | 6 +- x/ibc/client/cli/relay.go | 4 +- x/ibc/client/rest/transfer.go | 12 ++-- x/slashing/client/cli/tx.go | 6 +- x/slashing/client/rest/tx.go | 12 ++-- x/stake/client/cli/tx.go | 42 ++++++------- x/stake/client/rest/tx.go | 16 ++--- 16 files changed, 116 insertions(+), 116 deletions(-) diff --git a/client/utils/rest.go b/client/utils/rest.go index ea85dfa74c..e0fae753db 100644 --- a/client/utils/rest.go +++ b/client/utils/rest.go @@ -52,13 +52,13 @@ func ParseFloat64OrReturnBadRequest(w http.ResponseWriter, s string, defaultIfEm } // WriteGenerateStdTxResponse writes response for the generate_only mode. -func WriteGenerateStdTxResponse(w http.ResponseWriter, txBld authtxb.TxBuilder, msgs []sdk.Msg) { - stdMsg, err := txBld.Build(msgs) +func WriteGenerateStdTxResponse(w http.ResponseWriter, txBldr authtxb.TxBuilder, msgs []sdk.Msg) { + stdMsg, err := txBldr.Build(msgs) if err != nil { WriteErrorResponse(w, http.StatusBadRequest, err.Error()) return } - output, err := txBld.Codec.MarshalJSON(auth.NewStdTx(stdMsg.Msgs, stdMsg.Fee, nil, stdMsg.Memo)) + output, err := txBldr.Codec.MarshalJSON(auth.NewStdTx(stdMsg.Msgs, stdMsg.Fee, nil, stdMsg.Memo)) if err != nil { WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return diff --git a/client/utils/utils.go b/client/utils/utils.go index 341bba9a5d..108fd36164 100644 --- a/client/utils/utils.go +++ b/client/utils/utils.go @@ -18,18 +18,18 @@ import ( // ensures that the account exists, has a proper number and sequence set. In // addition, it builds and signs a transaction with the supplied messages. // Finally, it broadcasts the signed transaction to a node. -func SendTx(txBld authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) error { - txBld, err := prepareTxContext(txBld, cliCtx) +func SendTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) error { + txBldr, err := prepareTxContext(txBldr, cliCtx) if err != nil { return err } autogas := cliCtx.DryRun || (cliCtx.Gas == 0) if autogas { - txBld, err = EnrichCtxWithGas(txBld, cliCtx, cliCtx.FromAddressName, msgs) + txBldr, err = EnrichCtxWithGas(txBldr, cliCtx, cliCtx.FromAddressName, msgs) if err != nil { return err } - fmt.Fprintf(os.Stderr, "estimated gas = %v\n", txBld.Gas) + fmt.Fprintf(os.Stderr, "estimated gas = %v\n", txBldr.Gas) } if cliCtx.DryRun { return nil @@ -41,7 +41,7 @@ func SendTx(txBld authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) } // build and sign the transaction - txBytes, err := txBld.BuildAndSign(cliCtx.FromAddressName, passphrase, msgs) + txBytes, err := txBldr.BuildAndSign(cliCtx.FromAddressName, passphrase, msgs) if err != nil { return err } @@ -50,8 +50,8 @@ func SendTx(txBld authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) } // SimulateMsgs simulates the transaction and returns the gas estimate and the adjusted value. -func SimulateMsgs(txBld authtxb.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg, gas int64) (estimated, adjusted int64, err error) { - txBytes, err := txBld.WithGas(gas).BuildWithPubKey(name, msgs) +func SimulateMsgs(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg, gas int64) (estimated, adjusted int64, err error) { + txBytes, err := txBldr.WithGas(gas).BuildWithPubKey(name, msgs) if err != nil { return } @@ -61,12 +61,12 @@ func SimulateMsgs(txBld authtxb.TxBuilder, cliCtx context.CLIContext, name strin // EnrichCtxWithGas calculates the gas estimate that would be consumed by the // transaction and set the transaction's respective value accordingly. -func EnrichCtxWithGas(txBld authtxb.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg) (authtxb.TxBuilder, error) { - _, adjusted, err := SimulateMsgs(txBld, cliCtx, name, msgs, 0) +func EnrichCtxWithGas(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg) (authtxb.TxBuilder, error) { + _, adjusted, err := SimulateMsgs(txBldr, cliCtx, name, msgs, 0) if err != nil { - return txBld, err + return txBldr, err } - return txBld.WithGas(adjusted), nil + return txBldr.WithGas(adjusted), nil } // CalculateGas simulates the execution of a transaction and returns @@ -87,12 +87,12 @@ func CalculateGas(queryFunc func(string, common.HexBytes) ([]byte, error), cdc * } // PrintUnsignedStdTx builds an unsigned StdTx and prints it to os.Stdout. -func PrintUnsignedStdTx(txBld authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) (err error) { - stdTx, err := buildUnsignedStdTx(txBld, cliCtx, msgs) +func PrintUnsignedStdTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) (err error) { + stdTx, err := buildUnsignedStdTx(txBldr, cliCtx, msgs) if err != nil { return } - json, err := txBld.Codec.MarshalJSON(stdTx) + json, err := txBldr.Codec.MarshalJSON(stdTx) if err == nil { fmt.Printf("%s\n", json) } @@ -111,53 +111,53 @@ func parseQueryResponse(cdc *amino.Codec, rawRes []byte) (int64, error) { return simulationResult.GasUsed, nil } -func prepareTxContext(txBld authtxb.TxBuilder, cliCtx context.CLIContext) (authtxb.TxBuilder, error) { +func prepareTxContext(txBldr authtxb.TxBuilder, cliCtx context.CLIContext) (authtxb.TxBuilder, error) { if err := cliCtx.EnsureAccountExists(); err != nil { - return txBld, err + return txBldr, err } from, err := cliCtx.GetFromAddress() if err != nil { - return txBld, err + return txBldr, err } // TODO: (ref #1903) Allow for user supplied account number without // automatically doing a manual lookup. - if txBld.AccountNumber == 0 { + if txBldr.AccountNumber == 0 { accNum, err := cliCtx.GetAccountNumber(from) if err != nil { - return txBld, err + return txBldr, err } - txBld = txBld.WithAccountNumber(accNum) + txBldr = txBldr.WithAccountNumber(accNum) } // TODO: (ref #1903) Allow for user supplied account sequence without // automatically doing a manual lookup. - if txBld.Sequence == 0 { + if txBldr.Sequence == 0 { accSeq, err := cliCtx.GetAccountSequence(from) if err != nil { - return txBld, err + return txBldr, err } - txBld = txBld.WithSequence(accSeq) + txBldr = txBldr.WithSequence(accSeq) } - return txBld, nil + return txBldr, nil } // buildUnsignedStdTx builds a StdTx as per the parameters passed in the // contexts. Gas is automatically estimated if gas wanted is set to 0. -func buildUnsignedStdTx(txBld authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) (stdTx auth.StdTx, err error) { - txBld, err = prepareTxContext(txBld, cliCtx) +func buildUnsignedStdTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) (stdTx auth.StdTx, err error) { + txBldr, err = prepareTxContext(txBldr, cliCtx) if err != nil { return } - if txBld.Gas == 0 { - txBld, err = EnrichCtxWithGas(txBld, cliCtx, cliCtx.FromAddressName, msgs) + if txBldr.Gas == 0 { + txBldr, err = EnrichCtxWithGas(txBldr, cliCtx, cliCtx.FromAddressName, msgs) if err != nil { return } - fmt.Fprintf(os.Stderr, "estimated gas = %v\n", txBld.Gas) + fmt.Fprintf(os.Stderr, "estimated gas = %v\n", txBldr.Gas) } - stdSignMsg, err := txBld.Build(msgs) + stdSignMsg, err := txBldr.Build(msgs) if err != nil { return } diff --git a/examples/democoin/x/cool/client/cli/tx.go b/examples/democoin/x/cool/client/cli/tx.go index abdfcb2401..1e41ff5b25 100644 --- a/examples/democoin/x/cool/client/cli/tx.go +++ b/examples/democoin/x/cool/client/cli/tx.go @@ -21,7 +21,7 @@ func QuizTxCmd(cdc *wire.Codec) *cobra.Command { Short: "What's cooler than being cool?", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) + txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -34,7 +34,7 @@ func QuizTxCmd(cdc *wire.Codec) *cobra.Command { msg := cool.NewMsgQuiz(from, args[0]) - return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg}) }, } } @@ -46,7 +46,7 @@ func SetTrendTxCmd(cdc *wire.Codec) *cobra.Command { Short: "You're so cool, tell us what is cool!", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) + txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -59,7 +59,7 @@ func SetTrendTxCmd(cdc *wire.Codec) *cobra.Command { msg := cool.NewMsgSetTrend(from, args[0]) - return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg}) }, } } diff --git a/examples/democoin/x/pow/client/cli/tx.go b/examples/democoin/x/pow/client/cli/tx.go index 3b576da880..15102b128a 100644 --- a/examples/democoin/x/pow/client/cli/tx.go +++ b/examples/democoin/x/pow/client/cli/tx.go @@ -22,7 +22,7 @@ func MineCmd(cdc *wire.Codec) *cobra.Command { Short: "Mine some coins with proof-of-work!", Args: cobra.ExactArgs(4), RunE: func(cmd *cobra.Command, args []string) error { - txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) + txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -53,7 +53,7 @@ func MineCmd(cdc *wire.Codec) *cobra.Command { // Build and sign the transaction, then broadcast to a Tendermint // node. - return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg}) }, } } diff --git a/examples/democoin/x/simplestake/client/cli/commands.go b/examples/democoin/x/simplestake/client/cli/commands.go index 75a5cacc8c..9f6eb40f7e 100644 --- a/examples/democoin/x/simplestake/client/cli/commands.go +++ b/examples/democoin/x/simplestake/client/cli/commands.go @@ -30,7 +30,7 @@ func BondTxCmd(cdc *wire.Codec) *cobra.Command { Use: "bond", Short: "Bond to a validator", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) + txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -68,7 +68,7 @@ func BondTxCmd(cdc *wire.Codec) *cobra.Command { // Build and sign the transaction, then broadcast to a Tendermint // node. - return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg}) }, } @@ -84,7 +84,7 @@ func UnbondTxCmd(cdc *wire.Codec) *cobra.Command { Use: "unbond", Short: "Unbond from a validator", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) + txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout) @@ -98,7 +98,7 @@ func UnbondTxCmd(cdc *wire.Codec) *cobra.Command { // Build and sign the transaction, then broadcast to a Tendermint // node. - return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg}) }, } diff --git a/x/bank/client/cli/sendtx.go b/x/bank/client/cli/sendtx.go index 1ea3a27ef9..6c49fa4f08 100644 --- a/x/bank/client/cli/sendtx.go +++ b/x/bank/client/cli/sendtx.go @@ -27,7 +27,7 @@ func SendTxCmd(cdc *wire.Codec) *cobra.Command { Use: "send", Short: "Create and sign a send tx", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) + txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -69,10 +69,10 @@ func SendTxCmd(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint msg := client.BuildMsg(from, to, coins) if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}) } - return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg}) }, } diff --git a/x/bank/client/rest/sendtx.go b/x/bank/client/rest/sendtx.go index 436803c628..b3694959d2 100644 --- a/x/bank/client/rest/sendtx.go +++ b/x/bank/client/rest/sendtx.go @@ -80,7 +80,7 @@ func SendRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLICo return } - txBld := authtxb.TxBuilder{ + txBldr := authtxb.TxBuilder{ Codec: cdc, Gas: m.Gas, ChainID: m.ChainID, @@ -95,24 +95,24 @@ func SendRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLICo cliCtx = cliCtx.WithGasAdjustment(adjustment) if utils.HasDryRunArg(r) || m.Gas == 0 { - newCtx, err := utils.EnrichCtxWithGas(txBld, cliCtx, m.LocalAccountName, []sdk.Msg{msg}) + newCtx, err := utils.EnrichCtxWithGas(txBldr, cliCtx, m.LocalAccountName, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } if utils.HasDryRunArg(r) { - utils.WriteSimulationResponse(w, txBld.Gas) + utils.WriteSimulationResponse(w, txBldr.Gas) return } - txBld = newCtx + txBldr = newCtx } if utils.HasGenerateOnlyArg(r) { - utils.WriteGenerateStdTxResponse(w, txBld, []sdk.Msg{msg}) + utils.WriteGenerateStdTxResponse(w, txBldr, []sdk.Msg{msg}) return } - txBytes, err := txBld.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) + txBytes, err := txBldr.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error()) return diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index 6eb7a30582..4ac461c0a9 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -77,7 +77,7 @@ $ gaiacli gov submit-proposal --title="Test Proposal" --description="My awesome return err } - txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) + txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -105,13 +105,13 @@ $ gaiacli gov submit-proposal --title="Test Proposal" --description="My awesome } if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}) } // Build and sign the transaction, then broadcast to Tendermint // proposalID must be returned, and it is a part of response. cliCtx.PrintResponse = true - return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg}) }, } @@ -161,7 +161,7 @@ func GetCmdDeposit(cdc *wire.Codec) *cobra.Command { Use: "deposit", Short: "deposit tokens for activing proposal", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) + txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -186,12 +186,12 @@ func GetCmdDeposit(cdc *wire.Codec) *cobra.Command { } if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}) } // Build and sign the transaction, then broadcast to a Tendermint // node. - return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg}) }, } @@ -207,7 +207,7 @@ func GetCmdVote(cdc *wire.Codec) *cobra.Command { Use: "vote", Short: "vote for an active proposal, options: Yes/No/NoWithVeto/Abstain", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) + txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -233,7 +233,7 @@ func GetCmdVote(cdc *wire.Codec) *cobra.Command { } if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}) } fmt.Printf("Vote[Voter:%s,ProposalID:%d,Option:%s]", @@ -242,7 +242,7 @@ func GetCmdVote(cdc *wire.Codec) *cobra.Command { // Build and sign the transaction, then broadcast to a Tendermint // node. - return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg}) }, } diff --git a/x/gov/client/rest/util.go b/x/gov/client/rest/util.go index 83160ecd0e..f9987c0308 100644 --- a/x/gov/client/rest/util.go +++ b/x/gov/client/rest/util.go @@ -70,7 +70,7 @@ func (req baseReq) baseReqValidate(w http.ResponseWriter) bool { // (probably should live in client/lcd). func signAndBuild(w http.ResponseWriter, r *http.Request, cliCtx context.CLIContext, baseReq baseReq, msg sdk.Msg, cdc *wire.Codec) { var err error - txBld := authtxb.TxBuilder{ + txBldr := authtxb.TxBuilder{ Codec: cdc, AccountNumber: baseReq.AccountNumber, Sequence: baseReq.Sequence, @@ -85,24 +85,24 @@ func signAndBuild(w http.ResponseWriter, r *http.Request, cliCtx context.CLICont cliCtx = cliCtx.WithGasAdjustment(adjustment) if utils.HasDryRunArg(r) || baseReq.Gas == 0 { - newCtx, err := utils.EnrichCtxWithGas(txBld, cliCtx, baseReq.Name, []sdk.Msg{msg}) + newCtx, err := utils.EnrichCtxWithGas(txBldr, cliCtx, baseReq.Name, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } if utils.HasDryRunArg(r) { - utils.WriteSimulationResponse(w, txBld.Gas) + utils.WriteSimulationResponse(w, txBldr.Gas) return } - txBld = newCtx + txBldr = newCtx } if utils.HasGenerateOnlyArg(r) { - utils.WriteGenerateStdTxResponse(w, txBld, []sdk.Msg{msg}) + utils.WriteGenerateStdTxResponse(w, txBldr, []sdk.Msg{msg}) return } - txBytes, err := txBld.BuildAndSign(baseReq.Name, baseReq.Password, []sdk.Msg{msg}) + txBytes, err := txBldr.BuildAndSign(baseReq.Name, baseReq.Password, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error()) return diff --git a/x/ibc/client/cli/ibctx.go b/x/ibc/client/cli/ibctx.go index a8b90a6713..49494a2180 100644 --- a/x/ibc/client/cli/ibctx.go +++ b/x/ibc/client/cli/ibctx.go @@ -28,7 +28,7 @@ func IBCTransferCmd(cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "transfer", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) + txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -44,10 +44,10 @@ func IBCTransferCmd(cdc *wire.Codec) *cobra.Command { return err } if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}) } - return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg}) }, } diff --git a/x/ibc/client/cli/relay.go b/x/ibc/client/cli/relay.go index d274edd49a..e938069742 100644 --- a/x/ibc/client/cli/relay.go +++ b/x/ibc/client/cli/relay.go @@ -199,10 +199,10 @@ func (c relayCommander) refine(bz []byte, sequence int64, passphrase string) []b Sequence: sequence, } - txBld := authtxb.NewTxBuilderFromCLI().WithSequence(sequence).WithCodec(c.cdc) + txBldr := authtxb.NewTxBuilderFromCLI().WithSequence(sequence).WithCodec(c.cdc) cliCtx := context.NewCLIContext() - res, err := txBld.BuildAndSign(cliCtx.FromAddressName, passphrase, []sdk.Msg{msg}) + res, err := txBldr.BuildAndSign(cliCtx.FromAddressName, passphrase, []sdk.Msg{msg}) if err != nil { panic(err) } diff --git a/x/ibc/client/rest/transfer.go b/x/ibc/client/rest/transfer.go index 5367bc88b3..110efe601e 100644 --- a/x/ibc/client/rest/transfer.go +++ b/x/ibc/client/rest/transfer.go @@ -71,7 +71,7 @@ func TransferRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.C packet := ibc.NewIBCPacket(sdk.AccAddress(info.GetPubKey().Address()), to, m.Amount, m.SrcChainID, destChainID) msg := ibc.IBCTransferMsg{packet} - txBld := authtxb.TxBuilder{ + txBldr := authtxb.TxBuilder{ Codec: cdc, ChainID: m.SrcChainID, AccountNumber: m.AccountNumber, @@ -86,24 +86,24 @@ func TransferRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.C cliCtx = cliCtx.WithGasAdjustment(adjustment) if utils.HasDryRunArg(r) || m.Gas == 0 { - newCtx, err := utils.EnrichCtxWithGas(txBld, cliCtx, m.LocalAccountName, []sdk.Msg{msg}) + newCtx, err := utils.EnrichCtxWithGas(txBldr, cliCtx, m.LocalAccountName, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } if utils.HasDryRunArg(r) { - utils.WriteSimulationResponse(w, txBld.Gas) + utils.WriteSimulationResponse(w, txBldr.Gas) return } - txBld = newCtx + txBldr = newCtx } if utils.HasGenerateOnlyArg(r) { - utils.WriteGenerateStdTxResponse(w, txBld, []sdk.Msg{msg}) + utils.WriteGenerateStdTxResponse(w, txBldr, []sdk.Msg{msg}) return } - txBytes, err := txBld.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) + txBytes, err := txBldr.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error()) return diff --git a/x/slashing/client/cli/tx.go b/x/slashing/client/cli/tx.go index 86abdeade7..1810ffeedf 100644 --- a/x/slashing/client/cli/tx.go +++ b/x/slashing/client/cli/tx.go @@ -21,7 +21,7 @@ func GetCmdUnjail(cdc *wire.Codec) *cobra.Command { Args: cobra.NoArgs, Short: "unjail validator previously jailed for downtime", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) + txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -34,9 +34,9 @@ func GetCmdUnjail(cdc *wire.Codec) *cobra.Command { msg := slashing.NewMsgUnjail(sdk.ValAddress(valAddr)) if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}) } - return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg}) }, } diff --git a/x/slashing/client/rest/tx.go b/x/slashing/client/rest/tx.go index b8e4c46547..1d4fdefa1d 100644 --- a/x/slashing/client/rest/tx.go +++ b/x/slashing/client/rest/tx.go @@ -70,7 +70,7 @@ func unjailRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLI return } - txBld := authtxb.TxBuilder{ + txBldr := authtxb.TxBuilder{ Codec: cdc, ChainID: m.ChainID, AccountNumber: m.AccountNumber, @@ -87,24 +87,24 @@ func unjailRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLI cliCtx = cliCtx.WithGasAdjustment(adjustment) if utils.HasDryRunArg(r) || m.Gas == 0 { - newCtx, err := utils.EnrichCtxWithGas(txBld, cliCtx, m.LocalAccountName, []sdk.Msg{msg}) + newCtx, err := utils.EnrichCtxWithGas(txBldr, cliCtx, m.LocalAccountName, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } if utils.HasDryRunArg(r) { - utils.WriteSimulationResponse(w, txBld.Gas) + utils.WriteSimulationResponse(w, txBldr.Gas) return } - txBld = newCtx + txBldr = newCtx } if utils.HasGenerateOnlyArg(r) { - utils.WriteGenerateStdTxResponse(w, txBld, []sdk.Msg{msg}) + utils.WriteGenerateStdTxResponse(w, txBldr, []sdk.Msg{msg}) return } - txBytes, err := txBld.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) + txBytes, err := txBldr.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusUnauthorized, "Must use own validator address") return diff --git a/x/stake/client/cli/tx.go b/x/stake/client/cli/tx.go index b93fdb1f46..fad8818036 100644 --- a/x/stake/client/cli/tx.go +++ b/x/stake/client/cli/tx.go @@ -25,7 +25,7 @@ func GetCmdCreateValidator(cdc *wire.Codec) *cobra.Command { Use: "create-validator", Short: "create new validator initialized with a self-delegation to it", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) + txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -78,10 +78,10 @@ func GetCmdCreateValidator(cdc *wire.Codec) *cobra.Command { msg = stake.NewMsgCreateValidator(sdk.ValAddress(valAddr), pk, amount, description) } if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}) } // build and sign the transaction, then broadcast to Tendermint - return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg}) }, } @@ -99,7 +99,7 @@ func GetCmdEditValidator(cdc *wire.Codec) *cobra.Command { Use: "edit-validator", Short: "edit and existing validator account", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) + txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -120,10 +120,10 @@ func GetCmdEditValidator(cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgEditValidator(sdk.ValAddress(valAddr), description) if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}) } // build and sign the transaction, then broadcast to Tendermint - return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg}) }, } @@ -138,7 +138,7 @@ func GetCmdDelegate(cdc *wire.Codec) *cobra.Command { Use: "delegate", Short: "delegate liquid tokens to an validator", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) + txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -162,10 +162,10 @@ func GetCmdDelegate(cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgDelegate(delAddr, valAddr, amount) if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}) } // build and sign the transaction, then broadcast to Tendermint - return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg}) }, } @@ -197,7 +197,7 @@ func GetCmdBeginRedelegate(storeName string, cdc *wire.Codec) *cobra.Command { Use: "begin", Short: "begin redelegation", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) + txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -234,10 +234,10 @@ func GetCmdBeginRedelegate(storeName string, cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgBeginRedelegate(delAddr, valSrcAddr, valDstAddr, sharesAmount) if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}) } // build and sign the transaction, then broadcast to Tendermint - return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg}) }, } @@ -301,7 +301,7 @@ func GetCmdCompleteRedelegate(cdc *wire.Codec) *cobra.Command { Use: "complete", Short: "complete redelegation", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) + txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -325,10 +325,10 @@ func GetCmdCompleteRedelegate(cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgCompleteRedelegate(delAddr, valSrcAddr, valDstAddr) if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}) } // build and sign the transaction, then broadcast to Tendermint - return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg}) }, } @@ -359,7 +359,7 @@ func GetCmdBeginUnbonding(storeName string, cdc *wire.Codec) *cobra.Command { Use: "begin", Short: "begin unbonding", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) + txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -389,10 +389,10 @@ func GetCmdBeginUnbonding(storeName string, cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgBeginUnbonding(delAddr, valAddr, sharesAmount) if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}) } // build and sign the transaction, then broadcast to Tendermint - return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg}) }, } @@ -408,7 +408,7 @@ func GetCmdCompleteUnbonding(cdc *wire.Codec) *cobra.Command { Use: "complete", Short: "complete unbonding", RunE: func(cmd *cobra.Command, args []string) error { - txBld := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) + txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -427,10 +427,10 @@ func GetCmdCompleteUnbonding(cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgCompleteUnbonding(delAddr, valAddr) if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}) } // build and sign the transaction, then broadcast to Tendermint - return utils.SendTx(txBld, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg}) }, } diff --git a/x/stake/client/rest/tx.go b/x/stake/client/rest/tx.go index c506935a50..d84a8daea9 100644 --- a/x/stake/client/rest/tx.go +++ b/x/stake/client/rest/tx.go @@ -263,7 +263,7 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex i++ } - txBld := authtxb.TxBuilder{ + txBldr := authtxb.TxBuilder{ Codec: cdc, ChainID: m.ChainID, Gas: m.Gas, @@ -273,8 +273,8 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex signedTxs := make([][]byte, len(messages[:])) for i, msg := range messages { // increment sequence for each message - txBld = txBld.WithAccountNumber(m.AccountNumber) - txBld = txBld.WithSequence(m.Sequence) + txBldr = txBldr.WithAccountNumber(m.AccountNumber) + txBldr = txBldr.WithSequence(m.Sequence) m.Sequence++ @@ -285,24 +285,24 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex cliCtx = cliCtx.WithGasAdjustment(adjustment) if utils.HasDryRunArg(r) || m.Gas == 0 { - newCtx, err := utils.EnrichCtxWithGas(txBld, cliCtx, m.LocalAccountName, []sdk.Msg{msg}) + newCtx, err := utils.EnrichCtxWithGas(txBldr, cliCtx, m.LocalAccountName, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } if utils.HasDryRunArg(r) { - utils.WriteSimulationResponse(w, txBld.Gas) + utils.WriteSimulationResponse(w, txBldr.Gas) return } - txBld = newCtx + txBldr = newCtx } if utils.HasGenerateOnlyArg(r) { - utils.WriteGenerateStdTxResponse(w, txBld, []sdk.Msg{msg}) + utils.WriteGenerateStdTxResponse(w, txBldr, []sdk.Msg{msg}) return } - txBytes, err := txBld.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) + txBytes, err := txBldr.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error()) return From a27d83911a7bbd64c6a9f7e92136c6f66131b30e Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 7 Sep 2018 10:34:44 -0700 Subject: [PATCH 66/93] bld -> bldr in txbuilder.go --- x/auth/client/txbuilder/txbuilder.go | 76 ++++++++++++++-------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/x/auth/client/txbuilder/txbuilder.go b/x/auth/client/txbuilder/txbuilder.go index 41b8018051..82ef5afd93 100644 --- a/x/auth/client/txbuilder/txbuilder.go +++ b/x/auth/client/txbuilder/txbuilder.go @@ -45,58 +45,58 @@ func NewTxBuilderFromCLI() TxBuilder { } // WithCodec returns a copy of the context with an updated codec. -func (bld TxBuilder) WithCodec(cdc *wire.Codec) TxBuilder { - bld.Codec = cdc - return bld +func (bldr TxBuilder) WithCodec(cdc *wire.Codec) TxBuilder { + bldr.Codec = cdc + return bldr } // WithChainID returns a copy of the context with an updated chainID. -func (bld TxBuilder) WithChainID(chainID string) TxBuilder { - bld.ChainID = chainID - return bld +func (bldr TxBuilder) WithChainID(chainID string) TxBuilder { + bldr.ChainID = chainID + return bldr } // WithGas returns a copy of the context with an updated gas. -func (bld TxBuilder) WithGas(gas int64) TxBuilder { - bld.Gas = gas - return bld +func (bldr TxBuilder) WithGas(gas int64) TxBuilder { + bldr.Gas = gas + return bldr } // WithFee returns a copy of the context with an updated fee. -func (bld TxBuilder) WithFee(fee string) TxBuilder { - bld.Fee = fee - return bld +func (bldr TxBuilder) WithFee(fee string) TxBuilder { + bldr.Fee = fee + return bldr } // WithSequence returns a copy of the context with an updated sequence number. -func (bld TxBuilder) WithSequence(sequence int64) TxBuilder { - bld.Sequence = sequence - return bld +func (bldr TxBuilder) WithSequence(sequence int64) TxBuilder { + bldr.Sequence = sequence + return bldr } // WithMemo returns a copy of the context with an updated memo. -func (bld TxBuilder) WithMemo(memo string) TxBuilder { - bld.Memo = memo - return bld +func (bldr TxBuilder) WithMemo(memo string) TxBuilder { + bldr.Memo = memo + return bldr } // WithAccountNumber returns a copy of the context with an account number. -func (bld TxBuilder) WithAccountNumber(accnum int64) TxBuilder { - bld.AccountNumber = accnum - return bld +func (bldr TxBuilder) WithAccountNumber(accnum int64) TxBuilder { + bldr.AccountNumber = accnum + return bldr } // Build builds a single message to be signed from a TxBuilder given a set of // messages. It returns an error if a fee is supplied but cannot be parsed. -func (bld TxBuilder) Build(msgs []sdk.Msg) (auth.StdSignMsg, error) { - chainID := bld.ChainID +func (bldr TxBuilder) Build(msgs []sdk.Msg) (auth.StdSignMsg, error) { + chainID := bldr.ChainID if chainID == "" { return auth.StdSignMsg{}, errors.Errorf("chain ID required but not specified") } fee := sdk.Coin{} - if bld.Fee != "" { - parsedFee, err := sdk.ParseCoin(bld.Fee) + if bldr.Fee != "" { + parsedFee, err := sdk.ParseCoin(bldr.Fee) if err != nil { return auth.StdSignMsg{}, err } @@ -105,18 +105,18 @@ func (bld TxBuilder) Build(msgs []sdk.Msg) (auth.StdSignMsg, error) { } return auth.StdSignMsg{ - ChainID: bld.ChainID, - AccountNumber: bld.AccountNumber, - Sequence: bld.Sequence, - Memo: bld.Memo, + ChainID: bldr.ChainID, + AccountNumber: bldr.AccountNumber, + Sequence: bldr.Sequence, + Memo: bldr.Memo, Msgs: msgs, - Fee: auth.NewStdFee(bld.Gas, fee), + Fee: auth.NewStdFee(bldr.Gas, fee), }, nil } // Sign signs a transaction given a name, passphrase, and a single message to // signed. An error is returned if signing fails. -func (bld TxBuilder) Sign(name, passphrase string, msg auth.StdSignMsg) ([]byte, error) { +func (bldr TxBuilder) Sign(name, passphrase string, msg auth.StdSignMsg) ([]byte, error) { keybase, err := keys.GetKeyBase() if err != nil { return nil, err @@ -134,27 +134,27 @@ func (bld TxBuilder) Sign(name, passphrase string, msg auth.StdSignMsg) ([]byte, Signature: sig, }} - return bld.Codec.MarshalBinary(auth.NewStdTx(msg.Msgs, msg.Fee, sigs, msg.Memo)) + return bldr.Codec.MarshalBinary(auth.NewStdTx(msg.Msgs, msg.Fee, sigs, msg.Memo)) } // BuildAndSign builds a single message to be signed, and signs a transaction // with the built message given a name, passphrase, and a set of // messages. -func (bld TxBuilder) BuildAndSign(name, passphrase string, msgs []sdk.Msg) ([]byte, error) { - msg, err := bld.Build(msgs) +func (bldr TxBuilder) BuildAndSign(name, passphrase string, msgs []sdk.Msg) ([]byte, error) { + msg, err := bldr.Build(msgs) if err != nil { return nil, err } - return bld.Sign(name, passphrase, msg) + return bldr.Sign(name, passphrase, msg) } // BuildWithPubKey builds a single message to be signed from a TxBuilder given a set of // messages and attach the public key associated to the given name. // It returns an error if a fee is supplied but cannot be parsed or the key cannot be // retrieved. -func (bld TxBuilder) BuildWithPubKey(name string, msgs []sdk.Msg) ([]byte, error) { - msg, err := bld.Build(msgs) +func (bldr TxBuilder) BuildWithPubKey(name string, msgs []sdk.Msg) ([]byte, error) { + msg, err := bldr.Build(msgs) if err != nil { return nil, err } @@ -175,5 +175,5 @@ func (bld TxBuilder) BuildWithPubKey(name string, msgs []sdk.Msg) ([]byte, error PubKey: info.GetPubKey(), }} - return bld.Codec.MarshalBinary(auth.NewStdTx(msg.Msgs, msg.Fee, sigs, msg.Memo)) + return bldr.Codec.MarshalBinary(auth.NewStdTx(msg.Msgs, msg.Fee, sigs, msg.Memo)) } From e8129196490776141059e91e53ae1d50b3a029e8 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Fri, 7 Sep 2018 22:34:32 -0700 Subject: [PATCH 67/93] Rename coinKeeper -> bankKeeper Closes #2267 --- cmd/gaia/app/app.go | 12 +-- cmd/gaia/app/sim_test.go | 2 +- cmd/gaia/cmd/gaiadebug/hack.go | 10 +-- docs/sdk/core/app3.md | 8 +- docs/sdk/core/examples/app3.go | 4 +- docs/sdk/core/examples/app4.go | 4 +- .../simple-governance/app-constructor.md | 8 +- .../simple-governance/app-structure.md | 2 +- examples/basecoin/app/app.go | 8 +- examples/democoin/app/app.go | 14 +-- examples/democoin/x/cool/app_test.go | 4 +- examples/democoin/x/pow/app_test.go | 4 +- examples/democoin/x/simplestake/keeper.go | 4 +- .../democoin/x/simplestake/keeper_test.go | 4 +- x/bank/bench_test.go | 4 +- x/bank/keeper_test.go | 86 +++++++++---------- x/bank/simulation/sim_test.go | 4 +- x/distribution/keeper.go | 4 +- x/gov/simulation/sim_test.go | 6 +- x/ibc/app_test.go | 4 +- x/slashing/app_test.go | 4 +- x/stake/app_test.go | 4 +- x/stake/keeper/delegation.go | 6 +- x/stake/keeper/keeper.go | 4 +- x/stake/simulation/sim_test.go | 6 +- 25 files changed, 110 insertions(+), 110 deletions(-) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index f1ca2a7b66..36a02899b5 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -52,7 +52,7 @@ type GaiaApp struct { // Manage getting and setting accounts accountMapper auth.AccountMapper feeCollectionKeeper auth.FeeCollectionKeeper - coinKeeper bank.Keeper + bankKeeper bank.Keeper ibcMapper ibc.Mapper stakeKeeper stake.Keeper slashingKeeper slashing.Keeper @@ -89,19 +89,19 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio ) // add handlers - app.coinKeeper = bank.NewKeeper(app.accountMapper) + app.bankKeeper = bank.NewKeeper(app.accountMapper) app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace)) app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams) - app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.coinKeeper, app.RegisterCodespace(stake.DefaultCodespace)) + app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace)) app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace)) app.stakeKeeper = app.stakeKeeper.WithValidatorHooks(app.slashingKeeper.ValidatorHooks()) - app.govKeeper = gov.NewKeeper(app.cdc, app.keyGov, app.paramsKeeper.Setter(), app.coinKeeper, app.stakeKeeper, app.RegisterCodespace(gov.DefaultCodespace)) + app.govKeeper = gov.NewKeeper(app.cdc, app.keyGov, app.paramsKeeper.Setter(), app.bankKeeper, app.stakeKeeper, app.RegisterCodespace(gov.DefaultCodespace)) app.feeCollectionKeeper = auth.NewFeeCollectionKeeper(app.cdc, app.keyFeeCollection) // register message routes app.Router(). - AddRoute("bank", bank.NewHandler(app.coinKeeper)). - AddRoute("ibc", ibc.NewHandler(app.ibcMapper, app.coinKeeper)). + AddRoute("bank", bank.NewHandler(app.bankKeeper)). + AddRoute("ibc", ibc.NewHandler(app.ibcMapper, app.bankKeeper)). AddRoute("stake", stake.NewHandler(app.stakeKeeper)). AddRoute("slashing", slashing.NewHandler(app.slashingKeeper)). AddRoute("gov", gov.NewHandler(app.govKeeper)) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index ca864bf795..97de59a234 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -111,7 +111,7 @@ func invariants(app *GaiaApp) []simulation.Invariant { func(t *testing.T, baseapp *baseapp.BaseApp, log string) { banksim.NonnegativeBalanceInvariant(app.accountMapper)(t, baseapp, log) govsim.AllInvariants()(t, baseapp, log) - stakesim.AllInvariants(app.coinKeeper, app.stakeKeeper, app.accountMapper)(t, baseapp, log) + stakesim.AllInvariants(app.bankKeeper, app.stakeKeeper, app.accountMapper)(t, baseapp, log) slashingsim.AllInvariants()(t, baseapp, log) }, } diff --git a/cmd/gaia/cmd/gaiadebug/hack.go b/cmd/gaia/cmd/gaiadebug/hack.go index cab9d0ab00..873dd88295 100644 --- a/cmd/gaia/cmd/gaiadebug/hack.go +++ b/cmd/gaia/cmd/gaiadebug/hack.go @@ -140,7 +140,7 @@ type GaiaApp struct { // Manage getting and setting accounts accountMapper auth.AccountMapper feeCollectionKeeper auth.FeeCollectionKeeper - coinKeeper bank.Keeper + bankKeeper bank.Keeper ibcMapper ibc.Mapper stakeKeeper stake.Keeper slashingKeeper slashing.Keeper @@ -173,16 +173,16 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.BaseAp ) // add handlers - app.coinKeeper = bank.NewKeeper(app.accountMapper) + app.bankKeeper = bank.NewKeeper(app.accountMapper) app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace)) app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams) - app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.coinKeeper, app.RegisterCodespace(stake.DefaultCodespace)) + app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace)) app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace)) // register message routes app.Router(). - AddRoute("bank", bank.NewHandler(app.coinKeeper)). - AddRoute("ibc", ibc.NewHandler(app.ibcMapper, app.coinKeeper)). + AddRoute("bank", bank.NewHandler(app.bankKeeper)). + AddRoute("ibc", ibc.NewHandler(app.ibcMapper, app.bankKeeper)). AddRoute("stake", stake.NewHandler(app.stakeKeeper)) // initialize BaseApp diff --git a/docs/sdk/core/app3.md b/docs/sdk/core/app3.md index 203f61e444..fea42d449c 100644 --- a/docs/sdk/core/app3.md +++ b/docs/sdk/core/app3.md @@ -285,7 +285,7 @@ it can't increment sequence numbers, change PubKeys, or otherwise. A `bank.Keeper` is easily instantiated from an `AccountMapper`: ```go -coinKeeper = bank.NewKeeper(accountMapper) +bankKeeper = bank.NewKeeper(accountMapper) ``` We can then use it within a handler, instead of working directly with the @@ -295,7 +295,7 @@ We can then use it within a handler, instead of working directly with the // Finds account with addr in AccountMapper. // Adds coins to account's coin array. // Sets updated account in AccountMapper -app.coinKeeper.AddCoins(ctx, addr, coins) +app.bankKeeper.AddCoins(ctx, addr, coins) ``` See the [bank.Keeper API @@ -336,7 +336,7 @@ func NewApp3(logger log.Logger, db dbm.DB) *bapp.BaseApp { // Set various mappers/keepers to interact easily with underlying stores accountMapper := auth.NewAccountMapper(cdc, keyAccount, auth.ProtoBaseAccount) - coinKeeper := bank.NewKeeper(accountMapper) + bankKeeper := bank.NewKeeper(accountMapper) feeKeeper := auth.NewFeeCollectionKeeper(cdc, keyFees) app.SetAnteHandler(auth.NewAnteHandler(accountMapper, feeKeeper)) @@ -344,7 +344,7 @@ func NewApp3(logger log.Logger, db dbm.DB) *bapp.BaseApp { // Register message routes. // Note the handler gets access to app.Router(). - AddRoute("send", bank.NewHandler(coinKeeper)) + AddRoute("send", bank.NewHandler(bankKeeper)) // Mount stores and load the latest state. app.MountStoresIAVL(keyAccount, keyFees) diff --git a/docs/sdk/core/examples/app3.go b/docs/sdk/core/examples/app3.go index f7ae88c421..a423e37435 100644 --- a/docs/sdk/core/examples/app3.go +++ b/docs/sdk/core/examples/app3.go @@ -31,7 +31,7 @@ func NewApp3(logger log.Logger, db dbm.DB) *bapp.BaseApp { // Set various mappers/keepers to interact easily with underlying stores accountMapper := auth.NewAccountMapper(cdc, keyAccount, auth.ProtoBaseAccount) - coinKeeper := bank.NewKeeper(accountMapper) + bankKeeper := bank.NewKeeper(accountMapper) feeKeeper := auth.NewFeeCollectionKeeper(cdc, keyFees) app.SetAnteHandler(auth.NewAnteHandler(accountMapper, feeKeeper)) @@ -39,7 +39,7 @@ func NewApp3(logger log.Logger, db dbm.DB) *bapp.BaseApp { // Register message routes. // Note the handler gets access to app.Router(). - AddRoute("bank", bank.NewHandler(coinKeeper)) + AddRoute("bank", bank.NewHandler(bankKeeper)) // Mount stores and load the latest state. app.MountStoresIAVL(keyAccount, keyFees) diff --git a/docs/sdk/core/examples/app4.go b/docs/sdk/core/examples/app4.go index a4432b3da6..be4e5f4f4a 100644 --- a/docs/sdk/core/examples/app4.go +++ b/docs/sdk/core/examples/app4.go @@ -29,7 +29,7 @@ func NewApp4(logger log.Logger, db dbm.DB) *bapp.BaseApp { // Set various mappers/keepers to interact easily with underlying stores accountMapper := auth.NewAccountMapper(cdc, keyAccount, auth.ProtoBaseAccount) - coinKeeper := bank.NewKeeper(accountMapper) + bankKeeper := bank.NewKeeper(accountMapper) // TODO keyFees := sdk.NewKVStoreKey("fee") @@ -43,7 +43,7 @@ func NewApp4(logger log.Logger, db dbm.DB) *bapp.BaseApp { // Register message routes. // Note the handler gets access to the account store. app.Router(). - AddRoute("bank", bank.NewHandler(coinKeeper)) + AddRoute("bank", bank.NewHandler(bankKeeper)) // Mount stores and load the latest state. app.MountStoresIAVL(keyAccount, keyFees) diff --git a/docs/sdk/sdk-by-examples/simple-governance/app-constructor.md b/docs/sdk/sdk-by-examples/simple-governance/app-constructor.md index 84858edf4c..76c8a7a144 100644 --- a/docs/sdk/sdk-by-examples/simple-governance/app-constructor.md +++ b/docs/sdk/sdk-by-examples/simple-governance/app-constructor.md @@ -33,16 +33,16 @@ var cdc = MakeCodec() - Instantiate the keepers. Note that keepers generally need access to other module's keepers. In this case, make sure you only pass an instance of the keeper for the functionality that is needed. If a keeper only needs to read in another module's store, a read-only keeper should be passed to it. ```go -app.coinKeeper = bank.NewKeeper(app.accountMapper) -app.stakeKeeper = simplestake.NewKeeper(app.capKeyStakingStore, app.coinKeeper,app.RegisterCodespace(simplestake.DefaultCodespace)) -app.simpleGovKeeper = simpleGov.NewKeeper(app.capKeySimpleGovStore, app.coinKeeper, app.stakeKeeper, app.RegisterCodespace(simpleGov.DefaultCodespace)) +app.bankKeeper = bank.NewKeeper(app.accountMapper) +app.stakeKeeper = simplestake.NewKeeper(app.capKeyStakingStore, app.bankKeeper,app.RegisterCodespace(simplestake.DefaultCodespace)) +app.simpleGovKeeper = simpleGov.NewKeeper(app.capKeySimpleGovStore, app.bankKeeper, app.stakeKeeper, app.RegisterCodespace(simpleGov.DefaultCodespace)) ``` - Declare the handlers. ```go app.Router(). - AddRoute("bank", bank.NewHandler(app.coinKeeper)). + AddRoute("bank", bank.NewHandler(app.bankKeeper)). AddRoute("simplestake", simplestake.NewHandler(app.stakeKeeper)). AddRoute("simpleGov", simpleGov.NewHandler(app.simpleGovKeeper)) ``` diff --git a/docs/sdk/sdk-by-examples/simple-governance/app-structure.md b/docs/sdk/sdk-by-examples/simple-governance/app-structure.md index c213b673b7..7cec5aa5c8 100644 --- a/docs/sdk/sdk-by-examples/simple-governance/app-structure.md +++ b/docs/sdk/sdk-by-examples/simple-governance/app-structure.md @@ -38,7 +38,7 @@ type SimpleGovApp struct { // keepers feeCollectionKeeper auth.FeeCollectionKeeper - coinKeeper bank.Keeper + bankKeeper bank.Keeper stakeKeeper simplestake.Keeper simpleGovKeeper simpleGov.Keeper diff --git a/examples/basecoin/app/app.go b/examples/basecoin/app/app.go index 17f6de87b3..001d05d3a5 100644 --- a/examples/basecoin/app/app.go +++ b/examples/basecoin/app/app.go @@ -37,7 +37,7 @@ type BasecoinApp struct { // manage getting and setting accounts accountMapper auth.AccountMapper feeCollectionKeeper auth.FeeCollectionKeeper - coinKeeper bank.Keeper + bankKeeper bank.Keeper ibcMapper ibc.Mapper } @@ -67,13 +67,13 @@ func NewBasecoinApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.Ba return &types.AppAccount{} }, ) - app.coinKeeper = bank.NewKeeper(app.accountMapper) + app.bankKeeper = bank.NewKeeper(app.accountMapper) app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace)) // register message routes app.Router(). - AddRoute("bank", bank.NewHandler(app.coinKeeper)). - AddRoute("ibc", ibc.NewHandler(app.ibcMapper, app.coinKeeper)) + AddRoute("bank", bank.NewHandler(app.bankKeeper)). + AddRoute("ibc", ibc.NewHandler(app.ibcMapper, app.bankKeeper)) // perform initialization logic app.SetInitChainer(app.initChainer) diff --git a/examples/democoin/app/app.go b/examples/democoin/app/app.go index d4cbac6239..a7078a3b15 100644 --- a/examples/democoin/app/app.go +++ b/examples/democoin/app/app.go @@ -41,7 +41,7 @@ type DemocoinApp struct { // keepers feeCollectionKeeper auth.FeeCollectionKeeper - coinKeeper bank.Keeper + bankKeeper bank.Keeper coolKeeper cool.Keeper powKeeper pow.Keeper ibcMapper ibc.Mapper @@ -75,17 +75,17 @@ func NewDemocoinApp(logger log.Logger, db dbm.DB) *DemocoinApp { ) // Add handlers. - app.coinKeeper = bank.NewKeeper(app.accountMapper) - app.coolKeeper = cool.NewKeeper(app.capKeyMainStore, app.coinKeeper, app.RegisterCodespace(cool.DefaultCodespace)) - app.powKeeper = pow.NewKeeper(app.capKeyPowStore, pow.NewConfig("pow", int64(1)), app.coinKeeper, app.RegisterCodespace(pow.DefaultCodespace)) + app.bankKeeper = bank.NewKeeper(app.accountMapper) + app.coolKeeper = cool.NewKeeper(app.capKeyMainStore, app.bankKeeper, app.RegisterCodespace(cool.DefaultCodespace)) + app.powKeeper = pow.NewKeeper(app.capKeyPowStore, pow.NewConfig("pow", int64(1)), app.bankKeeper, app.RegisterCodespace(pow.DefaultCodespace)) app.ibcMapper = ibc.NewMapper(app.cdc, app.capKeyIBCStore, app.RegisterCodespace(ibc.DefaultCodespace)) - app.stakeKeeper = simplestake.NewKeeper(app.capKeyStakingStore, app.coinKeeper, app.RegisterCodespace(simplestake.DefaultCodespace)) + app.stakeKeeper = simplestake.NewKeeper(app.capKeyStakingStore, app.bankKeeper, app.RegisterCodespace(simplestake.DefaultCodespace)) app.Router(). - AddRoute("bank", bank.NewHandler(app.coinKeeper)). + AddRoute("bank", bank.NewHandler(app.bankKeeper)). AddRoute("cool", cool.NewHandler(app.coolKeeper)). AddRoute("pow", app.powKeeper.Handler). AddRoute("sketchy", sketchy.NewHandler()). - AddRoute("ibc", ibc.NewHandler(app.ibcMapper, app.coinKeeper)). + AddRoute("ibc", ibc.NewHandler(app.ibcMapper, app.bankKeeper)). AddRoute("simplestake", simplestake.NewHandler(app.stakeKeeper)) // Initialize BaseApp. diff --git a/examples/democoin/x/cool/app_test.go b/examples/democoin/x/cool/app_test.go index c0453a58ec..9e1aa776e4 100644 --- a/examples/democoin/x/cool/app_test.go +++ b/examples/democoin/x/cool/app_test.go @@ -49,8 +49,8 @@ func getMockApp(t *testing.T) *mock.App { RegisterWire(mapp.Cdc) keyCool := sdk.NewKVStoreKey("cool") - coinKeeper := bank.NewKeeper(mapp.AccountMapper) - keeper := NewKeeper(keyCool, coinKeeper, mapp.RegisterCodespace(DefaultCodespace)) + bankKeeper := bank.NewKeeper(mapp.AccountMapper) + keeper := NewKeeper(keyCool, bankKeeper, mapp.RegisterCodespace(DefaultCodespace)) mapp.Router().AddRoute("cool", NewHandler(keeper)) mapp.SetInitChainer(getInitChainer(mapp, keeper, "ice-cold")) diff --git a/examples/democoin/x/pow/app_test.go b/examples/democoin/x/pow/app_test.go index 76f062e3b0..2aa4ea9b0a 100644 --- a/examples/democoin/x/pow/app_test.go +++ b/examples/democoin/x/pow/app_test.go @@ -25,9 +25,9 @@ func getMockApp(t *testing.T) *mock.App { RegisterWire(mapp.Cdc) keyPOW := sdk.NewKVStoreKey("pow") - coinKeeper := bank.NewKeeper(mapp.AccountMapper) + bankKeeper := bank.NewKeeper(mapp.AccountMapper) config := Config{"pow", 1} - keeper := NewKeeper(keyPOW, config, coinKeeper, mapp.RegisterCodespace(DefaultCodespace)) + keeper := NewKeeper(keyPOW, config, bankKeeper, mapp.RegisterCodespace(DefaultCodespace)) mapp.Router().AddRoute("pow", keeper.Handler) mapp.SetInitChainer(getInitChainer(mapp, keeper)) diff --git a/examples/democoin/x/simplestake/keeper.go b/examples/democoin/x/simplestake/keeper.go index 43b1590bd2..eb3f340792 100644 --- a/examples/democoin/x/simplestake/keeper.go +++ b/examples/democoin/x/simplestake/keeper.go @@ -21,13 +21,13 @@ type Keeper struct { codespace sdk.CodespaceType } -func NewKeeper(key sdk.StoreKey, coinKeeper bank.Keeper, codespace sdk.CodespaceType) Keeper { +func NewKeeper(key sdk.StoreKey, bankKeeper bank.Keeper, codespace sdk.CodespaceType) Keeper { cdc := wire.NewCodec() wire.RegisterCrypto(cdc) return Keeper{ key: key, cdc: cdc, - ck: coinKeeper, + ck: bankKeeper, codespace: codespace, } } diff --git a/examples/democoin/x/simplestake/keeper_test.go b/examples/democoin/x/simplestake/keeper_test.go index 02dbd964ae..393bc1b335 100644 --- a/examples/democoin/x/simplestake/keeper_test.go +++ b/examples/democoin/x/simplestake/keeper_test.go @@ -66,8 +66,8 @@ func TestBonding(t *testing.T) { ctx := sdk.NewContext(ms, abci.Header{}, false, log.NewNopLogger()) accountMapper := auth.NewAccountMapper(cdc, authKey, auth.ProtoBaseAccount) - coinKeeper := bank.NewKeeper(accountMapper) - stakeKeeper := NewKeeper(capKey, coinKeeper, DefaultCodespace) + bankKeeper := bank.NewKeeper(accountMapper) + stakeKeeper := NewKeeper(capKey, bankKeeper, DefaultCodespace) addr := sdk.AccAddress([]byte("some-address")) privKey := ed25519.GenPrivKey() pubKey := privKey.PubKey() diff --git a/x/bank/bench_test.go b/x/bank/bench_test.go index aaa391b399..3d84a892df 100644 --- a/x/bank/bench_test.go +++ b/x/bank/bench_test.go @@ -16,8 +16,8 @@ func getBenchmarkMockApp() (*mock.App, error) { mapp := mock.NewApp() RegisterWire(mapp.Cdc) - coinKeeper := NewKeeper(mapp.AccountMapper) - mapp.Router().AddRoute("bank", NewHandler(coinKeeper)) + bankKeeper := NewKeeper(mapp.AccountMapper) + mapp.Router().AddRoute("bank", NewHandler(bankKeeper)) err := mapp.CompleteSetup([]*sdk.KVStoreKey{}) return mapp, err diff --git a/x/bank/keeper_test.go b/x/bank/keeper_test.go index a114f75ad3..36c0000e77 100644 --- a/x/bank/keeper_test.go +++ b/x/bank/keeper_test.go @@ -34,7 +34,7 @@ func TestKeeper(t *testing.T) { ctx := sdk.NewContext(ms, abci.Header{}, false, log.NewNopLogger()) accountMapper := auth.NewAccountMapper(cdc, authKey, auth.ProtoBaseAccount) - coinKeeper := NewKeeper(accountMapper) + bankKeeper := NewKeeper(accountMapper) addr := sdk.AccAddress([]byte("addr1")) addr2 := sdk.AccAddress([]byte("addr2")) @@ -43,57 +43,57 @@ func TestKeeper(t *testing.T) { // Test GetCoins/SetCoins accountMapper.SetAccount(ctx, acc) - require.True(t, coinKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{})) + require.True(t, bankKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{})) - coinKeeper.SetCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("foocoin", 10)}) - require.True(t, coinKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("foocoin", 10)})) + bankKeeper.SetCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("foocoin", 10)}) + require.True(t, bankKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("foocoin", 10)})) // Test HasCoins - require.True(t, coinKeeper.HasCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("foocoin", 10)})) - require.True(t, coinKeeper.HasCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("foocoin", 5)})) - require.False(t, coinKeeper.HasCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("foocoin", 15)})) - require.False(t, coinKeeper.HasCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("barcoin", 5)})) + require.True(t, bankKeeper.HasCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("foocoin", 10)})) + require.True(t, bankKeeper.HasCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("foocoin", 5)})) + require.False(t, bankKeeper.HasCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("foocoin", 15)})) + require.False(t, bankKeeper.HasCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("barcoin", 5)})) // Test AddCoins - coinKeeper.AddCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("foocoin", 15)}) - require.True(t, coinKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("foocoin", 25)})) + bankKeeper.AddCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("foocoin", 15)}) + require.True(t, bankKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("foocoin", 25)})) - coinKeeper.AddCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("barcoin", 15)}) - require.True(t, coinKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("barcoin", 15), sdk.NewInt64Coin("foocoin", 25)})) + bankKeeper.AddCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("barcoin", 15)}) + require.True(t, bankKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("barcoin", 15), sdk.NewInt64Coin("foocoin", 25)})) // Test SubtractCoins - coinKeeper.SubtractCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("foocoin", 10)}) - coinKeeper.SubtractCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("barcoin", 5)}) - require.True(t, coinKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 15)})) + bankKeeper.SubtractCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("foocoin", 10)}) + bankKeeper.SubtractCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("barcoin", 5)}) + require.True(t, bankKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 15)})) - coinKeeper.SubtractCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("barcoin", 11)}) - require.True(t, coinKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 15)})) + bankKeeper.SubtractCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("barcoin", 11)}) + require.True(t, bankKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 15)})) - coinKeeper.SubtractCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("barcoin", 10)}) - require.True(t, coinKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("foocoin", 15)})) - require.False(t, coinKeeper.HasCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("barcoin", 1)})) + bankKeeper.SubtractCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("barcoin", 10)}) + require.True(t, bankKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("foocoin", 15)})) + require.False(t, bankKeeper.HasCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("barcoin", 1)})) // Test SendCoins - coinKeeper.SendCoins(ctx, addr, addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 5)}) - require.True(t, coinKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("foocoin", 10)})) - require.True(t, coinKeeper.GetCoins(ctx, addr2).IsEqual(sdk.Coins{sdk.NewInt64Coin("foocoin", 5)})) + bankKeeper.SendCoins(ctx, addr, addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 5)}) + require.True(t, bankKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("foocoin", 10)})) + require.True(t, bankKeeper.GetCoins(ctx, addr2).IsEqual(sdk.Coins{sdk.NewInt64Coin("foocoin", 5)})) - _, err2 := coinKeeper.SendCoins(ctx, addr, addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 50)}) + _, err2 := bankKeeper.SendCoins(ctx, addr, addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 50)}) assert.Implements(t, (*sdk.Error)(nil), err2) - require.True(t, coinKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("foocoin", 10)})) - require.True(t, coinKeeper.GetCoins(ctx, addr2).IsEqual(sdk.Coins{sdk.NewInt64Coin("foocoin", 5)})) + require.True(t, bankKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("foocoin", 10)})) + require.True(t, bankKeeper.GetCoins(ctx, addr2).IsEqual(sdk.Coins{sdk.NewInt64Coin("foocoin", 5)})) - coinKeeper.AddCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("barcoin", 30)}) - coinKeeper.SendCoins(ctx, addr, addr2, sdk.Coins{sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 5)}) - require.True(t, coinKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("barcoin", 20), sdk.NewInt64Coin("foocoin", 5)})) - require.True(t, coinKeeper.GetCoins(ctx, addr2).IsEqual(sdk.Coins{sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 10)})) + bankKeeper.AddCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("barcoin", 30)}) + bankKeeper.SendCoins(ctx, addr, addr2, sdk.Coins{sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 5)}) + require.True(t, bankKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("barcoin", 20), sdk.NewInt64Coin("foocoin", 5)})) + require.True(t, bankKeeper.GetCoins(ctx, addr2).IsEqual(sdk.Coins{sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 10)})) // Test InputOutputCoins input1 := NewInput(addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 2)}) output1 := NewOutput(addr, sdk.Coins{sdk.NewInt64Coin("foocoin", 2)}) - coinKeeper.InputOutputCoins(ctx, []Input{input1}, []Output{output1}) - require.True(t, coinKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("barcoin", 20), sdk.NewInt64Coin("foocoin", 7)})) - require.True(t, coinKeeper.GetCoins(ctx, addr2).IsEqual(sdk.Coins{sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 8)})) + bankKeeper.InputOutputCoins(ctx, []Input{input1}, []Output{output1}) + require.True(t, bankKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("barcoin", 20), sdk.NewInt64Coin("foocoin", 7)})) + require.True(t, bankKeeper.GetCoins(ctx, addr2).IsEqual(sdk.Coins{sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 8)})) inputs := []Input{ NewInput(addr, sdk.Coins{sdk.NewInt64Coin("foocoin", 3)}), @@ -104,10 +104,10 @@ func TestKeeper(t *testing.T) { NewOutput(addr, sdk.Coins{sdk.NewInt64Coin("barcoin", 1)}), NewOutput(addr3, sdk.Coins{sdk.NewInt64Coin("barcoin", 2), sdk.NewInt64Coin("foocoin", 5)}), } - coinKeeper.InputOutputCoins(ctx, inputs, outputs) - require.True(t, coinKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("barcoin", 21), sdk.NewInt64Coin("foocoin", 4)})) - require.True(t, coinKeeper.GetCoins(ctx, addr2).IsEqual(sdk.Coins{sdk.NewInt64Coin("barcoin", 7), sdk.NewInt64Coin("foocoin", 6)})) - require.True(t, coinKeeper.GetCoins(ctx, addr3).IsEqual(sdk.Coins{sdk.NewInt64Coin("barcoin", 2), sdk.NewInt64Coin("foocoin", 5)})) + bankKeeper.InputOutputCoins(ctx, inputs, outputs) + require.True(t, bankKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("barcoin", 21), sdk.NewInt64Coin("foocoin", 4)})) + require.True(t, bankKeeper.GetCoins(ctx, addr2).IsEqual(sdk.Coins{sdk.NewInt64Coin("barcoin", 7), sdk.NewInt64Coin("foocoin", 6)})) + require.True(t, bankKeeper.GetCoins(ctx, addr3).IsEqual(sdk.Coins{sdk.NewInt64Coin("barcoin", 2), sdk.NewInt64Coin("foocoin", 5)})) } @@ -119,7 +119,7 @@ func TestSendKeeper(t *testing.T) { ctx := sdk.NewContext(ms, abci.Header{}, false, log.NewNopLogger()) accountMapper := auth.NewAccountMapper(cdc, authKey, auth.ProtoBaseAccount) - coinKeeper := NewKeeper(accountMapper) + bankKeeper := NewKeeper(accountMapper) sendKeeper := NewSendKeeper(accountMapper) addr := sdk.AccAddress([]byte("addr1")) @@ -131,7 +131,7 @@ func TestSendKeeper(t *testing.T) { accountMapper.SetAccount(ctx, acc) require.True(t, sendKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{})) - coinKeeper.SetCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("foocoin", 10)}) + bankKeeper.SetCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("foocoin", 10)}) require.True(t, sendKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("foocoin", 10)})) // Test HasCoins @@ -140,7 +140,7 @@ func TestSendKeeper(t *testing.T) { require.False(t, sendKeeper.HasCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("foocoin", 15)})) require.False(t, sendKeeper.HasCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("barcoin", 5)})) - coinKeeper.SetCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("foocoin", 15)}) + bankKeeper.SetCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("foocoin", 15)}) // Test SendCoins sendKeeper.SendCoins(ctx, addr, addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 5)}) @@ -152,7 +152,7 @@ func TestSendKeeper(t *testing.T) { require.True(t, sendKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("foocoin", 10)})) require.True(t, sendKeeper.GetCoins(ctx, addr2).IsEqual(sdk.Coins{sdk.NewInt64Coin("foocoin", 5)})) - coinKeeper.AddCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("barcoin", 30)}) + bankKeeper.AddCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("barcoin", 30)}) sendKeeper.SendCoins(ctx, addr, addr2, sdk.Coins{sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 5)}) require.True(t, sendKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("barcoin", 20), sdk.NewInt64Coin("foocoin", 5)})) require.True(t, sendKeeper.GetCoins(ctx, addr2).IsEqual(sdk.Coins{sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 10)})) @@ -188,7 +188,7 @@ func TestViewKeeper(t *testing.T) { ctx := sdk.NewContext(ms, abci.Header{}, false, log.NewNopLogger()) accountMapper := auth.NewAccountMapper(cdc, authKey, auth.ProtoBaseAccount) - coinKeeper := NewKeeper(accountMapper) + bankKeeper := NewKeeper(accountMapper) viewKeeper := NewViewKeeper(accountMapper) addr := sdk.AccAddress([]byte("addr1")) @@ -198,7 +198,7 @@ func TestViewKeeper(t *testing.T) { accountMapper.SetAccount(ctx, acc) require.True(t, viewKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{})) - coinKeeper.SetCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("foocoin", 10)}) + bankKeeper.SetCoins(ctx, addr, sdk.Coins{sdk.NewInt64Coin("foocoin", 10)}) require.True(t, viewKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{sdk.NewInt64Coin("foocoin", 10)})) // Test HasCoins diff --git a/x/bank/simulation/sim_test.go b/x/bank/simulation/sim_test.go index f61f72b4fa..38461bad47 100644 --- a/x/bank/simulation/sim_test.go +++ b/x/bank/simulation/sim_test.go @@ -18,8 +18,8 @@ func TestBankWithRandomMessages(t *testing.T) { bank.RegisterWire(mapp.Cdc) mapper := mapp.AccountMapper - coinKeeper := bank.NewKeeper(mapper) - mapp.Router().AddRoute("bank", bank.NewHandler(coinKeeper)) + bankKeeper := bank.NewKeeper(mapper) + mapp.Router().AddRoute("bank", bank.NewHandler(bankKeeper)) err := mapp.CompleteSetup([]*sdk.KVStoreKey{}) if err != nil { diff --git a/x/distribution/keeper.go b/x/distribution/keeper.go index aba07eaca1..858632f2ae 100644 --- a/x/distribution/keeper.go +++ b/x/distribution/keeper.go @@ -4,7 +4,7 @@ package stake //type Keeper struct { //storeKey sdk.StoreKey //cdc *wire.Codec -//coinKeeper bank.Keeper +//bankKeeper bank.Keeper //// codespace //codespace sdk.CodespaceType @@ -14,7 +14,7 @@ package stake //keeper := Keeper{ //storeKey: key, //cdc: cdc, -//coinKeeper: ck, +//bankKeeper: ck, //codespace: codespace, //} //return keeper diff --git a/x/gov/simulation/sim_test.go b/x/gov/simulation/sim_test.go index 540dcb4473..317864a612 100644 --- a/x/gov/simulation/sim_test.go +++ b/x/gov/simulation/sim_test.go @@ -24,13 +24,13 @@ func TestGovWithRandomMessages(t *testing.T) { bank.RegisterWire(mapp.Cdc) gov.RegisterWire(mapp.Cdc) mapper := mapp.AccountMapper - coinKeeper := bank.NewKeeper(mapper) + bankKeeper := bank.NewKeeper(mapper) stakeKey := sdk.NewKVStoreKey("stake") - stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, coinKeeper, stake.DefaultCodespace) + stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, bankKeeper, stake.DefaultCodespace) paramKey := sdk.NewKVStoreKey("params") paramKeeper := params.NewKeeper(mapp.Cdc, paramKey) govKey := sdk.NewKVStoreKey("gov") - govKeeper := gov.NewKeeper(mapp.Cdc, govKey, paramKeeper.Setter(), coinKeeper, stakeKeeper, gov.DefaultCodespace) + govKeeper := gov.NewKeeper(mapp.Cdc, govKey, paramKeeper.Setter(), bankKeeper, stakeKeeper, gov.DefaultCodespace) mapp.Router().AddRoute("gov", gov.NewHandler(govKeeper)) mapp.SetEndBlocker(func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock { gov.EndBlocker(ctx, govKeeper) diff --git a/x/ibc/app_test.go b/x/ibc/app_test.go index f761f861d6..eed7c982c7 100644 --- a/x/ibc/app_test.go +++ b/x/ibc/app_test.go @@ -21,8 +21,8 @@ func getMockApp(t *testing.T) *mock.App { RegisterWire(mapp.Cdc) keyIBC := sdk.NewKVStoreKey("ibc") ibcMapper := NewMapper(mapp.Cdc, keyIBC, mapp.RegisterCodespace(DefaultCodespace)) - coinKeeper := bank.NewKeeper(mapp.AccountMapper) - mapp.Router().AddRoute("ibc", NewHandler(ibcMapper, coinKeeper)) + bankKeeper := bank.NewKeeper(mapp.AccountMapper) + mapp.Router().AddRoute("ibc", NewHandler(ibcMapper, bankKeeper)) require.NoError(t, mapp.CompleteSetup([]*sdk.KVStoreKey{keyIBC})) return mapp diff --git a/x/slashing/app_test.go b/x/slashing/app_test.go index 96dd1ff871..e6c4d06ce6 100644 --- a/x/slashing/app_test.go +++ b/x/slashing/app_test.go @@ -28,9 +28,9 @@ func getMockApp(t *testing.T) (*mock.App, stake.Keeper, Keeper) { keyStake := sdk.NewKVStoreKey("stake") keySlashing := sdk.NewKVStoreKey("slashing") keyParams := sdk.NewKVStoreKey("params") - coinKeeper := bank.NewKeeper(mapp.AccountMapper) + bankKeeper := bank.NewKeeper(mapp.AccountMapper) paramsKeeper := params.NewKeeper(mapp.Cdc, keyParams) - stakeKeeper := stake.NewKeeper(mapp.Cdc, keyStake, coinKeeper, mapp.RegisterCodespace(stake.DefaultCodespace)) + stakeKeeper := stake.NewKeeper(mapp.Cdc, keyStake, bankKeeper, mapp.RegisterCodespace(stake.DefaultCodespace)) keeper := NewKeeper(mapp.Cdc, keySlashing, stakeKeeper, paramsKeeper.Getter(), mapp.RegisterCodespace(DefaultCodespace)) mapp.Router().AddRoute("stake", stake.NewHandler(stakeKeeper)) diff --git a/x/stake/app_test.go b/x/stake/app_test.go index bfeff5df76..f5c16fe89c 100644 --- a/x/stake/app_test.go +++ b/x/stake/app_test.go @@ -34,8 +34,8 @@ func getMockApp(t *testing.T) (*mock.App, Keeper) { RegisterWire(mApp.Cdc) keyStake := sdk.NewKVStoreKey("stake") - coinKeeper := bank.NewKeeper(mApp.AccountMapper) - keeper := NewKeeper(mApp.Cdc, keyStake, coinKeeper, mApp.RegisterCodespace(DefaultCodespace)) + bankKeeper := bank.NewKeeper(mApp.AccountMapper) + keeper := NewKeeper(mApp.Cdc, keyStake, bankKeeper, mApp.RegisterCodespace(DefaultCodespace)) mApp.Router().AddRoute("stake", NewHandler(keeper)) mApp.SetEndBlocker(getEndBlocker(keeper)) diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index 9a596ffbce..8508945619 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -234,7 +234,7 @@ func (k Keeper) Delegate(ctx sdk.Context, delAddr sdk.AccAddress, bondAmt sdk.Co if subtractAccount { // Account new shares, save - _, _, err = k.coinKeeper.SubtractCoins(ctx, delegation.DelegatorAddr, sdk.Coins{bondAmt}) + _, _, err = k.bankKeeper.SubtractCoins(ctx, delegation.DelegatorAddr, sdk.Coins{bondAmt}) if err != nil { return } @@ -362,7 +362,7 @@ func (k Keeper) BeginUnbonding(ctx sdk.Context, // no need to create the ubd object just complete now if completeNow { - _, _, err := k.coinKeeper.AddCoins(ctx, delAddr, sdk.Coins{balance}) + _, _, err := k.bankKeeper.AddCoins(ctx, delAddr, sdk.Coins{balance}) if err != nil { return err } @@ -395,7 +395,7 @@ func (k Keeper) CompleteUnbonding(ctx sdk.Context, delAddr sdk.AccAddress, valAd return types.ErrNotMature(k.Codespace(), "unbonding", "unit-time", ubd.MinTime, ctxTime) } - _, _, err := k.coinKeeper.AddCoins(ctx, ubd.DelegatorAddr, sdk.Coins{ubd.Balance}) + _, _, err := k.bankKeeper.AddCoins(ctx, ubd.DelegatorAddr, sdk.Coins{ubd.Balance}) if err != nil { return err } diff --git a/x/stake/keeper/keeper.go b/x/stake/keeper/keeper.go index 14c8343878..c928c97446 100644 --- a/x/stake/keeper/keeper.go +++ b/x/stake/keeper/keeper.go @@ -12,7 +12,7 @@ import ( type Keeper struct { storeKey sdk.StoreKey cdc *wire.Codec - coinKeeper bank.Keeper + bankKeeper bank.Keeper validatorHooks sdk.ValidatorHooks // codespace @@ -23,7 +23,7 @@ func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck bank.Keeper, codespace sdk. keeper := Keeper{ storeKey: key, cdc: cdc, - coinKeeper: ck, + bankKeeper: ck, validatorHooks: nil, codespace: codespace, } diff --git a/x/stake/simulation/sim_test.go b/x/stake/simulation/sim_test.go index c5d301c569..3feec637ba 100644 --- a/x/stake/simulation/sim_test.go +++ b/x/stake/simulation/sim_test.go @@ -21,9 +21,9 @@ func TestStakeWithRandomMessages(t *testing.T) { bank.RegisterWire(mapp.Cdc) mapper := mapp.AccountMapper - coinKeeper := bank.NewKeeper(mapper) + bankKeeper := bank.NewKeeper(mapper) stakeKey := sdk.NewKVStoreKey("stake") - stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, coinKeeper, stake.DefaultCodespace) + stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, bankKeeper, stake.DefaultCodespace) mapp.Router().AddRoute("stake", stake.NewHandler(stakeKeeper)) mapp.SetEndBlocker(func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock { validatorUpdates := stake.EndBlocker(ctx, stakeKeeper) @@ -55,7 +55,7 @@ func TestStakeWithRandomMessages(t *testing.T) { }, []simulation.RandSetup{ Setup(mapp, stakeKeeper), }, []simulation.Invariant{ - AllInvariants(coinKeeper, stakeKeeper, mapp.AccountMapper), + AllInvariants(bankKeeper, stakeKeeper, mapp.AccountMapper), }, 10, 100, false, ) From fb235724d5ef3037091100a0cbb740997a8b2048 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Fri, 7 Sep 2018 22:39:26 -0700 Subject: [PATCH 68/93] Fix unrelated lint error. --- x/gov/simulation/msgs.go | 1 + 1 file changed, 1 insertion(+) diff --git a/x/gov/simulation/msgs.go b/x/gov/simulation/msgs.go index 2bb4b07b08..0be299e496 100644 --- a/x/gov/simulation/msgs.go +++ b/x/gov/simulation/msgs.go @@ -151,6 +151,7 @@ func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.Operation { return operationSimulateMsgVote(k, sk, nil, -1) } +// nolint: unparam func operationSimulateMsgVote(k gov.Keeper, sk stake.Keeper, key crypto.PrivKey, proposalID int64) simulation.Operation { return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { if key == nil { From c800bc7a1a90b03839e441002e98ac3d4ed5a42d Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Sat, 8 Sep 2018 01:29:24 -0700 Subject: [PATCH 69/93] Merge PR #2274: simulation: Stop on SIGTERM --- PENDING.md | 1 + x/mock/simulation/random_simulate_blocks.go | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/PENDING.md b/PENDING.md index bfcbcd9781..5701d732cb 100644 --- a/PENDING.md +++ b/PENDING.md @@ -114,5 +114,6 @@ BUG FIXES * [ledger] [\#2064](https://github.com/cosmos/cosmos-sdk/issues/2064) Fix inability to sign and send transactions via the LCD by loading a Ledger device at runtime. * [\#2158](https://github.com/cosmos/cosmos-sdk/issues/2158) Fix non-deterministic ordering of validator iteration when slashing in `gov EndBlocker` + * [simulation] \#1924 Make simulation stop on SIGTERM * Tendermint diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index 3f7f5ed40f..b7a911e065 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -6,7 +6,9 @@ import ( "math" "math/rand" "os" + "os/signal" "sort" + "syscall" "testing" "time" @@ -76,6 +78,16 @@ func SimulateFromSeed( header := abci.Header{Height: 0, Time: timestamp} opCount := 0 + // Setup code to catch SIGTERM's + c := make(chan os.Signal) + signal.Notify(c, os.Interrupt, syscall.SIGTERM) + go func() { + <-c + fmt.Printf("Exiting early due to SIGTERM, on block %d, operation %d\n", header.Height, opCount) + DisplayEvents(events) + os.Exit(128 + int(syscall.SIGTERM)) + }() + var pastTimes []time.Time var pastSigningValidators [][]abci.SigningValidator From f68e5a7542eac4b9427cff36ee6cda617b65cc29 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Sat, 8 Sep 2018 09:33:55 +0100 Subject: [PATCH 70/93] Merge PR #2266: Fix CLI commands JSON output When running with --json, commands should produce correctly JSON-encoded output. --- PENDING.md | 1 + client/context/query.go | 4 ++-- cmd/gaia/cli_test/cli_test.go | 12 +++++++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/PENDING.md b/PENDING.md index 5701d732cb..6876a215c7 100644 --- a/PENDING.md +++ b/PENDING.md @@ -105,6 +105,7 @@ BUG FIXES * Gaia CLI (`gaiacli`) * [cli] [\#1997](https://github.com/cosmos/cosmos-sdk/issues/1997) Handle panics gracefully when `gaiacli stake {delegation,unbond}` fail to unmarshal delegation. + * [cli] [\#2265](https://github.com/cosmos/cosmos-sdk/issues/2265) Fix JSON formatting of the `gaiacli send` command. * Gaia diff --git a/client/context/query.go b/client/context/query.go index 33610bc15b..fc35e53515 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -255,11 +255,11 @@ func (ctx CLIContext) ensureBroadcastTx(txBytes []byte) error { type toJSON struct { Height int64 TxHash string - Response string + Response abci.ResponseDeliverTx } if ctx.Logger != nil { - resJSON := toJSON{res.Height, res.Hash.String(), fmt.Sprintf("%+v", res.DeliverTx)} + resJSON := toJSON{res.Height, res.Hash.String(), res.DeliverTx} bz, err := ctx.Codec.MarshalJSON(resJSON) if err != nil { return err diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index d8d242e5b7..5cdf293716 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tendermint/libs/common" @@ -112,8 +113,17 @@ func TestGaiaCLIGasAuto(t *testing.T) { require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf("steak").Int64()) // Enable auto gas - success = executeWrite(t, fmt.Sprintf("gaiacli send %v --gas=0 --amount=10steak --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass) + success, stdout, _ := executeWriteRetStdStreams(t, fmt.Sprintf("gaiacli send %v --json --gas=0 --amount=10steak --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass) require.True(t, success) + // check that gas wanted == gas used + cdc := app.MakeCodec() + jsonOutput := struct { + Height int64 + TxHash string + Response abci.ResponseDeliverTx + }{} + require.Nil(t, cdc.UnmarshalJSON([]byte(stdout), &jsonOutput)) + require.Equal(t, jsonOutput.Response.GasWanted, jsonOutput.Response.GasUsed) tests.WaitForNextNBlocksTM(2, port) // Check state has changed accordingly fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", fooAddr, flags)) From 0edfa17b53fefd7649625070cb7a62cdfa257422 Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk Date: Sat, 8 Sep 2018 04:44:58 -0400 Subject: [PATCH 71/93] Merge PR #2251: Refactor Bech32 Prefixes and Nomenclature of Validator Pubkey and Operator --- PENDING.md | 20 ++-- client/lcd/lcd_test.go | 15 +-- client/lcd/test_helpers.go | 2 +- cmd/gaia/app/genesis.go | 4 +- cmd/gaia/cli_test/cli_test.go | 2 +- cmd/gaia/cmd/gaiadebug/hack.go | 2 +- .../transactions.md | 2 +- docs/clients/lcd-rest-api.yaml | 4 +- docs/sdk/clients.md | 8 +- docs/spec/other/bech32.md | 16 +-- docs/spec/staking/state.md | 104 +++++++++--------- docs/validators/validator-faq.md | 6 +- docs/validators/validator-setup.md | 2 +- types/address.go | 10 +- types/stake.go | 6 +- x/gov/tally_test.go | 2 +- x/slashing/app_test.go | 4 +- x/slashing/keys.go | 8 +- x/slashing/msg.go | 2 +- x/slashing/msg_test.go | 2 +- x/slashing/signing_info.go | 8 +- x/slashing/slashing_period.go | 4 +- x/stake/app_test.go | 4 +- x/stake/client/rest/query.go | 4 +- x/stake/handler.go | 2 +- x/stake/handler_test.go | 12 +- x/stake/keeper/delegation.go | 8 +- x/stake/keeper/key.go | 12 +- x/stake/keeper/slash.go | 2 +- x/stake/keeper/validator.go | 46 ++++---- x/stake/keeper/validator_test.go | 48 ++++---- x/stake/types/errors.go | 2 +- x/stake/types/validator.go | 56 +++++----- x/stake/types/validator_test.go | 20 ++-- 34 files changed, 226 insertions(+), 223 deletions(-) diff --git a/PENDING.md b/PENDING.md index 6876a215c7..e9182f22af 100644 --- a/PENDING.md +++ b/PENDING.md @@ -13,10 +13,10 @@ BREAKING CHANGES * [cli] [\#2061](https://github.com/cosmos/cosmos-sdk/issues/2061) changed proposalID in governance REST endpoints to proposal-id * [cli] [\#2014](https://github.com/cosmos/cosmos-sdk/issues/2014) `gaiacli advanced` no longer exists - to access `ibc`, `rest-server`, and `validator-set` commands use `gaiacli ibc`, `gaiacli rest-server`, and `gaiacli tendermint`, respectively * [makefile] `get_vendor_deps` no longer updates lock file it just updates vendor directory. Use `update_vendor_deps` to update the lock file. [#2152](https://github.com/cosmos/cosmos-sdk/pull/2152) + * [cli] [\#2221](https://github.com/cosmos/cosmos-sdk/issues/2221) All commands that + utilize a validator's operator address must now use the new Bech32 prefix, + `cosmosvaloper`. * [cli] [\#2190](https://github.com/cosmos/cosmos-sdk/issues/2190) `gaiacli init --gen-txs` is now `gaiacli init --with-txs` to reduce confusion - * [\#2040](https://github.com/cosmos/cosmos-sdk/issues/2040) All commands that utilize a validator's address must now use the new - bech32 prefix, `cosmosval`. A validator's Tendermint signing key and address - now use a new bech32 prefix, `cosmoscons`. * Gaia * Make the transient store key use a distinct store key. [#2013](https://github.com/cosmos/cosmos-sdk/pull/2013) @@ -25,11 +25,15 @@ BREAKING CHANGES * [x/stake, x/slashing] [#1305](https://github.com/cosmos/cosmos-sdk/issues/1305) - Rename "revoked" to "jailed" * [x/stake] [#1676] Revoked and jailed validators put into the unbonding state * [x/stake] [#1877] Redelegations/unbonding-delegation from unbonding validator have reduced time - * [x/stake] [\#2040](https://github.com/cosmos/cosmos-sdk/issues/2040) Validator operator type has now changed to `sdk.ValAddress` - * A new bech32 prefix has been introduced for Tendermint signing keys and - addresses, `cosmosconspub` and `cosmoscons` respectively. - * [x/gov] \#2195 Made governance use BFT Time instead of Block Heights for deposit and voting periods. - + * [x/stake] [\#2040](https://github.com/cosmos/cosmos-sdk/issues/2040) Validator + operator type has now changed to `sdk.ValAddress` + * [x/stake] [\#2221](https://github.com/cosmos/cosmos-sdk/issues/2221) New + Bech32 prefixes have been introduced for a validator's consensus address and + public key: `cosmosvalcons` and `cosmosvalconspub` respectively. Also, existing Bech32 prefixes have been + renamed for accounts and validator operators: + * `cosmosaccaddr` / `cosmosaccpub` => `cosmos` / `cosmospub` + * `cosmosvaladdr` / `cosmosvalpub` => `cosmosvaloper` / `cosmosvaloperpub` + * SDK * [core] [\#1807](https://github.com/cosmos/cosmos-sdk/issues/1807) Switch from use of rational to decimal * [types] [\#1901](https://github.com/cosmos/cosmos-sdk/issues/1901) Validator interface's GetOwner() renamed to GetOperator() diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index 8b4e318684..e6cfd24a7b 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -206,8 +206,8 @@ func TestValidators(t *testing.T) { require.NotEqual(t, rpc.ResultValidatorsOutput{}, resultVals) - require.Contains(t, resultVals.Validators[0].Address.String(), "cosmosval") - require.Contains(t, resultVals.Validators[0].PubKey, "cosmosconspub") + require.Contains(t, resultVals.Validators[0].Address.String(), "cosmosvaloper") + require.Contains(t, resultVals.Validators[0].PubKey, "cosmosvalconspub") // -- @@ -461,10 +461,11 @@ func TestValidatorsQuery(t *testing.T) { // make sure all the validators were found (order unknown because sorted by operator addr) foundVal := false pkBech := sdk.MustBech32ifyConsPub(pks[0]) - if validators[0].PubKey == pkBech { + if validators[0].ConsPubKey == pkBech { foundVal = true } - require.True(t, foundVal, "pkBech %v, operator %v", pkBech, validators[0].Operator) + + require.True(t, foundVal, "pkBech %v, operator %v", pkBech, validators[0].OperatorAddr) } func TestValidatorQuery(t *testing.T) { @@ -474,7 +475,7 @@ func TestValidatorQuery(t *testing.T) { validator1Operator := sdk.ValAddress(pks[0].Address()) validator := getValidator(t, port, validator1Operator) - assert.Equal(t, validator.Operator, validator1Operator, "The returned validator does not hold the correct data") + assert.Equal(t, validator.OperatorAddr, validator1Operator, "The returned validator does not hold the correct data") } func TestBonding(t *testing.T) { @@ -510,11 +511,11 @@ func TestBonding(t *testing.T) { bondedValidators := getDelegatorValidators(t, port, addr) require.Len(t, bondedValidators, 1) - require.Equal(t, validator1Operator, bondedValidators[0].Operator) + require.Equal(t, validator1Operator, bondedValidators[0].OperatorAddr) require.Equal(t, validator.DelegatorShares.Add(sdk.NewDec(60)).String(), bondedValidators[0].DelegatorShares.String()) bondedValidator := getDelegatorValidator(t, port, addr, validator1Operator) - require.Equal(t, validator1Operator, bondedValidator.Operator) + require.Equal(t, validator1Operator, bondedValidator.OperatorAddr) ////////////////////// // testing unbonding diff --git a/client/lcd/test_helpers.go b/client/lcd/test_helpers.go index 7d9a46403c..5936904077 100644 --- a/client/lcd/test_helpers.go +++ b/client/lcd/test_helpers.go @@ -151,7 +151,7 @@ func InitializeTestLCD(t *testing.T, nValidators int, initAddrs []sdk.AccAddress var validatorsPKs []crypto.PubKey - // NOTE: It's bad practice to reuse public key address for the owner + // NOTE: It's bad practice to reuse public key address for the operator // address but doing in the test for simplicity. var appGenTxs []json.RawMessage for _, gdValidator := range genDoc.Validators { diff --git a/cmd/gaia/app/genesis.go b/cmd/gaia/app/genesis.go index bfcaa92dde..16c2919037 100644 --- a/cmd/gaia/app/genesis.go +++ b/cmd/gaia/app/genesis.go @@ -205,8 +205,8 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (genesisState // create the self-delegation from the issuedDelShares delegation := stake.Delegation{ - DelegatorAddr: sdk.AccAddress(validator.Operator), - ValidatorAddr: validator.Operator, + DelegatorAddr: sdk.AccAddress(validator.OperatorAddr), + ValidatorAddr: validator.OperatorAddr, Shares: issuedDelShares, Height: 0, } diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 5cdf293716..ab1a39ac8d 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -188,7 +188,7 @@ 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", sdk.ValAddress(barAddr), flags)) - require.Equal(t, validator.Operator, sdk.ValAddress(barAddr)) + require.Equal(t, validator.OperatorAddr, sdk.ValAddress(barAddr)) require.True(sdk.DecEq(t, sdk.NewDec(2), validator.Tokens)) // unbond a single share diff --git a/cmd/gaia/cmd/gaiadebug/hack.go b/cmd/gaia/cmd/gaiadebug/hack.go index 873dd88295..a321a50823 100644 --- a/cmd/gaia/cmd/gaiadebug/hack.go +++ b/cmd/gaia/cmd/gaiadebug/hack.go @@ -65,7 +65,7 @@ func runHackCmd(cmd *cobra.Command, args []string) error { // The following powerKey was there, but the corresponding "trouble" validator did not exist. // So here we do a binary search on the past states to find when the powerKey first showed up ... - // owner of the validator the bonds, gets revoked, later unbonds, and then later is still found in the bypower store + // operator of the validator the bonds, gets revoked, later unbonds, and then later is still found in the bypower store trouble := hexToBytes("D3DC0FF59F7C3B548B7AFA365561B87FD0208AF8") // this is his "bypower" key powerKey := hexToBytes("05303030303030303030303033FFFFFFFFFFFF4C0C0000FFFED3DC0FF59F7C3B548B7AFA365561B87FD0208AF8") diff --git a/docs/_attic/WIP-lamborghini-distribution/transactions.md b/docs/_attic/WIP-lamborghini-distribution/transactions.md index 1401c3b851..085f3b6e3a 100644 --- a/docs/_attic/WIP-lamborghini-distribution/transactions.md +++ b/docs/_attic/WIP-lamborghini-distribution/transactions.md @@ -213,7 +213,7 @@ Note that the distribution scenario structures are found in `state.md`. #### Delegation's entitlement to Global.Pool For delegations (including validator's self-delegation) all fees from fee pool -are subject to commission rate from the owner of the validator. The global +are subject to commission rate from the operator of the validator. The global shares should be taken as true number of global bonded shares. The recipients shares should be taken as the bonded tokens less the validator's commission. diff --git a/docs/clients/lcd-rest-api.yaml b/docs/clients/lcd-rest-api.yaml index 4f402089ad..9b7301de60 100644 --- a/docs/clients/lcd-rest-api.yaml +++ b/docs/clients/lcd-rest-api.yaml @@ -714,7 +714,7 @@ definitions: ValidatorAddress: type: string description: bech32 encoded addres - example: cosmosval:zgnkwr7eyyv643dllwfpdwensmgdtz89yu73zq + example: cosmosvaloper:zgnkwr7eyyv643dllwfpdwensmgdtz89yu73zq PubKey: type: string description: bech32 encoded public key @@ -722,7 +722,7 @@ definitions: ValidatorPubKey: type: string description: bech32 encoded public key - example: cosmosvalpub:zgnkwr7eyyv643dllwfpdwensmgdtz89yu73zq + example: cosmosvalconspub:zgnkwr7eyyv643dllwfpdwensmgdtz89yu73zq Coins: type: object properties: diff --git a/docs/sdk/clients.md b/docs/sdk/clients.md index 0cc87cf215..2b2e8e52a4 100644 --- a/docs/sdk/clients.md +++ b/docs/sdk/clients.md @@ -22,17 +22,17 @@ There are three types of key representations that are used: - Derived from account keys generated by `gaiacli keys add` - Used to receive funds - e.g. `cosmos15h6vd5f0wqps26zjlwrc6chah08ryu4hzzdwhc` -* `cosmosval` +* `cosmosvaloper` * Used to associate a validator to it's operator * Used to invoke staking commands - * e.g. `cosmosval1carzvgq3e6y3z5kz5y6gxp3wpy3qdrv928vyah` + * e.g. `cosmosvaloper1carzvgq3e6y3z5kz5y6gxp3wpy3qdrv928vyah` - `cosmospub` - Derived from account keys generated by `gaiacli keys add` - e.g. `cosmospub1zcjduc3q7fu03jnlu2xpl75s2nkt7krm6grh4cc5aqth73v0zwmea25wj2hsqhlqzm` -- `cosmosconspub` +- `cosmosvalconspub` - Generated when the node is created with `gaiad init`. - Get this value with `gaiad tendermint show-validator` - - e.g. `cosmosconspub1zcjduepq0ms2738680y72v44tfyqm3c9ppduku8fs6sr73fx7m666sjztznqzp2emf` + - e.g. `cosmosvalconspub1zcjduepq0ms2738680y72v44tfyqm3c9ppduku8fs6sr73fx7m666sjztznqzp2emf` #### Generate Keys diff --git a/docs/spec/other/bech32.md b/docs/spec/other/bech32.md index 911102a8a7..e2f0ef1ba7 100644 --- a/docs/spec/other/bech32.md +++ b/docs/spec/other/bech32.md @@ -6,14 +6,14 @@ In the Cosmos network, keys and addresses may refer to a number of different rol ## HRP table -| HRP | Definition | -|---------------|--------------------------------------| -| cosmos | Cosmos Account Address | -| cosmospub | Cosmos Account Public Key | -| cosmoscons | Cosmos Consensus Address | -| cosmosconspub | Cosmos Consensus Public Key | -| cosmosval | Cosmos Validator Operator Address | -| cosmosvalpub | Cosmos Validator Operator Public Key | +| HRP | Definition | +|-------------------|---------------------------------------| +| cosmos | Cosmos Account Address | +| cosmospub | Cosmos Account Public Key | +| cosmosvalcons | Cosmos Validator Consensus Address | +| cosmosvalconspub | Cosmos Validator Consensus Public Key | +| cosmosvaloper | Cosmos Validator Operator Address | +| cosmosvaloperpub | Cosmos Validator Operator Public Key | ## Encoding diff --git a/docs/spec/staking/state.md b/docs/spec/staking/state.md index 58bd67cd5e..f2d6f98541 100644 --- a/docs/spec/staking/state.md +++ b/docs/spec/staking/state.md @@ -14,7 +14,7 @@ type Pool struct { BondedTokens int64 // reserve of bonded tokens InflationLastTime int64 // block which the last inflation was processed // TODO make time Inflation sdk.Dec // current annual inflation rate - + DateLastCommissionReset int64 // unix timestamp for last commission accounting reset (daily) } ``` @@ -29,41 +29,40 @@ overall functioning of the stake module. ```golang type Params struct { 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 + 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 + MaxValidators uint16 // maximum number of validators + BondDenom string // bondable coin denomination } ``` ### Validator -Validators are identified according to the `ValOwnerAddr`, -an SDK account address for the owner of the validator. +Validators are identified according to the `OperatorAddr`, an SDK validator +address for the operator of the validator. -Validators also have a `ValTendermintAddr`, the address -of the public key of the validator. +Validators also have a `ConsPubKey`, the public key of the validator. Validators are indexed in the store using the following maps: - - Validators: `0x02 | ValOwnerAddr -> amino(validator)` - - ValidatorsByPubKey: `0x03 | ValTendermintAddr -> ValOwnerAddr` - - ValidatorsByPower: `0x05 | power | blockHeight | blockTx -> ValOwnerAddr` +- Validators: `0x02 | OperatorAddr -> amino(validator)` +- ValidatorsByPubKey: `0x03 | ConsPubKey -> OperatorAddr` +- ValidatorsByPower: `0x05 | power | blockHeight | blockTx -> OperatorAddr` - `Validators` is the primary index - it ensures that each owner can have only one - associated validator, where the public key of that validator can change in the - future. Delegators can refer to the immutable owner of the validator, without - concern for the changing public key. +`Validators` is the primary index - it ensures that each operator can have only one +associated validator, where the public key of that validator can change in the +future. Delegators can refer to the immutable operator of the validator, without +concern for the changing public key. - `ValidatorsByPubKey` is a secondary index that enables lookups for slashing. - When Tendermint reports evidence, it provides the validator address, so this - map is needed to find the owner. +`ValidatorsByPubKey` is a secondary index that enables lookups for slashing. +When Tendermint reports evidence, it provides the validator address, so this +map is needed to find the operator. - `ValidatorsByPower` is a secondary index that provides a sorted list of - potential validators to quickly determine the current active set. For instance, - the first 100 validators in this list can be returned with every EndBlock. +`ValidatorsByPower` is a secondary index that provides a sorted list of +potential validators to quickly determine the current active set. For instance, +the first 100 validators in this list can be returned with every EndBlock. The `Validator` holds the current state and some historical actions of the validator. @@ -72,18 +71,18 @@ validator. type Validator struct { ConsensusPubKey crypto.PubKey // Tendermint consensus pubkey of validator Jailed bool // has the validator been jailed? - - Status sdk.BondStatus // validator status (bonded/unbonding/unbonded) - Tokens sdk.Dec // delegated tokens (incl. self-delegation) + + Status sdk.BondStatus // validator status (bonded/unbonding/unbonded) + 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 - + // Needed for ordering vals in the by-power key BondHeight int64 // earliest height as a bonded validator BondIntraTxCounter int16 // block-local tx index of validator change - + CommissionInfo CommissionInfo // info about the validator's commission } @@ -96,42 +95,41 @@ type CommissionInfo struct { } type Description struct { - Moniker string // name - Identity string // optional identity signature (ex. UPort or Keybase) - Website string // optional website link - Details string // optional details + Moniker string // name + Identity string // optional identity signature (ex. UPort or Keybase) + Website string // optional website link + Details string // optional details } ``` ### Delegation -Delegations are identified by combining `DelegatorAddr` (the address of the delegator) with the ValOwnerAddr -Delegators are indexed in the store as follows: +Delegations are identified by combining `DelegatorAddr` (the address of the delegator) +with the `OperatorAddr` Delegators are indexed in the store as follows: - - Delegation: ` 0x0A | DelegatorAddr | ValOwnerAddr -> amino(delegation)` +- Delegation: ` 0x0A | DelegatorAddr | OperatorAddr -> amino(delegation)` Atom holders may delegate coins to validators; under this circumstance their -funds are held in a `Delegation` data structure. It is owned by one -delegator, and is associated with the shares for one validator. The sender of +funds are held in a `Delegation` data structure. It is owned by one +delegator, and is associated with the shares for one validator. The sender of the transaction is the owner of the bond. ```golang type Delegation struct { - Shares sdk.Dec // delegation shares recieved - Height int64 // last height bond updated + Shares sdk.Dec // delegation shares received + Height int64 // last height bond updated } ``` ### UnbondingDelegation -Shares in a `Delegation` can be unbonded, but they must for some time exist as an `UnbondingDelegation`, -where shares can be reduced if Byzantine behaviour is detected. +Shares in a `Delegation` can be unbonded, but they must for some time exist as an `UnbondingDelegation`, where shares can be reduced if Byzantine behavior is detected. `UnbondingDelegation` are indexed in the store as: - - UnbondingDelegationByDelegator: ` 0x0B | DelegatorAddr | ValOwnerAddr -> +- UnbondingDelegationByDelegator: ` 0x0B | DelegatorAddr | OperatorAddr -> amino(unbondingDelegation)` - - UnbondingDelegationByValOwner: ` 0x0C | ValOwnerAddr | DelegatorAddr | ValOwnerAddr -> +- UnbondingDelegationByValOwner: ` 0x0C | OperatorAddr | DelegatorAddr | OperatorAddr -> nil` The first map here is used in queries, to lookup all unbonding delegations for @@ -148,26 +146,26 @@ type UnbondingDelegation struct { Tokens sdk.Coins // the value in Atoms of the amount of shares which are unbonding CompleteTime int64 // unix time to complete redelegation } -``` +``` ### Redelegation -Shares in a `Delegation` can be rebonded to a different validator, but they must for some time exist as a `Redelegation`, -where shares can be reduced if Byzantine behaviour is detected. This is tracked -as moving a delegation from a `FromValOwnerAddr` to a `ToValOwnerAddr`. +Shares in a `Delegation` can be rebonded to a different validator, but they must +for some time exist as a `Redelegation`, where shares can be reduced if Byzantine +behavior is detected. This is tracked as moving a delegation from a `FromOperatorAddr` +to a `ToOperatorAddr`. `Redelegation` are indexed in the store as: - - Redelegations: `0x0D | DelegatorAddr | FromValOwnerAddr | ToValOwnerAddr -> + - Redelegations: `0x0D | DelegatorAddr | FromOperatorAddr | ToOperatorAddr -> amino(redelegation)` - - RedelegationsBySrc: `0x0E | FromValOwnerAddr | ToValOwnerAddr | + - RedelegationsBySrc: `0x0E | FromOperatorAddr | ToOperatorAddr | DelegatorAddr -> nil` - - RedelegationsByDst: `0x0F | ToValOwnerAddr | FromValOwnerAddr | DelegatorAddr + - RedelegationsByDst: `0x0F | ToOperatorAddr | FromOperatorAddr | DelegatorAddr -> nil` - The first map here is used for queries, to lookup all redelegations for a given -delegator. The second map is used for slashing based on the FromValOwnerAddr, +delegator. The second map is used for slashing based on the `FromOperatorAddr`, while the third map is for slashing based on the ToValOwnerAddr. A redelegation object is created every time a redelegation occurs. The diff --git a/docs/validators/validator-faq.md b/docs/validators/validator-faq.md index 470f139d43..14644daf26 100644 --- a/docs/validators/validator-faq.md +++ b/docs/validators/validator-faq.md @@ -77,14 +77,14 @@ We view testnet participation as a great way to signal to the community that you In short, there are two types of keys: -* **Tendermint Key**: This is a unique key used to sign block hashes. It is associated with a public key `cosmosconspub`. +* **Tendermint Key**: This is a unique key used to sign block hashes. It is associated with a public key `cosmosvalconspub`. * Generated when the node is created with gaiad init. * Get this value with `gaiad tendermint show-validator` - e.g. `cosmosconspub1zcjduc3qcyj09qc03elte23zwshdx92jm6ce88fgc90rtqhjx8v0608qh5ssp0w94c` + e.g. `cosmosvalconspub1zcjduc3qcyj09qc03elte23zwshdx92jm6ce88fgc90rtqhjx8v0608qh5ssp0w94c` * **Application keys**: These keys are created from the application and used to sign transactions. As a validator, you will probably use one key to sign staking-related transactions, and another key to sign governance-related transactions. Application keys are associated with a public key `cosmospub` and an address `cosmos`. Both are derived from account keys generated by `gaiacli keys add`. * Note: A validator's operator key is directly tied to an application key, but - uses reserved prefixes solely for this purpose: `cosmosval` and `cosmosvalpub` + uses reserved prefixes solely for this purpose: `cosmosvaloper` and `cosmosvaloperpub` ### What are the different states a validator can be in? diff --git a/docs/validators/validator-setup.md b/docs/validators/validator-setup.md index 8bf3e951de..8a842ea205 100644 --- a/docs/validators/validator-setup.md +++ b/docs/validators/validator-setup.md @@ -16,7 +16,7 @@ If you want to become a validator for the Hub's `mainnet`, you should [research ### Create Your Validator -Your `cosmosconspub` can be used to create a new validator by staking tokens. You can find your validator pubkey by running: +Your `cosmosvalconspub` can be used to create a new validator by staking tokens. You can find your validator pubkey by running: ```bash gaiad tendermint show-validator diff --git a/types/address.go b/types/address.go index 943867d79b..58b694f5da 100644 --- a/types/address.go +++ b/types/address.go @@ -22,13 +22,13 @@ const ( // Bech32PrefixAccPub defines the Bech32 prefix of an account's public key Bech32PrefixAccPub = "cosmospub" // Bech32PrefixValAddr defines the Bech32 prefix of a validator's operator address - Bech32PrefixValAddr = "cosmosval" + Bech32PrefixValAddr = "cosmosvaloper" // Bech32PrefixValPub defines the Bech32 prefix of a validator's operator public key - Bech32PrefixValPub = "cosmosvalpub" + Bech32PrefixValPub = "cosmosvaloperpub" // Bech32PrefixConsAddr defines the Bech32 prefix of a consensus node address - Bech32PrefixConsAddr = "cosmoscons" + Bech32PrefixConsAddr = "cosmosvalcons" // Bech32PrefixConsPub defines the Bech32 prefix of a consensus node public key - Bech32PrefixConsPub = "cosmosconspub" + Bech32PrefixConsPub = "cosmosvalconspub" ) // ---------------------------------------------------------------------------- @@ -146,7 +146,7 @@ func (aa AccAddress) Format(s fmt.State, verb rune) { } // ---------------------------------------------------------------------------- -// validator owner +// validator operator // ---------------------------------------------------------------------------- // ValAddress defines a wrapper around bytes meant to present a validator's diff --git a/types/stake.go b/types/stake.go index ba11cd5f86..0b9f32b4b8 100644 --- a/types/stake.go +++ b/types/stake.go @@ -40,7 +40,7 @@ type Validator interface { GetJailed() bool // whether the validator is jailed GetMoniker() string // moniker of the validator GetStatus() BondStatus // status of the validator - GetOperator() ValAddress // owner address to receive/return validators coins + GetOperator() ValAddress // operator address to receive/return validators coins GetPubKey() crypto.PubKey // validation pubkey GetPower() Dec // validation power GetTokens() Dec // validation tokens @@ -59,11 +59,11 @@ func ABCIValidator(v Validator) abci.Validator { // properties for the set of all validators type ValidatorSet interface { - // iterate through validator by owner-AccAddress, execute func for each validator + // iterate through validators by operator address, execute func for each validator IterateValidators(Context, func(index int64, validator Validator) (stop bool)) - // iterate through bonded validator by pubkey-AccAddress, execute func for each validator + // iterate through bonded validators by operator address, execute func for each validator IterateValidatorsBonded(Context, func(index int64, validator Validator) (stop bool)) diff --git a/x/gov/tally_test.go b/x/gov/tally_test.go index 24740731f0..6c6d64aa67 100644 --- a/x/gov/tally_test.go +++ b/x/gov/tally_test.go @@ -440,7 +440,7 @@ func TestTallyJailedValidator(t *testing.T) { val2, found := sk.GetValidator(ctx, sdk.ValAddress(addrs[1])) require.True(t, found) - sk.Jail(ctx, val2.PubKey) + sk.Jail(ctx, val2.ConsPubKey) proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText) proposalID := proposal.GetProposalID() diff --git a/x/slashing/app_test.go b/x/slashing/app_test.go index e6c4d06ce6..e0b84cef7d 100644 --- a/x/slashing/app_test.go +++ b/x/slashing/app_test.go @@ -107,10 +107,10 @@ func TestSlashingMsgs(t *testing.T) { mapp.BeginBlock(abci.RequestBeginBlock{}) validator := checkValidator(t, mapp, stakeKeeper, addr1, true) - require.Equal(t, sdk.ValAddress(addr1), validator.Operator) + require.Equal(t, sdk.ValAddress(addr1), validator.OperatorAddr) require.Equal(t, sdk.Bonded, validator.Status) require.True(sdk.DecEq(t, sdk.NewDec(10), validator.BondedTokens())) - unjailMsg := MsgUnjail{ValidatorAddr: sdk.ValAddress(validator.PubKey.Address())} + unjailMsg := MsgUnjail{ValidatorAddr: sdk.ValAddress(validator.ConsPubKey.Address())} // no signing info yet checkValidatorSigningInfo(t, mapp, keeper, sdk.ConsAddress(addr1), false) diff --git a/x/slashing/keys.go b/x/slashing/keys.go index 2af9e069a1..1f84a285dd 100644 --- a/x/slashing/keys.go +++ b/x/slashing/keys.go @@ -14,24 +14,24 @@ var ( AddrPubkeyRelationKey = []byte{0x04} // Prefix for address-pubkey relation ) -// stored by *Tendermint* address (not owner address) +// stored by *Tendermint* address (not operator address) func GetValidatorSigningInfoKey(v sdk.ConsAddress) []byte { return append(ValidatorSigningInfoKey, v.Bytes()...) } -// stored by *Tendermint* address (not owner address) +// stored by *Tendermint* address (not operator address) func GetValidatorSigningBitArrayKey(v sdk.ConsAddress, i int64) []byte { b := make([]byte, 8) binary.LittleEndian.PutUint64(b, uint64(i)) return append(ValidatorSigningBitArrayKey, append(v.Bytes(), b...)...) } -// stored by *Tendermint* address (not owner address) +// stored by *Tendermint* address (not operator address) func GetValidatorSlashingPeriodPrefix(v sdk.ConsAddress) []byte { return append(ValidatorSlashingPeriodKey, v.Bytes()...) } -// stored by *Tendermint* address (not owner address) followed by start height +// stored by *Tendermint* address (not operator address) followed by start height func GetValidatorSlashingPeriodKey(v sdk.ConsAddress, startHeight int64) []byte { b := make([]byte, 8) binary.LittleEndian.PutUint64(b, uint64(startHeight)) diff --git a/x/slashing/msg.go b/x/slashing/msg.go index 7791012185..3d2bdedca9 100644 --- a/x/slashing/msg.go +++ b/x/slashing/msg.go @@ -15,7 +15,7 @@ var _ sdk.Msg = &MsgUnjail{} // MsgUnjail - struct for unjailing jailed validator type MsgUnjail struct { - ValidatorAddr sdk.ValAddress `json:"address"` // address of the validator owner + ValidatorAddr sdk.ValAddress `json:"address"` // address of the validator operator } func NewMsgUnjail(validatorAddr sdk.ValAddress) MsgUnjail { diff --git a/x/slashing/msg_test.go b/x/slashing/msg_test.go index ff8619041e..594658ce86 100644 --- a/x/slashing/msg_test.go +++ b/x/slashing/msg_test.go @@ -12,5 +12,5 @@ func TestMsgUnjailGetSignBytes(t *testing.T) { addr := sdk.AccAddress("abcd") msg := NewMsgUnjail(sdk.ValAddress(addr)) bytes := msg.GetSignBytes() - require.Equal(t, string(bytes), `{"address":"cosmosval1v93xxeq7xkcrf"}`) + require.Equal(t, string(bytes), `{"address":"cosmosvaloper1v93xxeqhg9nn6"}`) } diff --git a/x/slashing/signing_info.go b/x/slashing/signing_info.go index e76fea53f2..1adf49abc1 100644 --- a/x/slashing/signing_info.go +++ b/x/slashing/signing_info.go @@ -7,7 +7,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// Stored by *validator* address (not owner address) +// Stored by *validator* address (not operator address) func (k Keeper) getValidatorSigningInfo(ctx sdk.Context, address sdk.ConsAddress) (info ValidatorSigningInfo, found bool) { store := ctx.KVStore(k.storeKey) bz := store.Get(GetValidatorSigningInfoKey(address)) @@ -20,14 +20,14 @@ func (k Keeper) getValidatorSigningInfo(ctx sdk.Context, address sdk.ConsAddress return } -// Stored by *validator* address (not owner address) +// Stored by *validator* address (not operator address) func (k Keeper) setValidatorSigningInfo(ctx sdk.Context, address sdk.ConsAddress, info ValidatorSigningInfo) { store := ctx.KVStore(k.storeKey) bz := k.cdc.MustMarshalBinary(info) store.Set(GetValidatorSigningInfoKey(address), bz) } -// Stored by *validator* address (not owner address) +// Stored by *validator* address (not operator address) func (k Keeper) getValidatorSigningBitArray(ctx sdk.Context, address sdk.ConsAddress, index int64) (signed bool) { store := ctx.KVStore(k.storeKey) bz := store.Get(GetValidatorSigningBitArrayKey(address, index)) @@ -40,7 +40,7 @@ func (k Keeper) getValidatorSigningBitArray(ctx sdk.Context, address sdk.ConsAdd return } -// Stored by *validator* address (not owner address) +// Stored by *validator* address (not operator address) func (k Keeper) setValidatorSigningBitArray(ctx sdk.Context, address sdk.ConsAddress, index int64, signed bool) { store := ctx.KVStore(k.storeKey) bz := k.cdc.MustMarshalBinary(signed) diff --git a/x/slashing/slashing_period.go b/x/slashing/slashing_period.go index 61d25071eb..fc57e663ae 100644 --- a/x/slashing/slashing_period.go +++ b/x/slashing/slashing_period.go @@ -32,7 +32,7 @@ func (k Keeper) capBySlashingPeriod(ctx sdk.Context, address sdk.ConsAddress, fr return } -// Stored by validator Tendermint address (not owner address) +// Stored by validator Tendermint address (not operator address) // This function retrieves the most recent slashing period starting // before a particular height - so the slashing period that was "in effect" // at the time of an infraction committed at that height. @@ -49,7 +49,7 @@ func (k Keeper) getValidatorSlashingPeriodForHeight(ctx sdk.Context, address sdk return } -// Stored by validator Tendermint address (not owner address) +// Stored by validator Tendermint address (not operator address) // This function sets a validator slashing period for a particular validator, // start height, end height, and current slashed-so-far total, or updates // an existing slashing period for the same validator and start height. diff --git a/x/stake/app_test.go b/x/stake/app_test.go index f5c16fe89c..98dc8d56f9 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, sdk.ValAddress(addr1), true) - require.Equal(t, sdk.ValAddress(addr1), validator.Operator) + require.Equal(t, sdk.ValAddress(addr1), validator.OperatorAddr) require.Equal(t, sdk.Bonded, validator.Status) require.True(sdk.DecEq(t, sdk.NewDec(10), validator.BondedTokens())) @@ -150,7 +150,7 @@ func TestStakeMsgs(t *testing.T) { mApp.BeginBlock(abci.RequestBeginBlock{}) validator = checkValidator(t, mApp, keeper, sdk.ValAddress(addr2), true) - require.Equal(t, sdk.ValAddress(addr2), validator.Operator) + require.Equal(t, sdk.ValAddress(addr2), validator.OperatorAddr) require.Equal(t, sdk.Bonded, validator.Status) require.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens)) diff --git a/x/stake/client/rest/query.go b/x/stake/client/rest/query.go index bf929387dd..5d280daf3d 100644 --- a/x/stake/client/rest/query.go +++ b/x/stake/client/rest/query.go @@ -126,7 +126,7 @@ func delegatorHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.Handler } for _, validator := range validators { - valAddr = validator.Operator + valAddr = validator.OperatorAddr // Delegations delegations, statusCode, errMsg, err := getDelegatorDelegations(cliCtx, cdc, delAddr, valAddr) @@ -410,7 +410,7 @@ func delegatorValidatorsHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) ht for _, validator := range validators { // get all transactions from the delegator to val and append - valAddr = validator.Operator + valAddr = validator.OperatorAddr validator, statusCode, errMsg, errRes := getDelegatorValidator(cliCtx, cdc, delegatorAddr, valAddr) if errRes != nil { diff --git a/x/stake/handler.go b/x/stake/handler.go index 4b478fffd7..e6ceb5e7b0 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -138,7 +138,7 @@ func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper) return ErrBadDenom(k.Codespace()).Result() } - if validator.Jailed && !bytes.Equal(validator.Operator, msg.DelegatorAddr) { + if validator.Jailed && !bytes.Equal(validator.OperatorAddr, msg.DelegatorAddr) { return ErrValidatorJailed(k.Codespace()).Result() } diff --git a/x/stake/handler_test.go b/x/stake/handler_test.go index a733b7f156..4862b14c33 100644 --- a/x/stake/handler_test.go +++ b/x/stake/handler_test.go @@ -136,8 +136,8 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) { require.True(t, found) assert.Equal(t, sdk.Bonded, validator.Status) - assert.Equal(t, addr1, validator.Operator) - assert.Equal(t, pk1, validator.PubKey) + assert.Equal(t, addr1, validator.OperatorAddr) + assert.Equal(t, pk1, validator.ConsPubKey) assert.Equal(t, sdk.NewDec(10), validator.BondedTokens()) assert.Equal(t, sdk.NewDec(10), validator.DelegatorShares) assert.Equal(t, Description{}, validator.Description) @@ -160,8 +160,8 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) { require.True(t, found) assert.Equal(t, sdk.Bonded, validator.Status) - assert.Equal(t, addr2, validator.Operator) - assert.Equal(t, pk2, validator.PubKey) + assert.Equal(t, addr2, validator.OperatorAddr) + assert.Equal(t, pk2, validator.ConsPubKey) assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens)) assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares)) assert.Equal(t, Description{}, validator.Description) @@ -180,8 +180,8 @@ func TestDuplicatesMsgCreateValidatorOnBehalfOf(t *testing.T) { require.True(t, found) assert.Equal(t, sdk.Bonded, validator.Status) - assert.Equal(t, validatorAddr, validator.Operator) - assert.Equal(t, pk, validator.PubKey) + assert.Equal(t, validatorAddr, validator.OperatorAddr) + assert.Equal(t, pk, validator.ConsPubKey) 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) diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index 8508945619..0ef3eb9cfb 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -223,11 +223,11 @@ func (k Keeper) Delegate(ctx sdk.Context, delAddr sdk.AccAddress, bondAmt sdk.Co validator types.Validator, subtractAccount bool) (newShares sdk.Dec, err sdk.Error) { // Get or create the delegator delegation - delegation, found := k.GetDelegation(ctx, delAddr, validator.Operator) + delegation, found := k.GetDelegation(ctx, delAddr, validator.OperatorAddr) if !found { delegation = types.Delegation{ DelegatorAddr: delAddr, - ValidatorAddr: validator.Operator, + ValidatorAddr: validator.OperatorAddr, Shares: sdk.ZeroDec(), } } @@ -286,7 +286,7 @@ func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValA // if the delegation is the operator of the validator then // trigger a jail validator - if bytes.Equal(delegation.DelegatorAddr, validator.Operator) && validator.Jailed == false { + if bytes.Equal(delegation.DelegatorAddr, validator.OperatorAddr) && validator.Jailed == false { validator.Jailed = true } @@ -306,7 +306,7 @@ func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValA // update then remove validator if necessary validator = k.UpdateValidator(ctx, validator) if validator.DelegatorShares.IsZero() { - k.RemoveValidator(ctx, validator.Operator) + k.RemoveValidator(ctx, validator.OperatorAddr) } return amount, nil diff --git a/x/stake/keeper/key.go b/x/stake/keeper/key.go index f3e2967c81..9dbf50c03f 100644 --- a/x/stake/keeper/key.go +++ b/x/stake/keeper/key.go @@ -26,10 +26,10 @@ var ( IntraTxCounterKey = []byte{0x09} // key for intra-block tx index DelegationKey = []byte{0x0A} // key for a delegation UnbondingDelegationKey = []byte{0x0B} // key for an unbonding-delegation - UnbondingDelegationByValIndexKey = []byte{0x0C} // prefix for each key for an unbonding-delegation, by validator owner + UnbondingDelegationByValIndexKey = []byte{0x0C} // prefix for each key for an unbonding-delegation, by validator operator RedelegationKey = []byte{0x0D} // key for a redelegation - RedelegationByValSrcIndexKey = []byte{0x0E} // prefix for each key for an redelegation, by source validator owner - RedelegationByValDstIndexKey = []byte{0x0F} // prefix for each key for an redelegation, by destination validator owner + RedelegationByValSrcIndexKey = []byte{0x0E} // prefix for each key for an redelegation, by source validator operator + RedelegationByValDstIndexKey = []byte{0x0F} // prefix for each key for an redelegation, by destination validator operator ) const maxDigitsForAccount = 12 // ~220,000,000 atoms created at launch @@ -41,7 +41,7 @@ func GetValidatorKey(operatorAddr sdk.ValAddress) []byte { } // gets the key for the validator with pubkey -// VALUE: validator owner address ([]byte) +// VALUE: validator operator address ([]byte) func GetValidatorByPubKeyIndexKey(pubkey crypto.PubKey) []byte { return append(ValidatorsByPubKeyIndexKey, pubkey.Bytes()...) } @@ -52,7 +52,7 @@ func GetValidatorsBondedIndexKey(operatorAddr sdk.ValAddress) []byte { return append(ValidatorsBondedIndexKey, operatorAddr.Bytes()...) } -// Get the validator owner address from ValBondedIndexKey +// Get the validator operator address from ValBondedIndexKey func GetAddressFromValBondedIndexKey(IndexKey []byte) []byte { return IndexKey[1:] // remove prefix bytes } @@ -60,7 +60,7 @@ func GetAddressFromValBondedIndexKey(IndexKey []byte) []byte { // get the validator by power index. // Power index is the key used in the power-store, and represents the relative // power ranking of the validator. -// VALUE: validator owner address ([]byte) +// VALUE: validator operator address ([]byte) func GetValidatorsByPowerIndexKey(validator types.Validator, pool types.Pool) []byte { // NOTE the address doesn't need to be stored because counter bytes must always be different return getValidatorPowerRank(validator, pool) diff --git a/x/stake/keeper/slash.go b/x/stake/keeper/slash.go index e077accb71..5a004e807a 100644 --- a/x/stake/keeper/slash.go +++ b/x/stake/keeper/slash.go @@ -112,7 +112,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in // remove validator if it has no more tokens if validator.Tokens.IsZero() { - k.RemoveValidator(ctx, validator.Operator) + k.RemoveValidator(ctx, validator.OperatorAddr) } // Log that a slash occurred! diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 96719d8607..d2411de723 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -38,7 +38,7 @@ func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator ty if val, ok := validatorCache[strValue]; ok { valToReturn := val.val // Doesn't mutate the cache's value - valToReturn.Operator = addr + valToReturn.OperatorAddr = addr return valToReturn, true } @@ -72,25 +72,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.Operator), bz) + store.Set(GetValidatorKey(validator.OperatorAddr), bz) } // validator index func (k Keeper) SetValidatorByPubKeyIndex(ctx sdk.Context, validator types.Validator) { store := ctx.KVStore(k.storeKey) - store.Set(GetValidatorByPubKeyIndexKey(validator.PubKey), validator.Operator) + store.Set(GetValidatorByPubKeyIndexKey(validator.ConsPubKey), validator.OperatorAddr) } // 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.Operator) + store.Set(GetValidatorsByPowerIndexKey(validator, pool), validator.OperatorAddr) } // validator index func (k Keeper) SetValidatorBondedIndex(ctx sdk.Context, validator types.Validator) { store := ctx.KVStore(k.storeKey) - store.Set(GetValidatorsBondedIndexKey(validator.Operator), []byte{}) + store.Set(GetValidatorsBondedIndexKey(validator.OperatorAddr), []byte{}) } // used in testing @@ -239,7 +239,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.Operator) + oldValidator, oldFound := k.GetValidator(ctx, validator.OperatorAddr) validator = k.updateForJailing(ctx, oldFound, oldValidator, validator) powerIncreasing := k.getPowerIncreasing(ctx, oldFound, oldValidator, validator) @@ -257,11 +257,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.Operator), bz) + store.Set(GetTendermintUpdatesKey(validator.OperatorAddr), bz) if cliffPower != nil { cliffAddr := sdk.ValAddress(k.GetCliffValidator(ctx)) - if bytes.Equal(cliffAddr, validator.Operator) { + if bytes.Equal(cliffAddr, validator.OperatorAddr) { k.updateCliffValidator(ctx, validator) } } @@ -293,7 +293,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.Operator), bz) + store.Set(GetTendermintUpdatesKey(validator.OperatorAddr), bz) } } @@ -344,7 +344,7 @@ func (k Keeper) updateCliffValidator(ctx sdk.Context, affectedVal types.Validato affectedValRank := GetValidatorsByPowerIndexKey(affectedVal, pool) newCliffValRank := GetValidatorsByPowerIndexKey(newCliffVal, pool) - if bytes.Equal(affectedVal.Operator, newCliffVal.Operator) { + if bytes.Equal(affectedVal.OperatorAddr, newCliffVal.OperatorAddr) { // The affected validator remains the cliff validator, however, since // the store does not contain the new power, update the new power rank. @@ -407,7 +407,7 @@ func (k Keeper) updateValidatorPower(ctx sdk.Context, oldFound bool, oldValidato store.Delete(GetValidatorsByPowerIndexKey(oldValidator, pool)) } valPower = GetValidatorsByPowerIndexKey(newValidator, pool) - store.Set(valPower, newValidator.Operator) + store.Set(valPower, newValidator.OperatorAddr) return valPower } @@ -449,7 +449,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.Operator) { + if bytes.Equal(ownerAddr, affectedValidator.OperatorAddr) { validator = affectedValidator } else { var found bool @@ -486,7 +486,7 @@ func (k Keeper) UpdateBondedValidators( iterator.Close() - if newValidatorBonded && bytes.Equal(oldCliffValidatorAddr, validator.Operator) { + if newValidatorBonded && bytes.Equal(oldCliffValidatorAddr, validator.OperatorAddr) { panic("cliff validator has not been changed, yet we bonded a new validator") } @@ -506,7 +506,7 @@ func (k Keeper) UpdateBondedValidators( panic(fmt.Sprintf("validator record not found for address: %v\n", oldCliffValidatorAddr)) } - if bytes.Equal(validatorToBond.Operator, affectedValidator.Operator) { + if bytes.Equal(validatorToBond.OperatorAddr, affectedValidator.OperatorAddr) { // begin unbonding the old cliff validator iff the affected // validator was newly bonded and has greater power @@ -520,7 +520,7 @@ func (k Keeper) UpdateBondedValidators( } validator = k.bondValidator(ctx, validatorToBond) - if bytes.Equal(validator.Operator, affectedValidator.Operator) { + if bytes.Equal(validator.OperatorAddr, affectedValidator.OperatorAddr) { return validator, true } @@ -637,10 +637,10 @@ func (k Keeper) beginUnbondingValidator(ctx sdk.Context, validator types.Validat // add to accumulated changes for tendermint bzABCI := k.cdc.MustMarshalBinary(validator.ABCIValidatorZero()) - store.Set(GetTendermintUpdatesKey(validator.Operator), bzABCI) + store.Set(GetTendermintUpdatesKey(validator.OperatorAddr), bzABCI) // also remove from the Bonded types.Validators Store - store.Delete(GetValidatorsBondedIndexKey(validator.Operator)) + store.Delete(GetValidatorsBondedIndexKey(validator.OperatorAddr)) // call the unbond hook if present if k.validatorHooks != nil { @@ -668,11 +668,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.Operator), []byte{}) + store.Set(GetValidatorsBondedIndexKey(validator.OperatorAddr), []byte{}) // add to accumulated changes for tendermint bzABCI := k.cdc.MustMarshalBinary(validator.ABCIValidator()) - store.Set(GetTendermintUpdatesKey(validator.Operator), bzABCI) + store.Set(GetTendermintUpdatesKey(validator.OperatorAddr), bzABCI) // call the bond hook if present if k.validatorHooks != nil { @@ -696,15 +696,15 @@ func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) { store := ctx.KVStore(k.storeKey) pool := k.GetPool(ctx) store.Delete(GetValidatorKey(address)) - store.Delete(GetValidatorByPubKeyIndexKey(validator.PubKey)) + store.Delete(GetValidatorByPubKeyIndexKey(validator.ConsPubKey)) store.Delete(GetValidatorsByPowerIndexKey(validator, pool)) // 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.Operator)) == nil { + if store.Get(GetValidatorsBondedIndexKey(validator.OperatorAddr)) == nil { return } - store.Delete(GetValidatorsBondedIndexKey(validator.Operator)) + store.Delete(GetValidatorsBondedIndexKey(validator.OperatorAddr)) bz := k.cdc.MustMarshalBinary(validator.ABCIValidatorZero()) store.Set(GetTendermintUpdatesKey(address), bz) @@ -729,7 +729,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.Operator) + store.Set(ValidatorCliffIndexKey, validator.OperatorAddr) } // 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 2f471a2a5e..87fbcbc651 100644 --- a/x/stake/keeper/validator_test.go +++ b/x/stake/keeper/validator_test.go @@ -129,7 +129,7 @@ func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) { // require the cliff validator has changed cliffVal := validators[numVals-maxVals-1] - require.Equal(t, cliffVal.Operator, sdk.ValAddress(keeper.GetCliffValidator(ctx))) + require.Equal(t, cliffVal.OperatorAddr, sdk.ValAddress(keeper.GetCliffValidator(ctx))) // require the cliff validator power has changed cliffPower := keeper.GetCliffValidatorPower(ctx) @@ -142,7 +142,7 @@ func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) { // require all the validators have their respective statuses for valIdx, status := range expectedValStatus { - valAddr := validators[valIdx].Operator + valAddr := validators[valIdx].OperatorAddr val, _ := keeper.GetValidator(ctx, valAddr) assert.Equal( @@ -192,7 +192,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.Operator, sdk.ValAddress(keeper.GetCliffValidator(ctx))) + require.Equal(t, newCliffVal.OperatorAddr, sdk.ValAddress(keeper.GetCliffValidator(ctx))) // assert cliff validator power should have been updated cliffPower := keeper.GetCliffValidatorPower(ctx) @@ -205,7 +205,7 @@ func TestCliffValidatorChange(t *testing.T) { // assert cliff validator has not change but increased in power cliffPower = keeper.GetCliffValidatorPower(ctx) - require.Equal(t, newCliffVal.Operator, sdk.ValAddress(keeper.GetCliffValidator(ctx))) + require.Equal(t, newCliffVal.OperatorAddr, sdk.ValAddress(keeper.GetCliffValidator(ctx))) require.Equal(t, GetValidatorsByPowerIndexKey(newCliffVal, pool), cliffPower) // add enough power to cliff validator to be equal in rank to next validator @@ -215,7 +215,7 @@ func TestCliffValidatorChange(t *testing.T) { // assert new cliff validator due to power rank construction newCliffVal = validators[numVals-maxVals+2] - require.Equal(t, newCliffVal.Operator, sdk.ValAddress(keeper.GetCliffValidator(ctx))) + require.Equal(t, newCliffVal.OperatorAddr, sdk.ValAddress(keeper.GetCliffValidator(ctx))) // assert cliff validator power should have been updated cliffPower = keeper.GetCliffValidatorPower(ctx) @@ -317,7 +317,7 @@ func TestValidatorBasics(t *testing.T) { assert.True(ValEq(t, validators[2], resVals[2])) // remove a record - keeper.RemoveValidator(ctx, validators[1].Operator) + keeper.RemoveValidator(ctx, validators[1].OperatorAddr) _, found = keeper.GetValidator(ctx, addrVals[1]) require.False(t, found) } @@ -346,11 +346,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].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) + assert.Equal(t, validators[3].OperatorAddr, resValidators[0].OperatorAddr, "%v", resValidators) + assert.Equal(t, validators[4].OperatorAddr, resValidators[1].OperatorAddr, "%v", resValidators) + assert.Equal(t, validators[1].OperatorAddr, resValidators[2].OperatorAddr, "%v", resValidators) + assert.Equal(t, validators[2].OperatorAddr, resValidators[3].OperatorAddr, "%v", resValidators) + assert.Equal(t, validators[0].OperatorAddr, resValidators[4].OperatorAddr, "%v", resValidators) // test a basic increase in voting power validators[3].Tokens = sdk.NewDec(500) @@ -457,11 +457,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].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) + assert.Equal(t, validators[3].OperatorAddr, resValidators[0].OperatorAddr, "%v", resValidators) + assert.Equal(t, validators[4].OperatorAddr, resValidators[1].OperatorAddr, "%v", resValidators) + assert.Equal(t, validators[1].OperatorAddr, resValidators[2].OperatorAddr, "%v", resValidators) + assert.Equal(t, validators[2].OperatorAddr, resValidators[3].OperatorAddr, "%v", resValidators) + assert.Equal(t, validators[0].OperatorAddr, resValidators[4].OperatorAddr, "%v", resValidators) } // TODO separate out into multiple tests @@ -488,7 +488,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { } for i := range amts { - validators[i], found = keeper.GetValidator(ctx, validators[i].Operator) + validators[i], found = keeper.GetValidator(ctx, validators[i].OperatorAddr) require.True(t, found) } resValidators := keeper.GetValidatorsByPower(ctx) @@ -512,7 +512,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { // validator 3 enters bonded validator set ctx = ctx.WithBlockHeight(40) - validators[3], found = keeper.GetValidator(ctx, validators[3].Operator) + validators[3], found = keeper.GetValidator(ctx, validators[3].OperatorAddr) require.True(t, found) validators[3], pool, _ = validators[3].AddTokensFromDel(pool, sdk.NewInt(1)) keeper.SetPool(ctx, pool) @@ -539,7 +539,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].Operator) + validator, exists := keeper.GetValidator(ctx, validators[3].OperatorAddr) require.Equal(t, exists, true) require.Equal(t, int64(40), validator.BondHeight) } @@ -609,7 +609,7 @@ func TestFullValidatorSetPowerChange(t *testing.T) { } for i := range amts { var found bool - validators[i], found = keeper.GetValidator(ctx, validators[i].Operator) + validators[i], found = keeper.GetValidator(ctx, validators[i].OperatorAddr) require.True(t, found) } assert.Equal(t, sdk.Unbonding, validators[0].Status) @@ -682,13 +682,13 @@ func TestGetTendermintUpdatesAllNone(t *testing.T) { keeper.ClearTendermintUpdates(ctx) require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx))) - keeper.RemoveValidator(ctx, validators[0].Operator) - keeper.RemoveValidator(ctx, validators[1].Operator) + keeper.RemoveValidator(ctx, validators[0].OperatorAddr) + keeper.RemoveValidator(ctx, validators[1].OperatorAddr) updates = keeper.GetTendermintUpdates(ctx) assert.Equal(t, 2, len(updates)) - assert.Equal(t, tmtypes.TM2PB.PubKey(validators[0].PubKey), updates[0].PubKey) - assert.Equal(t, tmtypes.TM2PB.PubKey(validators[1].PubKey), updates[1].PubKey) + assert.Equal(t, tmtypes.TM2PB.PubKey(validators[0].ConsPubKey), updates[0].PubKey) + assert.Equal(t, tmtypes.TM2PB.PubKey(validators[1].ConsPubKey), updates[1].PubKey) assert.Equal(t, int64(0), updates[0].Power) assert.Equal(t, int64(0), updates[1].Power) } diff --git a/x/stake/types/errors.go b/x/stake/types/errors.go index 0c1d9192d7..366012bbfb 100644 --- a/x/stake/types/errors.go +++ b/x/stake/types/errors.go @@ -37,7 +37,7 @@ func ErrNoValidatorFound(codespace sdk.CodespaceType) sdk.Error { } func ErrValidatorOwnerExists(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidValidator, "validator already exist for this owner-address, must use new validator-owner address") + return sdk.NewError(codespace, CodeInvalidValidator, "validator already exist for this operator address, must use new validator operator address") } func ErrValidatorPubKeyExists(codespace sdk.CodespaceType) sdk.Error { diff --git a/x/stake/types/validator.go b/x/stake/types/validator.go index 0d93093118..c0efdb357c 100644 --- a/x/stake/types/validator.go +++ b/x/stake/types/validator.go @@ -21,9 +21,9 @@ import ( // exchange rate. Voting power can be calculated as total bonds multiplied by // exchange rate. type Validator struct { - Operator sdk.ValAddress `json:"operator"` // sender of BondTx - UnbondTx returns here - PubKey crypto.PubKey `json:"pub_key"` // pubkey of validator - Jailed bool `json:"jailed"` // has the validator been jailed from bonded status? + OperatorAddr sdk.ValAddress `json:"operator_address"` // address of the validator's operator + ConsPubKey crypto.PubKey `json:"consensus_pubkey"` // the consensus public key of the validator + Jailed bool `json:"jailed"` // has the validator been jailed from bonded status? Status sdk.BondStatus `json:"status"` // validator status (bonded/unbonding/unbonded) Tokens sdk.Dec `json:"tokens"` // delegated tokens (incl. self-delegation) @@ -45,8 +45,8 @@ type Validator struct { // NewValidator - initialize a new validator func NewValidator(operator sdk.ValAddress, pubKey crypto.PubKey, description Description) Validator { return Validator{ - Operator: operator, - PubKey: pubKey, + OperatorAddr: operator, + ConsPubKey: pubKey, Jailed: false, Status: sdk.Unbonded, Tokens: sdk.ZeroDec(), @@ -65,7 +65,7 @@ func NewValidator(operator sdk.ValAddress, pubKey crypto.PubKey, description Des // what's kept in the store value type validatorValue struct { - PubKey crypto.PubKey + ConsPubKey crypto.PubKey Jailed bool Status sdk.BondStatus Tokens sdk.Dec @@ -84,7 +84,7 @@ type validatorValue struct { // return the redelegation without fields contained within the key for the store func MustMarshalValidator(cdc *wire.Codec, validator Validator) []byte { val := validatorValue{ - PubKey: validator.PubKey, + ConsPubKey: validator.ConsPubKey, Jailed: validator.Jailed, Status: validator.Status, Tokens: validator.Tokens, @@ -124,8 +124,8 @@ func UnmarshalValidator(cdc *wire.Codec, operatorAddr, value []byte) (validator } return Validator{ - Operator: operatorAddr, - PubKey: storeValue.PubKey, + OperatorAddr: operatorAddr, + ConsPubKey: storeValue.ConsPubKey, Jailed: storeValue.Jailed, Tokens: storeValue.Tokens, Status: storeValue.Status, @@ -146,14 +146,14 @@ func UnmarshalValidator(cdc *wire.Codec, operatorAddr, value []byte) (validator // 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) { - bechConsPubKey, err := sdk.Bech32ifyConsPub(v.PubKey) + bechConsPubKey, err := sdk.Bech32ifyConsPub(v.ConsPubKey) if err != nil { return "", err } resp := "Validator \n" - resp += fmt.Sprintf("Operator: %s\n", v.Operator) - resp += fmt.Sprintf("Validator: %s\n", bechConsPubKey) + resp += fmt.Sprintf("Operator Address: %s\n", v.OperatorAddr) + resp += fmt.Sprintf("Validator Consensus Pubkey: %s\n", bechConsPubKey) resp += fmt.Sprintf("Jailed: %v\n", v.Jailed) resp += fmt.Sprintf("Status: %s\n", sdk.BondStatusToString(v.Status)) resp += fmt.Sprintf("Tokens: %s\n", v.Tokens.String()) @@ -174,9 +174,9 @@ func (v Validator) HumanReadableString() (string, error) { // validator struct for bech output type BechValidator struct { - Operator sdk.ValAddress `json:"operator"` // in bech32 - PubKey string `json:"pub_key"` // in bech32 - Jailed bool `json:"jailed"` // has the validator been jailed from bonded status? + OperatorAddr sdk.ValAddress `json:"operator_address"` // the bech32 address of the validator's operator + ConsPubKey string `json:"consensus_pubkey"` // the bech32 consensus public key of the validator + Jailed bool `json:"jailed"` // has the validator been jailed from bonded status? Status sdk.BondStatus `json:"status"` // validator status (bonded/unbonding/unbonded) Tokens sdk.Dec `json:"tokens"` // delegated tokens (incl. self-delegation) @@ -197,15 +197,15 @@ type BechValidator struct { // get the bech validator from the the regular validator func (v Validator) Bech32Validator() (BechValidator, error) { - bechConsPubKey, err := sdk.Bech32ifyConsPub(v.PubKey) + bechConsPubKey, err := sdk.Bech32ifyConsPub(v.ConsPubKey) if err != nil { return BechValidator{}, err } return BechValidator{ - Operator: v.Operator, - PubKey: bechConsPubKey, - Jailed: v.Jailed, + OperatorAddr: v.OperatorAddr, + ConsPubKey: bechConsPubKey, + Jailed: v.Jailed, Status: v.Status, Tokens: v.Tokens, @@ -229,8 +229,8 @@ func (v Validator) Bech32Validator() (BechValidator, error) { // only the vitals - does not check bond height of IntraTxCounter // nolint gocyclo - why dis fail? func (v Validator) Equal(c2 Validator) bool { - return v.PubKey.Equals(c2.PubKey) && - bytes.Equal(v.Operator, c2.Operator) && + return v.ConsPubKey.Equals(c2.ConsPubKey) && + bytes.Equal(v.OperatorAddr, c2.OperatorAddr) && v.Status.Equal(c2.Status) && v.Tokens.Equal(c2.Tokens) && v.DelegatorShares.Equal(c2.DelegatorShares) && @@ -243,7 +243,7 @@ func (v Validator) Equal(c2 Validator) bool { // return the TM validator address func (v Validator) ConsAddress() sdk.ConsAddress { - return sdk.ConsAddress(v.PubKey.Address()) + return sdk.ConsAddress(v.ConsPubKey.Address()) } // constant used in flags to indicate that description field should not be updated @@ -312,8 +312,8 @@ func (d Description) EnsureLength() (Description, sdk.Error) { // ABCIValidator returns an abci.Validator from a staked validator type. func (v Validator) ABCIValidator() abci.Validator { return abci.Validator{ - PubKey: tmtypes.TM2PB.PubKey(v.PubKey), - Address: v.PubKey.Address(), + PubKey: tmtypes.TM2PB.PubKey(v.ConsPubKey), + Address: v.ConsPubKey.Address(), Power: v.BondedTokens().RoundInt64(), } } @@ -322,8 +322,8 @@ func (v Validator) ABCIValidator() abci.Validator { // with with zero power used for validator updates. func (v Validator) ABCIValidatorZero() abci.Validator { return abci.Validator{ - PubKey: tmtypes.TM2PB.PubKey(v.PubKey), - Address: v.PubKey.Address(), + PubKey: tmtypes.TM2PB.PubKey(v.ConsPubKey), + Address: v.ConsPubKey.Address(), Power: 0, } } @@ -446,8 +446,8 @@ var _ sdk.Validator = Validator{} func (v Validator) GetJailed() bool { return v.Jailed } func (v Validator) GetMoniker() string { return v.Description.Moniker } func (v Validator) GetStatus() sdk.BondStatus { return v.Status } -func (v Validator) GetOperator() sdk.ValAddress { return v.Operator } -func (v Validator) GetPubKey() crypto.PubKey { return v.PubKey } +func (v Validator) GetOperator() sdk.ValAddress { return v.OperatorAddr } +func (v Validator) GetPubKey() crypto.PubKey { return v.ConsPubKey } 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 } diff --git a/x/stake/types/validator_test.go b/x/stake/types/validator_test.go index b81ae44585..60c5f9d74f 100644 --- a/x/stake/types/validator_test.go +++ b/x/stake/types/validator_test.go @@ -57,7 +57,7 @@ func TestABCIValidator(t *testing.T) { validator := NewValidator(addr1, pk1, Description{}) abciVal := validator.ABCIValidator() - require.Equal(t, tmtypes.TM2PB.PubKey(validator.PubKey), abciVal.PubKey) + require.Equal(t, tmtypes.TM2PB.PubKey(validator.ConsPubKey), abciVal.PubKey) require.Equal(t, validator.BondedTokens().RoundInt64(), abciVal.Power) } @@ -65,15 +65,15 @@ func TestABCIValidatorZero(t *testing.T) { validator := NewValidator(addr1, pk1, Description{}) abciVal := validator.ABCIValidatorZero() - require.Equal(t, tmtypes.TM2PB.PubKey(validator.PubKey), abciVal.PubKey) + require.Equal(t, tmtypes.TM2PB.PubKey(validator.ConsPubKey), abciVal.PubKey) require.Equal(t, int64(0), abciVal.Power) } func TestRemoveTokens(t *testing.T) { validator := Validator{ - Operator: addr1, - PubKey: pk1, + OperatorAddr: addr1, + ConsPubKey: pk1, Status: sdk.Bonded, Tokens: sdk.NewDec(100), DelegatorShares: sdk.NewDec(100), @@ -148,8 +148,8 @@ func TestAddTokensValidatorUnbonded(t *testing.T) { // TODO refactor to make simpler like the AddToken tests above func TestRemoveDelShares(t *testing.T) { valA := Validator{ - Operator: addr1, - PubKey: pk1, + OperatorAddr: addr1, + ConsPubKey: pk1, Status: sdk.Bonded, Tokens: sdk.NewDec(100), DelegatorShares: sdk.NewDec(100), @@ -176,8 +176,8 @@ func TestRemoveDelShares(t *testing.T) { poolTokens := sdk.NewDec(5102) delShares := sdk.NewDec(115) validator := Validator{ - Operator: addr1, - PubKey: pk1, + OperatorAddr: addr1, + ConsPubKey: pk1, Status: sdk.Bonded, Tokens: poolTokens, DelegatorShares: delShares, @@ -229,8 +229,8 @@ func TestPossibleOverflow(t *testing.T) { poolTokens := sdk.NewDec(2159) delShares := sdk.NewDec(391432570689183511).Quo(sdk.NewDec(40113011844664)) validator := Validator{ - Operator: addr1, - PubKey: pk1, + OperatorAddr: addr1, + ConsPubKey: pk1, Status: sdk.Bonded, Tokens: poolTokens, DelegatorShares: delShares, From 88a2ddeb25b29d16689412e757e79b6b9a332656 Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Sat, 8 Sep 2018 01:55:49 -0700 Subject: [PATCH 72/93] Merge PR #2276: make simulation no longer generate new privkeys --- x/auth/ante.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/x/auth/ante.go b/x/auth/ante.go index 65071e69a7..5b2cdb1559 100644 --- a/x/auth/ante.go +++ b/x/auth/ante.go @@ -2,6 +2,7 @@ package auth import ( "bytes" + "encoding/hex" "fmt" sdk "github.com/cosmos/cosmos-sdk/types" @@ -190,6 +191,13 @@ func processSig( return } +var dummySecp256k1Pubkey secp256k1.PubKeySecp256k1 + +func init() { + bz, _ := hex.DecodeString("035AD6810A47F073553FF30D2FCC7E0D3B1C0B74B61A1AAA2582344037151E143A") + copy(dummySecp256k1Pubkey[:], bz) +} + func processPubKey(acc Account, sig StdSignature, simulate bool) (crypto.PubKey, sdk.Result) { // If pubkey is not known for account, // set it from the StdSignature. @@ -200,7 +208,7 @@ func processPubKey(acc Account, sig StdSignature, simulate bool) (crypto.PubKey, // and gasKVStore.Set() shall consume the largest amount, i.e. // it takes more gas to verifiy secp256k1 keys than ed25519 ones. if pubKey == nil { - return secp256k1.GenPrivKey().PubKey(), sdk.Result{} + return dummySecp256k1Pubkey, sdk.Result{} } return pubKey, sdk.Result{} } From 4448d175ade1e3df09a1285b40cf5745a8fe8886 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Sat, 8 Sep 2018 10:26:20 +0100 Subject: [PATCH 73/93] Merge PR #2240: New broadcast command Implement broadcast command/REST endpoint to submit transactions generated offline with --generated-only and the sign command. --- PENDING.md | 10 +++--- client/lcd/lcd_test.go | 24 ++++++++++++-- cmd/gaia/cli_test/cli_test.go | 41 +++++++++++++++++------- cmd/gaia/cmd/gaiacli/main.go | 1 + docs/light/api.md | 44 +++++++++++++++++++++++-- docs/sdk/clients.md | 6 ++++ x/auth/client/rest/query.go | 2 +- x/bank/client/cli/broadcast.go | 52 ++++++++++++++++++++++++++++++ x/bank/client/rest/broadcast.go | 57 +++++++++++++++++++++++++++++++++ x/bank/client/rest/sendtx.go | 1 + 10 files changed, 216 insertions(+), 22 deletions(-) create mode 100644 x/bank/client/cli/broadcast.go create mode 100644 x/bank/client/rest/broadcast.go diff --git a/PENDING.md b/PENDING.md index e9182f22af..9254f69b9a 100644 --- a/PENDING.md +++ b/PENDING.md @@ -49,10 +49,11 @@ BREAKING CHANGES FEATURES * Gaia REST API (`gaiacli advanced rest-server`) - * [lcd] Endpoints to query staking pool and params - * [lcd] [\#2110](https://github.com/cosmos/cosmos-sdk/issues/2110) Add support for `simulate=true` requests query argument to endpoints that send txs to run simulations of transactions - * [lcd] [\#966](https://github.com/cosmos/cosmos-sdk/issues/966) Add support for `generate_only=true` query argument to generate offline unsigned transactions - * [lcd] [\#1953](https://github.com/cosmos/cosmos-sdk/issues/1953) Add /sign endpoint to sign transactions generated with `generate_only=true`. + * [gaia-lite] Endpoints to query staking pool and params + * [gaia-lite] [\#2110](https://github.com/cosmos/cosmos-sdk/issues/2110) Add support for `simulate=true` requests query argument to endpoints that send txs to run simulations of transactions + * [gaia-lite] [\#966](https://github.com/cosmos/cosmos-sdk/issues/966) Add support for `generate_only=true` query argument to generate offline unsigned transactions + * [gaia-lite] [\#1953](https://github.com/cosmos/cosmos-sdk/issues/1953) Add /sign endpoint to sign transactions generated with `generate_only=true`. + * [gaia-lite] [\#1954](https://github.com/cosmos/cosmos-sdk/issues/1954) Add /broadcast endpoint to broadcast transactions signed by the /sign endpoint. * Gaia CLI (`gaiacli`) * [cli] Cmds to query staking pool and params @@ -65,6 +66,7 @@ FEATURES * [cli] [\#2204](https://github.com/cosmos/cosmos-sdk/issues/2204) Support generating and broadcasting messages with multiple signatures via command line: * [\#966](https://github.com/cosmos/cosmos-sdk/issues/966) Add --generate-only flag to build an unsigned transaction and write it to STDOUT. * [\#1953](https://github.com/cosmos/cosmos-sdk/issues/1953) New `sign` command to sign transactions generated with the --generate-only flag. + * [\#1954](https://github.com/cosmos/cosmos-sdk/issues/1954) New `broadcast` command to broadcast transactions generated offline and signed with the `sign` command. * Gaia * [cli] #2170 added ability to show the node's address via `gaiad tendermint show-address` diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index e6cfd24a7b..7fc98aef6f 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -314,11 +314,12 @@ func TestIBCTransfer(t *testing.T) { // TODO: query ibc egress packet state } -func TestCoinSendGenerateAndSign(t *testing.T) { +func TestCoinSendGenerateSignAndBroadcast(t *testing.T) { name, password := "test", "1234567890" addr, seed := CreateAddr(t, "test", password, GetKeyBase(t)) cleanup, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}) defer cleanup() + acc := getAccount(t, port, addr) // generate TX res, body, _ := doSendWithGas(t, port, seed, name, password, addr, 0, 0, "?generate_only=true") @@ -329,10 +330,10 @@ func TestCoinSendGenerateAndSign(t *testing.T) { require.Equal(t, msg.Msgs[0].Type(), "bank") require.Equal(t, msg.Msgs[0].GetSigners(), []sdk.AccAddress{addr}) require.Equal(t, 0, len(msg.Signatures)) + gasEstimate := msg.Fee.Gas // sign tx var signedMsg auth.StdTx - acc := getAccount(t, port, addr) accnum := acc.GetAccountNumber() sequence := acc.GetSequence() @@ -346,13 +347,30 @@ func TestCoinSendGenerateAndSign(t *testing.T) { } json, err := cdc.MarshalJSON(payload) require.Nil(t, err) - res, body = Request(t, port, "POST", "/sign", json) + res, body = Request(t, port, "POST", "/tx/sign", json) require.Equal(t, http.StatusOK, res.StatusCode, body) require.Nil(t, cdc.UnmarshalJSON([]byte(body), &signedMsg)) require.Equal(t, len(msg.Msgs), len(signedMsg.Msgs)) require.Equal(t, msg.Msgs[0].Type(), signedMsg.Msgs[0].Type()) require.Equal(t, msg.Msgs[0].GetSigners(), signedMsg.Msgs[0].GetSigners()) require.Equal(t, 1, len(signedMsg.Signatures)) + + // broadcast tx + broadcastPayload := struct { + Tx auth.StdTx `json:"tx"` + }{Tx: signedMsg} + json, err = cdc.MarshalJSON(broadcastPayload) + require.Nil(t, err) + res, body = Request(t, port, "POST", "/tx/broadcast", json) + require.Equal(t, http.StatusOK, res.StatusCode, body) + + // check if tx was committed + var resultTx ctypes.ResultBroadcastTxCommit + require.Nil(t, cdc.UnmarshalJSON([]byte(body), &resultTx)) + require.Equal(t, uint32(0), resultTx.CheckTx.Code) + require.Equal(t, uint32(0), resultTx.DeliverTx.Code) + require.Equal(t, gasEstimate, resultTx.DeliverTx.GasWanted) + require.Equal(t, gasEstimate, resultTx.DeliverTx.GasUsed) } func TestTxs(t *testing.T) { diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index ab1a39ac8d..032482e7bc 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -343,7 +343,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) { require.Equal(t, " 2 - Apples", proposalsQuery) } -func TestGaiaCLISendGenerateAndSign(t *testing.T) { +func TestGaiaCLISendGenerateSignAndBroadcast(t *testing.T) { chainID, servAddr, port := initializeFixtures(t) flags := fmt.Sprintf("--home=%s --node=%v --chain-id=%v", gaiacliHome, servAddr, chainID) @@ -368,16 +368,6 @@ func TestGaiaCLISendGenerateAndSign(t *testing.T) { require.Equal(t, len(msg.Msgs), 1) require.Equal(t, 0, len(msg.GetSignatures())) - // Test generate sendTx, estimate gas - success, stdout, stderr = executeWriteRetStdStreams(t, fmt.Sprintf( - "gaiacli send %v --amount=10steak --to=%s --from=foo --gas=0 --generate-only", - flags, barAddr), []string{}...) - require.True(t, success) - require.NotEmpty(t, stderr) - msg = unmarshalStdTx(t, stdout) - require.NotZero(t, msg.Fee.Gas) - require.Equal(t, len(msg.Msgs), 1) - // Test generate sendTx with --gas=$amount success, stdout, stderr = executeWriteRetStdStreams(t, fmt.Sprintf( "gaiacli send %v --amount=10steak --to=%s --from=foo --gas=100 --generate-only", @@ -389,6 +379,16 @@ func TestGaiaCLISendGenerateAndSign(t *testing.T) { require.Equal(t, len(msg.Msgs), 1) require.Equal(t, 0, len(msg.GetSignatures())) + // Test generate sendTx, estimate gas + success, stdout, stderr = executeWriteRetStdStreams(t, fmt.Sprintf( + "gaiacli send %v --amount=10steak --to=%s --from=foo --gas=0 --generate-only", + flags, barAddr), []string{}...) + require.True(t, success) + require.NotEmpty(t, stderr) + msg = unmarshalStdTx(t, stdout) + require.True(t, msg.Fee.Gas > 0) + require.Equal(t, len(msg.Msgs), 1) + // Write the output to disk unsignedTxFile := writeToNewTempFile(t, stdout) defer os.Remove(unsignedTxFile.Name()) @@ -417,6 +417,25 @@ func TestGaiaCLISendGenerateAndSign(t *testing.T) { "gaiacli sign %v --print-sigs %v", flags, signedTxFile.Name())) require.True(t, success) require.Equal(t, fmt.Sprintf("Signers:\n 0: %v\n\nSignatures:\n 0: %v\n", fooAddr.String(), fooAddr.String()), stdout) + + // Test broadcast + fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", fooAddr, flags)) + require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf("steak").Int64()) + + success, stdout, _ = executeWriteRetStdStreams(t, fmt.Sprintf("gaiacli broadcast %v --json %v", flags, signedTxFile.Name())) + require.True(t, success) + var result struct { + Response abci.ResponseDeliverTx + } + require.Nil(t, app.MakeCodec().UnmarshalJSON([]byte(stdout), &result)) + require.Equal(t, msg.Fee.Gas, result.Response.GasUsed) + require.Equal(t, msg.Fee.Gas, result.Response.GasWanted) + tests.WaitForNextNBlocksTM(2, port) + + barAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", barAddr, flags)) + require.Equal(t, int64(10), barAcc.GetCoins().AmountOf("steak").Int64()) + fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", fooAddr, flags)) + require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf("steak").Int64()) } //___________________________________________________________________________________ diff --git a/cmd/gaia/cmd/gaiacli/main.go b/cmd/gaia/cmd/gaiacli/main.go index 7a1af62214..c216bb2eb0 100644 --- a/cmd/gaia/cmd/gaiacli/main.go +++ b/cmd/gaia/cmd/gaiacli/main.go @@ -132,6 +132,7 @@ func main() { rootCmd.AddCommand( client.PostCommands( bankcmd.SendTxCmd(cdc), + bankcmd.GetBroadcastCommand(cdc), )...) // add proxy, version and key info diff --git a/docs/light/api.md b/docs/light/api.md index 293b023cd0..6c7f9de177 100644 --- a/docs/light/api.md +++ b/docs/light/api.md @@ -226,12 +226,11 @@ Returns on success: "sequence": 7 } } -} ``` -### POST /auth/accounts/sign +### POST /auth/tx/sign -- **URL**: `/auth/sign` +- **URL**: `/auth/tx/sign` - **Functionality**: Sign a transaction without broadcasting it. - Returns on success: @@ -298,6 +297,45 @@ Returns on success: } ``` +### POST /auth/tx/broadcast + +- **URL**: `/auth/broadcast` +- **Functionality**: Broadcast a transaction. +- Returns on success: + +```json +{ + "rest api": "1.0", + "code": 200, + "error": "", + "result": + { + "check_tx": { + "log": "Msg 0: ", + "gasWanted": "2742", + "gasUsed": "1002" + }, + "deliver_tx": { + "log": "Msg 0: ", + "gasWanted": "2742", + "gasUsed": "2742", + "tags": [ + { + "key": "c2VuZGVy", + "value": "Y29zbW9zMXdjNTl6ZXU3MmNjdnp5ZWR6ZGE1N3pzcXh2eXZ2Y3poaHBhdDI4" + }, + { + "key": "cmVjaXBpZW50", + "value": "Y29zbW9zMTJ4OTNmY3V2azg3M3o1ejZnejRlNTl2dnlxcXp1eDdzdDcwNWd5" + } + ] + }, + "hash": "784314784503582AC885BD6FB0D2A5B79FF703A7", + "height": "5" + } +} +``` + ## ICS20 - TokenAPI The TokenAPI exposes all functionality needed to query account balances and send transactions. diff --git a/docs/sdk/clients.md b/docs/sdk/clients.md index 2b2e8e52a4..4d02d3c908 100644 --- a/docs/sdk/clients.md +++ b/docs/sdk/clients.md @@ -159,6 +159,12 @@ gaiacli sign \ unsignedSendTx.json > signedSendTx.json ``` +You can broadcast the signed transaction to a node by providing the JSON file to the following command: + +``` +gaiacli broadcast --node= signedSendTx.json +``` + ### Staking #### Set up a Validator diff --git a/x/auth/client/rest/query.go b/x/auth/client/rest/query.go index 3a5ab756d1..9e5fc88b5c 100644 --- a/x/auth/client/rest/query.go +++ b/x/auth/client/rest/query.go @@ -21,7 +21,7 @@ func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *wire.Codec, s QueryAccountRequestHandlerFn(storeName, cdc, authcmd.GetAccountDecoder(cdc), cliCtx), ).Methods("GET") r.HandleFunc( - "/sign", + "/tx/sign", SignTxRequestHandlerFn(cdc, cliCtx), ).Methods("POST") } diff --git a/x/bank/client/cli/broadcast.go b/x/bank/client/cli/broadcast.go new file mode 100644 index 0000000000..cef88246c4 --- /dev/null +++ b/x/bank/client/cli/broadcast.go @@ -0,0 +1,52 @@ +package cli + +import ( + "io/ioutil" + "os" + + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/spf13/cobra" + amino "github.com/tendermint/go-amino" +) + +// GetSignCommand returns the sign command +func GetBroadcastCommand(codec *amino.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "broadcast ", + Short: "Broadcast transactions generated offline", + Long: `Broadcast transactions created with the --generate-only flag and signed with the sign command. +Read a transaction from and broadcast it to a node. If you supply a dash (-) argument +in place of an input filename, the command reads from standard input.`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) (err error) { + cliCtx := context.NewCLIContext().WithCodec(codec).WithLogger(os.Stdout) + stdTx, err := readAndUnmarshalStdTx(cliCtx.Codec, args[0]) + if err != nil { + return + } + txBytes, err := cliCtx.Codec.MarshalBinary(stdTx) + if err != nil { + return + } + return cliCtx.EnsureBroadcastTx(txBytes) + }, + } + return cmd +} + +func readAndUnmarshalStdTx(cdc *amino.Codec, filename string) (stdTx auth.StdTx, err error) { + var bytes []byte + if filename == "-" { + bytes, err = ioutil.ReadAll(os.Stdin) + } else { + bytes, err = ioutil.ReadFile(filename) + } + if err != nil { + return + } + if err = cdc.UnmarshalJSON(bytes, &stdTx); err != nil { + return + } + return +} diff --git a/x/bank/client/rest/broadcast.go b/x/bank/client/rest/broadcast.go new file mode 100644 index 0000000000..5124b791ba --- /dev/null +++ b/x/bank/client/rest/broadcast.go @@ -0,0 +1,57 @@ +package rest + +import ( + "io/ioutil" + "net/http" + + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/utils" + "github.com/cosmos/cosmos-sdk/wire" + "github.com/cosmos/cosmos-sdk/x/auth" +) + +type broadcastBody struct { + Tx auth.StdTx `json:"tx"` +} + +// BroadcastTxRequestHandlerFn returns the broadcast tx REST handler +func BroadcastTxRequestHandlerFn(cdc *wire.Codec, cliCtx context.CLIContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var m broadcastBody + if ok := unmarshalBodyOrReturnBadRequest(cliCtx, w, r, &m); !ok { + return + } + + txBytes, err := cliCtx.Codec.MarshalBinary(m.Tx) + if err != nil { + utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + res, err := cliCtx.BroadcastTx(txBytes) + if err != nil { + utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + + output, err := wire.MarshalJSONIndent(cdc, res) + if err != nil { + utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + w.Write(output) + } +} + +func unmarshalBodyOrReturnBadRequest(cliCtx context.CLIContext, w http.ResponseWriter, r *http.Request, m *broadcastBody) bool { + body, err := ioutil.ReadAll(r.Body) + if err != nil { + utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return false + } + err = cliCtx.Codec.UnmarshalJSON(body, m) + if err != nil { + utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return false + } + return true +} diff --git a/x/bank/client/rest/sendtx.go b/x/bank/client/rest/sendtx.go index b3694959d2..82df24642f 100644 --- a/x/bank/client/rest/sendtx.go +++ b/x/bank/client/rest/sendtx.go @@ -20,6 +20,7 @@ import ( // RegisterRoutes - Central function to define routes that get registered by the main application func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *wire.Codec, kb keys.Keybase) { r.HandleFunc("/accounts/{address}/send", SendRequestHandlerFn(cdc, kb, cliCtx)).Methods("POST") + r.HandleFunc("/tx/broadcast", BroadcastTxRequestHandlerFn(cdc, cliCtx)).Methods("POST") } type sendBody struct { From 1a700206b8ce1c90290daa228d2bc56ecbc0fea1 Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Sat, 8 Sep 2018 02:29:34 -0700 Subject: [PATCH 74/93] Merge PR #2275: genesis: Ensure there are no duplicate accounts in genesis file This also contains a light refactor of genesis state parsing, so that the tests file didn't duplicate a lot of this code. --- PENDING.md | 1 + cmd/gaia/app/app.go | 5 ++ cmd/gaia/app/genesis.go | 90 +++++++++++++++++++++++++----------- cmd/gaia/app/genesis_test.go | 39 ++++++++++++++++ 4 files changed, 107 insertions(+), 28 deletions(-) diff --git a/PENDING.md b/PENDING.md index 9254f69b9a..3b6033b9e4 100644 --- a/PENDING.md +++ b/PENDING.md @@ -95,6 +95,7 @@ IMPROVEMENTS * [x/auth] Signature verification's gas cost now accounts for pubkey type. [#2046](https://github.com/tendermint/tendermint/pull/2046) * [x/stake] [x/slashing] Ensure delegation invariants to jailed validators [#1883](https://github.com/cosmos/cosmos-sdk/issues/1883). * [x/stake] Improve speed of GetValidator, which was shown to be a performance bottleneck. [#2046](https://github.com/tendermint/tendermint/pull/2200) + * [genesis] \#2229 Ensure that there are no duplicate accounts in the genesis state. * SDK * [tools] Make get_vendor_deps deletes `.vendor-new` directories, in case scratch files are present. * [spec] Added simple piggy bank distribution spec diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 36a02899b5..14ed1b2c17 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -190,6 +190,11 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci slashing.InitGenesis(ctx, app.slashingKeeper, genesisState.StakeData) gov.InitGenesis(ctx, app.govKeeper, genesisState.GovData) + err = GaiaValidateGenesisState(genesisState) + if err != nil { + // TODO find a way to do this w/o panics + panic(err) + } return abci.ResponseInitChain{ Validators: validators, diff --git a/cmd/gaia/app/genesis.go b/cmd/gaia/app/genesis.go index 16c2919037..4967361b14 100644 --- a/cmd/gaia/app/genesis.go +++ b/cmd/gaia/app/genesis.go @@ -180,38 +180,12 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (genesisState } // create the genesis account, give'm few steaks and a buncha token with there name - accAuth := auth.NewBaseAccountWithAddress(genTx.Address) - accAuth.Coins = sdk.Coins{ - {genTx.Name + "Token", sdk.NewInt(1000)}, - {"steak", freeFermionsAcc}, - } - acc := NewGenesisAccount(&accAuth) - genaccs[i] = acc + genaccs[i] = genesisAccountFromGenTx(genTx) stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewDecFromInt(freeFermionsAcc)) // increase the supply // add the validator if len(genTx.Name) > 0 { - desc := stake.NewDescription(genTx.Name, "", "", "") - validator := stake.NewValidator( - sdk.ValAddress(genTx.Address), sdk.MustGetConsPubKeyBech32(genTx.PubKey), desc, - ) - - stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewDec(freeFermionVal)) // increase the supply - - // add some new shares to the validator - var issuedDelShares sdk.Dec - validator, stakeData.Pool, issuedDelShares = validator.AddTokensFromDel(stakeData.Pool, sdk.NewInt(freeFermionVal)) - stakeData.Validators = append(stakeData.Validators, validator) - - // create the self-delegation from the issuedDelShares - delegation := stake.Delegation{ - DelegatorAddr: sdk.AccAddress(validator.OperatorAddr), - ValidatorAddr: validator.OperatorAddr, - Shares: issuedDelShares, - Height: 0, - } - - stakeData.Bonds = append(stakeData.Bonds, delegation) + stakeData = addValidatorToStakeData(genTx, stakeData) } } @@ -224,6 +198,66 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (genesisState return } +func addValidatorToStakeData(genTx GaiaGenTx, stakeData stake.GenesisState) stake.GenesisState { + desc := stake.NewDescription(genTx.Name, "", "", "") + validator := stake.NewValidator( + sdk.ValAddress(genTx.Address), sdk.MustGetConsPubKeyBech32(genTx.PubKey), desc, + ) + + stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewDec(freeFermionVal)) // increase the supply + + // add some new shares to the validator + var issuedDelShares sdk.Dec + validator, stakeData.Pool, issuedDelShares = validator.AddTokensFromDel(stakeData.Pool, sdk.NewInt(freeFermionVal)) + stakeData.Validators = append(stakeData.Validators, validator) + + // create the self-delegation from the issuedDelShares + delegation := stake.Delegation{ + DelegatorAddr: sdk.AccAddress(validator.OperatorAddr), + ValidatorAddr: validator.OperatorAddr, + Shares: issuedDelShares, + Height: 0, + } + + stakeData.Bonds = append(stakeData.Bonds, delegation) + return stakeData +} + +func genesisAccountFromGenTx(genTx GaiaGenTx) GenesisAccount { + accAuth := auth.NewBaseAccountWithAddress(genTx.Address) + accAuth.Coins = sdk.Coins{ + {genTx.Name + "Token", sdk.NewInt(1000)}, + {"steak", freeFermionsAcc}, + } + return NewGenesisAccount(&accAuth) +} + +// GaiaValidateGenesisState ensures that the genesis state obeys the expected invariants +// TODO: No validators are both bonded and revoked (#2088) +// TODO: Error if there is a duplicate validator (#1708) +// TODO: Ensure all state machine parameters are in genesis (#1704) +func GaiaValidateGenesisState(genesisState GenesisState) (err error) { + err = validateGenesisStateAccounts(genesisState.Accounts) + if err != nil { + return + } + return +} + +// Ensures that there are no duplicate accounts in the genesis state, +func validateGenesisStateAccounts(accs []GenesisAccount) (err error) { + addrMap := make(map[string]bool, len(accs)) + for i := 0; i < len(accs); i++ { + acc := accs[i] + strAddr := string(acc.Address) + if _, ok := addrMap[strAddr]; ok { + return fmt.Errorf("Duplicate account in genesis state: Address %v", acc.Address) + } + addrMap[strAddr] = true + } + return +} + // GaiaAppGenState but with JSON func GaiaAppGenStateJSON(cdc *wire.Codec, appGenTxs []json.RawMessage) (appState json.RawMessage, err error) { diff --git a/cmd/gaia/app/genesis_test.go b/cmd/gaia/app/genesis_test.go index 85b5b0d9b4..755a90ebe7 100644 --- a/cmd/gaia/app/genesis_test.go +++ b/cmd/gaia/app/genesis_test.go @@ -5,10 +5,36 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/gov" + stake "github.com/cosmos/cosmos-sdk/x/stake" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto/ed25519" ) +func makeGenesisState(genTxs []GaiaGenTx) GenesisState { + // start with the default staking genesis state + stakeData := stake.DefaultGenesisState() + + // get genesis flag account information + genaccs := make([]GenesisAccount, len(genTxs)) + for i, genTx := range genTxs { + genaccs[i] = genesisAccountFromGenTx(genTx) + stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewDecFromInt(freeFermionsAcc)) // increase the supply + + // add the validator + if len(genTx.Name) > 0 { + stakeData = addValidatorToStakeData(genTx, stakeData) + } + } + + // create the final app state + return GenesisState{ + Accounts: genaccs, + StakeData: stakeData, + GovData: gov.DefaultGenesisState(), + } +} + func TestToAccount(t *testing.T) { priv := ed25519.GenPrivKey() addr := sdk.AccAddress(priv.PubKey().Address()) @@ -34,3 +60,16 @@ func TestGaiaAppGenState(t *testing.T) { // TODO test with both one and two genesis transactions: // TODO correct: genesis account created, canididates created, pool token variance } + +func TestGaiaGenesisValidation(t *testing.T) { + genTxs := make([]GaiaGenTx, 2) + privKey := ed25519.GenPrivKey() + pubKey := privKey.PubKey() + addr := pubKey.Address() + // Test duplicate accounts fails + genTxs[0] = GaiaGenTx{"", sdk.AccAddress(addr), ""} + genTxs[1] = GaiaGenTx{"", sdk.AccAddress(addr), ""} + genesisState := makeGenesisState(genTxs) + err := GaiaValidateGenesisState(genesisState) + require.NotNil(t, err) +} From 3cf3ab11b0965eddbce0fb447babcb46a11138fc Mon Sep 17 00:00:00 2001 From: HaoyangLiu Date: Sun, 9 Sep 2018 08:47:36 +0800 Subject: [PATCH 75/93] Merge PR #2037: transient store missed to implement store type interface * transientstore missed to implement store type interface * rename pointer name from rs to ts --- store/transientstore.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/store/transientstore.go b/store/transientstore.go index 1c099fa0dd..89cbaf693b 100644 --- a/store/transientstore.go +++ b/store/transientstore.go @@ -2,6 +2,7 @@ package store import ( dbm "github.com/tendermint/tendermint/libs/db" + sdk "github.com/cosmos/cosmos-sdk/types" ) var _ KVStore = (*transientStore)(nil) @@ -41,3 +42,8 @@ func (ts *transientStore) Prefix(prefix []byte) KVStore { func (ts *transientStore) Gas(meter GasMeter, config GasConfig) KVStore { return NewGasKVStore(meter, config, ts) } + +// Implements Store. +func (ts *transientStore) GetStoreType() StoreType { + return sdk.StoreTypeTransient +} From 43ccbd4185bc877086a71ee16fe6073f4a127bbd Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Sun, 9 Sep 2018 08:13:17 -0700 Subject: [PATCH 76/93] Merge PR #2281: Update to iavl 0.11.0 --- Gopkg.lock | 48 +++++++++++++++++++++++----------------------- Gopkg.toml | 2 +- PENDING.md | 2 +- store/iavlstore.go | 4 ++-- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index f5221a4e50..b647d20212 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -34,7 +34,7 @@ [[projects]] branch = "master" - digest = "1:2c00f064ba355903866cbfbf3f7f4c0fe64af6638cc7d1b8bdcf3181bc67f1d8" + digest = "1:6aabc1566d6351115d561d038da82a4c19b46c3b6e17f4a0a2fa60260663dc79" name = "github.com/btcsuite/btcd" packages = ["btcec"] pruneopts = "UT" @@ -71,7 +71,7 @@ version = "v1.4.7" [[projects]] - digest = "1:fdf5169073fb0ad6dc12a70c249145e30f4058647bea25f0abd48b6d9f228a11" + digest = "1:fa30c0652956e159cdb97dcb2ef8b8db63ed668c02a5c3a40961c8f0641252fe" name = "github.com/go-kit/kit" packages = [ "log", @@ -103,7 +103,7 @@ version = "v1.7.0" [[projects]] - digest = "1:35621fe20f140f05a0c4ef662c26c0ab4ee50bca78aa30fe87d33120bd28165e" + digest = "1:212285efb97b9ec2e20550d81f0446cb7897e57cbdfd7301b1363ab113d8be45" name = "github.com/gogo/protobuf" packages = [ "gogoproto", @@ -118,7 +118,7 @@ version = "v1.1.1" [[projects]] - digest = "1:17fe264ee908afc795734e8c4e63db2accabaf57326dbf21763a7d6b86096260" + digest = "1:cb22af0ed7c72d495d8be1106233ee553898950f15fd3f5404406d44c2e86888" name = "github.com/golang/protobuf" packages = [ "proto", @@ -165,7 +165,7 @@ [[projects]] branch = "master" - digest = "1:12247a2e99a060cc692f6680e5272c8adf0b8f572e6bce0d7095e624c958a240" + digest = "1:8951fe6e358876736d8fa1f3992624fdbb2dec6bc49401c1381d1ef8abbb544f" name = "github.com/hashicorp/hcl" packages = [ ".", @@ -262,7 +262,7 @@ version = "v1.0.0" [[projects]] - digest = "1:c1a04665f9613e082e1209cf288bf64f4068dcd6c87a64bf1c4ff006ad422ba0" + digest = "1:98225904b7abff96c052b669b25788f18225a36673fba022fb93514bb9a2a64e" name = "github.com/prometheus/client_golang" packages = [ "prometheus", @@ -273,7 +273,7 @@ [[projects]] branch = "master" - digest = "1:2d5cd61daa5565187e1d96bae64dbbc6080dacf741448e9629c64fd93203b0d4" + digest = "1:0f37e09b3e92aaeda5991581311f8dbf38944b36a3edec61cc2d1991f527554a" name = "github.com/prometheus/client_model" packages = ["go"] pruneopts = "UT" @@ -281,7 +281,7 @@ [[projects]] branch = "master" - digest = "1:63b68062b8968092eb86bedc4e68894bd096ea6b24920faca8b9dcf451f54bb5" + digest = "1:dad2e5a2153ee7a6c9ab8fc13673a16ee4fb64434a7da980965a3741b0c981a3" name = "github.com/prometheus/common" packages = [ "expfmt", @@ -293,7 +293,7 @@ [[projects]] branch = "master" - digest = "1:8c49953a1414305f2ff5465147ee576dd705487c35b15918fcd4efdc0cb7a290" + digest = "1:a37c98f4b7a66bb5c539c0539f0915a74ef1c8e0b3b6f45735289d94cae92bfd" name = "github.com/prometheus/procfs" packages = [ ".", @@ -312,7 +312,7 @@ revision = "e2704e165165ec55d062f5919b4b29494e9fa790" [[projects]] - digest = "1:bd1ae00087d17c5a748660b8e89e1043e1e5479d0fea743352cda2f8dd8c4f84" + digest = "1:37ace7f35375adec11634126944bdc45a673415e2fcc07382d03b75ec76ea94c" name = "github.com/spf13/afero" packages = [ ".", @@ -331,7 +331,7 @@ version = "v1.2.0" [[projects]] - digest = "1:7ffc0983035bc7e297da3688d9fe19d60a420e9c38bef23f845c53788ed6a05e" + digest = "1:627ab2f549a6a55c44f46fa24a4307f4d0da81bfc7934ed0473bf38b24051d26" name = "github.com/spf13/cobra" packages = ["."] pruneopts = "UT" @@ -363,7 +363,7 @@ version = "v1.0.0" [[projects]] - digest = "1:7e8d267900c7fa7f35129a2a37596e38ed0f11ca746d6d9ba727980ee138f9f6" + digest = "1:73697231b93fb74a73ebd8384b68b9a60c57ea6b13c56d2425414566a72c8e6d" name = "github.com/stretchr/testify" packages = [ "assert", @@ -375,7 +375,7 @@ [[projects]] branch = "master" - digest = "1:f2ffd421680b0a3f7887501b3c6974bcf19217ecd301d0e2c9b681940ec363d5" + digest = "1:442d2ffa75ffae302ce8800bf4144696b92bef02917923ea132ce2d39efe7d65" name = "github.com/syndtr/goleveldb" packages = [ "leveldb", @@ -396,7 +396,7 @@ [[projects]] branch = "master" - digest = "1:087aaa7920e5d0bf79586feb57ce01c35c830396ab4392798112e8aae8c47722" + digest = "1:203b409c21115233a576f99e8f13d8e07ad82b25500491f7e1cca12588fb3232" name = "github.com/tendermint/ed25519" packages = [ ".", @@ -415,15 +415,15 @@ version = "v0.12.0-rc0" [[projects]] - digest = "1:e99ef92d64f2391efbbfb15310df635f96247532bbac2676ea43e466d706401d" + digest = "1:53397098d6acb7613358683cc84ae59281a60c6033f0bff62fa8d3f279c6c430" name = "github.com/tendermint/iavl" packages = ["."] pruneopts = "UT" - revision = "e5726c0066ccdd299a2ec9262f93c7896cdfcd87" - version = "v0.10.0" + revision = "3acc91fb8811db2c5409a855ae1f8e441fe98e2d" + version = "v0.11.0" [[projects]] - digest = "1:4f15e95fe3888cc75dd34f407d6394cbc7fd3ff24920851b92b295f6a8b556e6" + digest = "1:963f6c04345ce36f900c1d6367200eebc3cc2db6ee632ff865ea8dcf64b748a0" name = "github.com/tendermint/tendermint" packages = [ "abci/client", @@ -490,7 +490,7 @@ version = "v0.23.1-rc0" [[projects]] - digest = "1:bf6d9a827ea3cad964c2f863302e4f6823170d0b5ed16f72cf1184a7c615067e" + digest = "1:ad879bb8c71020a3f92f0c61f414d93eae1d5dc2f37023b6abaa3cc84b00165e" name = "github.com/tendermint/tmlibs" packages = ["cli"] pruneopts = "UT" @@ -507,7 +507,7 @@ [[projects]] branch = "master" - digest = "1:27507554c6d4f060d8d700c31c624a43d3a92baa634e178ddc044bdf7d13b44a" + digest = "1:2a3ce1f08dcae8bac666deb6e4c88b5d7170c510da38fd746231144cac351704" name = "golang.org/x/crypto" packages = [ "blowfish", @@ -529,7 +529,7 @@ revision = "614d502a4dac94afa3a6ce146bd1736da82514c6" [[projects]] - digest = "1:d36f55a999540d29b6ea3c2ea29d71c76b1d9853fdcd3e5c5cb4836f2ba118f1" + digest = "1:04dda8391c3e2397daf254ac68003f30141c069b228d06baec8324a5f81dc1e9" name = "golang.org/x/net" packages = [ "context", @@ -546,7 +546,7 @@ [[projects]] branch = "master" - digest = "1:86171d21d59449dcf7cee0b7d2da83dff989dab9b9b69bfe0a3d59c3c1ca6081" + digest = "1:9d9e5fc87553258c36ee18d38023587edd61e4b2521f4473da34b47a83a492e5" name = "golang.org/x/sys" packages = [ "cpu", @@ -556,7 +556,7 @@ revision = "4ea2f632f6e912459fe60b26b1749377f0d889d5" [[projects]] - digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" + digest = "1:7509ba4347d1f8de6ae9be8818b0cd1abc3deeffe28aeaf4be6d4b6b5178d9ca" name = "golang.org/x/text" packages = [ "collate", @@ -587,7 +587,7 @@ revision = "c66870c02cf823ceb633bcd05be3c7cda29976f4" [[projects]] - digest = "1:2dab32a43451e320e49608ff4542fdfc653c95dcc35d0065ec9c6c3dd540ed74" + digest = "1:4515e3030c440845b046354fd5d57671238428b820deebce2e9dabb5cd3c51ac" name = "google.golang.org/grpc" packages = [ ".", diff --git a/Gopkg.toml b/Gopkg.toml index 1b440891de..2b5928a897 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -53,7 +53,7 @@ [[override]] name = "github.com/tendermint/iavl" - version = "=v0.10.0" + version = "=v0.11.0" [[override]] name = "github.com/tendermint/tendermint" diff --git a/PENDING.md b/PENDING.md index 3b6033b9e4..76db897ca4 100644 --- a/PENDING.md +++ b/PENDING.md @@ -101,7 +101,7 @@ IMPROVEMENTS * [spec] Added simple piggy bank distribution spec * [cli] [\#1632](https://github.com/cosmos/cosmos-sdk/issues/1632) Add integration tests to ensure `basecoind init && basecoind` start sequences run successfully for both `democoin` and `basecoin` examples. * [store] Speedup IAVL iteration, and consequently everything that requires IAVL iteration. [#2143](https://github.com/cosmos/cosmos-sdk/issues/2143) - * [store] \#1952 Update IAVL dependency to v0.10.0 + * [store] \#1952, \#2281 Update IAVL dependency to v0.11.0 * [simulation] Make timestamps randomized [#2153](https://github.com/cosmos/cosmos-sdk/pull/2153) * Tendermint diff --git a/store/iavlstore.go b/store/iavlstore.go index 61bdc56307..d301da771e 100644 --- a/store/iavlstore.go +++ b/store/iavlstore.go @@ -96,7 +96,7 @@ func (st *iavlStore) Commit() CommitID { // Implements Committer. func (st *iavlStore) LastCommitID() CommitID { return CommitID{ - Version: st.tree.Version64(), + Version: st.tree.Version(), Hash: st.tree.Hash(), } } @@ -180,7 +180,7 @@ func (st *iavlStore) ReverseIterator(start, end []byte) Iterator { func getHeight(tree *iavl.MutableTree, req abci.RequestQuery) int64 { height := req.Height if height == 0 { - latest := tree.Version64() + latest := tree.Version() if tree.VersionExists(latest - 1) { height = latest - 1 } else { From 8b8028e0dde1c5616cca51530c5d88d929570768 Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Sun, 9 Sep 2018 08:23:51 -0700 Subject: [PATCH 77/93] Merge PR #2280: genesis: Ensure no dup validators, or bonded and revoked validators --- PENDING.md | 3 ++- cmd/gaia/app/genesis.go | 21 +++++++++++++++++++++ cmd/gaia/app/genesis_test.go | 36 ++++++++++++++++++++++++++++++++---- 3 files changed, 55 insertions(+), 5 deletions(-) diff --git a/PENDING.md b/PENDING.md index 76db897ca4..a63b17c7e5 100644 --- a/PENDING.md +++ b/PENDING.md @@ -95,7 +95,8 @@ IMPROVEMENTS * [x/auth] Signature verification's gas cost now accounts for pubkey type. [#2046](https://github.com/tendermint/tendermint/pull/2046) * [x/stake] [x/slashing] Ensure delegation invariants to jailed validators [#1883](https://github.com/cosmos/cosmos-sdk/issues/1883). * [x/stake] Improve speed of GetValidator, which was shown to be a performance bottleneck. [#2046](https://github.com/tendermint/tendermint/pull/2200) - * [genesis] \#2229 Ensure that there are no duplicate accounts in the genesis state. + * [genesis] \#2229 Ensure that there are no duplicate accounts or validators in the genesis state. + * SDK * [tools] Make get_vendor_deps deletes `.vendor-new` directories, in case scratch files are present. * [spec] Added simple piggy bank distribution spec diff --git a/cmd/gaia/app/genesis.go b/cmd/gaia/app/genesis.go index 4967361b14..10c7e4126e 100644 --- a/cmd/gaia/app/genesis.go +++ b/cmd/gaia/app/genesis.go @@ -13,6 +13,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/gov" "github.com/cosmos/cosmos-sdk/x/stake" + stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types" "github.com/spf13/pflag" @@ -241,6 +242,26 @@ func GaiaValidateGenesisState(genesisState GenesisState) (err error) { if err != nil { return } + err = validateGenesisStateValidators(genesisState.StakeData.Validators) + if err != nil { + return + } + return +} + +func validateGenesisStateValidators(validators []stakeTypes.Validator) (err error) { + addrMap := make(map[string]bool, len(validators)) + for i := 0; i < len(validators); i++ { + val := validators[i] + strKey := string(val.ConsPubKey.Bytes()) + if _, ok := addrMap[strKey]; ok { + return fmt.Errorf("Duplicate validator in genesis state: moniker %v, Address %v", val.Description.Moniker, val.ConsAddress()) + } + if val.Jailed && val.Status == sdk.Bonded { + return fmt.Errorf("Validator is bonded and revoked in genesis state: moniker %v, Address %v", val.Description.Moniker, val.ConsAddress()) + } + addrMap[strKey] = true + } return } diff --git a/cmd/gaia/app/genesis_test.go b/cmd/gaia/app/genesis_test.go index 755a90ebe7..f671bebb41 100644 --- a/cmd/gaia/app/genesis_test.go +++ b/cmd/gaia/app/genesis_test.go @@ -6,11 +6,25 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/gov" - stake "github.com/cosmos/cosmos-sdk/x/stake" + "github.com/cosmos/cosmos-sdk/x/stake" + stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types" "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" ) +var ( + pk1 = ed25519.GenPrivKey().PubKey() + pk2 = ed25519.GenPrivKey().PubKey() + pk3 = ed25519.GenPrivKey().PubKey() + addr1 = sdk.ValAddress(pk1.Address()) + addr2 = sdk.ValAddress(pk2.Address()) + addr3 = sdk.ValAddress(pk3.Address()) + + emptyAddr sdk.ValAddress + emptyPubkey crypto.PubKey +) + func makeGenesisState(genTxs []GaiaGenTx) GenesisState { // start with the default staking genesis state stakeData := stake.DefaultGenesisState() @@ -63,13 +77,27 @@ func TestGaiaAppGenState(t *testing.T) { func TestGaiaGenesisValidation(t *testing.T) { genTxs := make([]GaiaGenTx, 2) - privKey := ed25519.GenPrivKey() - pubKey := privKey.PubKey() - addr := pubKey.Address() + addr := pk1.Address() // Test duplicate accounts fails genTxs[0] = GaiaGenTx{"", sdk.AccAddress(addr), ""} genTxs[1] = GaiaGenTx{"", sdk.AccAddress(addr), ""} genesisState := makeGenesisState(genTxs) err := GaiaValidateGenesisState(genesisState) require.NotNil(t, err) + // Test bonded + revoked validator fails + genesisState = makeGenesisState(genTxs[:1]) + val1 := stakeTypes.NewValidator(addr1, pk1, stakeTypes.Description{Moniker: "test #2"}) + val1.Jailed = true + val1.Status = sdk.Bonded + genesisState.StakeData.Validators = append(genesisState.StakeData.Validators, val1) + err = GaiaValidateGenesisState(genesisState) + require.NotNil(t, err) + // Test duplicate validator fails + val1.Jailed = false + genesisState = makeGenesisState(genTxs[:1]) + val2 := stakeTypes.NewValidator(addr1, pk1, stakeTypes.Description{Moniker: "test #3"}) + genesisState.StakeData.Validators = append(genesisState.StakeData.Validators, val1) + genesisState.StakeData.Validators = append(genesisState.StakeData.Validators, val2) + err = GaiaValidateGenesisState(genesisState) + require.NotNil(t, err) } From 173ed6a63d29a31679cb4a4eabbf8eb860dded35 Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Sun, 9 Sep 2018 08:34:09 -0700 Subject: [PATCH 78/93] Merge PR #2282: simulation: Switch the log method from a single string to string builders --- Makefile | 2 +- PENDING.md | 2 + cmd/gaia/app/sim_test.go | 11 ++- x/bank/simulation/invariants.go | 23 ++++--- x/bank/simulation/msgs.go | 28 ++++---- x/gov/simulation/invariants.go | 8 +-- x/gov/simulation/msgs.go | 31 +++++---- x/mock/simulation/random_simulate_blocks.go | 76 +++++++++------------ x/mock/simulation/types.go | 20 +++--- x/mock/simulation/util.go | 44 ++++++++++++ x/slashing/simulation/invariants.go | 8 +-- x/slashing/simulation/msgs.go | 5 +- x/stake/simulation/invariants.go | 34 ++++++--- x/stake/simulation/msgs.go | 29 ++++---- 14 files changed, 178 insertions(+), 143 deletions(-) diff --git a/Makefile b/Makefile index 2f23fd54fe..88ead03e6a 100644 --- a/Makefile +++ b/Makefile @@ -157,7 +157,7 @@ test_sim_gaia_nondeterminism: test_sim_gaia_fast: @echo "Running quick Gaia simulation. This may take several minutes..." - @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=150 -v -timeout 24h + @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=200 -v -timeout 24h test_sim_gaia_slow: @echo "Running full Gaia simulation. This may take awhile!" diff --git a/PENDING.md b/PENDING.md index a63b17c7e5..331d1fc852 100644 --- a/PENDING.md +++ b/PENDING.md @@ -40,6 +40,7 @@ BREAKING CHANGES * [x/slashing] [#2122](https://github.com/cosmos/cosmos-sdk/pull/2122) - Implement slashing period * [types] [\#2119](https://github.com/cosmos/cosmos-sdk/issues/2119) Parsed error messages and ABCI log errors to make them more human readable. * [simulation] Rename TestAndRunTx to Operation [#2153](https://github.com/cosmos/cosmos-sdk/pull/2153) + * [simulation] Remove log and testing.TB from Operation and Invariants, in favor of using errors \#2282 * [tools] Removed gocyclo [#2211](https://github.com/cosmos/cosmos-sdk/issues/2211) * [baseapp] Remove `SetTxDecoder` in favor of requiring the decoder be set in baseapp initialization. [#1441](https://github.com/cosmos/cosmos-sdk/issues/1441) @@ -104,6 +105,7 @@ IMPROVEMENTS * [store] Speedup IAVL iteration, and consequently everything that requires IAVL iteration. [#2143](https://github.com/cosmos/cosmos-sdk/issues/2143) * [store] \#1952, \#2281 Update IAVL dependency to v0.11.0 * [simulation] Make timestamps randomized [#2153](https://github.com/cosmos/cosmos-sdk/pull/2153) + * [simulation] Make logs not just pure strings, speeding it up by a large factor at greater block heights \#2282 * Tendermint diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 97de59a234..e809495fc6 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -14,7 +14,6 @@ import ( dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/libs/log" - "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" banksim "github.com/cosmos/cosmos-sdk/x/bank/simulation" "github.com/cosmos/cosmos-sdk/x/gov" @@ -108,12 +107,10 @@ func testAndRunTxs(app *GaiaApp) []simulation.Operation { func invariants(app *GaiaApp) []simulation.Invariant { return []simulation.Invariant{ - func(t *testing.T, baseapp *baseapp.BaseApp, log string) { - banksim.NonnegativeBalanceInvariant(app.accountMapper)(t, baseapp, log) - govsim.AllInvariants()(t, baseapp, log) - stakesim.AllInvariants(app.bankKeeper, app.stakeKeeper, app.accountMapper)(t, baseapp, log) - slashingsim.AllInvariants()(t, baseapp, log) - }, + banksim.NonnegativeBalanceInvariant(app.accountMapper), + govsim.AllInvariants(), + stakesim.AllInvariants(app.bankKeeper, app.stakeKeeper, app.accountMapper), + slashingsim.AllInvariants(), } } diff --git a/x/bank/simulation/invariants.go b/x/bank/simulation/invariants.go index 847288e1f1..20aa9570bf 100644 --- a/x/bank/simulation/invariants.go +++ b/x/bank/simulation/invariants.go @@ -1,10 +1,8 @@ package simulation import ( + "errors" "fmt" - "testing" - - "github.com/stretchr/testify/require" "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" @@ -16,25 +14,25 @@ import ( // NonnegativeBalanceInvariant checks that all accounts in the application have non-negative balances func NonnegativeBalanceInvariant(mapper auth.AccountMapper) simulation.Invariant { - return func(t *testing.T, app *baseapp.BaseApp, log string) { + return func(app *baseapp.BaseApp) error { ctx := app.NewContext(false, abci.Header{}) accts := mock.GetAllAccounts(mapper, ctx) for _, acc := range accts { coins := acc.GetCoins() - require.True(t, coins.IsNotNegative(), - fmt.Sprintf("%s has a negative denomination of %s\n%s", + if !coins.IsNotNegative() { + return fmt.Errorf("%s has a negative denomination of %s", acc.GetAddress().String(), - coins.String(), - log), - ) + coins.String()) + } } + return nil } } // TotalCoinsInvariant checks that the sum of the coins across all accounts // is what is expected func TotalCoinsInvariant(mapper auth.AccountMapper, totalSupplyFn func() sdk.Coins) simulation.Invariant { - return func(t *testing.T, app *baseapp.BaseApp, log string) { + return func(app *baseapp.BaseApp) error { ctx := app.NewContext(false, abci.Header{}) totalCoins := sdk.Coins{} @@ -45,6 +43,9 @@ func TotalCoinsInvariant(mapper auth.AccountMapper, totalSupplyFn func() sdk.Coi } mapper.IterateAccounts(ctx, chkAccount) - require.Equal(t, totalSupplyFn(), totalCoins, log) + if !totalSupplyFn().IsEqual(totalCoins) { + return errors.New("total calculated coins doesn't equal expected coins") + } + return nil } } diff --git a/x/bank/simulation/msgs.go b/x/bank/simulation/msgs.go index c53916a613..cefa2a460b 100644 --- a/x/bank/simulation/msgs.go +++ b/x/bank/simulation/msgs.go @@ -5,9 +5,6 @@ import ( "fmt" "math/big" "math/rand" - "testing" - - "github.com/stretchr/testify/require" "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" @@ -21,7 +18,7 @@ import ( // SimulateSingleInputMsgSend tests and runs a single msg send, with one input and one output, where both // accounts already exist. func SimulateSingleInputMsgSend(mapper auth.AccountMapper) simulation.Operation { - return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOps []simulation.FutureOperation, err sdk.Error) { + return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOps []simulation.FutureOperation, err error) { fromKey := simulation.RandomKey(r, keys) fromAddr := sdk.AccAddress(fromKey.PubKey().Address()) toKey := simulation.RandomKey(r, keys) @@ -51,14 +48,16 @@ func SimulateSingleInputMsgSend(mapper auth.AccountMapper) simulation.Operation initFromCoins[denomIndex].Denom, toAddr.String(), ) - log = fmt.Sprintf("%s\n%s", log, action) coins := sdk.Coins{{initFromCoins[denomIndex].Denom, amt}} var msg = bank.MsgSend{ Inputs: []bank.Input{bank.NewInput(fromAddr, coins)}, Outputs: []bank.Output{bank.NewOutput(toAddr, coins)}, } - sendAndVerifyMsgSend(tb, app, mapper, msg, ctx, log, []crypto.PrivKey{fromKey}) + goErr = sendAndVerifyMsgSend(app, mapper, msg, ctx, []crypto.PrivKey{fromKey}) + if goErr != nil { + return "", nil, goErr + } event("bank/sendAndVerifyMsgSend/ok") return action, nil, nil @@ -66,7 +65,7 @@ func SimulateSingleInputMsgSend(mapper auth.AccountMapper) simulation.Operation } // Sends and verifies the transition of a msg send. This fails if there are repeated inputs or outputs -func sendAndVerifyMsgSend(tb testing.TB, app *baseapp.BaseApp, mapper auth.AccountMapper, msg bank.MsgSend, ctx sdk.Context, log string, privkeys []crypto.PrivKey) { +func sendAndVerifyMsgSend(app *baseapp.BaseApp, mapper auth.AccountMapper, msg bank.MsgSend, ctx sdk.Context, privkeys []crypto.PrivKey) error { initialInputAddrCoins := make([]sdk.Coins, len(msg.Inputs)) initialOutputAddrCoins := make([]sdk.Coins, len(msg.Outputs)) AccountNumbers := make([]int64, len(msg.Inputs)) @@ -89,25 +88,22 @@ func sendAndVerifyMsgSend(tb testing.TB, app *baseapp.BaseApp, mapper auth.Accou res := app.Deliver(tx) if !res.IsOK() { // TODO: Do this in a more 'canonical' way - fmt.Println(res) - fmt.Println(log) - tb.FailNow() + return fmt.Errorf("Deliver failed %v", res) } for i := 0; i < len(msg.Inputs); i++ { terminalInputCoins := mapper.GetAccount(ctx, msg.Inputs[i].Address).GetCoins() - require.Equal(tb, - initialInputAddrCoins[i].Minus(msg.Inputs[i].Coins), - terminalInputCoins, - fmt.Sprintf("Input #%d had an incorrect amount of coins\n%s", i, log), - ) + if !initialInputAddrCoins[i].Minus(msg.Inputs[i].Coins).IsEqual(terminalInputCoins) { + return fmt.Errorf("input #%d had an incorrect amount of coins", i) + } } for i := 0; i < len(msg.Outputs); i++ { terminalOutputCoins := mapper.GetAccount(ctx, msg.Outputs[i].Address).GetCoins() if !terminalOutputCoins.IsEqual(initialOutputAddrCoins[i].Plus(msg.Outputs[i].Coins)) { - tb.Fatalf("Output #%d had an incorrect amount of coins\n%s", i, log) + return fmt.Errorf("output #%d had an incorrect amount of coins", i) } } + return nil } func randPositiveInt(r *rand.Rand, max sdk.Int) (sdk.Int, error) { diff --git a/x/gov/simulation/invariants.go b/x/gov/simulation/invariants.go index e9275f3c1a..6d5f419184 100644 --- a/x/gov/simulation/invariants.go +++ b/x/gov/simulation/invariants.go @@ -1,19 +1,15 @@ package simulation import ( - "testing" - - "github.com/stretchr/testify/require" - "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/x/mock/simulation" ) // AllInvariants tests all governance invariants func AllInvariants() simulation.Invariant { - return func(t *testing.T, app *baseapp.BaseApp, log string) { + return func(app *baseapp.BaseApp) error { // TODO Add some invariants! // Checking proposal queues, no passed-but-unexecuted proposals, etc. - require.Nil(t, nil) + return nil } } diff --git a/x/gov/simulation/msgs.go b/x/gov/simulation/msgs.go index 0be299e496..399f735120 100644 --- a/x/gov/simulation/msgs.go +++ b/x/gov/simulation/msgs.go @@ -4,7 +4,6 @@ import ( "fmt" "math" "math/rand" - "testing" "github.com/tendermint/tendermint/crypto" @@ -45,10 +44,13 @@ func SimulateSubmittingVotingAndSlashingForProposal(k gov.Keeper, sk stake.Keepe }) statePercentageArray := []float64{1, .9, .75, .4, .15, 0} curNumVotesState := 1 - return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOps []simulation.FutureOperation, err sdk.Error) { + return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOps []simulation.FutureOperation, err error) { // 1) submit proposal now sender := simulation.RandomKey(r, keys) - msg := simulationCreateMsgSubmitProposal(tb, r, sender, log) + msg, err := simulationCreateMsgSubmitProposal(r, sender) + if err != nil { + return "", nil, err + } action = simulateHandleMsgSubmitProposal(msg, sk, handler, ctx, event) proposalID := k.GetLastProposalID(ctx) // 2) Schedule operations for votes @@ -77,9 +79,12 @@ func SimulateSubmittingVotingAndSlashingForProposal(k gov.Keeper, sk stake.Keepe // Note: Currently doesn't ensure that the proposal txt is in JSON form func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.Operation { handler := gov.NewHandler(k) - return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOps []simulation.FutureOperation, err sdk.Error) { + return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOps []simulation.FutureOperation, err error) { sender := simulation.RandomKey(r, keys) - msg := simulationCreateMsgSubmitProposal(tb, r, sender, log) + msg, err := simulationCreateMsgSubmitProposal(r, sender) + if err != nil { + return "", nil, err + } action = simulateHandleMsgSubmitProposal(msg, sk, handler, ctx, event) return action, nil, nil } @@ -100,10 +105,10 @@ func simulateHandleMsgSubmitProposal(msg gov.MsgSubmitProposal, sk stake.Keeper, return action } -func simulationCreateMsgSubmitProposal(tb testing.TB, r *rand.Rand, sender crypto.PrivKey, log string) gov.MsgSubmitProposal { +func simulationCreateMsgSubmitProposal(r *rand.Rand, sender crypto.PrivKey) (msg gov.MsgSubmitProposal, err error) { addr := sdk.AccAddress(sender.PubKey().Address()) deposit := randomDeposit(r) - msg := gov.NewMsgSubmitProposal( + msg = gov.NewMsgSubmitProposal( simulation.RandStringOfLength(r, 5), simulation.RandStringOfLength(r, 5), gov.ProposalTypeText, @@ -111,14 +116,14 @@ func simulationCreateMsgSubmitProposal(tb testing.TB, r *rand.Rand, sender crypt deposit, ) if msg.ValidateBasic() != nil { - tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) + err = fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) } - return msg + return } // SimulateMsgDeposit func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation { - return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { + return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOp []simulation.FutureOperation, err error) { key := simulation.RandomKey(r, keys) addr := sdk.AccAddress(key.PubKey().Address()) proposalID, ok := randomProposalID(r, k, ctx) @@ -128,7 +133,7 @@ func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation { deposit := randomDeposit(r) msg := gov.NewMsgDeposit(addr, proposalID, deposit) if msg.ValidateBasic() != nil { - tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) + return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) } ctx, write := ctx.CacheContext() result := gov.NewHandler(k)(ctx, msg) @@ -153,7 +158,7 @@ func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.Operation { // nolint: unparam func operationSimulateMsgVote(k gov.Keeper, sk stake.Keeper, key crypto.PrivKey, proposalID int64) simulation.Operation { - return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { + return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOp []simulation.FutureOperation, err error) { if key == nil { key = simulation.RandomKey(r, keys) } @@ -168,7 +173,7 @@ func operationSimulateMsgVote(k gov.Keeper, sk stake.Keeper, key crypto.PrivKey, option := randomVotingOption(r) msg := gov.NewMsgVote(addr, proposalID, option) if msg.ValidateBasic() != nil { - tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) + return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) } ctx, write := ctx.CacheContext() result := gov.NewHandler(k)(ctx, msg) diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index b7a911e065..08b70d1018 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -8,6 +8,7 @@ import ( "os" "os/signal" "sort" + "strings" "syscall" "testing" "time" @@ -57,11 +58,10 @@ func SimulateFromSeed( invariants []Invariant, numBlocks int, blockSize int, commit bool, ) { testingMode, t, b := getTestingMode(tb) - log := fmt.Sprintf("Starting SimulateFromSeed with randomness created with seed %d", int(seed)) + fmt.Printf("Starting SimulateFromSeed with randomness created with seed %d\n", int(seed)) r := rand.New(rand.NewSource(seed)) timestamp := randTimestamp(r) - log = updateLog(testingMode, log, "Starting the simulation from time %v, unixtime %v", timestamp.UTC().Format(time.UnixDate), timestamp.Unix()) - fmt.Printf("%s\n", log) + fmt.Printf("Starting the simulation from time %v, unixtime %v\n", timestamp.UTC().Format(time.UnixDate), timestamp.Unix()) timeDiff := maxTimePerBlock - minTimePerBlock keys, accs := mock.GeneratePrivKeyAddressPairsFromRand(r, numKeys) @@ -69,7 +69,6 @@ func SimulateFromSeed( // Setup event stats events := make(map[string]uint) event := func(what string) { - log = updateLog(testingMode, log, "event - %s", what) events[what]++ } @@ -91,14 +90,18 @@ func SimulateFromSeed( var pastTimes []time.Time var pastSigningValidators [][]abci.SigningValidator - request := RandomRequestBeginBlock(r, validators, livenessTransitionMatrix, evidenceFraction, pastTimes, pastSigningValidators, event, header, log) + request := RandomRequestBeginBlock(r, validators, livenessTransitionMatrix, evidenceFraction, pastTimes, pastSigningValidators, event, header) // These are operations which have been queued by previous operations operationQueue := make(map[int][]Operation) + var blockLogBuilders []*strings.Builder if !testingMode { b.ResetTimer() + } else { + blockLogBuilders = make([]*strings.Builder, numBlocks) } - blockSimulator := createBlockSimulator(testingMode, tb, t, event, invariants, ops, operationQueue, numBlocks) + displayLogs := logPrinter(testingMode, blockLogBuilders) + blockSimulator := createBlockSimulator(testingMode, tb, t, event, invariants, ops, operationQueue, numBlocks, displayLogs) for i := 0; i < numBlocks; i++ { // Log the header time for future lookup @@ -107,38 +110,38 @@ func SimulateFromSeed( // Run the BeginBlock handler app.BeginBlock(request) - log = updateLog(testingMode, log, "BeginBlock") if testingMode { // Make sure invariants hold at beginning of block - AssertAllInvariants(t, app, invariants, log) + assertAllInvariants(t, app, invariants, displayLogs) } + logWriter := addLogMessage(testingMode, blockLogBuilders, i) ctx := app.NewContext(false, header) thisBlockSize := getBlockSize(r, blockSize) // Run queued operations. Ignores blocksize if blocksize is too small - log, numQueuedOpsRan := runQueuedOperations(operationQueue, int(header.Height), tb, r, app, ctx, keys, log, event) + numQueuedOpsRan := runQueuedOperations(operationQueue, int(header.Height), tb, r, app, ctx, keys, logWriter, displayLogs, event) opCount += numQueuedOpsRan thisBlockSize -= numQueuedOpsRan - log, operations := blockSimulator(thisBlockSize, r, app, ctx, keys, log, header) + operations := blockSimulator(thisBlockSize, r, app, ctx, keys, header, logWriter) opCount += operations res := app.EndBlock(abci.RequestEndBlock{}) header.Height++ header.Time = header.Time.Add(time.Duration(minTimePerBlock) * time.Second).Add(time.Duration(int64(r.Intn(int(timeDiff)))) * time.Second) - log = updateLog(testingMode, log, "EndBlock") + logWriter("EndBlock") if testingMode { // Make sure invariants hold at end of block - AssertAllInvariants(t, app, invariants, log) + assertAllInvariants(t, app, invariants, displayLogs) } if commit { app.Commit() } // Generate a random RequestBeginBlock with the current validator set for the next block - request = RandomRequestBeginBlock(r, validators, livenessTransitionMatrix, evidenceFraction, pastTimes, pastSigningValidators, event, header, log) + request = RandomRequestBeginBlock(r, validators, livenessTransitionMatrix, evidenceFraction, pastTimes, pastSigningValidators, event, header) // Update the validator set validators = updateValidators(tb, r, validators, res.ValidatorUpdates, event) @@ -150,21 +153,22 @@ func SimulateFromSeed( // Returns a function to simulate blocks. Written like this to avoid constant parameters being passed everytime, to minimize // memory overhead -func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, event func(string), invariants []Invariant, ops []Operation, operationQueue map[int][]Operation, totalNumBlocks int) func( - blocksize int, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, privKeys []crypto.PrivKey, log string, header abci.Header) (updatedLog string, opCount int) { +func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, event func(string), invariants []Invariant, ops []Operation, operationQueue map[int][]Operation, totalNumBlocks int, displayLogs func()) func( + blocksize int, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, privKeys []crypto.PrivKey, header abci.Header, logWriter func(string)) (opCount int) { return func(blocksize int, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, - keys []crypto.PrivKey, log string, header abci.Header) (updatedLog string, opCount int) { + keys []crypto.PrivKey, header abci.Header, logWriter func(string)) (opCount int) { for j := 0; j < blocksize; j++ { - logUpdate, futureOps, err := ops[r.Intn(len(ops))](tb, r, app, ctx, keys, log, event) - log = updateLog(testingMode, log, logUpdate) + logUpdate, futureOps, err := ops[r.Intn(len(ops))](r, app, ctx, keys, event) if err != nil { - tb.Fatalf("error on operation %d within block %d, %v, log %s", header.Height, opCount, err, log) + displayLogs() + tb.Fatalf("error on operation %d within block %d, %v", header.Height, opCount, err) } + logWriter(logUpdate) queueOperations(operationQueue, futureOps) if testingMode { if onOperation { - AssertAllInvariants(t, app, invariants, log) + assertAllInvariants(t, app, invariants, displayLogs) } if opCount%50 == 0 { fmt.Printf("\rSimulating... block %d/%d, operation %d/%d. ", header.Height, totalNumBlocks, opCount, blocksize) @@ -172,7 +176,7 @@ func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, event f } opCount++ } - return log, opCount + return opCount } } @@ -187,14 +191,6 @@ func getTestingMode(tb testing.TB) (testingMode bool, t *testing.T, b *testing.B return } -func updateLog(testingMode bool, log string, update string, args ...interface{}) (updatedLog string) { - if testingMode { - update = fmt.Sprintf(update, args...) - return fmt.Sprintf("%s\n%s", log, update) - } - return "" -} - func getBlockSize(r *rand.Rand, blockSize int) int { load := r.Float64() switch { @@ -223,25 +219,24 @@ func queueOperations(queuedOperations map[int][]Operation, futureOperations []Fu // nolint: errcheck func runQueuedOperations(queueOperations map[int][]Operation, height int, tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, - privKeys []crypto.PrivKey, log string, event func(string)) (updatedLog string, numOpsRan int) { - updatedLog = log + privKeys []crypto.PrivKey, logWriter func(string), displayLogs func(), event func(string)) (numOpsRan int) { if queuedOps, ok := queueOperations[height]; ok { numOps := len(queuedOps) for i := 0; i < numOps; i++ { // For now, queued operations cannot queue more operations. // If a need arises for us to support queued messages to queue more messages, this can // be changed. - logUpdate, _, err := queuedOps[i](tb, r, app, ctx, privKeys, updatedLog, event) - updatedLog = fmt.Sprintf("%s\n%s", updatedLog, logUpdate) + logUpdate, _, err := queuedOps[i](r, app, ctx, privKeys, event) + logWriter(logUpdate) if err != nil { - fmt.Fprint(os.Stderr, updatedLog) + displayLogs() tb.FailNow() } } delete(queueOperations, height) - return updatedLog, numOps + return numOps } - return log, 0 + return 0 } func getKeys(validators map[string]mockValidator) []string { @@ -258,7 +253,7 @@ func getKeys(validators map[string]mockValidator) []string { // RandomRequestBeginBlock generates a list of signing validators according to the provided list of validators, signing fraction, and evidence fraction // nolint: unparam func RandomRequestBeginBlock(r *rand.Rand, validators map[string]mockValidator, livenessTransitions TransitionMatrix, evidenceFraction float64, - pastTimes []time.Time, pastSigningValidators [][]abci.SigningValidator, event func(string), header abci.Header, log string) abci.RequestBeginBlock { + pastTimes []time.Time, pastSigningValidators [][]abci.SigningValidator, event func(string), header abci.Header) abci.RequestBeginBlock { if len(validators) == 0 { return abci.RequestBeginBlock{Header: header} } @@ -326,13 +321,6 @@ func RandomRequestBeginBlock(r *rand.Rand, validators map[string]mockValidator, } } -// AssertAllInvariants asserts a list of provided invariants against application state -func AssertAllInvariants(t *testing.T, app *baseapp.BaseApp, tests []Invariant, log string) { - for i := 0; i < len(tests); i++ { - tests[i](t, app, log) - } -} - // updateValidators mimicks Tendermint's update logic // nolint: unparam func updateValidators(tb testing.TB, r *rand.Rand, current map[string]mockValidator, updates []abci.Validator, event func(string)) map[string]mockValidator { diff --git a/x/mock/simulation/types.go b/x/mock/simulation/types.go index 2f91a4f263..25fb1a6e8a 100644 --- a/x/mock/simulation/types.go +++ b/x/mock/simulation/types.go @@ -2,7 +2,6 @@ package simulation import ( "math/rand" - "testing" "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" @@ -22,18 +21,18 @@ type ( // // Operations can optionally provide a list of "FutureOperations" to run later // These will be ran at the beginning of the corresponding block. - Operation func( - tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, - privKeys []crypto.PrivKey, log string, event func(string), - ) (action string, futureOperations []FutureOperation, err sdk.Error) + Operation func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + privKeys []crypto.PrivKey, event func(string), + ) (action string, futureOperations []FutureOperation, err error) // RandSetup performs the random setup the mock module needs. RandSetup func(r *rand.Rand, privKeys []crypto.PrivKey) // An Invariant is a function which tests a particular invariant. - // If the invariant has been broken, the function should halt the - // test and output the log. - Invariant func(t *testing.T, app *baseapp.BaseApp, log string) + // If the invariant has been broken, it should return an error + // containing a descriptive message about what happened. + // The simulator will then halt and print the logs. + Invariant func(app *baseapp.BaseApp) error mockValidator struct { val abci.Validator @@ -54,9 +53,10 @@ type ( // a given invariant if the mock application's last block modulo the given // period is congruent to the given offset. func PeriodicInvariant(invariant Invariant, period int, offset int) Invariant { - return func(t *testing.T, app *baseapp.BaseApp, log string) { + return func(app *baseapp.BaseApp) error { if int(app.LastBlockHeight())%period == offset { - invariant(t, app, log) + return invariant(app) } + return nil } } diff --git a/x/mock/simulation/util.go b/x/mock/simulation/util.go index 1d64ba30dd..d4e1ca1a76 100644 --- a/x/mock/simulation/util.go +++ b/x/mock/simulation/util.go @@ -4,9 +4,12 @@ import ( "fmt" "math/rand" "sort" + "strings" + "testing" "github.com/tendermint/tendermint/crypto" + "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -62,3 +65,44 @@ func RandomKey(r *rand.Rand, keys []crypto.PrivKey) crypto.PrivKey { func RandomAmount(r *rand.Rand, max sdk.Int) sdk.Int { return sdk.NewInt(int64(r.Intn(int(max.Int64())))) } + +// Builds a function to add logs for this particular block +func addLogMessage(testingmode bool, blockLogBuilders []*strings.Builder, height int) func(string) { + if testingmode { + blockLogBuilders[height] = &strings.Builder{} + return func(x string) { + (*blockLogBuilders[height]).WriteString(x) + (*blockLogBuilders[height]).WriteString("\n") + } + } + return func(x string) {} +} + +// assertAllInvariants asserts a list of provided invariants against application state +func assertAllInvariants(t *testing.T, app *baseapp.BaseApp, invariants []Invariant, displayLogs func()) { + for i := 0; i < len(invariants); i++ { + err := invariants[i](app) + if err != nil { + fmt.Println(err.Error()) + displayLogs() + t.Fatal() + } + } +} + +// Creates a function to print out the logs +func logPrinter(testingmode bool, logs []*strings.Builder) func() { + if testingmode { + return func() { + for i := 0; i < len(logs); i++ { + // We're passed the last created block + if logs[i] == nil { + return + } + fmt.Printf("Begin block %d\n", i) + fmt.Println((*logs[i]).String()) + } + } + } + return func() {} +} diff --git a/x/slashing/simulation/invariants.go b/x/slashing/simulation/invariants.go index 7352aa5032..637a8064bc 100644 --- a/x/slashing/simulation/invariants.go +++ b/x/slashing/simulation/invariants.go @@ -1,18 +1,14 @@ package simulation import ( - "testing" - - "github.com/stretchr/testify/require" - "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/x/mock/simulation" ) // AllInvariants tests all slashing invariants func AllInvariants() simulation.Invariant { - return func(t *testing.T, app *baseapp.BaseApp, log string) { + return func(app *baseapp.BaseApp) error { // TODO Any invariants to check here? - require.Nil(t, nil) + return nil } } diff --git a/x/slashing/simulation/msgs.go b/x/slashing/simulation/msgs.go index 9cbb2c48a9..da9340baf4 100644 --- a/x/slashing/simulation/msgs.go +++ b/x/slashing/simulation/msgs.go @@ -3,7 +3,6 @@ package simulation import ( "fmt" "math/rand" - "testing" "github.com/tendermint/tendermint/crypto" @@ -15,12 +14,12 @@ import ( // SimulateMsgUnjail func SimulateMsgUnjail(k slashing.Keeper) simulation.Operation { - return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { + return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOp []simulation.FutureOperation, err error) { key := simulation.RandomKey(r, keys) address := sdk.ValAddress(key.PubKey().Address()) msg := slashing.NewMsgUnjail(address) if msg.ValidateBasic() != nil { - tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) + return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) } ctx, write := ctx.CacheContext() result := slashing.NewHandler(k)(ctx, msg) diff --git a/x/stake/simulation/invariants.go b/x/stake/simulation/invariants.go index 8f218f45be..2ab0717042 100644 --- a/x/stake/simulation/invariants.go +++ b/x/stake/simulation/invariants.go @@ -1,9 +1,7 @@ package simulation import ( - "testing" - - "github.com/stretchr/testify/require" + "fmt" "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" @@ -17,17 +15,24 @@ import ( // AllInvariants runs all invariants of the stake module. // Currently: total supply, positive power func AllInvariants(ck bank.Keeper, k stake.Keeper, am auth.AccountMapper) simulation.Invariant { - return func(t *testing.T, app *baseapp.BaseApp, log string) { - SupplyInvariants(ck, k, am)(t, app, log) - PositivePowerInvariant(k)(t, app, log) - ValidatorSetInvariant(k)(t, app, log) + return func(app *baseapp.BaseApp) error { + err := SupplyInvariants(ck, k, am)(app) + if err != nil { + return err + } + err = PositivePowerInvariant(k)(app) + if err != nil { + return err + } + err = ValidatorSetInvariant(k)(app) + return err } } // SupplyInvariants checks that the total supply reflects all held loose tokens, bonded tokens, and unbonding delegations // nolint: unparam func SupplyInvariants(ck bank.Keeper, k stake.Keeper, am auth.AccountMapper) simulation.Invariant { - return func(t *testing.T, app *baseapp.BaseApp, log string) { + return func(app *baseapp.BaseApp) error { ctx := app.NewContext(false, abci.Header{}) //pool := k.GetPool(ctx) @@ -64,23 +69,30 @@ func SupplyInvariants(ck bank.Keeper, k stake.Keeper, am auth.AccountMapper) sim // pool.BondedTokens.RoundInt64(), bonded.RoundInt64(), log) // TODO Inflation check on total supply + return nil } } // PositivePowerInvariant checks that all stored validators have > 0 power func PositivePowerInvariant(k stake.Keeper) simulation.Invariant { - return func(t *testing.T, app *baseapp.BaseApp, log string) { + return func(app *baseapp.BaseApp) error { ctx := app.NewContext(false, abci.Header{}) + var err error k.IterateValidatorsBonded(ctx, func(_ int64, validator sdk.Validator) bool { - require.True(t, validator.GetPower().GT(sdk.ZeroDec()), "validator with non-positive power stored") + if !validator.GetPower().GT(sdk.ZeroDec()) { + err = fmt.Errorf("validator with non-positive power stored. (pubkey %v)", validator.GetPubKey()) + return true + } return false }) + return err } } // ValidatorSetInvariant checks equivalence of Tendermint validator set and SDK validator set func ValidatorSetInvariant(k stake.Keeper) simulation.Invariant { - return func(t *testing.T, app *baseapp.BaseApp, log string) { + return func(app *baseapp.BaseApp) error { // TODO + return nil } } diff --git a/x/stake/simulation/msgs.go b/x/stake/simulation/msgs.go index 2644601324..5b2bc1ee81 100644 --- a/x/stake/simulation/msgs.go +++ b/x/stake/simulation/msgs.go @@ -3,7 +3,6 @@ package simulation import ( "fmt" "math/rand" - "testing" "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" @@ -18,7 +17,7 @@ import ( // SimulateMsgCreateValidator func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation.Operation { handler := stake.NewHandler(k) - return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { + return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOp []simulation.FutureOperation, err error) { denom := k.GetParams(ctx).BondDenom description := stake.Description{ @@ -42,7 +41,7 @@ func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation Delegation: sdk.NewCoin(denom, amount), } if msg.ValidateBasic() != nil { - tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) + return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) } ctx, write := ctx.CacheContext() result := handler(ctx, msg) @@ -59,7 +58,7 @@ func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation // SimulateMsgEditValidator func SimulateMsgEditValidator(k stake.Keeper) simulation.Operation { handler := stake.NewHandler(k) - return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { + return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOp []simulation.FutureOperation, err error) { description := stake.Description{ Moniker: simulation.RandStringOfLength(r, 10), @@ -75,7 +74,7 @@ func SimulateMsgEditValidator(k stake.Keeper) simulation.Operation { ValidatorAddr: address, } if msg.ValidateBasic() != nil { - tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) + return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) } ctx, write := ctx.CacheContext() result := handler(ctx, msg) @@ -91,7 +90,7 @@ func SimulateMsgEditValidator(k stake.Keeper) simulation.Operation { // SimulateMsgDelegate func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operation { handler := stake.NewHandler(k) - return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { + return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOp []simulation.FutureOperation, err error) { denom := k.GetParams(ctx).BondDenom validatorKey := simulation.RandomKey(r, keys) @@ -111,7 +110,7 @@ func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operat Delegation: sdk.NewCoin(denom, amount), } if msg.ValidateBasic() != nil { - tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) + return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) } ctx, write := ctx.CacheContext() result := handler(ctx, msg) @@ -127,7 +126,7 @@ func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operat // SimulateMsgBeginUnbonding func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation.Operation { handler := stake.NewHandler(k) - return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { + return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOp []simulation.FutureOperation, err error) { denom := k.GetParams(ctx).BondDenom validatorKey := simulation.RandomKey(r, keys) @@ -147,7 +146,7 @@ func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation. SharesAmount: sdk.NewDecFromInt(amount), } if msg.ValidateBasic() != nil { - tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) + return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) } ctx, write := ctx.CacheContext() result := handler(ctx, msg) @@ -163,7 +162,7 @@ func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation. // SimulateMsgCompleteUnbonding func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.Operation { handler := stake.NewHandler(k) - return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { + return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOp []simulation.FutureOperation, err error) { validatorKey := simulation.RandomKey(r, keys) validatorAddress := sdk.ValAddress(validatorKey.PubKey().Address()) @@ -174,7 +173,7 @@ func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.Operation { ValidatorAddr: validatorAddress, } if msg.ValidateBasic() != nil { - tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) + return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) } ctx, write := ctx.CacheContext() result := handler(ctx, msg) @@ -190,7 +189,7 @@ func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.Operation { // SimulateMsgBeginRedelegate func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operation { handler := stake.NewHandler(k) - return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { + return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOp []simulation.FutureOperation, err error) { denom := k.GetParams(ctx).BondDenom sourceValidatorKey := simulation.RandomKey(r, keys) @@ -214,7 +213,7 @@ func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation SharesAmount: sdk.NewDecFromInt(amount), } if msg.ValidateBasic() != nil { - tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) + return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) } ctx, write := ctx.CacheContext() result := handler(ctx, msg) @@ -230,7 +229,7 @@ func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation // SimulateMsgCompleteRedelegate func SimulateMsgCompleteRedelegate(k stake.Keeper) simulation.Operation { handler := stake.NewHandler(k) - return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { + return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOp []simulation.FutureOperation, err error) { validatorSrcKey := simulation.RandomKey(r, keys) validatorSrcAddress := sdk.ValAddress(validatorSrcKey.PubKey().Address()) @@ -244,7 +243,7 @@ func SimulateMsgCompleteRedelegate(k stake.Keeper) simulation.Operation { ValidatorDstAddr: validatorDstAddress, } if msg.ValidateBasic() != nil { - tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log) + return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) } ctx, write := ctx.CacheContext() result := handler(ctx, msg) From e13cdc02606eb32d23fe94e05590b4e6914201d4 Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk Date: Mon, 10 Sep 2018 14:25:34 -0400 Subject: [PATCH 79/93] Merge PR #2146: x/bank: Keeper Interfaces * Update banking module to implement and use keeper interfaces * Cleanup/consolidate x/bank keeper interface --- cmd/gaia/app/app.go | 2 +- cmd/gaia/cmd/gaiadebug/hack.go | 2 +- docs/sdk/core/app3.md | 4 +- docs/sdk/core/examples/app3.go | 2 +- docs/sdk/core/examples/app4.go | 2 +- .../simple-governance/app-constructor.md | 2 +- examples/basecoin/app/app.go | 2 +- examples/democoin/app/app.go | 2 +- examples/democoin/x/cool/app_test.go | 2 +- examples/democoin/x/cool/keeper_test.go | 2 +- examples/democoin/x/pow/app_test.go | 2 +- examples/democoin/x/pow/handler_test.go | 2 +- examples/democoin/x/pow/keeper_test.go | 2 +- .../democoin/x/simplestake/keeper_test.go | 4 +- store/transientstore.go | 2 +- x/bank/bench_test.go | 2 +- x/bank/keeper.go | 103 +++++++++++++----- x/bank/keeper_test.go | 10 +- x/bank/simulation/sim_test.go | 2 +- x/gov/simulation/sim_test.go | 2 +- x/gov/test_common.go | 2 +- x/ibc/app_test.go | 2 +- x/ibc/ibc_test.go | 2 +- x/slashing/app_test.go | 2 +- x/slashing/test_common.go | 2 +- x/stake/app_test.go | 2 +- x/stake/keeper/test_common.go | 2 +- x/stake/simulation/sim_test.go | 2 +- 28 files changed, 108 insertions(+), 61 deletions(-) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 14ed1b2c17..c80da0bd04 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -89,7 +89,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio ) // add handlers - app.bankKeeper = bank.NewKeeper(app.accountMapper) + app.bankKeeper = bank.NewBaseKeeper(app.accountMapper) app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace)) app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams) app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace)) diff --git a/cmd/gaia/cmd/gaiadebug/hack.go b/cmd/gaia/cmd/gaiadebug/hack.go index a321a50823..b2f1183b3e 100644 --- a/cmd/gaia/cmd/gaiadebug/hack.go +++ b/cmd/gaia/cmd/gaiadebug/hack.go @@ -173,7 +173,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.BaseAp ) // add handlers - app.bankKeeper = bank.NewKeeper(app.accountMapper) + app.bankKeeper = bank.NewBaseKeeper(app.accountMapper) app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace)) app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams) app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace)) diff --git a/docs/sdk/core/app3.md b/docs/sdk/core/app3.md index fea42d449c..b84313adc5 100644 --- a/docs/sdk/core/app3.md +++ b/docs/sdk/core/app3.md @@ -285,7 +285,7 @@ it can't increment sequence numbers, change PubKeys, or otherwise. A `bank.Keeper` is easily instantiated from an `AccountMapper`: ```go -bankKeeper = bank.NewKeeper(accountMapper) +bankKeeper = bank.NewBaseKeeper(accountMapper) ``` We can then use it within a handler, instead of working directly with the @@ -336,7 +336,7 @@ func NewApp3(logger log.Logger, db dbm.DB) *bapp.BaseApp { // Set various mappers/keepers to interact easily with underlying stores accountMapper := auth.NewAccountMapper(cdc, keyAccount, auth.ProtoBaseAccount) - bankKeeper := bank.NewKeeper(accountMapper) + bankKeeper := bank.NewBaseKeeper(accountMapper) feeKeeper := auth.NewFeeCollectionKeeper(cdc, keyFees) app.SetAnteHandler(auth.NewAnteHandler(accountMapper, feeKeeper)) diff --git a/docs/sdk/core/examples/app3.go b/docs/sdk/core/examples/app3.go index a423e37435..787c75d96e 100644 --- a/docs/sdk/core/examples/app3.go +++ b/docs/sdk/core/examples/app3.go @@ -31,7 +31,7 @@ func NewApp3(logger log.Logger, db dbm.DB) *bapp.BaseApp { // Set various mappers/keepers to interact easily with underlying stores accountMapper := auth.NewAccountMapper(cdc, keyAccount, auth.ProtoBaseAccount) - bankKeeper := bank.NewKeeper(accountMapper) + bankKeeper := bank.NewBaseKeeper(accountMapper) feeKeeper := auth.NewFeeCollectionKeeper(cdc, keyFees) app.SetAnteHandler(auth.NewAnteHandler(accountMapper, feeKeeper)) diff --git a/docs/sdk/core/examples/app4.go b/docs/sdk/core/examples/app4.go index be4e5f4f4a..620913bb69 100644 --- a/docs/sdk/core/examples/app4.go +++ b/docs/sdk/core/examples/app4.go @@ -29,7 +29,7 @@ func NewApp4(logger log.Logger, db dbm.DB) *bapp.BaseApp { // Set various mappers/keepers to interact easily with underlying stores accountMapper := auth.NewAccountMapper(cdc, keyAccount, auth.ProtoBaseAccount) - bankKeeper := bank.NewKeeper(accountMapper) + bankKeeper := bank.NewBaseKeeper(accountMapper) // TODO keyFees := sdk.NewKVStoreKey("fee") diff --git a/docs/sdk/sdk-by-examples/simple-governance/app-constructor.md b/docs/sdk/sdk-by-examples/simple-governance/app-constructor.md index 76c8a7a144..149e97277c 100644 --- a/docs/sdk/sdk-by-examples/simple-governance/app-constructor.md +++ b/docs/sdk/sdk-by-examples/simple-governance/app-constructor.md @@ -33,7 +33,7 @@ var cdc = MakeCodec() - Instantiate the keepers. Note that keepers generally need access to other module's keepers. In this case, make sure you only pass an instance of the keeper for the functionality that is needed. If a keeper only needs to read in another module's store, a read-only keeper should be passed to it. ```go -app.bankKeeper = bank.NewKeeper(app.accountMapper) +app.bankKeeper = bank.NewBaseKeeper(app.accountMapper) app.stakeKeeper = simplestake.NewKeeper(app.capKeyStakingStore, app.bankKeeper,app.RegisterCodespace(simplestake.DefaultCodespace)) app.simpleGovKeeper = simpleGov.NewKeeper(app.capKeySimpleGovStore, app.bankKeeper, app.stakeKeeper, app.RegisterCodespace(simpleGov.DefaultCodespace)) ``` diff --git a/examples/basecoin/app/app.go b/examples/basecoin/app/app.go index 001d05d3a5..6330e9f31e 100644 --- a/examples/basecoin/app/app.go +++ b/examples/basecoin/app/app.go @@ -67,7 +67,7 @@ func NewBasecoinApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.Ba return &types.AppAccount{} }, ) - app.bankKeeper = bank.NewKeeper(app.accountMapper) + app.bankKeeper = bank.NewBaseKeeper(app.accountMapper) app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace)) // register message routes diff --git a/examples/democoin/app/app.go b/examples/democoin/app/app.go index a7078a3b15..e66dc0cb3d 100644 --- a/examples/democoin/app/app.go +++ b/examples/democoin/app/app.go @@ -75,7 +75,7 @@ func NewDemocoinApp(logger log.Logger, db dbm.DB) *DemocoinApp { ) // Add handlers. - app.bankKeeper = bank.NewKeeper(app.accountMapper) + app.bankKeeper = bank.NewBaseKeeper(app.accountMapper) app.coolKeeper = cool.NewKeeper(app.capKeyMainStore, app.bankKeeper, app.RegisterCodespace(cool.DefaultCodespace)) app.powKeeper = pow.NewKeeper(app.capKeyPowStore, pow.NewConfig("pow", int64(1)), app.bankKeeper, app.RegisterCodespace(pow.DefaultCodespace)) app.ibcMapper = ibc.NewMapper(app.cdc, app.capKeyIBCStore, app.RegisterCodespace(ibc.DefaultCodespace)) diff --git a/examples/democoin/x/cool/app_test.go b/examples/democoin/x/cool/app_test.go index 9e1aa776e4..8d778045ee 100644 --- a/examples/democoin/x/cool/app_test.go +++ b/examples/democoin/x/cool/app_test.go @@ -49,7 +49,7 @@ func getMockApp(t *testing.T) *mock.App { RegisterWire(mapp.Cdc) keyCool := sdk.NewKVStoreKey("cool") - bankKeeper := bank.NewKeeper(mapp.AccountMapper) + bankKeeper := bank.NewBaseKeeper(mapp.AccountMapper) keeper := NewKeeper(keyCool, bankKeeper, mapp.RegisterCodespace(DefaultCodespace)) mapp.Router().AddRoute("cool", NewHandler(keeper)) diff --git a/examples/democoin/x/cool/keeper_test.go b/examples/democoin/x/cool/keeper_test.go index ab59ea6101..50b38fc3ee 100644 --- a/examples/democoin/x/cool/keeper_test.go +++ b/examples/democoin/x/cool/keeper_test.go @@ -31,7 +31,7 @@ func TestCoolKeeper(t *testing.T) { am := auth.NewAccountMapper(cdc, capKey, auth.ProtoBaseAccount) ctx := sdk.NewContext(ms, abci.Header{}, false, nil) - ck := bank.NewKeeper(am) + ck := bank.NewBaseKeeper(am) keeper := NewKeeper(capKey, ck, DefaultCodespace) err := InitGenesis(ctx, keeper, Genesis{"icy"}) diff --git a/examples/democoin/x/pow/app_test.go b/examples/democoin/x/pow/app_test.go index 2aa4ea9b0a..de8642e4c3 100644 --- a/examples/democoin/x/pow/app_test.go +++ b/examples/democoin/x/pow/app_test.go @@ -25,7 +25,7 @@ func getMockApp(t *testing.T) *mock.App { RegisterWire(mapp.Cdc) keyPOW := sdk.NewKVStoreKey("pow") - bankKeeper := bank.NewKeeper(mapp.AccountMapper) + bankKeeper := bank.NewBaseKeeper(mapp.AccountMapper) config := Config{"pow", 1} keeper := NewKeeper(keyPOW, config, bankKeeper, mapp.RegisterCodespace(DefaultCodespace)) mapp.Router().AddRoute("pow", keeper.Handler) diff --git a/examples/democoin/x/pow/handler_test.go b/examples/democoin/x/pow/handler_test.go index a203d27764..03613f7166 100644 --- a/examples/democoin/x/pow/handler_test.go +++ b/examples/democoin/x/pow/handler_test.go @@ -22,7 +22,7 @@ func TestPowHandler(t *testing.T) { am := auth.NewAccountMapper(cdc, capKey, auth.ProtoBaseAccount) ctx := sdk.NewContext(ms, abci.Header{}, false, log.NewNopLogger()) config := NewConfig("pow", int64(1)) - ck := bank.NewKeeper(am) + ck := bank.NewBaseKeeper(am) keeper := NewKeeper(capKey, config, ck, DefaultCodespace) handler := keeper.Handler diff --git a/examples/democoin/x/pow/keeper_test.go b/examples/democoin/x/pow/keeper_test.go index a6802cb212..dbab3e6178 100644 --- a/examples/democoin/x/pow/keeper_test.go +++ b/examples/democoin/x/pow/keeper_test.go @@ -35,7 +35,7 @@ func TestPowKeeperGetSet(t *testing.T) { am := auth.NewAccountMapper(cdc, capKey, auth.ProtoBaseAccount) ctx := sdk.NewContext(ms, abci.Header{}, false, log.NewNopLogger()) config := NewConfig("pow", int64(1)) - ck := bank.NewKeeper(am) + ck := bank.NewBaseKeeper(am) keeper := NewKeeper(capKey, config, ck, DefaultCodespace) err := InitGenesis(ctx, keeper, Genesis{uint64(1), uint64(0)}) diff --git a/examples/democoin/x/simplestake/keeper_test.go b/examples/democoin/x/simplestake/keeper_test.go index 393bc1b335..417356f66c 100644 --- a/examples/democoin/x/simplestake/keeper_test.go +++ b/examples/democoin/x/simplestake/keeper_test.go @@ -36,7 +36,7 @@ func TestKeeperGetSet(t *testing.T) { auth.RegisterBaseAccount(cdc) accountMapper := auth.NewAccountMapper(cdc, authKey, auth.ProtoBaseAccount) - stakeKeeper := NewKeeper(capKey, bank.NewKeeper(accountMapper), DefaultCodespace) + stakeKeeper := NewKeeper(capKey, bank.NewBaseKeeper(accountMapper), DefaultCodespace) ctx := sdk.NewContext(ms, abci.Header{}, false, log.NewNopLogger()) addr := sdk.AccAddress([]byte("some-address")) @@ -66,7 +66,7 @@ func TestBonding(t *testing.T) { ctx := sdk.NewContext(ms, abci.Header{}, false, log.NewNopLogger()) accountMapper := auth.NewAccountMapper(cdc, authKey, auth.ProtoBaseAccount) - bankKeeper := bank.NewKeeper(accountMapper) + bankKeeper := bank.NewBaseKeeper(accountMapper) stakeKeeper := NewKeeper(capKey, bankKeeper, DefaultCodespace) addr := sdk.AccAddress([]byte("some-address")) privKey := ed25519.GenPrivKey() diff --git a/store/transientstore.go b/store/transientstore.go index 89cbaf693b..a3ce896317 100644 --- a/store/transientstore.go +++ b/store/transientstore.go @@ -1,8 +1,8 @@ package store import ( - dbm "github.com/tendermint/tendermint/libs/db" sdk "github.com/cosmos/cosmos-sdk/types" + dbm "github.com/tendermint/tendermint/libs/db" ) var _ KVStore = (*transientStore)(nil) diff --git a/x/bank/bench_test.go b/x/bank/bench_test.go index 3d84a892df..998d4e4bce 100644 --- a/x/bank/bench_test.go +++ b/x/bank/bench_test.go @@ -16,7 +16,7 @@ func getBenchmarkMockApp() (*mock.App, error) { mapp := mock.NewApp() RegisterWire(mapp.Cdc) - bankKeeper := NewKeeper(mapp.AccountMapper) + bankKeeper := NewBaseKeeper(mapp.AccountMapper) mapp.Router().AddRoute("bank", NewHandler(bankKeeper)) err := mapp.CompleteSetup([]*sdk.KVStoreKey{}) diff --git a/x/bank/keeper.go b/x/bank/keeper.go index 1494c8cafa..2da4eedc8b 100644 --- a/x/bank/keeper.go +++ b/x/bank/keeper.go @@ -15,102 +15,149 @@ const ( costAddCoins sdk.Gas = 10 ) -// Keeper manages transfers between accounts -type Keeper struct { +// Keeper defines a module interface that facilitates the transfer of coins +// between accounts. +type Keeper interface { + SendKeeper + SetCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) sdk.Error + SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Tags, sdk.Error) + AddCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Tags, sdk.Error) +} + +var _ Keeper = (*BaseKeeper)(nil) + +// BaseKeeper manages transfers between accounts. It implements the Keeper +// interface. +type BaseKeeper struct { am auth.AccountMapper } -// NewKeeper returns a new Keeper -func NewKeeper(am auth.AccountMapper) Keeper { - return Keeper{am: am} +// NewBaseKeeper returns a new BaseKeeper +func NewBaseKeeper(am auth.AccountMapper) BaseKeeper { + return BaseKeeper{am: am} } // GetCoins returns the coins at the addr. -func (keeper Keeper) GetCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins { +func (keeper BaseKeeper) GetCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins { return getCoins(ctx, keeper.am, addr) } // SetCoins sets the coins at the addr. -func (keeper Keeper) SetCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) sdk.Error { +func (keeper BaseKeeper) SetCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) sdk.Error { return setCoins(ctx, keeper.am, addr, amt) } // HasCoins returns whether or not an account has at least amt coins. -func (keeper Keeper) HasCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) bool { +func (keeper BaseKeeper) HasCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) bool { return hasCoins(ctx, keeper.am, addr, amt) } // SubtractCoins subtracts amt from the coins at the addr. -func (keeper Keeper) SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Tags, sdk.Error) { +func (keeper BaseKeeper) SubtractCoins( + ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins, +) (sdk.Coins, sdk.Tags, sdk.Error) { + return subtractCoins(ctx, keeper.am, addr, amt) } // AddCoins adds amt to the coins at the addr. -func (keeper Keeper) AddCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Tags, sdk.Error) { +func (keeper BaseKeeper) AddCoins( + ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins, +) (sdk.Coins, sdk.Tags, sdk.Error) { + return addCoins(ctx, keeper.am, addr, amt) } // SendCoins moves coins from one account to another -func (keeper Keeper) SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) (sdk.Tags, sdk.Error) { +func (keeper BaseKeeper) SendCoins( + ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins, +) (sdk.Tags, sdk.Error) { + return sendCoins(ctx, keeper.am, fromAddr, toAddr, amt) } // InputOutputCoins handles a list of inputs and outputs -func (keeper Keeper) InputOutputCoins(ctx sdk.Context, inputs []Input, outputs []Output) (sdk.Tags, sdk.Error) { +func (keeper BaseKeeper) InputOutputCoins(ctx sdk.Context, inputs []Input, outputs []Output) (sdk.Tags, sdk.Error) { return inputOutputCoins(ctx, keeper.am, inputs, outputs) } //______________________________________________________________________________________________ -// SendKeeper only allows transfers between accounts, without the possibility of creating coins -type SendKeeper struct { +// SendKeeper defines a module interface that facilitates the transfer of coins +// between accounts without the possibility of creating coins. +type SendKeeper interface { + ViewKeeper + SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) (sdk.Tags, sdk.Error) + InputOutputCoins(ctx sdk.Context, inputs []Input, outputs []Output) (sdk.Tags, sdk.Error) +} + +var _ SendKeeper = (*BaseSendKeeper)(nil) + +// SendKeeper only allows transfers between accounts without the possibility of +// creating coins. It implements the SendKeeper interface. +type BaseSendKeeper struct { am auth.AccountMapper } -// NewSendKeeper returns a new Keeper -func NewSendKeeper(am auth.AccountMapper) SendKeeper { - return SendKeeper{am: am} +// NewBaseSendKeeper returns a new BaseSendKeeper. +func NewBaseSendKeeper(am auth.AccountMapper) BaseSendKeeper { + return BaseSendKeeper{am: am} } // GetCoins returns the coins at the addr. -func (keeper SendKeeper) GetCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins { +func (keeper BaseSendKeeper) GetCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins { return getCoins(ctx, keeper.am, addr) } // HasCoins returns whether or not an account has at least amt coins. -func (keeper SendKeeper) HasCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) bool { +func (keeper BaseSendKeeper) HasCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) bool { return hasCoins(ctx, keeper.am, addr, amt) } // SendCoins moves coins from one account to another -func (keeper SendKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) (sdk.Tags, sdk.Error) { +func (keeper BaseSendKeeper) SendCoins( + ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins, +) (sdk.Tags, sdk.Error) { + return sendCoins(ctx, keeper.am, fromAddr, toAddr, amt) } // InputOutputCoins handles a list of inputs and outputs -func (keeper SendKeeper) InputOutputCoins(ctx sdk.Context, inputs []Input, outputs []Output) (sdk.Tags, sdk.Error) { +func (keeper BaseSendKeeper) InputOutputCoins( + ctx sdk.Context, inputs []Input, outputs []Output, +) (sdk.Tags, sdk.Error) { + return inputOutputCoins(ctx, keeper.am, inputs, outputs) } //______________________________________________________________________________________________ -// ViewKeeper only allows reading of balances -type ViewKeeper struct { +// ViewKeeper defines a module interface that facilitates read only access to +// account balances. +type ViewKeeper interface { + GetCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins + HasCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) bool +} + +var _ ViewKeeper = (*BaseViewKeeper)(nil) + +// BaseViewKeeper implements a read only keeper implementation of ViewKeeper. +type BaseViewKeeper struct { am auth.AccountMapper } -// NewViewKeeper returns a new Keeper -func NewViewKeeper(am auth.AccountMapper) ViewKeeper { - return ViewKeeper{am: am} +// NewBaseViewKeeper returns a new BaseViewKeeper. +func NewBaseViewKeeper(am auth.AccountMapper) BaseViewKeeper { + return BaseViewKeeper{am: am} } // GetCoins returns the coins at the addr. -func (keeper ViewKeeper) GetCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins { +func (keeper BaseViewKeeper) GetCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins { return getCoins(ctx, keeper.am, addr) } // HasCoins returns whether or not an account has at least amt coins. -func (keeper ViewKeeper) HasCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) bool { +func (keeper BaseViewKeeper) HasCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) bool { return hasCoins(ctx, keeper.am, addr, amt) } diff --git a/x/bank/keeper_test.go b/x/bank/keeper_test.go index 36c0000e77..ee45ae1ca9 100644 --- a/x/bank/keeper_test.go +++ b/x/bank/keeper_test.go @@ -34,7 +34,7 @@ func TestKeeper(t *testing.T) { ctx := sdk.NewContext(ms, abci.Header{}, false, log.NewNopLogger()) accountMapper := auth.NewAccountMapper(cdc, authKey, auth.ProtoBaseAccount) - bankKeeper := NewKeeper(accountMapper) + bankKeeper := NewBaseKeeper(accountMapper) addr := sdk.AccAddress([]byte("addr1")) addr2 := sdk.AccAddress([]byte("addr2")) @@ -119,8 +119,8 @@ func TestSendKeeper(t *testing.T) { ctx := sdk.NewContext(ms, abci.Header{}, false, log.NewNopLogger()) accountMapper := auth.NewAccountMapper(cdc, authKey, auth.ProtoBaseAccount) - bankKeeper := NewKeeper(accountMapper) - sendKeeper := NewSendKeeper(accountMapper) + bankKeeper := NewBaseKeeper(accountMapper) + sendKeeper := NewBaseSendKeeper(accountMapper) addr := sdk.AccAddress([]byte("addr1")) addr2 := sdk.AccAddress([]byte("addr2")) @@ -188,8 +188,8 @@ func TestViewKeeper(t *testing.T) { ctx := sdk.NewContext(ms, abci.Header{}, false, log.NewNopLogger()) accountMapper := auth.NewAccountMapper(cdc, authKey, auth.ProtoBaseAccount) - bankKeeper := NewKeeper(accountMapper) - viewKeeper := NewViewKeeper(accountMapper) + bankKeeper := NewBaseKeeper(accountMapper) + viewKeeper := NewBaseViewKeeper(accountMapper) addr := sdk.AccAddress([]byte("addr1")) acc := accountMapper.NewAccountWithAddress(ctx, addr) diff --git a/x/bank/simulation/sim_test.go b/x/bank/simulation/sim_test.go index 38461bad47..f0279abef3 100644 --- a/x/bank/simulation/sim_test.go +++ b/x/bank/simulation/sim_test.go @@ -18,7 +18,7 @@ func TestBankWithRandomMessages(t *testing.T) { bank.RegisterWire(mapp.Cdc) mapper := mapp.AccountMapper - bankKeeper := bank.NewKeeper(mapper) + bankKeeper := bank.NewBaseKeeper(mapper) mapp.Router().AddRoute("bank", bank.NewHandler(bankKeeper)) err := mapp.CompleteSetup([]*sdk.KVStoreKey{}) diff --git a/x/gov/simulation/sim_test.go b/x/gov/simulation/sim_test.go index 317864a612..b7f0be580e 100644 --- a/x/gov/simulation/sim_test.go +++ b/x/gov/simulation/sim_test.go @@ -24,7 +24,7 @@ func TestGovWithRandomMessages(t *testing.T) { bank.RegisterWire(mapp.Cdc) gov.RegisterWire(mapp.Cdc) mapper := mapp.AccountMapper - bankKeeper := bank.NewKeeper(mapper) + bankKeeper := bank.NewBaseKeeper(mapper) stakeKey := sdk.NewKVStoreKey("stake") stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, bankKeeper, stake.DefaultCodespace) paramKey := sdk.NewKVStoreKey("params") diff --git a/x/gov/test_common.go b/x/gov/test_common.go index 502cfbbf04..a0d5565214 100644 --- a/x/gov/test_common.go +++ b/x/gov/test_common.go @@ -31,7 +31,7 @@ func getMockApp(t *testing.T, numGenAccs int) (*mock.App, Keeper, stake.Keeper, keyGov := sdk.NewKVStoreKey("gov") pk := params.NewKeeper(mapp.Cdc, keyGlobalParams) - ck := bank.NewKeeper(mapp.AccountMapper) + ck := bank.NewBaseKeeper(mapp.AccountMapper) sk := stake.NewKeeper(mapp.Cdc, keyStake, ck, mapp.RegisterCodespace(stake.DefaultCodespace)) keeper := NewKeeper(mapp.Cdc, keyGov, pk.Setter(), ck, sk, DefaultCodespace) mapp.Router().AddRoute("gov", NewHandler(keeper)) diff --git a/x/ibc/app_test.go b/x/ibc/app_test.go index eed7c982c7..07c3616cee 100644 --- a/x/ibc/app_test.go +++ b/x/ibc/app_test.go @@ -21,7 +21,7 @@ func getMockApp(t *testing.T) *mock.App { RegisterWire(mapp.Cdc) keyIBC := sdk.NewKVStoreKey("ibc") ibcMapper := NewMapper(mapp.Cdc, keyIBC, mapp.RegisterCodespace(DefaultCodespace)) - bankKeeper := bank.NewKeeper(mapp.AccountMapper) + bankKeeper := bank.NewBaseKeeper(mapp.AccountMapper) mapp.Router().AddRoute("ibc", NewHandler(ibcMapper, bankKeeper)) require.NoError(t, mapp.CompleteSetup([]*sdk.KVStoreKey{keyIBC})) diff --git a/x/ibc/ibc_test.go b/x/ibc/ibc_test.go index 88718b4a22..acc484e0a7 100644 --- a/x/ibc/ibc_test.go +++ b/x/ibc/ibc_test.go @@ -65,7 +65,7 @@ func TestIBC(t *testing.T) { ctx := defaultContext(key) am := auth.NewAccountMapper(cdc, key, auth.ProtoBaseAccount) - ck := bank.NewKeeper(am) + ck := bank.NewBaseKeeper(am) src := newAddress() dest := newAddress() diff --git a/x/slashing/app_test.go b/x/slashing/app_test.go index e0b84cef7d..4ceeac94db 100644 --- a/x/slashing/app_test.go +++ b/x/slashing/app_test.go @@ -28,7 +28,7 @@ func getMockApp(t *testing.T) (*mock.App, stake.Keeper, Keeper) { keyStake := sdk.NewKVStoreKey("stake") keySlashing := sdk.NewKVStoreKey("slashing") keyParams := sdk.NewKVStoreKey("params") - bankKeeper := bank.NewKeeper(mapp.AccountMapper) + bankKeeper := bank.NewBaseKeeper(mapp.AccountMapper) paramsKeeper := params.NewKeeper(mapp.Cdc, keyParams) stakeKeeper := stake.NewKeeper(mapp.Cdc, keyStake, bankKeeper, mapp.RegisterCodespace(stake.DefaultCodespace)) diff --git a/x/slashing/test_common.go b/x/slashing/test_common.go index afbe47d553..b10c640f52 100644 --- a/x/slashing/test_common.go +++ b/x/slashing/test_common.go @@ -65,7 +65,7 @@ func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, para ctx := sdk.NewContext(ms, abci.Header{Time: time.Unix(0, 0)}, false, log.NewTMLogger(os.Stdout)) cdc := createTestCodec() accountMapper := auth.NewAccountMapper(cdc, keyAcc, auth.ProtoBaseAccount) - ck := bank.NewKeeper(accountMapper) + ck := bank.NewBaseKeeper(accountMapper) params := params.NewKeeper(cdc, keyParams) sk := stake.NewKeeper(cdc, keyStake, ck, stake.DefaultCodespace) genesis := stake.DefaultGenesisState() diff --git a/x/stake/app_test.go b/x/stake/app_test.go index 98dc8d56f9..b5cf904334 100644 --- a/x/stake/app_test.go +++ b/x/stake/app_test.go @@ -34,7 +34,7 @@ func getMockApp(t *testing.T) (*mock.App, Keeper) { RegisterWire(mApp.Cdc) keyStake := sdk.NewKVStoreKey("stake") - bankKeeper := bank.NewKeeper(mApp.AccountMapper) + bankKeeper := bank.NewBaseKeeper(mApp.AccountMapper) keeper := NewKeeper(mApp.Cdc, keyStake, bankKeeper, mApp.RegisterCodespace(DefaultCodespace)) mApp.Router().AddRoute("stake", NewHandler(keeper)) diff --git a/x/stake/keeper/test_common.go b/x/stake/keeper/test_common.go index b84ce9d93a..247ff262b2 100644 --- a/x/stake/keeper/test_common.go +++ b/x/stake/keeper/test_common.go @@ -106,7 +106,7 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context keyAcc, // target store auth.ProtoBaseAccount, // prototype ) - ck := bank.NewKeeper(accountMapper) + ck := bank.NewBaseKeeper(accountMapper) keeper := NewKeeper(cdc, keyStake, ck, types.DefaultCodespace) keeper.SetPool(ctx, types.InitialPool()) keeper.SetNewParams(ctx, types.DefaultParams()) diff --git a/x/stake/simulation/sim_test.go b/x/stake/simulation/sim_test.go index 3feec637ba..6ad8b41825 100644 --- a/x/stake/simulation/sim_test.go +++ b/x/stake/simulation/sim_test.go @@ -21,7 +21,7 @@ func TestStakeWithRandomMessages(t *testing.T) { bank.RegisterWire(mapp.Cdc) mapper := mapp.AccountMapper - bankKeeper := bank.NewKeeper(mapper) + bankKeeper := bank.NewBaseKeeper(mapper) stakeKey := sdk.NewKVStoreKey("stake") stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, bankKeeper, stake.DefaultCodespace) mapp.Router().AddRoute("stake", stake.NewHandler(stakeKeeper)) From 06f094563a107af14dd431e7d0ec82a10ba51935 Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Mon, 10 Sep 2018 23:37:03 +0100 Subject: [PATCH 80/93] Merge PR #2301: remove BechValidator - replace with and unexported struct and amino's ability to override / implement MarshalJSON & UnmarshalJSON to have the pub key bechified - replaced default time to UTC as I (from London) always got an error while decoding (epoch but in BST ;-) - remove all occurrences of `BechValidator --- client/lcd/lcd_test.go | 22 +++++----- x/stake/client/rest/query.go | 11 +---- x/stake/client/rest/utils.go | 32 ++++++-------- x/stake/stake.go | 1 - x/stake/types/validator.go | 75 ++++++++++++++++++++++----------- x/stake/types/validator_test.go | 14 ++++++ 6 files changed, 90 insertions(+), 65 deletions(-) diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index 7fc98aef6f..977c03cf72 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -478,12 +478,12 @@ func TestValidatorsQuery(t *testing.T) { // make sure all the validators were found (order unknown because sorted by operator addr) foundVal := false - pkBech := sdk.MustBech32ifyConsPub(pks[0]) - if validators[0].ConsPubKey == pkBech { + + if validators[0].ConsPubKey == pks[0] { foundVal = true } - require.True(t, foundVal, "pkBech %v, operator %v", pkBech, validators[0].OperatorAddr) + require.True(t, foundVal, "pk %v, operator %v", pks[0], validators[0].OperatorAddr) } func TestValidatorQuery(t *testing.T) { @@ -950,11 +950,11 @@ func getBondingTxs(t *testing.T, port string, delegatorAddr sdk.AccAddress, quer return txs } -func getDelegatorValidators(t *testing.T, port string, delegatorAddr sdk.AccAddress) []stake.BechValidator { +func getDelegatorValidators(t *testing.T, port string, delegatorAddr sdk.AccAddress) []stake.Validator { 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 + var bondedValidators []stake.Validator err := cdc.UnmarshalJSON([]byte(body), &bondedValidators) require.Nil(t, err) @@ -962,11 +962,11 @@ func getDelegatorValidators(t *testing.T, port string, delegatorAddr sdk.AccAddr return bondedValidators } -func getDelegatorValidator(t *testing.T, port string, delAddr sdk.AccAddress, valAddr sdk.ValAddress) stake.BechValidator { +func getDelegatorValidator(t *testing.T, port string, delAddr sdk.AccAddress, valAddr sdk.ValAddress) stake.Validator { res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/validators/%s", delAddr, valAddr), nil) require.Equal(t, http.StatusOK, res.StatusCode, body) - var bondedValidator stake.BechValidator + var bondedValidator stake.Validator err := cdc.UnmarshalJSON([]byte(body), &bondedValidator) require.Nil(t, err) @@ -1086,19 +1086,19 @@ func doBeginRedelegation(t *testing.T, port, seed, name, password string, return results[0] } -func getValidators(t *testing.T, port string) []stake.BechValidator { +func getValidators(t *testing.T, port string) []stake.Validator { res, body := Request(t, port, "GET", "/stake/validators", nil) require.Equal(t, http.StatusOK, res.StatusCode, body) - var validators []stake.BechValidator + var validators []stake.Validator err := cdc.UnmarshalJSON([]byte(body), &validators) require.Nil(t, err) return validators } -func getValidator(t *testing.T, port string, valAddr sdk.ValAddress) stake.BechValidator { +func getValidator(t *testing.T, port string, valAddr sdk.ValAddress) stake.Validator { res, body := Request(t, port, "GET", fmt.Sprintf("/stake/validators/%s", valAddr.String()), nil) require.Equal(t, http.StatusOK, res.StatusCode, body) - var validator stake.BechValidator + var validator stake.Validator err := cdc.UnmarshalJSON([]byte(body), &validator) require.Nil(t, err) return validator diff --git a/x/stake/client/rest/query.go b/x/stake/client/rest/query.go index 5d280daf3d..7a0602ee2d 100644 --- a/x/stake/client/rest/query.go +++ b/x/stake/client/rest/query.go @@ -376,7 +376,7 @@ func delegatorValidatorsHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) ht return func(w http.ResponseWriter, r *http.Request) { var valAddr sdk.ValAddress - var bondedValidators []types.BechValidator + var bondedValidators []types.Validator // read parameters vars := mux.Vars(r) @@ -544,14 +544,7 @@ func validatorHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.Handler return } - bech32Validator, err := validator.Bech32Validator() - if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) - return - } - - output, err = cdc.MarshalJSON(bech32Validator) + output, err = cdc.MarshalJSON(validator) 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 d8ad5fec55..13f3abb74c 100644 --- a/x/stake/client/rest/utils.go +++ b/x/stake/client/rest/utils.go @@ -25,35 +25,31 @@ func contains(stringSlice []string, txType string) bool { } func getDelegatorValidator(cliCtx context.CLIContext, cdc *wire.Codec, delAddr sdk.AccAddress, valAddr sdk.ValAddress) ( - bech32Validator types.BechValidator, httpStatusCode int, errMsg string, err error) { + validator types.Validator, httpStatusCode int, errMsg string, err error) { key := stake.GetDelegationKey(delAddr, valAddr) res, err := cliCtx.QueryStore(key, storeName) if err != nil { - return types.BechValidator{}, http.StatusInternalServerError, "couldn't query delegation. Error: ", err + return types.Validator{}, http.StatusInternalServerError, "couldn't query delegation. Error: ", err } if len(res) == 0 { - return types.BechValidator{}, http.StatusNoContent, "", nil + return types.Validator{}, http.StatusNoContent, "", nil } key = stake.GetValidatorKey(valAddr) res, err = cliCtx.QueryStore(key, storeName) if err != nil { - return types.BechValidator{}, http.StatusInternalServerError, "couldn't query validator. Error: ", err + return types.Validator{}, http.StatusInternalServerError, "couldn't query validator. Error: ", err } if len(res) == 0 { - return types.BechValidator{}, http.StatusNoContent, "", nil + return types.Validator{}, http.StatusNoContent, "", nil } - validator, err := types.UnmarshalValidator(cdc, valAddr, res) + validator, err = types.UnmarshalValidator(cdc, valAddr, res) if err != nil { - return types.BechValidator{}, http.StatusBadRequest, "", err - } - bech32Validator, err = validator.Bech32Validator() - if err != nil { - return types.BechValidator{}, http.StatusBadRequest, "", err + return types.Validator{}, http.StatusBadRequest, "", err } - return bech32Validator, http.StatusOK, "", nil + return validator, http.StatusOK, "", nil } func getDelegatorDelegations( @@ -143,8 +139,8 @@ func queryTxs(node rpcclient.Client, cdc *wire.Codec, tag string, delegatorAddr } // gets all validators -func getValidators(validatorKVs []sdk.KVPair, cdc *wire.Codec) ([]types.BechValidator, error) { - validators := make([]types.BechValidator, len(validatorKVs)) +func getValidators(validatorKVs []sdk.KVPair, cdc *wire.Codec) ([]types.Validator, error) { + validators := make([]types.Validator, len(validatorKVs)) for i, kv := range validatorKVs { addr := kv.Key[1:] @@ -153,11 +149,7 @@ func getValidators(validatorKVs []sdk.KVPair, cdc *wire.Codec) ([]types.BechVali return nil, err } - bech32Validator, err := validator.Bech32Validator() - if err != nil { - return nil, err - } - validators[i] = bech32Validator + validators[i] = validator } return validators, nil } @@ -165,7 +157,7 @@ func getValidators(validatorKVs []sdk.KVPair, cdc *wire.Codec) ([]types.BechVali // gets all Bech32 validators from a key // nolint: unparam func getBech32Validators(storeName string, cliCtx context.CLIContext, cdc *wire.Codec) ( - validators []types.BechValidator, httpStatusCode int, errMsg string, err error) { + validators []types.Validator, httpStatusCode int, errMsg string, err error) { // Get all validators using key kvs, err := cliCtx.QuerySubspace(stake.ValidatorsKey, storeName) diff --git a/x/stake/stake.go b/x/stake/stake.go index 2782957ceb..d60e402995 100644 --- a/x/stake/stake.go +++ b/x/stake/stake.go @@ -10,7 +10,6 @@ import ( type ( Keeper = keeper.Keeper Validator = types.Validator - BechValidator = types.BechValidator Description = types.Description Delegation = types.Delegation UnbondingDelegation = types.UnbondingDelegation diff --git a/x/stake/types/validator.go b/x/stake/types/validator.go index c0efdb357c..31af4daaa3 100644 --- a/x/stake/types/validator.go +++ b/x/stake/types/validator.go @@ -21,8 +21,8 @@ import ( // exchange rate. Voting power can be calculated as total bonds multiplied by // exchange rate. type Validator struct { - OperatorAddr sdk.ValAddress `json:"operator_address"` // address of the validator's operator - ConsPubKey crypto.PubKey `json:"consensus_pubkey"` // the consensus public key of the validator + OperatorAddr sdk.ValAddress `json:"operator_address"` // address of the validator's operator; bech encoded in JSON + ConsPubKey crypto.PubKey `json:"consensus_pubkey"` // the consensus public key of the validator; bech encoded in JSON Jailed bool `json:"jailed"` // has the validator been jailed from bonded status? Status sdk.BondStatus `json:"status"` // validator status (bonded/unbonding/unbonded) @@ -55,7 +55,7 @@ func NewValidator(operator sdk.ValAddress, pubKey crypto.PubKey, description Des BondHeight: int64(0), BondIntraTxCounter: int16(0), UnbondingHeight: int64(0), - UnbondingMinTime: time.Unix(0, 0), + UnbondingMinTime: time.Unix(0, 0).UTC(), Commission: sdk.ZeroDec(), CommissionMax: sdk.ZeroDec(), CommissionChangeRate: sdk.ZeroDec(), @@ -172,8 +172,8 @@ func (v Validator) HumanReadableString() (string, error) { //___________________________________________________________________ -// validator struct for bech output -type BechValidator struct { +// this is a helper struct used for JSON de- and encoding only +type bechValidator struct { OperatorAddr sdk.ValAddress `json:"operator_address"` // the bech32 address of the validator's operator ConsPubKey string `json:"consensus_pubkey"` // the bech32 consensus public key of the validator Jailed bool `json:"jailed"` // has the validator been jailed from bonded status? @@ -195,33 +195,60 @@ type BechValidator struct { CommissionChangeToday sdk.Dec `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time) } -// get the bech validator from the the regular validator -func (v Validator) Bech32Validator() (BechValidator, error) { +// MarshalJSON marshals the validator to JSON using Bech32 +func (v Validator) MarshalJSON() ([]byte, error) { bechConsPubKey, err := sdk.Bech32ifyConsPub(v.ConsPubKey) if err != nil { - return BechValidator{}, err + return nil, err } - return BechValidator{ - OperatorAddr: v.OperatorAddr, - ConsPubKey: bechConsPubKey, - Jailed: v.Jailed, - - Status: v.Status, - Tokens: v.Tokens, - DelegatorShares: v.DelegatorShares, - - Description: v.Description, - BondHeight: v.BondHeight, - BondIntraTxCounter: v.BondIntraTxCounter, - UnbondingHeight: v.UnbondingHeight, - UnbondingMinTime: v.UnbondingMinTime, - + return wire.Cdc.MarshalJSON(bechValidator{ + OperatorAddr: v.OperatorAddr, + ConsPubKey: bechConsPubKey, + Jailed: v.Jailed, + Status: v.Status, + Tokens: v.Tokens, + DelegatorShares: v.DelegatorShares, + Description: v.Description, + BondHeight: v.BondHeight, + BondIntraTxCounter: v.BondIntraTxCounter, + UnbondingHeight: v.UnbondingHeight, + UnbondingMinTime: v.UnbondingMinTime, Commission: v.Commission, CommissionMax: v.CommissionMax, CommissionChangeRate: v.CommissionChangeRate, CommissionChangeToday: v.CommissionChangeToday, - }, nil + }) +} + +// UnmarshalJSON unmarshals the validator from JSON using Bech32 +func (v *Validator) UnmarshalJSON(data []byte) error { + bv := &bechValidator{} + if err := wire.Cdc.UnmarshalJSON(data, bv); err != nil { + return err + } + consPubKey, err := sdk.GetConsPubKeyBech32(bv.ConsPubKey) + if err != nil { + return err + } + *v = Validator{ + OperatorAddr: bv.OperatorAddr, + ConsPubKey: consPubKey, + Jailed: bv.Jailed, + Tokens: bv.Tokens, + Status: bv.Status, + DelegatorShares: bv.DelegatorShares, + Description: bv.Description, + BondHeight: bv.BondHeight, + BondIntraTxCounter: bv.BondIntraTxCounter, + UnbondingHeight: bv.UnbondingHeight, + UnbondingMinTime: bv.UnbondingMinTime, + Commission: bv.Commission, + CommissionMax: bv.CommissionMax, + CommissionChangeRate: bv.CommissionChangeRate, + CommissionChangeToday: bv.CommissionChangeToday, + } + return nil } //___________________________________________________________________ diff --git a/x/stake/types/validator_test.go b/x/stake/types/validator_test.go index 60c5f9d74f..70ab5f105e 100644 --- a/x/stake/types/validator_test.go +++ b/x/stake/types/validator_test.go @@ -6,6 +6,8 @@ import ( "time" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/wire" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" tmtypes "github.com/tendermint/tendermint/types" @@ -260,3 +262,15 @@ func TestHumanReadableString(t *testing.T) { require.Nil(t, err) require.NotEmpty(t, valStr) } + +func TestValidatorMarshalUnmarshalJSON(t *testing.T) { + validator := NewValidator(addr1, pk1, Description{}) + js, err := wire.Cdc.MarshalJSON(validator) + require.NoError(t, err) + require.NotEmpty(t, js) + require.Contains(t, string(js), "\"consensus_pubkey\":\"cosmosvalconspu") + got := &Validator{} + err = wire.Cdc.UnmarshalJSON(js, got) + assert.NoError(t, err) + assert.Equal(t, validator, *got) +} From 4f0c3cb25a3a2f74d29555254699b3115f4ef0a3 Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Tue, 11 Sep 2018 02:12:35 -0700 Subject: [PATCH 81/93] Merge PR #2291: x/staking: standardize validator record not found error --- x/stake/keeper/validator.go | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index d2411de723..c628dbea87 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -158,9 +158,7 @@ func (k Keeper) GetValidatorsBonded(ctx sdk.Context) (validators []types.Validat } address := GetAddressFromValBondedIndexKey(iterator.Key()) validator, found := k.GetValidator(ctx, address) - if !found { - panic(fmt.Sprintf("validator record not found for address: %v\n", address)) - } + ensureValidatorFound(found, address) validators[i] = validator i++ @@ -184,9 +182,8 @@ func (k Keeper) GetValidatorsByPower(ctx sdk.Context) []types.Validator { } address := iterator.Value() validator, found := k.GetValidator(ctx, address) - if !found { - panic(fmt.Sprintf("validator record not found for address: %v\n", address)) - } + ensureValidatorFound(found, address) + if validator.Status == sdk.Bonded { validators[i] = validator i++ @@ -327,9 +324,7 @@ func (k Keeper) updateCliffValidator(ctx sdk.Context, affectedVal types.Validato if iterator.Valid() { ownerAddr := iterator.Value() currVal, found := k.GetValidator(ctx, ownerAddr) - if !found { - panic(fmt.Sprintf("validator record not found for address: %v\n", ownerAddr)) - } + ensureValidatorFound(found, ownerAddr) if currVal.Status != sdk.Bonded || currVal.Jailed { panic(fmt.Sprintf("unexpected jailed or unbonded validator for address: %s\n", ownerAddr)) @@ -454,9 +449,7 @@ func (k Keeper) UpdateBondedValidators( } else { var found bool validator, found = k.GetValidator(ctx, ownerAddr) - if !found { - panic(fmt.Sprintf("validator record not found for address: %v\n", ownerAddr)) - } + ensureValidatorFound(found, ownerAddr) } // if we've reached jailed validators no further bonded validators exist @@ -502,9 +495,7 @@ func (k Keeper) UpdateBondedValidators( if newValidatorBonded { if oldCliffValidatorAddr != nil { oldCliffVal, found := k.GetValidator(ctx, oldCliffValidatorAddr) - if !found { - panic(fmt.Sprintf("validator record not found for address: %v\n", oldCliffValidatorAddr)) - } + ensureValidatorFound(found, oldCliffValidatorAddr) if bytes.Equal(validatorToBond.OperatorAddr, affectedValidator.OperatorAddr) { @@ -560,9 +551,7 @@ func (k Keeper) UpdateBondedValidatorsFull(ctx sdk.Context) { ownerAddr := iterator.Value() validator, found = k.GetValidator(ctx, ownerAddr) - if !found { - panic(fmt.Sprintf("validator record not found for address: %v\n", ownerAddr)) - } + ensureValidatorFound(found, ownerAddr) _, found = toKickOut[string(ownerAddr)] if found { @@ -605,9 +594,7 @@ func kickOutValidators(k Keeper, ctx sdk.Context, toKickOut map[string]byte) { for key := range toKickOut { ownerAddr := []byte(key) validator, found := k.GetValidator(ctx, ownerAddr) - if !found { - panic(fmt.Sprintf("validator record not found for address: %v\n", ownerAddr)) - } + ensureValidatorFound(found, ownerAddr) k.beginUnbondingValidator(ctx, validator) } } @@ -738,3 +725,9 @@ func (k Keeper) clearCliffValidator(ctx sdk.Context) { store.Delete(ValidatorPowerCliffKey) store.Delete(ValidatorCliffIndexKey) } + +func ensureValidatorFound(found bool, ownerAddr []byte) { + if !found { + panic(fmt.Sprintf("validator record not found for address: %X\n", ownerAddr)) + } +} From 2e0fc15dd4b0d58f5ff0264b4ad573e484c7045f Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Tue, 11 Sep 2018 02:14:32 -0700 Subject: [PATCH 82/93] Merge PR #2292: x/staking: Use variable names in switch case --- x/stake/keeper/validator.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index c628dbea87..c5fe3def73 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -243,6 +243,11 @@ func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) type validator.BondHeight, validator.BondIntraTxCounter = k.bondIncrement(ctx, oldFound, oldValidator, validator) valPower := k.updateValidatorPower(ctx, oldFound, oldValidator, validator, pool) cliffPower := k.GetCliffValidatorPower(ctx) + cliffValExists := (cliffPower != nil) + var valPowerLTcliffPower bool + if cliffValExists { + valPowerLTcliffPower = (bytes.Compare(valPower, cliffPower) == -1) + } switch { @@ -256,7 +261,7 @@ func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) type bz := k.cdc.MustMarshalBinary(validator.ABCIValidator()) store.Set(GetTendermintUpdatesKey(validator.OperatorAddr), bz) - if cliffPower != nil { + if cliffValExists { cliffAddr := sdk.ValAddress(k.GetCliffValidator(ctx)) if bytes.Equal(cliffAddr, validator.OperatorAddr) { k.updateCliffValidator(ctx, validator) @@ -264,14 +269,13 @@ func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) type } // if is a new validator and the new power is less than the cliff validator - case cliffPower != nil && !oldFound && - bytes.Compare(valPower, cliffPower) == -1: //(valPower < cliffPower + case cliffValExists && !oldFound && valPowerLTcliffPower: // skip to completion // if was unbonded and the new power is less than the cliff validator - case cliffPower != nil && + case cliffValExists && (oldFound && oldValidator.Status == sdk.Unbonded) && - bytes.Compare(valPower, cliffPower) == -1: //(valPower < cliffPower + valPowerLTcliffPower: //(valPower < cliffPower // skip to completion default: From 2a49406e9b686bc64e74547d5ec9152b8ef73cbc Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Tue, 11 Sep 2018 02:15:38 -0700 Subject: [PATCH 83/93] Merge PR #2284: Prevent create_empty_blocks=false --- PENDING.md | 1 + server/util.go | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/PENDING.md b/PENDING.md index 331d1fc852..1acffb10ab 100644 --- a/PENDING.md +++ b/PENDING.md @@ -97,6 +97,7 @@ IMPROVEMENTS * [x/stake] [x/slashing] Ensure delegation invariants to jailed validators [#1883](https://github.com/cosmos/cosmos-sdk/issues/1883). * [x/stake] Improve speed of GetValidator, which was shown to be a performance bottleneck. [#2046](https://github.com/tendermint/tendermint/pull/2200) * [genesis] \#2229 Ensure that there are no duplicate accounts or validators in the genesis state. + * Add SDK validation to `config.toml` (namely disabling `create_empty_blocks`) \#1571 * SDK * [tools] Make get_vendor_deps deletes `.vendor-new` directories, in case scratch files are present. diff --git a/server/util.go b/server/util.go index 04c539eb42..6aff529651 100644 --- a/server/util.go +++ b/server/util.go @@ -51,6 +51,10 @@ func PersistentPreRunEFn(context *Context) func(*cobra.Command, []string) error if err != nil { return err } + err = validateConfig(config) + if err != nil { + return err + } logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) logger, err = tmflags.ParseLogLevel(config.LogLevel, logger, cfg.DefaultLogLevel()) if err != nil { @@ -96,6 +100,14 @@ func interceptLoadConfig() (conf *cfg.Config, err error) { return } +// validate the config with the sdk's requirements. +func validateConfig(conf *cfg.Config) error { + if conf.Consensus.CreateEmptyBlocks == false { + return errors.New("config option CreateEmptyBlocks = false is currently unsupported") + } + return nil +} + // add server commands func AddCommands( ctx *Context, cdc *wire.Codec, From 962b04d98522cddfa94de5ba751a7de34973b01c Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Tue, 11 Sep 2018 02:18:58 -0700 Subject: [PATCH 84/93] Merge PR #2285: simulation: Write logs on panic --- PENDING.md | 1 + cmd/gaia/app/sim_test.go | 9 +++- x/mock/simulation/random_simulate_blocks.go | 48 ++++++++++++++------- x/mock/simulation/util.go | 29 +++++++++++-- 4 files changed, 67 insertions(+), 20 deletions(-) diff --git a/PENDING.md b/PENDING.md index 1acffb10ab..b82f34f2e6 100644 --- a/PENDING.md +++ b/PENDING.md @@ -107,6 +107,7 @@ IMPROVEMENTS * [store] \#1952, \#2281 Update IAVL dependency to v0.11.0 * [simulation] Make timestamps randomized [#2153](https://github.com/cosmos/cosmos-sdk/pull/2153) * [simulation] Make logs not just pure strings, speeding it up by a large factor at greater block heights \#2282 + * [simulation] Logs get written to file if large, and also get printed on panics \#2285 * Tendermint diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index e809495fc6..497aa1383d 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -131,7 +131,7 @@ func BenchmarkFullGaiaSimulation(b *testing.B) { // Run randomized simulation // TODO parameterize numbers, save for a later PR - simulation.SimulateFromSeed( + err := simulation.SimulateFromSeed( b, app.BaseApp, appStateFn, seed, testAndRunTxs(app), []simulation.RandSetup{}, @@ -140,6 +140,10 @@ func BenchmarkFullGaiaSimulation(b *testing.B) { blockSize, commit, ) + if err != nil { + fmt.Println(err) + b.Fail() + } if commit { fmt.Println("GoLevelDB Stats") fmt.Println(db.Stats()["leveldb.stats"]) @@ -164,7 +168,7 @@ func TestFullGaiaSimulation(t *testing.T) { require.Equal(t, "GaiaApp", app.Name()) // Run randomized simulation - simulation.SimulateFromSeed( + err := simulation.SimulateFromSeed( t, app.BaseApp, appStateFn, seed, testAndRunTxs(app), []simulation.RandSetup{}, @@ -176,6 +180,7 @@ func TestFullGaiaSimulation(t *testing.T) { if commit { fmt.Println("Database Size", db.Stats()["database.size"]) } + require.Nil(t, err) } // TODO: Make another test for the fuzzer itself, which just has noOp txs diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index 08b70d1018..e4a263e23f 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -7,6 +7,7 @@ import ( "math/rand" "os" "os/signal" + "runtime/debug" "sort" "strings" "syscall" @@ -26,9 +27,9 @@ import ( func Simulate( t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, ops []Operation, setups []RandSetup, invariants []Invariant, numBlocks int, blockSize int, commit bool, -) { +) error { time := time.Now().UnixNano() - SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numBlocks, blockSize, commit) + return SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numBlocks, blockSize, commit) } func initChain(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress, setups []RandSetup, app *baseapp.BaseApp, @@ -56,7 +57,9 @@ func randTimestamp(r *rand.Rand) time.Time { func SimulateFromSeed( tb testing.TB, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, seed int64, ops []Operation, setups []RandSetup, invariants []Invariant, numBlocks int, blockSize int, commit bool, -) { +) (simError error) { + // in case we have to end early, don't os.Exit so that we can run cleanup code. + stopEarly := false testingMode, t, b := getTestingMode(tb) fmt.Printf("Starting SimulateFromSeed with randomness created with seed %d\n", int(seed)) r := rand.New(rand.NewSource(seed)) @@ -79,12 +82,12 @@ func SimulateFromSeed( // Setup code to catch SIGTERM's c := make(chan os.Signal) - signal.Notify(c, os.Interrupt, syscall.SIGTERM) + signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGINT) go func() { - <-c - fmt.Printf("Exiting early due to SIGTERM, on block %d, operation %d\n", header.Height, opCount) - DisplayEvents(events) - os.Exit(128 + int(syscall.SIGTERM)) + receivedSignal := <-c + fmt.Printf("Exiting early due to %s, on block %d, operation %d\n", receivedSignal, header.Height, opCount) + simError = fmt.Errorf("Exited due to %s", receivedSignal) + stopEarly = true }() var pastTimes []time.Time @@ -95,15 +98,27 @@ func SimulateFromSeed( operationQueue := make(map[int][]Operation) var blockLogBuilders []*strings.Builder - if !testingMode { - b.ResetTimer() - } else { + if testingMode { blockLogBuilders = make([]*strings.Builder, numBlocks) } displayLogs := logPrinter(testingMode, blockLogBuilders) blockSimulator := createBlockSimulator(testingMode, tb, t, event, invariants, ops, operationQueue, numBlocks, displayLogs) + if !testingMode { + b.ResetTimer() + } else { + // Recover logs in case of panic + defer func() { + if r := recover(); r != nil { + fmt.Println("Panic with err\n", r) + stackTrace := string(debug.Stack()) + fmt.Println(stackTrace) + displayLogs() + simError = fmt.Errorf("Simulation halted due to panic on block %d", header.Height) + } + }() + } - for i := 0; i < numBlocks; i++ { + for i := 0; i < numBlocks && !stopEarly; i++ { // Log the header time for future lookup pastTimes = append(pastTimes, header.Time) pastSigningValidators = append(pastSigningValidators, request.LastCommitInfo.Validators) @@ -122,10 +137,9 @@ func SimulateFromSeed( // Run queued operations. Ignores blocksize if blocksize is too small numQueuedOpsRan := runQueuedOperations(operationQueue, int(header.Height), tb, r, app, ctx, keys, logWriter, displayLogs, event) - opCount += numQueuedOpsRan thisBlockSize -= numQueuedOpsRan operations := blockSimulator(thisBlockSize, r, app, ctx, keys, header, logWriter) - opCount += operations + opCount += operations + numQueuedOpsRan res := app.EndBlock(abci.RequestEndBlock{}) header.Height++ @@ -146,9 +160,13 @@ func SimulateFromSeed( // Update the validator set validators = updateValidators(tb, r, validators, res.ValidatorUpdates, event) } - + if stopEarly { + DisplayEvents(events) + return + } fmt.Printf("\nSimulation complete. Final height (blocks): %d, final time (seconds), : %v, operations ran %d\n", header.Height, header.Time, opCount) DisplayEvents(events) + return nil } // Returns a function to simulate blocks. Written like this to avoid constant parameters being passed everytime, to minimize diff --git a/x/mock/simulation/util.go b/x/mock/simulation/util.go index d4e1ca1a76..a46d6dd549 100644 --- a/x/mock/simulation/util.go +++ b/x/mock/simulation/util.go @@ -3,9 +3,11 @@ package simulation import ( "fmt" "math/rand" + "os" "sort" "strings" "testing" + "time" "github.com/tendermint/tendermint/crypto" @@ -94,13 +96,34 @@ func assertAllInvariants(t *testing.T, app *baseapp.BaseApp, invariants []Invari func logPrinter(testingmode bool, logs []*strings.Builder) func() { if testingmode { return func() { + numLoggers := 0 for i := 0; i < len(logs); i++ { // We're passed the last created block if logs[i] == nil { - return + numLoggers = i - 1 + break + } + } + var f *os.File + if numLoggers > 10 { + fileName := fmt.Sprintf("simulation_log_%s.txt", time.Now().Format("2006-01-02 15:04:05")) + fmt.Printf("Too many logs to display, instead writing to %s\n", fileName) + f, _ = os.Create(fileName) + } + for i := 0; i < numLoggers; i++ { + if f != nil { + _, err := f.WriteString(fmt.Sprintf("Begin block %d\n", i)) + if err != nil { + panic("Failed to write logs to file") + } + _, err = f.WriteString((*logs[i]).String()) + if err != nil { + panic("Failed to write logs to file") + } + } else { + fmt.Printf("Begin block %d\n", i) + fmt.Println((*logs[i]).String()) } - fmt.Printf("Begin block %d\n", i) - fmt.Println((*logs[i]).String()) } } } From fb0cc0b07845e093482c68c1a55714943a1ede43 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Wed, 12 Sep 2018 01:31:30 +0100 Subject: [PATCH 85/93] Merge PR #2306: Change --gas=0 semantic and introduce --gas=simulate * Change --gas=0 semantic and introduce --gas=simulate Make --gas flag accept a conventional "simulate" string value in addition to integers. Passing --gas=simulate would trigger the tx simulation and set the gas according to the gas estimate returned by the simulation. Any other integer value passed to --gas would be interpreted as-is and and set as gas wanted value. Closes: #2300 * Add test cases with gas=0 * ACK suggestion from @alexanderbez * s/GasFlagSimulateString/GasFlagSimulate/ * Drop TODO comment on Gas type * Enrich TODO with ref --- PENDING.md | 5 ++- client/context/context.go | 10 ----- client/flags.go | 58 ++++++++++++++++++++++++++-- client/lcd/lcd_test.go | 28 +++++++++----- client/utils/utils.go | 28 +++++++------- cmd/gaia/cli_test/cli_test.go | 12 +++++- docs/light/api.md | 4 +- docs/sdk/clients.md | 2 +- x/auth/client/txbuilder/txbuilder.go | 8 +++- x/bank/client/rest/sendtx.go | 30 ++++++++------ x/gov/client/rest/util.go | 31 ++++++++------- x/ibc/client/rest/transfer.go | 25 +++++++----- x/slashing/client/rest/tx.go | 12 +++--- x/stake/client/rest/tx.go | 34 +++++++++------- 14 files changed, 184 insertions(+), 103 deletions(-) diff --git a/PENDING.md b/PENDING.md index b82f34f2e6..aec65f3d56 100644 --- a/PENDING.md +++ b/PENDING.md @@ -61,8 +61,9 @@ FEATURES * [gov][cli] #2062 added `--proposal` flag to `submit-proposal` that allows a JSON file containing a proposal to be passed in * [\#2040](https://github.com/cosmos/cosmos-sdk/issues/2040) Add `--bech` to `gaiacli keys show` and respective REST endpoint to provide desired Bech32 prefix encoding - * [cli] [\#2047](https://github.com/cosmos/cosmos-sdk/issues/2047) Setting the --gas flag value to 0 triggers a simulation of the tx before the actual execution. The gas estimate obtained via the simulation will be used as gas limit in the actual execution. - * [cli] [\#2047](https://github.com/cosmos/cosmos-sdk/issues/2047) The --gas-adjustment flag can be used to adjust the estimate obtained via the simulation triggered by --gas=0. + * [cli] [\#2047](https://github.com/cosmos/cosmos-sdk/issues/2047) [\#2306](https://github.com/cosmos/cosmos-sdk/pull/2306) Passing --gas=simulate triggers a simulation of the tx before the actual execution. + The gas estimate obtained via the simulation will be used as gas limit in the actual execution. + * [cli] [\#2047](https://github.com/cosmos/cosmos-sdk/issues/2047) The --gas-adjustment flag can be used to adjust the estimate obtained via the simulation triggered by --gas=simulate. * [cli] [\#2110](https://github.com/cosmos/cosmos-sdk/issues/2110) Add --dry-run flag to perform a simulation of a transaction without broadcasting it. The --gas flag is ignored as gas would be automatically estimated. * [cli] [\#2204](https://github.com/cosmos/cosmos-sdk/issues/2204) Support generating and broadcasting messages with multiple signatures via command line: * [\#966](https://github.com/cosmos/cosmos-sdk/issues/966) Add --generate-only flag to build an unsigned transaction and write it to STDOUT. diff --git a/client/context/context.go b/client/context/context.go index a4d4afd3b3..3e785a28e2 100644 --- a/client/context/context.go +++ b/client/context/context.go @@ -27,8 +27,6 @@ type CLIContext struct { Client rpcclient.Client Logger io.Writer Height int64 - Gas int64 - GasAdjustment float64 NodeURI string FromAddressName string AccountStore string @@ -58,8 +56,6 @@ func NewCLIContext() CLIContext { AccountStore: ctxAccStoreName, FromAddressName: viper.GetString(client.FlagFrom), Height: viper.GetInt64(client.FlagHeight), - Gas: viper.GetInt64(client.FlagGas), - GasAdjustment: viper.GetFloat64(client.FlagGasAdjustment), TrustNode: viper.GetBool(client.FlagTrustNode), UseLedger: viper.GetBool(client.FlagUseLedger), Async: viper.GetBool(client.FlagAsync), @@ -164,9 +160,3 @@ func (ctx CLIContext) WithCertifier(certifier tmlite.Certifier) CLIContext { ctx.Certifier = certifier return ctx } - -// WithGasAdjustment returns a copy of the context with an updated GasAdjustment flag. -func (ctx CLIContext) WithGasAdjustment(adjustment float64) CLIContext { - ctx.GasAdjustment = adjustment - return ctx -} diff --git a/client/flags.go b/client/flags.go index 97fce42a58..c988980291 100644 --- a/client/flags.go +++ b/client/flags.go @@ -1,6 +1,11 @@ package client -import "github.com/spf13/cobra" +import ( + "fmt" + "strconv" + + "github.com/spf13/cobra" +) // nolint const ( @@ -9,6 +14,7 @@ const ( // occur between the tx simulation and the actual run. DefaultGasAdjustment = 1.0 DefaultGasLimit = 200000 + GasFlagSimulate = "simulate" FlagUseLedger = "ledger" FlagChainID = "chain-id" @@ -32,7 +38,10 @@ const ( // LineBreak can be included in a command list to provide a blank line // to help with readability -var LineBreak = &cobra.Command{Run: func(*cobra.Command, []string) {}} +var ( + LineBreak = &cobra.Command{Run: func(*cobra.Command, []string) {}} + GasFlagVar = GasSetting{Gas: DefaultGasLimit} +) // GetCommands adds common flags to query commands func GetCommands(cmds ...*cobra.Command) []*cobra.Command { @@ -58,7 +67,6 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command { c.Flags().String(FlagChainID, "", "Chain ID of tendermint node") c.Flags().String(FlagNode, "tcp://localhost:26657", ": to tendermint rpc interface for this chain") c.Flags().Bool(FlagUseLedger, false, "Use a connected Ledger device") - c.Flags().Int64(FlagGas, DefaultGasLimit, "gas limit to set per-transaction; set to 0 to calculate required gas automatically") c.Flags().Float64(FlagGasAdjustment, DefaultGasAdjustment, "adjustment factor to be multiplied against the estimate returned by the tx simulation; if the gas limit is set manually this flag is ignored ") c.Flags().Bool(FlagAsync, false, "broadcast transactions asynchronously") c.Flags().Bool(FlagJson, false, "return output in json format") @@ -66,6 +74,50 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command { c.Flags().Bool(FlagTrustNode, true, "Don't verify proofs for query responses") c.Flags().Bool(FlagDryRun, false, "ignore the --gas flag and perform a simulation of a transaction, but don't broadcast it") c.Flags().Bool(FlagGenerateOnly, false, "build an unsigned transaction and write it to STDOUT") + // --gas can accept integers and "simulate" + c.Flags().Var(&GasFlagVar, "gas", fmt.Sprintf( + "gas limit to set per-transaction; set to %q to calculate required gas automatically (default %d)", GasFlagSimulate, DefaultGasLimit)) } return cmds } + +// Gas flag parsing functions + +// GasSetting encapsulates the possible values passed through the --gas flag. +type GasSetting struct { + Simulate bool + Gas int64 +} + +// Type returns the flag's value type. +func (v *GasSetting) Type() string { return "string" } + +// Set parses and sets the value of the --gas flag. +func (v *GasSetting) Set(s string) (err error) { + v.Simulate, v.Gas, err = ReadGasFlag(s) + return +} + +func (v *GasSetting) String() string { + if v.Simulate { + return GasFlagSimulate + } + return strconv.FormatInt(v.Gas, 10) +} + +// ParseGasFlag parses the value of the --gas flag. +func ReadGasFlag(s string) (simulate bool, gas int64, err error) { + switch s { + case "": + gas = DefaultGasLimit + case GasFlagSimulate: + simulate = true + default: + gas, err = strconv.ParseInt(s, 10, 64) + if err != nil { + err = fmt.Errorf("gas must be either integer or %q", GasFlagSimulate) + return + } + } + return +} diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index 977c03cf72..b3c27bfbab 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -267,21 +267,29 @@ func TestCoinSend(t *testing.T) { require.Equal(t, int64(1), mycoins.Amount.Int64()) // test failure with too little gas - res, body, _ = doSendWithGas(t, port, seed, name, password, addr, 100, 0, "") + res, body, _ = doSendWithGas(t, port, seed, name, password, addr, "100", 0, "") + require.Equal(t, http.StatusInternalServerError, res.StatusCode, body) + + // test failure with negative gas + res, body, _ = doSendWithGas(t, port, seed, name, password, addr, "-200", 0, "") + require.Equal(t, http.StatusInternalServerError, res.StatusCode, body) + + // test failure with 0 gas + res, body, _ = doSendWithGas(t, port, seed, name, password, addr, "0", 0, "") require.Equal(t, http.StatusInternalServerError, res.StatusCode, body) // test failure with wrong adjustment - res, body, _ = doSendWithGas(t, port, seed, name, password, addr, 0, 0.1, "") + res, body, _ = doSendWithGas(t, port, seed, name, password, addr, "simulate", 0.1, "") require.Equal(t, http.StatusInternalServerError, res.StatusCode, body) // run simulation and test success with estimated gas - res, body, _ = doSendWithGas(t, port, seed, name, password, addr, 0, 0, "?simulate=true") + res, body, _ = doSendWithGas(t, port, seed, name, password, addr, "", 0, "?simulate=true") require.Equal(t, http.StatusOK, res.StatusCode, body) var responseBody struct { GasEstimate int64 `json:"gas_estimate"` } require.Nil(t, json.Unmarshal([]byte(body), &responseBody)) - res, body, _ = doSendWithGas(t, port, seed, name, password, addr, responseBody.GasEstimate, 0, "") + res, body, _ = doSendWithGas(t, port, seed, name, password, addr, fmt.Sprintf("%v", responseBody.GasEstimate), 0, "") require.Equal(t, http.StatusOK, res.StatusCode, body) } @@ -322,7 +330,7 @@ func TestCoinSendGenerateSignAndBroadcast(t *testing.T) { acc := getAccount(t, port, addr) // generate TX - res, body, _ := doSendWithGas(t, port, seed, name, password, addr, 0, 0, "?generate_only=true") + res, body, _ := doSendWithGas(t, port, seed, name, password, addr, "simulate", 0, "?generate_only=true") require.Equal(t, http.StatusOK, res.StatusCode, body) var msg auth.StdTx require.Nil(t, cdc.UnmarshalJSON([]byte(body), &msg)) @@ -792,7 +800,7 @@ func getAccount(t *testing.T, port string, addr sdk.AccAddress) auth.Account { return acc } -func doSendWithGas(t *testing.T, port, seed, name, password string, addr sdk.AccAddress, gas int64, gasAdjustment float64, queryStr string) (res *http.Response, body string, receiveAddr sdk.AccAddress) { +func doSendWithGas(t *testing.T, port, seed, name, password string, addr sdk.AccAddress, gas string, gasAdjustment float64, queryStr string) (res *http.Response, body string, receiveAddr sdk.AccAddress) { // create receive address kb := client.MockKeyBase() @@ -811,14 +819,14 @@ func doSendWithGas(t *testing.T, port, seed, name, password string, addr sdk.Acc } gasStr := "" - if gas > 0 { + if len(gas) != 0 { gasStr = fmt.Sprintf(` - "gas":"%v", + "gas":%q, `, gas) } gasAdjustmentStr := "" if gasAdjustment > 0 { - gasStr = fmt.Sprintf(` + gasAdjustmentStr = fmt.Sprintf(` "gas_adjustment":"%v", `, gasAdjustment) } @@ -837,7 +845,7 @@ func doSendWithGas(t *testing.T, port, seed, name, password string, addr sdk.Acc } func doSend(t *testing.T, port, seed, name, password string, addr sdk.AccAddress) (receiveAddr sdk.AccAddress, resultTx ctypes.ResultBroadcastTxCommit) { - res, body, receiveAddr := doSendWithGas(t, port, seed, name, password, addr, 0, 0, "") + res, body, receiveAddr := doSendWithGas(t, port, seed, name, password, addr, "", 0, "") require.Equal(t, http.StatusOK, res.StatusCode, body) err := cdc.UnmarshalJSON([]byte(body), &resultTx) diff --git a/client/utils/utils.go b/client/utils/utils.go index 54d9dd584c..52472ba1eb 100644 --- a/client/utils/utils.go +++ b/client/utils/utils.go @@ -24,8 +24,8 @@ func SendTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) if err != nil { return err } - autogas := cliCtx.DryRun || (cliCtx.Gas == 0) - if autogas { + + if txBldr.SimulateGas || cliCtx.DryRun { txBldr, err = EnrichCtxWithGas(txBldr, cliCtx, cliCtx.FromAddressName, msgs) if err != nil { return err @@ -50,20 +50,10 @@ func SendTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) return cliCtx.EnsureBroadcastTx(txBytes) } -// SimulateMsgs simulates the transaction and returns the gas estimate and the adjusted value. -func SimulateMsgs(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg, gas int64) (estimated, adjusted int64, err error) { - txBytes, err := txBldr.WithGas(gas).BuildWithPubKey(name, msgs) - if err != nil { - return - } - estimated, adjusted, err = CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, cliCtx.GasAdjustment) - return -} - // EnrichCtxWithGas calculates the gas estimate that would be consumed by the // transaction and set the transaction's respective value accordingly. func EnrichCtxWithGas(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg) (authtxb.TxBuilder, error) { - _, adjusted, err := SimulateMsgs(txBldr, cliCtx, name, msgs, 0) + _, adjusted, err := simulateMsgs(txBldr, cliCtx, name, msgs) if err != nil { return txBldr, err } @@ -143,6 +133,16 @@ func SignStdTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name string, return txBldr.SignStdTx(name, passphrase, stdTx, appendSig) } +// SimulateMsgs simulates the transaction and returns the gas estimate and the adjusted value. +func simulateMsgs(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg) (estimated, adjusted int64, err error) { + txBytes, err := txBldr.BuildWithPubKey(name, msgs) + if err != nil { + return + } + estimated, adjusted, err = CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, txBldr.GasAdjustment) + return +} + func adjustGasEstimate(estimate int64, adjustment float64) int64 { return int64(adjustment * float64(estimate)) } @@ -194,7 +194,7 @@ func buildUnsignedStdTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msg if err != nil { return } - if txBldr.Gas == 0 { + if txBldr.SimulateGas { txBldr, err = EnrichCtxWithGas(txBldr, cliCtx, cliCtx.FromAddressName, msgs) if err != nil { return diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 032482e7bc..43f35925e3 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -112,8 +112,16 @@ func TestGaiaCLIGasAuto(t *testing.T) { fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", fooAddr, flags)) require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf("steak").Int64()) + // Test failure with negative gas + success = executeWrite(t, fmt.Sprintf("gaiacli send %v --gas=-100 --amount=10steak --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass) + require.False(t, success) + + // Test failure with 0 gas + success = executeWrite(t, fmt.Sprintf("gaiacli send %v --gas=0 --amount=10steak --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass) + require.False(t, success) + // Enable auto gas - success, stdout, _ := executeWriteRetStdStreams(t, fmt.Sprintf("gaiacli send %v --json --gas=0 --amount=10steak --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass) + success, stdout, _ := executeWriteRetStdStreams(t, fmt.Sprintf("gaiacli send %v --json --gas=simulate --amount=10steak --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass) require.True(t, success) // check that gas wanted == gas used cdc := app.MakeCodec() @@ -381,7 +389,7 @@ func TestGaiaCLISendGenerateSignAndBroadcast(t *testing.T) { // Test generate sendTx, estimate gas success, stdout, stderr = executeWriteRetStdStreams(t, fmt.Sprintf( - "gaiacli send %v --amount=10steak --to=%s --from=foo --gas=0 --generate-only", + "gaiacli send %v --amount=10steak --to=%s --from=foo --gas=simulate --generate-only", flags, barAddr), []string{}...) require.True(t, success) require.NotEmpty(t, stderr) diff --git a/docs/light/api.md b/docs/light/api.md index 6c7f9de177..7fbf9fbe19 100644 --- a/docs/light/api.md +++ b/docs/light/api.md @@ -763,7 +763,7 @@ The GovernanceAPI exposes all functionality needed for casting votes on plain te "chain_id": "string", "account_number": 0, "sequence": 0, - "gas": 0 + "gas": "simulate" }, "depositer": "string", "amount": 0, @@ -866,7 +866,7 @@ The GovernanceAPI exposes all functionality needed for casting votes on plain te "chain_id": "string", "account_number": 0, "sequence": 0, - "gas": 0 + "gas": "simulate" }, // A cosmos address "voter": "string", diff --git a/docs/sdk/clients.md b/docs/sdk/clients.md index 4d02d3c908..5b7d3ca866 100644 --- a/docs/sdk/clients.md +++ b/docs/sdk/clients.md @@ -111,7 +111,7 @@ The `--amount` flag accepts the format `--amount=`. ::: tip Note You may want to cap the maximum gas that can be consumed by the transaction via the `--gas` flag. -If set to 0, the gas limit will be automatically estimated. +If you pass `--gas=simulate`, the gas limit will be automatically estimated. Gas estimate might be inaccurate as state changes could occur in between the end of the simulation and the actual execution of a transaction, thus an adjustment is applied on top of the original estimate in order to ensure the transaction is broadcasted successfully. The adjustment can be controlled via the `--gas-adjustment` flag, whose default value is 1.0. ::: diff --git a/x/auth/client/txbuilder/txbuilder.go b/x/auth/client/txbuilder/txbuilder.go index 026eabecef..6daa75e120 100644 --- a/x/auth/client/txbuilder/txbuilder.go +++ b/x/auth/client/txbuilder/txbuilder.go @@ -16,7 +16,9 @@ type TxBuilder struct { Codec *wire.Codec AccountNumber int64 Sequence int64 - Gas int64 + Gas int64 // TODO: should this turn into uint64? requires further discussion - see #2173 + GasAdjustment float64 + SimulateGas bool ChainID string Memo string Fee string @@ -36,9 +38,11 @@ func NewTxBuilderFromCLI() TxBuilder { return TxBuilder{ ChainID: chainID, - Gas: viper.GetInt64(client.FlagGas), AccountNumber: viper.GetInt64(client.FlagAccountNumber), + Gas: client.GasFlagVar.Gas, + GasAdjustment: viper.GetFloat64(client.FlagGasAdjustment), Sequence: viper.GetInt64(client.FlagSequence), + SimulateGas: client.GasFlagVar.Simulate, Fee: viper.GetString(client.FlagFee), Memo: viper.GetString(client.FlagMemo), } diff --git a/x/bank/client/rest/sendtx.go b/x/bank/client/rest/sendtx.go index 82df24642f..02a66f2b90 100644 --- a/x/bank/client/rest/sendtx.go +++ b/x/bank/client/rest/sendtx.go @@ -32,7 +32,7 @@ type sendBody struct { ChainID string `json:"chain_id"` AccountNumber int64 `json:"account_number"` Sequence int64 `json:"sequence"` - Gas int64 `json:"gas"` + Gas string `json:"gas"` GasAdjustment string `json:"gas_adjustment"` } @@ -81,31 +81,37 @@ func SendRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLICo return } - txBldr := authtxb.TxBuilder{ - Codec: cdc, - Gas: m.Gas, - ChainID: m.ChainID, - AccountNumber: m.AccountNumber, - Sequence: m.Sequence, + simulateGas, gas, err := cliclient.ReadGasFlag(m.Gas) + if err != nil { + utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return } adjustment, ok := utils.ParseFloat64OrReturnBadRequest(w, m.GasAdjustment, cliclient.DefaultGasAdjustment) if !ok { return } - cliCtx = cliCtx.WithGasAdjustment(adjustment) + txBldr := authtxb.TxBuilder{ + Codec: cdc, + Gas: gas, + GasAdjustment: adjustment, + SimulateGas: simulateGas, + ChainID: m.ChainID, + AccountNumber: m.AccountNumber, + Sequence: m.Sequence, + } - if utils.HasDryRunArg(r) || m.Gas == 0 { - newCtx, err := utils.EnrichCtxWithGas(txBldr, cliCtx, m.LocalAccountName, []sdk.Msg{msg}) + if utils.HasDryRunArg(r) || txBldr.SimulateGas { + newBldr, err := utils.EnrichCtxWithGas(txBldr, cliCtx, m.LocalAccountName, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } if utils.HasDryRunArg(r) { - utils.WriteSimulationResponse(w, txBldr.Gas) + utils.WriteSimulationResponse(w, newBldr.Gas) return } - txBldr = newCtx + txBldr = newBldr } if utils.HasGenerateOnlyArg(r) { diff --git a/x/gov/client/rest/util.go b/x/gov/client/rest/util.go index f9987c0308..b152cb20b2 100644 --- a/x/gov/client/rest/util.go +++ b/x/gov/client/rest/util.go @@ -20,7 +20,7 @@ type baseReq struct { ChainID string `json:"chain_id"` AccountNumber int64 `json:"account_number"` Sequence int64 `json:"sequence"` - Gas int64 `json:"gas"` + Gas string `json:"gas"` GasAdjustment string `json:"gas_adjustment"` } @@ -69,32 +69,37 @@ func (req baseReq) baseReqValidate(w http.ResponseWriter) bool { // TODO: Build this function out into a more generic base-request // (probably should live in client/lcd). func signAndBuild(w http.ResponseWriter, r *http.Request, cliCtx context.CLIContext, baseReq baseReq, msg sdk.Msg, cdc *wire.Codec) { - var err error - txBldr := authtxb.TxBuilder{ - Codec: cdc, - AccountNumber: baseReq.AccountNumber, - Sequence: baseReq.Sequence, - ChainID: baseReq.ChainID, - Gas: baseReq.Gas, + simulateGas, gas, err := client.ReadGasFlag(baseReq.Gas) + if err != nil { + utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return } adjustment, ok := utils.ParseFloat64OrReturnBadRequest(w, baseReq.GasAdjustment, client.DefaultGasAdjustment) if !ok { return } - cliCtx = cliCtx.WithGasAdjustment(adjustment) + txBldr := authtxb.TxBuilder{ + Codec: cdc, + Gas: gas, + GasAdjustment: adjustment, + SimulateGas: simulateGas, + ChainID: baseReq.ChainID, + AccountNumber: baseReq.AccountNumber, + Sequence: baseReq.Sequence, + } - if utils.HasDryRunArg(r) || baseReq.Gas == 0 { - newCtx, err := utils.EnrichCtxWithGas(txBldr, cliCtx, baseReq.Name, []sdk.Msg{msg}) + if utils.HasDryRunArg(r) || txBldr.SimulateGas { + newBldr, err := utils.EnrichCtxWithGas(txBldr, cliCtx, baseReq.Name, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } if utils.HasDryRunArg(r) { - utils.WriteSimulationResponse(w, txBldr.Gas) + utils.WriteSimulationResponse(w, newBldr.Gas) return } - txBldr = newCtx + txBldr = newBldr } if utils.HasGenerateOnlyArg(r) { diff --git a/x/ibc/client/rest/transfer.go b/x/ibc/client/rest/transfer.go index 110efe601e..5a7b632e83 100644 --- a/x/ibc/client/rest/transfer.go +++ b/x/ibc/client/rest/transfer.go @@ -29,7 +29,7 @@ type transferBody struct { SrcChainID string `json:"src_chain_id"` AccountNumber int64 `json:"account_number"` Sequence int64 `json:"sequence"` - Gas int64 `json:"gas"` + Gas string `json:"gas"` GasAdjustment string `json:"gas_adjustment"` } @@ -71,21 +71,26 @@ func TransferRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.C packet := ibc.NewIBCPacket(sdk.AccAddress(info.GetPubKey().Address()), to, m.Amount, m.SrcChainID, destChainID) msg := ibc.IBCTransferMsg{packet} - txBldr := authtxb.TxBuilder{ - Codec: cdc, - ChainID: m.SrcChainID, - AccountNumber: m.AccountNumber, - Sequence: m.Sequence, - Gas: m.Gas, + simulateGas, gas, err := client.ReadGasFlag(m.Gas) + if err != nil { + utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return } - adjustment, ok := utils.ParseFloat64OrReturnBadRequest(w, m.GasAdjustment, client.DefaultGasAdjustment) if !ok { return } - cliCtx = cliCtx.WithGasAdjustment(adjustment) + txBldr := authtxb.TxBuilder{ + Codec: cdc, + Gas: gas, + GasAdjustment: adjustment, + SimulateGas: simulateGas, + ChainID: m.SrcChainID, + AccountNumber: m.AccountNumber, + Sequence: m.Sequence, + } - if utils.HasDryRunArg(r) || m.Gas == 0 { + if utils.HasDryRunArg(r) || txBldr.SimulateGas { newCtx, err := utils.EnrichCtxWithGas(txBldr, cliCtx, m.LocalAccountName, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) diff --git a/x/slashing/client/rest/tx.go b/x/slashing/client/rest/tx.go index 1d4fdefa1d..969cdcce09 100644 --- a/x/slashing/client/rest/tx.go +++ b/x/slashing/client/rest/tx.go @@ -70,22 +70,20 @@ func unjailRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLI return } + adjustment, ok := utils.ParseFloat64OrReturnBadRequest(w, m.GasAdjustment, client.DefaultGasAdjustment) + if !ok { + return + } txBldr := authtxb.TxBuilder{ Codec: cdc, ChainID: m.ChainID, AccountNumber: m.AccountNumber, Sequence: m.Sequence, Gas: m.Gas, + GasAdjustment: adjustment, } msg := slashing.NewMsgUnjail(valAddr) - - adjustment, ok := utils.ParseFloat64OrReturnBadRequest(w, m.GasAdjustment, client.DefaultGasAdjustment) - if !ok { - return - } - cliCtx = cliCtx.WithGasAdjustment(adjustment) - if utils.HasDryRunArg(r) || m.Gas == 0 { newCtx, err := utils.EnrichCtxWithGas(txBldr, cliCtx, m.LocalAccountName, []sdk.Msg{msg}) if err != nil { diff --git a/x/stake/client/rest/tx.go b/x/stake/client/rest/tx.go index d84a8daea9..fda92f85aa 100644 --- a/x/stake/client/rest/tx.go +++ b/x/stake/client/rest/tx.go @@ -60,7 +60,7 @@ type EditDelegationsBody struct { ChainID string `json:"chain_id"` AccountNumber int64 `json:"account_number"` Sequence int64 `json:"sequence"` - Gas int64 `json:"gas"` + Gas string `json:"gas"` GasAdjustment string `json:"gas_adjustment"` Delegations []msgDelegationsInput `json:"delegations"` BeginUnbondings []msgBeginUnbondingInput `json:"begin_unbondings"` @@ -263,10 +263,21 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex i++ } + simulateGas, gas, err := client.ReadGasFlag(m.Gas) + if err != nil { + utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + adjustment, ok := utils.ParseFloat64OrReturnBadRequest(w, m.GasAdjustment, client.DefaultGasAdjustment) + if !ok { + return + } txBldr := authtxb.TxBuilder{ - Codec: cdc, - ChainID: m.ChainID, - Gas: m.Gas, + Codec: cdc, + Gas: gas, + GasAdjustment: adjustment, + SimulateGas: simulateGas, + ChainID: m.ChainID, } // sign messages @@ -275,26 +286,19 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex // increment sequence for each message txBldr = txBldr.WithAccountNumber(m.AccountNumber) txBldr = txBldr.WithSequence(m.Sequence) - m.Sequence++ - adjustment, ok := utils.ParseFloat64OrReturnBadRequest(w, m.GasAdjustment, client.DefaultGasAdjustment) - if !ok { - return - } - cliCtx = cliCtx.WithGasAdjustment(adjustment) - - if utils.HasDryRunArg(r) || m.Gas == 0 { - newCtx, err := utils.EnrichCtxWithGas(txBldr, cliCtx, m.LocalAccountName, []sdk.Msg{msg}) + if utils.HasDryRunArg(r) || txBldr.SimulateGas { + newBldr, err := utils.EnrichCtxWithGas(txBldr, cliCtx, m.LocalAccountName, []sdk.Msg{msg}) if err != nil { utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } if utils.HasDryRunArg(r) { - utils.WriteSimulationResponse(w, txBldr.Gas) + utils.WriteSimulationResponse(w, newBldr.Gas) return } - txBldr = newCtx + txBldr = newBldr } if utils.HasGenerateOnlyArg(r) { From 358b48771cb406a6edc02e25ab81c87f20d129ac Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Wed, 12 Sep 2018 00:13:14 -0700 Subject: [PATCH 86/93] Merge PR #2308: Remove ripemd160 entirely * Remove ripemd160 entirely We already made this decision awhile ago, and have had tendermint switched for awhile. I was surprised to find ripemd still used within the storeinfo. This actually leads me to think the new "byter" API change in the tendermint PR RFC compliance is better, as it avoids things like this from ever happening. * Get ripemd160 removed from the gopkg imports --- Gopkg.lock | 1 - PENDING.md | 1 + examples/README.md | 2 +- store/multistoreproof.go | 2 +- store/multistoreproof_test.go | 9 +++++---- store/rootmultistore.go | 5 ++--- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index b647d20212..d5ccc65899 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -679,7 +679,6 @@ "github.com/tendermint/tmlibs/cli", "github.com/zondax/ledger-goclient", "golang.org/x/crypto/blowfish", - "golang.org/x/crypto/ripemd160", ] solver-name = "gps-cdcl" solver-version = 1 diff --git a/PENDING.md b/PENDING.md index aec65f3d56..652da599b0 100644 --- a/PENDING.md +++ b/PENDING.md @@ -43,6 +43,7 @@ BREAKING CHANGES * [simulation] Remove log and testing.TB from Operation and Invariants, in favor of using errors \#2282 * [tools] Removed gocyclo [#2211](https://github.com/cosmos/cosmos-sdk/issues/2211) * [baseapp] Remove `SetTxDecoder` in favor of requiring the decoder be set in baseapp initialization. [#1441](https://github.com/cosmos/cosmos-sdk/issues/1441) + * [store] Change storeInfo within the root multistore to use tmhash instead of ripemd160 \#2308 * Tendermint diff --git a/examples/README.md b/examples/README.md index 11aef9d280..5d872a7c93 100644 --- a/examples/README.md +++ b/examples/README.md @@ -253,7 +253,7 @@ first time. Accounts are serialized and stored in a Merkle tree under the key ``base/a/
``, where ``
`` is the address of the account. -Typically, the address of the account is the 20-byte ``RIPEMD160`` hash +Typically, the address of the account is the first 20-bytes of the ``sha256`` hash of the public key, but other formats are acceptable as well, as defined in the `Tendermint crypto library `__. The Merkle tree diff --git a/store/multistoreproof.go b/store/multistoreproof.go index e25f1cc1f2..d62bc4aca5 100644 --- a/store/multistoreproof.go +++ b/store/multistoreproof.go @@ -2,6 +2,7 @@ package store import ( "bytes" + "github.com/pkg/errors" "github.com/tendermint/iavl" cmn "github.com/tendermint/tendermint/libs/common" @@ -47,7 +48,6 @@ func VerifyMultiStoreCommitInfo(storeName string, storeInfos []storeInfo, appHas Version: height, StoreInfos: storeInfos, } - if !bytes.Equal(appHash, ci.Hash()) { return nil, cmn.NewError("the merkle root of multiStoreCommitInfo doesn't equal to appHash") } diff --git a/store/multistoreproof_test.go b/store/multistoreproof_test.go index 790588fb29..45a102cd3b 100644 --- a/store/multistoreproof_test.go +++ b/store/multistoreproof_test.go @@ -5,13 +5,14 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/tendermint/iavl" cmn "github.com/tendermint/tendermint/libs/common" "github.com/tendermint/tendermint/libs/db" ) func TestVerifyMultiStoreCommitInfo(t *testing.T) { - appHash, _ := hex.DecodeString("ebf3c1fb724d3458023c8fefef7b33add2fc1e84") + appHash, _ := hex.DecodeString("69959B1B4E68E0F7BD3551A50C8F849B81801AF2") substoreRootHash, _ := hex.DecodeString("ea5d468431015c2cd6295e9a0bb1fc0e49033828") storeName := "acc" @@ -83,13 +84,13 @@ func TestVerifyMultiStoreCommitInfo(t *testing.T) { }) commitHash, err := VerifyMultiStoreCommitInfo(storeName, storeInfos, appHash) - assert.Nil(t, err) - assert.Equal(t, commitHash, substoreRootHash) + require.Nil(t, err) + require.Equal(t, commitHash, substoreRootHash) appHash, _ = hex.DecodeString("29de216bf5e2531c688de36caaf024cd3bb09ee3") _, err = VerifyMultiStoreCommitInfo(storeName, storeInfos, appHash) - assert.Error(t, err, "appHash doesn't match to the merkle root of multiStoreCommitInfo") + require.Error(t, err, "appHash doesn't match to the merkle root of multiStoreCommitInfo") } func TestVerifyRangeProof(t *testing.T) { diff --git a/store/rootmultistore.go b/store/rootmultistore.go index d9cf8a29a2..8aa2da0ba3 100644 --- a/store/rootmultistore.go +++ b/store/rootmultistore.go @@ -5,10 +5,9 @@ import ( "io" "strings" - "golang.org/x/crypto/ripemd160" - abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto/merkle" + "github.com/tendermint/tendermint/crypto/tmhash" dbm "github.com/tendermint/tendermint/libs/db" sdk "github.com/cosmos/cosmos-sdk/types" @@ -424,7 +423,7 @@ func (si storeInfo) Hash() []byte { // Doesn't write Name, since merkle.SimpleHashFromMap() will // include them via the keys. bz, _ := cdc.MarshalBinary(si.Core) // Does not error - hasher := ripemd160.New() + hasher := tmhash.New() _, err := hasher.Write(bz) if err != nil { // TODO: Handle with #870 From 55b7c6adf11f4949793b44c9755cfa409c478eb4 Mon Sep 17 00:00:00 2001 From: Jia Chenhui Date: Wed, 12 Sep 2018 15:14:29 +0800 Subject: [PATCH 87/93] Merge PR #2304: client/keys: remove excess code and uniform code style --- client/keys/show.go | 86 +++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 46 deletions(-) diff --git a/client/keys/show.go b/client/keys/show.go index 9710cac11e..c7cae1f7cc 100644 --- a/client/keys/show.go +++ b/client/keys/show.go @@ -5,9 +5,7 @@ import ( "fmt" "net/http" - "github.com/cosmos/cosmos-sdk/crypto/keys" "github.com/gorilla/mux" - "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -19,7 +17,7 @@ const ( FlagAddress = "address" // FlagPublicKey represents the user's public key on the command line. FlagPublicKey = "pubkey" - // FlagBechPrefix defines a desired Bech32 prefix encoding for a key + // FlagBechPrefix defines a desired Bech32 prefix encoding for a key. FlagBechPrefix = "bech" ) @@ -29,39 +27,7 @@ func showKeysCmd() *cobra.Command { Short: "Show key info for the given name", Long: `Return public details of one local key.`, Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - name := args[0] - info, err := getKey(name) - if err != nil { - return err - } - - showAddress := viper.GetBool(FlagAddress) - showPublicKey := viper.GetBool(FlagPublicKey) - outputSet := cmd.Flag(cli.OutputFlag).Changed - - if showAddress && showPublicKey { - return errors.New("cannot use both --address and --pubkey at once") - } - if outputSet && (showAddress || showPublicKey) { - return errors.New("cannot use --output with --address or --pubkey") - } - - bechKeyOut, err := getBechKeyOut(viper.GetString(FlagBechPrefix)) - if err != nil { - return err - } - - switch { - case showAddress: - printKeyAddress(info, bechKeyOut) - case showPublicKey: - printPubKey(info, bechKeyOut) - default: - printKeyInfo(info, bechKeyOut) - } - return nil - }, + RunE: runShowCmd, } cmd.Flags().String(FlagBechPrefix, "acc", "The Bech32 prefix encoding for a key (acc|val|cons)") @@ -71,6 +37,43 @@ func showKeysCmd() *cobra.Command { return cmd } +func runShowCmd(cmd *cobra.Command, args []string) error { + name := args[0] + + info, err := GetKeyInfo(name) + if err != nil { + return err + } + + isShowAddr := viper.GetBool(FlagAddress) + isShowPubKey := viper.GetBool(FlagPublicKey) + isOutputSet := cmd.Flag(cli.OutputFlag).Changed + + if isShowAddr && isShowPubKey { + return errors.New("cannot use both --address and --pubkey at once") + } + + if isOutputSet && (isShowAddr || isShowPubKey) { + return errors.New("cannot use --output with --address or --pubkey") + } + + bechKeyOut, err := getBechKeyOut(viper.GetString(FlagBechPrefix)) + if err != nil { + return err + } + + switch { + case isShowAddr: + printKeyAddress(info, bechKeyOut) + case isShowPubKey: + printPubKey(info, bechKeyOut) + default: + printKeyInfo(info, bechKeyOut) + } + + return nil +} + func getBechKeyOut(bechPrefix string) (bechKeyOutFn, error) { switch bechPrefix { case "acc": @@ -84,15 +87,6 @@ func getBechKeyOut(bechPrefix string) (bechKeyOutFn, error) { return nil, fmt.Errorf("invalid Bech32 prefix encoding provided: %s", bechPrefix) } -func getKey(name string) (keys.Info, error) { - kb, err := GetKeyBase() - if err != nil { - return nil, err - } - - return kb.Get(name) -} - /////////////////////////// // REST @@ -113,7 +107,7 @@ func GetKeyRequestHandler(w http.ResponseWriter, r *http.Request) { return } - info, err := getKey(name) + info, err := GetKeyInfo(name) // TODO: check for the error if key actually does not exist, instead of // assuming this as the reason if err != nil { From 854aca2f7dd486263fcbf338e251de4f3c61c279 Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk Date: Wed, 12 Sep 2018 07:16:28 +0000 Subject: [PATCH 88/93] Merge PR #2238: Ensure Tendermint Validator Update Invariants --- PENDING.md | 2 + docs/spec/staking/end_block.md | 2 +- x/gov/simulation/msgs.go | 6 + x/mock/simulation/random_simulate_blocks.go | 15 +- x/stake/handler.go | 2 +- x/stake/keeper/validator.go | 71 +++--- x/stake/keeper/validator_test.go | 232 +++++++++++++++++--- 7 files changed, 258 insertions(+), 72 deletions(-) diff --git a/PENDING.md b/PENDING.md index 652da599b0..dd4acbe41b 100644 --- a/PENDING.md +++ b/PENDING.md @@ -122,6 +122,8 @@ BUG FIXES * [cli] [\#2265](https://github.com/cosmos/cosmos-sdk/issues/2265) Fix JSON formatting of the `gaiacli send` command. * Gaia + * [x/stake] Return correct Tendermint validator update set on `EndBlocker` by not + including non previously bonded validators that have zero power. [#2189](https://github.com/cosmos/cosmos-sdk/issues/2189) * SDK * [\#1988](https://github.com/cosmos/cosmos-sdk/issues/1988) Make us compile on OpenBSD (disable ledger) [#1988] (https://github.com/cosmos/cosmos-sdk/issues/1988) diff --git a/docs/spec/staking/end_block.md b/docs/spec/staking/end_block.md index c2fe143baf..a294692610 100644 --- a/docs/spec/staking/end_block.md +++ b/docs/spec/staking/end_block.md @@ -12,7 +12,7 @@ the changes cleared ```golang EndBlock() ValidatorSetChanges - vsc = GetTendermintUpdates() + vsc = GetValidTendermintUpdates() ClearTendermintUpdates() return vsc ``` diff --git a/x/gov/simulation/msgs.go b/x/gov/simulation/msgs.go index 399f735120..3eb21b79a5 100644 --- a/x/gov/simulation/msgs.go +++ b/x/gov/simulation/msgs.go @@ -156,13 +156,16 @@ func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.Operation { return operationSimulateMsgVote(k, sk, nil, -1) } + // nolint: unparam func operationSimulateMsgVote(k gov.Keeper, sk stake.Keeper, key crypto.PrivKey, proposalID int64) simulation.Operation { return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOp []simulation.FutureOperation, err error) { if key == nil { key = simulation.RandomKey(r, keys) } + var ok bool + if proposalID < 0 { proposalID, ok = randomProposalID(r, k, ctx) if !ok { @@ -171,15 +174,18 @@ func operationSimulateMsgVote(k gov.Keeper, sk stake.Keeper, key crypto.PrivKey, } addr := sdk.AccAddress(key.PubKey().Address()) option := randomVotingOption(r) + msg := gov.NewMsgVote(addr, proposalID, option) if msg.ValidateBasic() != nil { return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) } + ctx, write := ctx.CacheContext() result := gov.NewHandler(k)(ctx, msg) if result.IsOK() { write() } + event(fmt.Sprintf("gov/MsgVote/%v", result.IsOK())) action = fmt.Sprintf("TestMsgVote: ok %v, msg %s", result.IsOK(), msg.GetSignBytes()) return action, nil, nil diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index e4a263e23f..3f91b2a663 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -342,18 +342,14 @@ func RandomRequestBeginBlock(r *rand.Rand, validators map[string]mockValidator, // updateValidators mimicks Tendermint's update logic // nolint: unparam func updateValidators(tb testing.TB, r *rand.Rand, current map[string]mockValidator, updates []abci.Validator, event func(string)) map[string]mockValidator { + for _, update := range updates { switch { case update.Power == 0: - // // TEMPORARY DEBUG CODE TO PROVE THAT THE OLD METHOD WAS BROKEN - // // (i.e. didn't catch in the event of problem) - // if val, ok := tb.(*testing.T); ok { - // require.NotNil(val, current[string(update.PubKey.Data)]) - // } - // // CORRECT CHECK - // if _, ok := current[string(update.PubKey.Data)]; !ok { - // tb.Fatalf("tried to delete a nonexistent validator") - // } + if _, ok := current[string(update.PubKey.Data)]; !ok { + tb.Fatalf("tried to delete a nonexistent validator") + } + event("endblock/validatorupdates/kicked") delete(current, string(update.PubKey.Data)) default: @@ -368,5 +364,6 @@ func updateValidators(tb testing.TB, r *rand.Rand, current map[string]mockValida } } } + return current } diff --git a/x/stake/handler.go b/x/stake/handler.go index e6ceb5e7b0..b00db571d2 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -52,7 +52,7 @@ func EndBlocker(ctx sdk.Context, k keeper.Keeper) (ValidatorUpdates []abci.Valid k.SetIntraTxCounter(ctx, 0) // calculate validator set changes - ValidatorUpdates = k.GetTendermintUpdates(ctx) + ValidatorUpdates = k.GetValidTendermintUpdates(ctx) k.ClearTendermintUpdates(ctx) return } diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index c5fe3def73..aaed74be41 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -198,16 +198,37 @@ func (k Keeper) GetValidatorsByPower(ctx sdk.Context) []types.Validator { // Accumulated updates to the active/bonded validator set for tendermint // get the most recently updated validators -func (k Keeper) GetTendermintUpdates(ctx sdk.Context) (updates []abci.Validator) { +// +// CONTRACT: Only validators with non-zero power or zero-power that were bonded +// at the previous block height or were removed from the validator set entirely +// are returned to Tendermint. +func (k Keeper) GetValidTendermintUpdates(ctx sdk.Context) (updates []abci.Validator) { store := ctx.KVStore(k.storeKey) - iterator := sdk.KVStorePrefixIterator(store, TendermintUpdatesKey) //smallest to largest + iterator := sdk.KVStorePrefixIterator(store, TendermintUpdatesKey) for ; iterator.Valid(); iterator.Next() { - valBytes := iterator.Value() - var val abci.Validator - k.cdc.MustUnmarshalBinary(valBytes, &val) - updates = append(updates, val) + var abciVal abci.Validator + + abciValBytes := iterator.Value() + k.cdc.MustUnmarshalBinary(abciValBytes, &abciVal) + + val, found := k.GetValidator(ctx, abciVal.GetAddress()) + if found { + // The validator is new or already exists in the store and must adhere to + // Tendermint invariants. + prevBonded := val.BondHeight < ctx.BlockHeight() && val.BondHeight > val.UnbondingHeight + zeroPower := val.GetPower().Equal(sdk.ZeroDec()) + + if !zeroPower || zeroPower && prevBonded { + updates = append(updates, abciVal) + } + } else { + // Add the ABCI validator in such a case where the validator was removed + // from the store as it must have existed before. + updates = append(updates, abciVal) + } } + iterator.Close() return } @@ -240,7 +261,7 @@ func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) type validator = k.updateForJailing(ctx, oldFound, oldValidator, validator) powerIncreasing := k.getPowerIncreasing(ctx, oldFound, oldValidator, validator) - validator.BondHeight, validator.BondIntraTxCounter = k.bondIncrement(ctx, oldFound, oldValidator, validator) + validator.BondHeight, validator.BondIntraTxCounter = k.bondIncrement(ctx, oldFound, oldValidator) valPower := k.updateValidatorPower(ctx, oldFound, oldValidator, validator, pool) cliffPower := k.GetCliffValidatorPower(ctx) cliffValExists := (cliffPower != nil) @@ -316,7 +337,7 @@ func (k Keeper) updateCliffValidator(ctx sdk.Context, affectedVal types.Validato oldCliffVal, found := k.GetValidator(ctx, cliffAddr) if !found { - panic(fmt.Sprintf("cliff validator record not found for address: %v\n", cliffAddr)) + panic(fmt.Sprintf("cliff validator record not found for address: %X\n", cliffAddr)) } // Create a validator iterator ranging from smallest to largest by power @@ -331,7 +352,7 @@ func (k Keeper) updateCliffValidator(ctx sdk.Context, affectedVal types.Validato ensureValidatorFound(found, ownerAddr) if currVal.Status != sdk.Bonded || currVal.Jailed { - panic(fmt.Sprintf("unexpected jailed or unbonded validator for address: %s\n", ownerAddr)) + panic(fmt.Sprintf("unexpected jailed or unbonded validator for address: %X\n", ownerAddr)) } newCliffVal = currVal @@ -344,13 +365,10 @@ func (k Keeper) updateCliffValidator(ctx sdk.Context, affectedVal types.Validato newCliffValRank := GetValidatorsByPowerIndexKey(newCliffVal, pool) if bytes.Equal(affectedVal.OperatorAddr, newCliffVal.OperatorAddr) { - // The affected validator remains the cliff validator, however, since // the store does not contain the new power, update the new power rank. store.Set(ValidatorPowerCliffKey, affectedValRank) - } else if bytes.Compare(affectedValRank, newCliffValRank) > 0 { - // The affected validator no longer remains the cliff validator as it's // power is greater than the new cliff validator. k.setCliffValidator(ctx, newCliffVal, pool) @@ -381,18 +399,20 @@ func (k Keeper) getPowerIncreasing(ctx sdk.Context, oldFound bool, oldValidator, // get the bond height and incremented intra-tx counter // nolint: unparam -func (k Keeper) bondIncrement(ctx sdk.Context, oldFound bool, oldValidator, - newValidator types.Validator) (height int64, intraTxCounter int16) { +func (k Keeper) bondIncrement( + ctx sdk.Context, found bool, oldValidator types.Validator) (height int64, intraTxCounter int16) { - // if already a validator, copy the old block height and counter, else set them - if oldFound && oldValidator.Status == sdk.Bonded { + // if already a validator, copy the old block height and counter + if found && oldValidator.Status == sdk.Bonded { height = oldValidator.BondHeight intraTxCounter = oldValidator.BondIntraTxCounter return } + height = ctx.BlockHeight() counter := k.GetIntraTxCounter(ctx) intraTxCounter = counter + k.SetIntraTxCounter(ctx, counter+1) return } @@ -458,22 +478,20 @@ func (k Keeper) UpdateBondedValidators( // if we've reached jailed validators no further bonded validators exist if validator.Jailed { - break - } - - // increment bondedValidatorsCount / get the validator to bond - if validator.Status != sdk.Bonded { - validatorToBond = validator - if newValidatorBonded { - panic("already decided to bond a validator, can't bond another!") + if validator.Status == sdk.Bonded { + panic(fmt.Sprintf("jailed validator cannot be bonded, address: %X\n", ownerAddr)) } - newValidatorBonded = true + + break } // increment the total number of bonded validators and potentially mark // the validator to bond if validator.Status != sdk.Bonded { validatorToBond = validator + if newValidatorBonded { + panic("already decided to bond a validator, can't bond another!") + } newValidatorBonded = true } @@ -507,7 +525,6 @@ func (k Keeper) UpdateBondedValidators( // validator was newly bonded and has greater power k.beginUnbondingValidator(ctx, oldCliffVal) } else { - // otherwise begin unbonding the affected validator, which must // have been kicked out affectedValidator = k.beginUnbondingValidator(ctx, affectedValidator) @@ -653,6 +670,8 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types. panic(fmt.Sprintf("should not already be bonded, validator: %v\n", validator)) } + validator.BondHeight = ctx.BlockHeight() + // set the status validator, pool = validator.UpdateStatus(pool, sdk.Bonded) k.SetPool(ctx, pool) diff --git a/x/stake/keeper/validator_test.go b/x/stake/keeper/validator_test.go index 87fbcbc651..d9531ae1a7 100644 --- a/x/stake/keeper/validator_test.go +++ b/x/stake/keeper/validator_test.go @@ -16,8 +16,11 @@ func TestSetValidator(t *testing.T) { ctx, _, keeper := CreateTestInput(t, false, 10) pool := keeper.GetPool(ctx) + valPubKey := PKs[0] + valAddr := sdk.ValAddress(valPubKey.Address().Bytes()) + // test how the validator is set from a purely unbonbed pool - validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) + validator := types.NewValidator(valAddr, valPubKey, types.Description{}) validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(10)) require.Equal(t, sdk.Unbonded, validator.Status) assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens)) @@ -26,14 +29,14 @@ func TestSetValidator(t *testing.T) { keeper.UpdateValidator(ctx, validator) // after the save the validator should be bonded - validator, found := keeper.GetValidator(ctx, addrVals[0]) + validator, found := keeper.GetValidator(ctx, valAddr) require.True(t, found) require.Equal(t, sdk.Bonded, validator.Status) 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]) + resVal, found := keeper.GetValidator(ctx, valAddr) assert.True(ValEq(t, validator, resVal)) require.True(t, found) @@ -45,7 +48,7 @@ func TestSetValidator(t *testing.T) { require.Equal(t, 1, len(resVals)) assert.True(ValEq(t, validator, resVals[0])) - updates := keeper.GetTendermintUpdates(ctx) + updates := keeper.GetValidTendermintUpdates(ctx) require.Equal(t, 1, len(updates)) require.Equal(t, validator.ABCIValidator(), updates[0]) } @@ -641,38 +644,47 @@ func TestClearTendermintUpdates(t *testing.T) { validators := make([]types.Validator, len(amts)) for i, amt := range amts { pool := keeper.GetPool(ctx) - validators[i] = types.NewValidator(sdk.ValAddress(Addrs[i]), PKs[i], types.Description{}) + + valPubKey := PKs[i] + valAddr := sdk.ValAddress(valPubKey.Address().Bytes()) + + validators[i] = types.NewValidator(valAddr, valPubKey, types.Description{}) validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) + keeper.SetPool(ctx, pool) keeper.UpdateValidator(ctx, validators[i]) } - updates := keeper.GetTendermintUpdates(ctx) + updates := keeper.GetValidTendermintUpdates(ctx) require.Equal(t, len(amts), len(updates)) keeper.ClearTendermintUpdates(ctx) - updates = keeper.GetTendermintUpdates(ctx) + updates = keeper.GetValidTendermintUpdates(ctx) require.Equal(t, 0, len(updates)) } -func TestGetTendermintUpdatesAllNone(t *testing.T) { +func TestGetValidTendermintUpdatesAllNone(t *testing.T) { ctx, _, keeper := CreateTestInput(t, false, 1000) amts := []int64{10, 20} var validators [2]types.Validator for i, amt := range amts { pool := keeper.GetPool(ctx) - validators[i] = types.NewValidator(sdk.ValAddress(Addrs[i]), PKs[i], types.Description{}) + + valPubKey := PKs[i+1] + valAddr := sdk.ValAddress(valPubKey.Address().Bytes()) + + validators[i] = types.NewValidator(valAddr, valPubKey, types.Description{}) validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) } // test from nothing to something // tendermintUpdate set: {} -> {c1, c3} - require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx))) + require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) validators[0] = keeper.UpdateValidator(ctx, validators[0]) validators[1] = keeper.UpdateValidator(ctx, validators[1]) - updates := keeper.GetTendermintUpdates(ctx) + updates := keeper.GetValidTendermintUpdates(ctx) assert.Equal(t, 2, len(updates)) assert.Equal(t, validators[0].ABCIValidator(), updates[0]) assert.Equal(t, validators[1].ABCIValidator(), updates[1]) @@ -680,12 +692,12 @@ func TestGetTendermintUpdatesAllNone(t *testing.T) { // test from something to nothing // tendermintUpdate set: {} -> {c1, c2, c3, c4} keeper.ClearTendermintUpdates(ctx) - require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx))) + require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) keeper.RemoveValidator(ctx, validators[0].OperatorAddr) keeper.RemoveValidator(ctx, validators[1].OperatorAddr) - updates = keeper.GetTendermintUpdates(ctx) + updates = keeper.GetValidTendermintUpdates(ctx) assert.Equal(t, 2, len(updates)) assert.Equal(t, tmtypes.TM2PB.PubKey(validators[0].ConsPubKey), updates[0].PubKey) assert.Equal(t, tmtypes.TM2PB.PubKey(validators[1].ConsPubKey), updates[1].PubKey) @@ -693,7 +705,7 @@ func TestGetTendermintUpdatesAllNone(t *testing.T) { assert.Equal(t, int64(0), updates[1].Power) } -func TestGetTendermintUpdatesIdentical(t *testing.T) { +func TestGetValidTendermintUpdatesIdentical(t *testing.T) { ctx, _, keeper := CreateTestInput(t, false, 1000) amts := []int64{10, 20} @@ -707,16 +719,16 @@ func TestGetTendermintUpdatesIdentical(t *testing.T) { validators[0] = keeper.UpdateValidator(ctx, validators[0]) validators[1] = keeper.UpdateValidator(ctx, validators[1]) keeper.ClearTendermintUpdates(ctx) - require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx))) + require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) // test identical, // tendermintUpdate set: {} -> {} validators[0] = keeper.UpdateValidator(ctx, validators[0]) validators[1] = keeper.UpdateValidator(ctx, validators[1]) - require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx))) + require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) } -func TestGetTendermintUpdatesSingleValueChange(t *testing.T) { +func TestGetValidTendermintUpdatesSingleValueChange(t *testing.T) { ctx, _, keeper := CreateTestInput(t, false, 1000) amts := []int64{10, 20} @@ -730,7 +742,7 @@ func TestGetTendermintUpdatesSingleValueChange(t *testing.T) { validators[0] = keeper.UpdateValidator(ctx, validators[0]) validators[1] = keeper.UpdateValidator(ctx, validators[1]) keeper.ClearTendermintUpdates(ctx) - require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx))) + require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) // test single value change // tendermintUpdate set: {} -> {c1'} @@ -738,13 +750,13 @@ func TestGetTendermintUpdatesSingleValueChange(t *testing.T) { validators[0].Tokens = sdk.NewDec(600) validators[0] = keeper.UpdateValidator(ctx, validators[0]) - updates := keeper.GetTendermintUpdates(ctx) + updates := keeper.GetValidTendermintUpdates(ctx) require.Equal(t, 1, len(updates)) require.Equal(t, validators[0].ABCIValidator(), updates[0]) } -func TestGetTendermintUpdatesMultipleValueChange(t *testing.T) { +func TestGetValidTendermintUpdatesMultipleValueChange(t *testing.T) { ctx, _, keeper := CreateTestInput(t, false, 1000) amts := []int64{10, 20} @@ -758,7 +770,7 @@ func TestGetTendermintUpdatesMultipleValueChange(t *testing.T) { validators[0] = keeper.UpdateValidator(ctx, validators[0]) validators[1] = keeper.UpdateValidator(ctx, validators[1]) keeper.ClearTendermintUpdates(ctx) - require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx))) + require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) // test multiple value change // tendermintUpdate set: {c1, c3} -> {c1', c3'} @@ -769,13 +781,13 @@ func TestGetTendermintUpdatesMultipleValueChange(t *testing.T) { validators[0] = keeper.UpdateValidator(ctx, validators[0]) validators[1] = keeper.UpdateValidator(ctx, validators[1]) - updates := keeper.GetTendermintUpdates(ctx) + updates := keeper.GetValidTendermintUpdates(ctx) require.Equal(t, 2, len(updates)) require.Equal(t, validators[0].ABCIValidator(), updates[0]) require.Equal(t, validators[1].ABCIValidator(), updates[1]) } -func TestGetTendermintUpdatesInserted(t *testing.T) { +func TestGetValidTendermintUpdatesInserted(t *testing.T) { ctx, _, keeper := CreateTestInput(t, false, 1000) amts := []int64{10, 20, 5, 15, 25} @@ -789,12 +801,12 @@ func TestGetTendermintUpdatesInserted(t *testing.T) { validators[0] = keeper.UpdateValidator(ctx, validators[0]) validators[1] = keeper.UpdateValidator(ctx, validators[1]) keeper.ClearTendermintUpdates(ctx) - require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx))) + require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) // test validtor added at the beginning // tendermintUpdate set: {} -> {c0} validators[2] = keeper.UpdateValidator(ctx, validators[2]) - updates := keeper.GetTendermintUpdates(ctx) + updates := keeper.GetValidTendermintUpdates(ctx) require.Equal(t, 1, len(updates)) require.Equal(t, validators[2].ABCIValidator(), updates[0]) @@ -802,7 +814,7 @@ func TestGetTendermintUpdatesInserted(t *testing.T) { // tendermintUpdate set: {} -> {c0} keeper.ClearTendermintUpdates(ctx) validators[3] = keeper.UpdateValidator(ctx, validators[3]) - updates = keeper.GetTendermintUpdates(ctx) + updates = keeper.GetValidTendermintUpdates(ctx) require.Equal(t, 1, len(updates)) require.Equal(t, validators[3].ABCIValidator(), updates[0]) @@ -810,12 +822,12 @@ func TestGetTendermintUpdatesInserted(t *testing.T) { // tendermintUpdate set: {} -> {c0} keeper.ClearTendermintUpdates(ctx) validators[4] = keeper.UpdateValidator(ctx, validators[4]) - updates = keeper.GetTendermintUpdates(ctx) + updates = keeper.GetValidTendermintUpdates(ctx) require.Equal(t, 1, len(updates)) require.Equal(t, validators[4].ABCIValidator(), updates[0]) } -func TestGetTendermintUpdatesWithCliffValidator(t *testing.T) { +func TestGetValidTendermintUpdatesWithCliffValidator(t *testing.T) { ctx, _, keeper := CreateTestInput(t, false, 1000) params := types.DefaultParams() params.MaxValidators = 2 @@ -832,31 +844,31 @@ func TestGetTendermintUpdatesWithCliffValidator(t *testing.T) { validators[0] = keeper.UpdateValidator(ctx, validators[0]) validators[1] = keeper.UpdateValidator(ctx, validators[1]) keeper.ClearTendermintUpdates(ctx) - require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx))) + require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) // test validator added at the end but not inserted in the valset // tendermintUpdate set: {} -> {} keeper.UpdateValidator(ctx, validators[2]) - updates := keeper.GetTendermintUpdates(ctx) + updates := keeper.GetValidTendermintUpdates(ctx) require.Equal(t, 0, len(updates)) // test validator change its power and become a gotValidator (pushing out an existing) // tendermintUpdate set: {} -> {c0, c4} keeper.ClearTendermintUpdates(ctx) - require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx))) + require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) pool := keeper.GetPool(ctx) validators[2], pool, _ = validators[2].AddTokensFromDel(pool, sdk.NewInt(10)) keeper.SetPool(ctx, pool) validators[2] = keeper.UpdateValidator(ctx, validators[2]) - updates = keeper.GetTendermintUpdates(ctx) + updates = keeper.GetValidTendermintUpdates(ctx) require.Equal(t, 2, len(updates), "%v", updates) require.Equal(t, validators[0].ABCIValidatorZero(), updates[0]) require.Equal(t, validators[2].ABCIValidator(), updates[1]) } -func TestGetTendermintUpdatesPowerDecrease(t *testing.T) { +func TestGetValidTendermintUpdatesPowerDecrease(t *testing.T) { ctx, _, keeper := CreateTestInput(t, false, 1000) amts := []int64{100, 100} @@ -870,7 +882,7 @@ func TestGetTendermintUpdatesPowerDecrease(t *testing.T) { validators[0] = keeper.UpdateValidator(ctx, validators[0]) validators[1] = keeper.UpdateValidator(ctx, validators[1]) keeper.ClearTendermintUpdates(ctx) - require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx))) + require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) // check initial power require.Equal(t, sdk.NewDec(100).RoundInt64(), validators[0].GetPower().RoundInt64()) @@ -890,8 +902,158 @@ func TestGetTendermintUpdatesPowerDecrease(t *testing.T) { require.Equal(t, sdk.NewDec(70).RoundInt64(), validators[1].GetPower().RoundInt64()) // Tendermint updates should reflect power change - updates := keeper.GetTendermintUpdates(ctx) + updates := keeper.GetValidTendermintUpdates(ctx) require.Equal(t, 2, len(updates)) require.Equal(t, validators[0].ABCIValidator(), updates[0]) require.Equal(t, validators[1].ABCIValidator(), updates[1]) } + +func TestGetValidTendermintUpdatesNewValidator(t *testing.T) { + ctx, _, keeper := CreateTestInput(t, false, 1000) + params := keeper.GetParams(ctx) + params.MaxValidators = uint16(3) + + keeper.SetParams(ctx, params) + + amts := []int64{100, 100} + var validators [2]types.Validator + + // initialize some validators into the state + for i, amt := range amts { + pool := keeper.GetPool(ctx) + valPubKey := PKs[i+1] + valAddr := sdk.ValAddress(valPubKey.Address().Bytes()) + + validators[i] = types.NewValidator(valAddr, valPubKey, types.Description{}) + validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) + + keeper.SetPool(ctx, pool) + validators[i] = keeper.UpdateValidator(ctx, validators[i]) + } + + // verify initial Tendermint updates are correct + updates := keeper.GetValidTendermintUpdates(ctx) + require.Equal(t, len(validators), len(updates)) + require.Equal(t, validators[0].ABCIValidator(), updates[0]) + require.Equal(t, validators[1].ABCIValidator(), updates[1]) + + keeper.ClearTendermintUpdates(ctx) + require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) + + // update initial validator set + for i, amt := range amts { + pool := keeper.GetPool(ctx) + validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) + + keeper.SetPool(ctx, pool) + validators[i] = keeper.UpdateValidator(ctx, validators[i]) + } + + // add a new validator that goes from zero power, to non-zero power, back to + // zero power + pool := keeper.GetPool(ctx) + valPubKey := PKs[len(validators)+1] + valAddr := sdk.ValAddress(valPubKey.Address().Bytes()) + amt := sdk.NewInt(100) + + validator := types.NewValidator(valAddr, valPubKey, types.Description{}) + validator, pool, _ = validator.AddTokensFromDel(pool, amt) + + keeper.SetPool(ctx, pool) + validator = keeper.UpdateValidator(ctx, validator) + + validator, pool, _ = validator.RemoveDelShares(pool, sdk.NewDecFromInt(amt)) + validator = keeper.UpdateValidator(ctx, validator) + + // add a new validator that increases in power + valPubKey = PKs[len(validators)+2] + valAddr = sdk.ValAddress(valPubKey.Address().Bytes()) + + validator = types.NewValidator(valAddr, valPubKey, types.Description{}) + validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(500)) + + keeper.SetPool(ctx, pool) + validator = keeper.UpdateValidator(ctx, validator) + + // verify initial Tendermint updates are correct + updates = keeper.GetValidTendermintUpdates(ctx) + require.Equal(t, len(validators)+1, len(updates)) + require.Equal(t, validator.ABCIValidator(), updates[0]) + require.Equal(t, validators[0].ABCIValidator(), updates[1]) + require.Equal(t, validators[1].ABCIValidator(), updates[2]) +} + +func TestGetValidTendermintUpdatesBondTransition(t *testing.T) { + ctx, _, keeper := CreateTestInput(t, false, 1000) + params := keeper.GetParams(ctx) + params.MaxValidators = uint16(2) + + keeper.SetParams(ctx, params) + + amts := []int64{100, 200, 300} + var validators [3]types.Validator + + // initialize some validators into the state + for i, amt := range amts { + pool := keeper.GetPool(ctx) + moniker := fmt.Sprintf("%d", i) + valPubKey := PKs[i+1] + valAddr := sdk.ValAddress(valPubKey.Address().Bytes()) + + validators[i] = types.NewValidator(valAddr, valPubKey, types.Description{Moniker: moniker}) + validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) + + keeper.SetPool(ctx, pool) + validators[i] = keeper.UpdateValidator(ctx, validators[i]) + } + + // verify initial Tendermint updates are correct + updates := keeper.GetValidTendermintUpdates(ctx) + require.Equal(t, 2, len(updates)) + require.Equal(t, validators[2].ABCIValidator(), updates[0]) + require.Equal(t, validators[1].ABCIValidator(), updates[1]) + + keeper.ClearTendermintUpdates(ctx) + require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) + + // delegate to validator with lowest power but not enough to bond + ctx = ctx.WithBlockHeight(1) + pool := keeper.GetPool(ctx) + + validator, found := keeper.GetValidator(ctx, validators[0].OperatorAddr) + require.True(t, found) + + validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(1)) + + keeper.SetPool(ctx, pool) + validators[0] = keeper.UpdateValidator(ctx, validator) + + // verify initial Tendermint updates are correct + require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) + + // create a series of events that will bond and unbond the validator with + // lowest power in a single block context (height) + ctx = ctx.WithBlockHeight(2) + pool = keeper.GetPool(ctx) + + validator, found = keeper.GetValidator(ctx, validators[1].OperatorAddr) + require.True(t, found) + + validator, pool, _ = validator.RemoveDelShares(pool, validator.DelegatorShares) + + keeper.SetPool(ctx, pool) + validator = keeper.UpdateValidator(ctx, validator) + + validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(250)) + + keeper.SetPool(ctx, pool) + validators[1] = keeper.UpdateValidator(ctx, validator) + + // verify initial Tendermint updates are correct + updates = keeper.GetValidTendermintUpdates(ctx) + require.Equal(t, 1, len(updates)) + require.Equal(t, validators[1].ABCIValidator(), updates[0]) + + keeper.ClearTendermintUpdates(ctx) + require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) +} From e5e7c4fa0fcbbbd807cc3d63db6145c00acba92a Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Wed, 12 Sep 2018 00:16:52 -0700 Subject: [PATCH 89/93] Merge PR #2303: simulation: Add weighted operation --- Makefile | 2 +- PENDING.md | 1 + cmd/gaia/app/sim_test.go | 26 ++++++++++----------- x/bank/simulation/sim_test.go | 4 ++-- x/gov/simulation/sim_test.go | 14 +++++------ x/mock/simulation/random_simulate_blocks.go | 23 ++++++++++++++---- x/mock/simulation/types.go | 7 ++++++ x/stake/simulation/sim_test.go | 16 ++++++------- 8 files changed, 58 insertions(+), 35 deletions(-) diff --git a/Makefile b/Makefile index 88ead03e6a..ee76c6d197 100644 --- a/Makefile +++ b/Makefile @@ -157,7 +157,7 @@ test_sim_gaia_nondeterminism: test_sim_gaia_fast: @echo "Running quick Gaia simulation. This may take several minutes..." - @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=200 -v -timeout 24h + @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=400 -SimulationBlockSize=200 -v -timeout 24h test_sim_gaia_slow: @echo "Running full Gaia simulation. This may take awhile!" diff --git a/PENDING.md b/PENDING.md index dd4acbe41b..d1d25c8279 100644 --- a/PENDING.md +++ b/PENDING.md @@ -109,6 +109,7 @@ IMPROVEMENTS * [store] \#1952, \#2281 Update IAVL dependency to v0.11.0 * [simulation] Make timestamps randomized [#2153](https://github.com/cosmos/cosmos-sdk/pull/2153) * [simulation] Make logs not just pure strings, speeding it up by a large factor at greater block heights \#2282 + * [simulation] Add a concept of weighting the operations \#2303 * [simulation] Logs get written to file if large, and also get printed on panics \#2285 * Tendermint diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 497aa1383d..b12f3978cc 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -89,19 +89,19 @@ func appStateFn(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json return appState } -func testAndRunTxs(app *GaiaApp) []simulation.Operation { - return []simulation.Operation{ - banksim.SimulateSingleInputMsgSend(app.accountMapper), - govsim.SimulateSubmittingVotingAndSlashingForProposal(app.govKeeper, app.stakeKeeper), - govsim.SimulateMsgDeposit(app.govKeeper, app.stakeKeeper), - stakesim.SimulateMsgCreateValidator(app.accountMapper, app.stakeKeeper), - stakesim.SimulateMsgEditValidator(app.stakeKeeper), - stakesim.SimulateMsgDelegate(app.accountMapper, app.stakeKeeper), - stakesim.SimulateMsgBeginUnbonding(app.accountMapper, app.stakeKeeper), - stakesim.SimulateMsgCompleteUnbonding(app.stakeKeeper), - stakesim.SimulateMsgBeginRedelegate(app.accountMapper, app.stakeKeeper), - stakesim.SimulateMsgCompleteRedelegate(app.stakeKeeper), - slashingsim.SimulateMsgUnjail(app.slashingKeeper), +func testAndRunTxs(app *GaiaApp) []simulation.WeightedOperation { + return []simulation.WeightedOperation{ + {100, banksim.SimulateSingleInputMsgSend(app.accountMapper)}, + {5, govsim.SimulateSubmittingVotingAndSlashingForProposal(app.govKeeper, app.stakeKeeper)}, + {100, govsim.SimulateMsgDeposit(app.govKeeper, app.stakeKeeper)}, + {100, stakesim.SimulateMsgCreateValidator(app.accountMapper, app.stakeKeeper)}, + {5, stakesim.SimulateMsgEditValidator(app.stakeKeeper)}, + {100, stakesim.SimulateMsgDelegate(app.accountMapper, app.stakeKeeper)}, + {100, stakesim.SimulateMsgBeginUnbonding(app.accountMapper, app.stakeKeeper)}, + {100, stakesim.SimulateMsgCompleteUnbonding(app.stakeKeeper)}, + {100, stakesim.SimulateMsgBeginRedelegate(app.accountMapper, app.stakeKeeper)}, + {100, stakesim.SimulateMsgCompleteRedelegate(app.stakeKeeper)}, + {100, slashingsim.SimulateMsgUnjail(app.slashingKeeper)}, } } diff --git a/x/bank/simulation/sim_test.go b/x/bank/simulation/sim_test.go index f0279abef3..555dc9a6c5 100644 --- a/x/bank/simulation/sim_test.go +++ b/x/bank/simulation/sim_test.go @@ -33,8 +33,8 @@ func TestBankWithRandomMessages(t *testing.T) { simulation.Simulate( t, mapp.BaseApp, appStateFn, - []simulation.Operation{ - SimulateSingleInputMsgSend(mapper), + []simulation.WeightedOperation{ + {1, SimulateSingleInputMsgSend(mapper)}, }, []simulation.RandSetup{}, []simulation.Invariant{ diff --git a/x/gov/simulation/sim_test.go b/x/gov/simulation/sim_test.go index b7f0be580e..411dbf0c87 100644 --- a/x/gov/simulation/sim_test.go +++ b/x/gov/simulation/sim_test.go @@ -56,10 +56,10 @@ func TestGovWithRandomMessages(t *testing.T) { // Test with unscheduled votes simulation.Simulate( t, mapp.BaseApp, appStateFn, - []simulation.Operation{ - SimulateMsgSubmitProposal(govKeeper, stakeKeeper), - SimulateMsgDeposit(govKeeper, stakeKeeper), - SimulateMsgVote(govKeeper, stakeKeeper), + []simulation.WeightedOperation{ + {2, SimulateMsgSubmitProposal(govKeeper, stakeKeeper)}, + {3, SimulateMsgDeposit(govKeeper, stakeKeeper)}, + {20, SimulateMsgVote(govKeeper, stakeKeeper)}, }, []simulation.RandSetup{ setup, }, []simulation.Invariant{ @@ -71,9 +71,9 @@ func TestGovWithRandomMessages(t *testing.T) { // Test with scheduled votes simulation.Simulate( t, mapp.BaseApp, appStateFn, - []simulation.Operation{ - SimulateSubmittingVotingAndSlashingForProposal(govKeeper, stakeKeeper), - SimulateMsgDeposit(govKeeper, stakeKeeper), + []simulation.WeightedOperation{ + {10, SimulateSubmittingVotingAndSlashingForProposal(govKeeper, stakeKeeper)}, + {5, SimulateMsgDeposit(govKeeper, stakeKeeper)}, }, []simulation.RandSetup{ setup, }, []simulation.Invariant{ diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index 3f91b2a663..c5bbd2ac12 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -25,7 +25,7 @@ import ( // Simulate tests application by sending random messages. func Simulate( - t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, ops []Operation, setups []RandSetup, + t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, ops []WeightedOperation, setups []RandSetup, invariants []Invariant, numBlocks int, blockSize int, commit bool, ) error { time := time.Now().UnixNano() @@ -55,7 +55,7 @@ func randTimestamp(r *rand.Rand) time.Time { // SimulateFromSeed tests an application by running the provided // operations, testing the provided invariants, but using the provided seed. func SimulateFromSeed( - tb testing.TB, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, seed int64, ops []Operation, setups []RandSetup, + tb testing.TB, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, seed int64, ops []WeightedOperation, setups []RandSetup, invariants []Invariant, numBlocks int, blockSize int, commit bool, ) (simError error) { // in case we have to end early, don't os.Exit so that we can run cleanup code. @@ -171,12 +171,27 @@ func SimulateFromSeed( // Returns a function to simulate blocks. Written like this to avoid constant parameters being passed everytime, to minimize // memory overhead -func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, event func(string), invariants []Invariant, ops []Operation, operationQueue map[int][]Operation, totalNumBlocks int, displayLogs func()) func( +func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, event func(string), invariants []Invariant, ops []WeightedOperation, operationQueue map[int][]Operation, totalNumBlocks int, displayLogs func()) func( blocksize int, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, privKeys []crypto.PrivKey, header abci.Header, logWriter func(string)) (opCount int) { + totalOpWeight := 0 + for i := 0; i < len(ops); i++ { + totalOpWeight += ops[i].Weight + } + selectOp := func(r *rand.Rand) Operation { + x := r.Intn(totalOpWeight) + for i := 0; i < len(ops); i++ { + if x <= ops[i].Weight { + return ops[i].Op + } + x -= ops[i].Weight + } + // shouldn't happen + return ops[0].Op + } return func(blocksize int, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, header abci.Header, logWriter func(string)) (opCount int) { for j := 0; j < blocksize; j++ { - logUpdate, futureOps, err := ops[r.Intn(len(ops))](r, app, ctx, keys, event) + logUpdate, futureOps, err := selectOp(r)(r, app, ctx, keys, event) if err != nil { displayLogs() tb.Fatalf("error on operation %d within block %d, %v", header.Height, opCount, err) diff --git a/x/mock/simulation/types.go b/x/mock/simulation/types.go index 25fb1a6e8a..401899efe3 100644 --- a/x/mock/simulation/types.go +++ b/x/mock/simulation/types.go @@ -47,6 +47,13 @@ type ( BlockHeight int Op Operation } + + // WeightedOperation is an operation with associated weight. + // This is used to bias the selection operation within the simulator. + WeightedOperation struct { + Weight int + Op Operation + } ) // PeriodicInvariant returns an Invariant function closure that asserts diff --git a/x/stake/simulation/sim_test.go b/x/stake/simulation/sim_test.go index 6ad8b41825..7644636047 100644 --- a/x/stake/simulation/sim_test.go +++ b/x/stake/simulation/sim_test.go @@ -44,14 +44,14 @@ func TestStakeWithRandomMessages(t *testing.T) { simulation.Simulate( t, mapp.BaseApp, appStateFn, - []simulation.Operation{ - SimulateMsgCreateValidator(mapper, stakeKeeper), - SimulateMsgEditValidator(stakeKeeper), - SimulateMsgDelegate(mapper, stakeKeeper), - SimulateMsgBeginUnbonding(mapper, stakeKeeper), - SimulateMsgCompleteUnbonding(stakeKeeper), - SimulateMsgBeginRedelegate(mapper, stakeKeeper), - SimulateMsgCompleteRedelegate(stakeKeeper), + []simulation.WeightedOperation{ + {10, SimulateMsgCreateValidator(mapper, stakeKeeper)}, + {5, SimulateMsgEditValidator(stakeKeeper)}, + {15, SimulateMsgDelegate(mapper, stakeKeeper)}, + {10, SimulateMsgBeginUnbonding(mapper, stakeKeeper)}, + {3, SimulateMsgCompleteUnbonding(stakeKeeper)}, + {10, SimulateMsgBeginRedelegate(mapper, stakeKeeper)}, + {3, SimulateMsgCompleteRedelegate(stakeKeeper)}, }, []simulation.RandSetup{ Setup(mapp, stakeKeeper), }, []simulation.Invariant{ From f1ac53b4ad1d08b3d0acd245e581ecd2d9864c55 Mon Sep 17 00:00:00 2001 From: Zach Date: Wed, 12 Sep 2018 03:39:34 -0400 Subject: [PATCH 90/93] Merge PR #2270: docs: lotion update --- docs/config.js | 4 ++- docs/lotion/building-an-app.md | 46 ----------------------------- docs/lotion/overview.md | 53 ++++++++++++++++++++++++++++++++-- 3 files changed, 54 insertions(+), 49 deletions(-) delete mode 100644 docs/lotion/building-an-app.md diff --git a/docs/config.js b/docs/config.js index 93426bcc5f..5de1661790 100644 --- a/docs/config.js +++ b/docs/config.js @@ -57,7 +57,9 @@ module.exports = { { title: "Lotion JS", collapsable: false, - children: [["/lotion/overview", "Overview"], "/lotion/building-an-app"] + children: [ + ["/lotion/overview", "Overview"] + ] }, { title: "Validators", diff --git a/docs/lotion/building-an-app.md b/docs/lotion/building-an-app.md deleted file mode 100644 index 93b3363c5e..0000000000 --- a/docs/lotion/building-an-app.md +++ /dev/null @@ -1,46 +0,0 @@ -# Building an App - -::: tip -Lotion requires __node v7.6.0__ or higher, and a mac or linux machine. -::: - -## Installation -``` -$ npm install lotion -``` - -## Simple App -`app.js`: -```js -let lotion = require('lotion') - -let app = lotion({ - initialState: { - count: 0 - } -}) - -app.use(function (state, tx) { - if(state.count === tx.nonce) { - state.count++ - } -}) - -app.listen(3000) -``` - -run `node app.js`, then: -```bash -$ curl http://localhost:3000/state -# { "count": 0 } - -$ curl http://localhost:3000/txs -d '{ "nonce": 0 }' -# { "ok": true } - -$ curl http://localhost:3000/state -# { "count": 1 } -``` - -## Learn More - -You can learn more about Lotion JS by visiting Lotion on [Github](https://github.com/keppel/lotion). diff --git a/docs/lotion/overview.md b/docs/lotion/overview.md index 03c79c5716..b28d2c75b4 100644 --- a/docs/lotion/overview.md +++ b/docs/lotion/overview.md @@ -1,5 +1,54 @@ -# Lotion JS Overview +# Overview -Lotion is a new way to create blockchain apps in JavaScript, which aims to make writing new blockchains fast and fun. It builds on top of Tendermint using the ABCI protocol. Lotion lets you write secure, scalable applications that can easily interoperate with other blockchains on the Cosmos Network using IBC. +Lotion is an alternative to the Cosmos SDK and allows you to create blockchain apps in JavaScript. It aims to make writing new blockchain apps fast and easy by using the ABCI protocol to build on top of Tendermint. Lotion lets you write secure, scalable applications that can easily interoperate with other blockchains on the Cosmos Network using IBC. Lotion itself is a tiny framework; its true power comes from the network of small, focused modules built upon it. Adding a fully-featured cryptocurrency to your blockchain, for example, takes only a few lines of code. + +For more information see the [website](https://lotionjs.com) and [GitHub repo](https://github.com/keppel/lotion), for complete documentation which expands on the following example. + +## Building an App + +### Installation + +::: tip +Lotion requires __node v7.6.0__ or higher, and a mac or linux machine. +::: + +``` +$ npm install lotion +``` + +### Simple App + +`app.js`: + +```js +let lotion = require('lotion') + +let app = lotion({ + initialState: { + count: 0 + } +}) + +app.use(function (state, tx) { + if(state.count === tx.nonce) { + state.count++ + } +}) + +app.listen(3000) +``` + +run `node app.js`, then: + +```bash +$ curl http://localhost:3000/state +# { "count": 0 } + +$ curl http://localhost:3000/txs -d '{ "nonce": 0 }' +# { "ok": true } + +$ curl http://localhost:3000/state +# { "count": 1 } +``` From 5834a500dae7c9de8df41f72a38c322dedaf3d54 Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Wed, 12 Sep 2018 09:41:09 +0200 Subject: [PATCH 91/93] Merge PR #2259: Minor changes on slashing logs and gov Querier --- x/gov/handler.go | 14 ++++++++++---- x/gov/queryable.go | 35 +++++++++++++++++++++++------------ x/stake/keeper/slash.go | 24 ++++++++++++++++-------- 3 files changed, 49 insertions(+), 24 deletions(-) diff --git a/x/gov/handler.go b/x/gov/handler.go index 6424bb0a10..5e45571552 100644 --- a/x/gov/handler.go +++ b/x/gov/handler.go @@ -114,8 +114,14 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) { resTags.AppendTag(tags.Action, tags.ActionProposalDropped) resTags.AppendTag(tags.ProposalID, proposalIDBytes) - logger.Info(fmt.Sprintf("Proposal %d - \"%s\" - didn't mean minimum deposit (had only %s), deleted", - inactiveProposal.GetProposalID(), inactiveProposal.GetTitle(), inactiveProposal.GetTotalDeposit())) + logger.Info( + fmt.Sprintf("proposal %d (%s) didn't meet minimum deposit of %v steak (had only %s steak); deleted", + inactiveProposal.GetProposalID(), + inactiveProposal.GetTitle(), + keeper.GetDepositProcedure(ctx).MinDeposit.AmountOf("steak"), + inactiveProposal.GetTotalDeposit().AmountOf("steak"), + ), + ) } // Check if earliest Active Proposal ended voting period yet @@ -143,7 +149,7 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) { activeProposal.SetTallyResult(tallyResults) keeper.SetProposal(ctx, activeProposal) - logger.Info(fmt.Sprintf("Proposal %d - \"%s\" - tallied, passed: %v", + logger.Info(fmt.Sprintf("proposal %d (%s) tallied; passed: %v", activeProposal.GetProposalID(), activeProposal.GetTitle(), passes)) for _, valAddr := range nonVotingVals { @@ -154,7 +160,7 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) { val.GetPower().RoundInt64(), keeper.GetTallyingProcedure(ctx).GovernancePenalty) - logger.Info(fmt.Sprintf("Validator %s failed to vote on proposal %d, slashing", + logger.Info(fmt.Sprintf("validator %s failed to vote on proposal %d; slashing", val.GetOperator(), activeProposal.GetProposalID())) } diff --git a/x/gov/queryable.go b/x/gov/queryable.go index 090b9a9145..6aa0c9884a 100644 --- a/x/gov/queryable.go +++ b/x/gov/queryable.go @@ -8,22 +8,33 @@ import ( abci "github.com/tendermint/tendermint/abci/types" ) +// query endpoints supported by the governance Querier +const ( + QueryProposals = "proposals" + QueryProposal = "proposal" + QueryDeposits = "deposits" + QueryDeposit = "deposit" + QueryVotes = "votes" + QueryVote = "vote" + QueryTally = "tally" +) + func NewQuerier(keeper Keeper) sdk.Querier { return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) { switch path[0] { - case "proposal": - return queryProposal(ctx, path[1:], req, keeper) - case "deposit": - return queryDeposit(ctx, path[1:], req, keeper) - case "vote": - return queryVote(ctx, path[1:], req, keeper) - case "deposits": - return queryDeposits(ctx, path[1:], req, keeper) - case "votes": - return queryVotes(ctx, path[1:], req, keeper) - case "proposals": + case QueryProposals: return queryProposals(ctx, path[1:], req, keeper) - case "tally": + case QueryProposal: + return queryProposal(ctx, path[1:], req, keeper) + case QueryDeposits: + return queryDeposits(ctx, path[1:], req, keeper) + case QueryDeposit: + return queryDeposit(ctx, path[1:], req, keeper) + case QueryVotes: + return queryVotes(ctx, path[1:], req, keeper) + case QueryVote: + return queryVote(ctx, path[1:], req, keeper) + case QueryTally: return queryTally(ctx, path[1:], req, keeper) default: return nil, sdk.ErrUnknownRequest("unknown gov query endpoint") diff --git a/x/stake/keeper/slash.go b/x/stake/keeper/slash.go index 5a004e807a..52dbd21c7e 100644 --- a/x/stake/keeper/slash.go +++ b/x/stake/keeper/slash.go @@ -28,7 +28,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in logger := ctx.Logger().With("module", "x/stake") if slashFactor.LT(sdk.ZeroDec()) { - panic(fmt.Errorf("attempted to slash with a negative slashFactor: %v", slashFactor)) + panic(fmt.Errorf("attempted to slash with a negative slash factor: %v", slashFactor)) } // Amount of slashing = slash slashFactor * power at time of infraction @@ -50,7 +50,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in // should not be slashing unbonded if validator.IsUnbonded(ctx) { - panic(fmt.Sprintf("should not be slashing unbonded validator: %v", validator)) + panic(fmt.Sprintf("should not be slashing unbonded validator: %s", validator.GetOperator())) } operatorAddress := validator.GetOperator() @@ -72,7 +72,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in // Special-case slash at current height for efficiency - we don't need to look through unbonding delegations or redelegations logger.Info(fmt.Sprintf( - "Slashing at current height %d, not scanning unbonding delegations & redelegations", + "slashing at current height %d, not scanning unbonding delegations & redelegations", infractionHeight)) case infractionHeight < ctx.BlockHeight(): @@ -117,8 +117,8 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in // Log that a slash occurred! logger.Info(fmt.Sprintf( - "Validator %s slashed by slashFactor %s, burned %v tokens", - pubkey.Address(), slashFactor.String(), tokensToBurn)) + "validator %s slashed by slash factor of %s; burned %v tokens", + validator.GetOperator(), slashFactor.String(), tokensToBurn)) // TODO Return event(s), blocked on https://github.com/tendermint/tendermint/pull/1803 return @@ -127,8 +127,12 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in // jail a validator func (k Keeper) Jail(ctx sdk.Context, pubkey crypto.PubKey) { k.setJailed(ctx, pubkey, true) + validatorAddr, err := sdk.ValAddressFromHex(pubkey.Address().String()) + if err != nil { + panic(err.Error()) + } logger := ctx.Logger().With("module", "x/stake") - logger.Info(fmt.Sprintf("Validator %s jailed", pubkey.Address())) + logger.Info(fmt.Sprintf("validator %s jailed", validatorAddr)) // TODO Return event(s), blocked on https://github.com/tendermint/tendermint/pull/1803 return } @@ -136,8 +140,12 @@ func (k Keeper) Jail(ctx sdk.Context, pubkey crypto.PubKey) { // unjail a validator func (k Keeper) Unjail(ctx sdk.Context, pubkey crypto.PubKey) { k.setJailed(ctx, pubkey, false) + validatorAddr, err := sdk.ValAddressFromHex(pubkey.Address().String()) + if err != nil { + panic(err.Error()) + } logger := ctx.Logger().With("module", "x/stake") - logger.Info(fmt.Sprintf("Validator %s unjailed", pubkey.Address())) + logger.Info(fmt.Sprintf("validator %s unjailed", validatorAddr)) // TODO Return event(s), blocked on https://github.com/tendermint/tendermint/pull/1803 return } @@ -146,7 +154,7 @@ func (k Keeper) Unjail(ctx sdk.Context, pubkey crypto.PubKey) { func (k Keeper) setJailed(ctx sdk.Context, pubkey crypto.PubKey, isJailed bool) { validator, found := k.GetValidatorByPubKey(ctx, pubkey) if !found { - panic(fmt.Errorf("Validator with pubkey %s not found, cannot set jailed to %v", pubkey, isJailed)) + panic(fmt.Errorf("validator with pubkey %s not found, cannot set jailed to %v", pubkey, isJailed)) } validator.Jailed = isJailed k.UpdateValidator(ctx, validator) // update validator, possibly unbonding or bonding it From 8682556fad5ab71defd16c6e983d16150f42a731 Mon Sep 17 00:00:00 2001 From: philipstanislaus Date: Wed, 12 Sep 2018 10:02:03 +0200 Subject: [PATCH 92/93] Merge PR #1993: Add optional flag to `gaiad testnet` to make config directory of daemon and cli configurable --- PENDING.md | 2 +- server/testnet.go | 23 ++++++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/PENDING.md b/PENDING.md index d1d25c8279..b313f5cf65 100644 --- a/PENDING.md +++ b/PENDING.md @@ -47,7 +47,6 @@ BREAKING CHANGES * Tendermint - FEATURES * Gaia REST API (`gaiacli advanced rest-server`) @@ -111,6 +110,7 @@ IMPROVEMENTS * [simulation] Make logs not just pure strings, speeding it up by a large factor at greater block heights \#2282 * [simulation] Add a concept of weighting the operations \#2303 * [simulation] Logs get written to file if large, and also get printed on panics \#2285 + * [gaiad] \#1992 Add optional flag to `gaiad testnet` to make config directory of daemon (default `gaiad`) and cli (default `gaiacli`) configurable * Tendermint diff --git a/server/testnet.go b/server/testnet.go index 93f563005f..951e378d1e 100644 --- a/server/testnet.go +++ b/server/testnet.go @@ -18,9 +18,11 @@ import ( ) var ( - nodeDirPrefix = "node-dir-prefix" - nValidators = "v" - outputDir = "output-dir" + nodeDirPrefix = "node-dir-prefix" + nValidators = "v" + outputDir = "output-dir" + nodeDaemonHome = "node-daemon-home" + nodeCliHome = "node-cli-home" startingIPAddress = "starting-ip-address" ) @@ -39,7 +41,7 @@ Note, strict routability for addresses is turned off in the config file. Example: - gaiad testnet --v 4 --output-dir ./output --starting-ip-address 192.168.10.2 + gaiad testnet --v 4 --o ./output --starting-ip-address 192.168.10.2 `, RunE: func(_ *cobra.Command, _ []string) error { config := ctx.Config @@ -53,6 +55,10 @@ Example: "Directory to store initialization data for the testnet") cmd.Flags().String(nodeDirPrefix, "node", "Prefix the directory name for each node with (node results in node0, node1, ...)") + cmd.Flags().String(nodeDaemonHome, "gaiad", + "Home directory of the node's daemon configuration") + cmd.Flags().String(nodeCliHome, "gaiacli", + "Home directory of the node's cli configuration") cmd.Flags().String(startingIPAddress, "192.168.0.1", "Starting IP address (192.168.0.1 results in persistent peers list ID0@192.168.0.1:46656, ID1@192.168.0.2:46656, ...)") @@ -66,8 +72,10 @@ func testnetWithConfig(config *cfg.Config, cdc *wire.Codec, appInit AppInit) err // Generate private key, node ID, initial transaction for i := 0; i < numValidators; i++ { nodeDirName := fmt.Sprintf("%s%d", viper.GetString(nodeDirPrefix), i) - nodeDir := filepath.Join(outDir, nodeDirName, "gaiad") - clientDir := filepath.Join(outDir, nodeDirName, "gaiacli") + nodeDaemonHomeName := viper.GetString(nodeDaemonHome) + nodeCliHomeName := viper.GetString(nodeCliHome) + nodeDir := filepath.Join(outDir, nodeDirName, nodeDaemonHomeName) + clientDir := filepath.Join(outDir, nodeDirName, nodeCliHomeName) gentxsDir := filepath.Join(outDir, "gentxs") config.SetRoot(nodeDir) @@ -122,7 +130,8 @@ func testnetWithConfig(config *cfg.Config, cdc *wire.Codec, appInit AppInit) err for i := 0; i < numValidators; i++ { nodeDirName := fmt.Sprintf("%s%d", viper.GetString(nodeDirPrefix), i) - nodeDir := filepath.Join(outDir, nodeDirName, "gaiad") + nodeDaemonHomeName := viper.GetString(nodeDaemonHome) + nodeDir := filepath.Join(outDir, nodeDirName, nodeDaemonHomeName) gentxsDir := filepath.Join(outDir, "gentxs") initConfig := InitConfig{ chainID, From 5bf9401e871af6f7ba715b54a86044e93de8fe7e Mon Sep 17 00:00:00 2001 From: Rigel Date: Thu, 13 Sep 2018 00:53:55 -0400 Subject: [PATCH 93/93] Merge PR #2310: staking transient store for Tendermint Updates * working * non-tests compile * fix mounting error, working on testing * stumped using transient store * joon comments * remove old comments * resolve ibc error * lint/sim_test * fix determinism sim test * sim enable commit * docs and pending --- Makefile | 4 +- PENDING.md | 1 + baseapp/baseapp.go | 9 ++- cmd/gaia/app/app.go | 9 ++- cmd/gaia/app/sim_test.go | 4 +- cmd/gaia/cmd/gaiadebug/hack.go | 4 +- examples/democoin/x/cool/app_test.go | 2 +- examples/democoin/x/pow/app_test.go | 2 +- x/bank/bench_test.go | 2 +- x/bank/simulation/sim_test.go | 2 +- x/gov/handler.go | 2 +- x/gov/simulation/sim_test.go | 5 +- x/gov/test_common.go | 5 +- x/ibc/app_test.go | 2 +- x/mock/app.go | 15 +++- x/mock/app_test.go | 2 +- x/mock/simulation/random_simulate_blocks.go | 18 ++--- x/slashing/app_test.go | 5 +- x/slashing/test_common.go | 4 +- x/stake/app_test.go | 5 +- x/stake/handler.go | 1 - x/stake/keeper/_store.md | 10 ++- x/stake/keeper/keeper.go | 4 +- x/stake/keeper/key.go | 22 +++--- x/stake/keeper/test_common.go | 4 +- x/stake/keeper/validator.go | 31 +++----- x/stake/keeper/validator_test.go | 80 +++++++-------------- x/stake/simulation/sim_test.go | 5 +- x/stake/stake.go | 4 +- 29 files changed, 134 insertions(+), 129 deletions(-) diff --git a/Makefile b/Makefile index ee76c6d197..a015e5a6b1 100644 --- a/Makefile +++ b/Makefile @@ -157,11 +157,11 @@ test_sim_gaia_nondeterminism: test_sim_gaia_fast: @echo "Running quick Gaia simulation. This may take several minutes..." - @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=400 -SimulationBlockSize=200 -v -timeout 24h + @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=400 -SimulationBlockSize=200 -SimulationCommit=true -v -timeout 24h test_sim_gaia_slow: @echo "Running full Gaia simulation. This may take awhile!" - @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=1000 -SimulationVerbose=true -v -timeout 24h + @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=1000 -SimulationVerbose=true -SimulationCommit=true -v -timeout 24h SIM_NUM_BLOCKS ?= 210 SIM_BLOCK_SIZE ?= 200 diff --git a/PENDING.md b/PENDING.md index b313f5cf65..33b60198c2 100644 --- a/PENDING.md +++ b/PENDING.md @@ -33,6 +33,7 @@ BREAKING CHANGES renamed for accounts and validator operators: * `cosmosaccaddr` / `cosmosaccpub` => `cosmos` / `cosmospub` * `cosmosvaladdr` / `cosmosvalpub` => `cosmosvaloper` / `cosmosvaloperpub` + * [x/stake] [#1013] TendermintUpdates now uses transient store * SDK * [core] [\#1807](https://github.com/cosmos/cosmos-sdk/issues/1807) Switch from use of rational to decimal diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 5552ff7847..10d9f55f77 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -120,13 +120,20 @@ func (app *BaseApp) RegisterCodespace(codespace sdk.CodespaceType) sdk.Codespace return app.codespacer.RegisterNext(codespace) } -// Mount a store to the provided key in the BaseApp multistore +// Mount IAVL stores to the provided keys in the BaseApp multistore func (app *BaseApp) MountStoresIAVL(keys ...*sdk.KVStoreKey) { for _, key := range keys { app.MountStore(key, sdk.StoreTypeIAVL) } } +// Mount stores to the provided keys in the BaseApp multistore +func (app *BaseApp) MountStoresTransient(keys ...*sdk.TransientStoreKey) { + for _, key := range keys { + app.MountStore(key, sdk.StoreTypeTransient) + } +} + // Mount a store to the provided key in the BaseApp multistore, using a specified DB func (app *BaseApp) MountStoreWithDB(key sdk.StoreKey, typ sdk.StoreType, db dbm.DB) { app.cms.MountStoreWithDB(key, typ, db) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index c80da0bd04..7cf235b163 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -43,6 +43,7 @@ type GaiaApp struct { keyAccount *sdk.KVStoreKey keyIBC *sdk.KVStoreKey keyStake *sdk.KVStoreKey + tkeyStake *sdk.TransientStoreKey keySlashing *sdk.KVStoreKey keyGov *sdk.KVStoreKey keyFeeCollection *sdk.KVStoreKey @@ -74,6 +75,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio keyAccount: sdk.NewKVStoreKey("acc"), keyIBC: sdk.NewKVStoreKey("ibc"), keyStake: sdk.NewKVStoreKey("stake"), + tkeyStake: sdk.NewTransientStoreKey("transient_stake"), keySlashing: sdk.NewKVStoreKey("slashing"), keyGov: sdk.NewKVStoreKey("gov"), keyFeeCollection: sdk.NewKVStoreKey("fee"), @@ -92,7 +94,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio app.bankKeeper = bank.NewBaseKeeper(app.accountMapper) app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace)) app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams) - app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace)) + app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.tkeyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace)) app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace)) app.stakeKeeper = app.stakeKeeper.WithValidatorHooks(app.slashingKeeper.ValidatorHooks()) app.govKeeper = gov.NewKeeper(app.cdc, app.keyGov, app.paramsKeeper.Setter(), app.bankKeeper, app.stakeKeeper, app.RegisterCodespace(gov.DefaultCodespace)) @@ -114,8 +116,9 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio app.SetBeginBlocker(app.BeginBlocker) app.SetEndBlocker(app.EndBlocker) app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeCollectionKeeper)) - app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, app.keyStake, app.keySlashing, app.keyGov, app.keyFeeCollection, app.keyParams) - app.MountStore(app.tkeyParams, sdk.StoreTypeTransient) + app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, app.keyStake, + app.keySlashing, app.keyGov, app.keyFeeCollection, app.keyParams) + app.MountStoresTransient(app.tkeyParams, app.tkeyStake) err := app.LoadLatestVersion(app.keyMain) if err != nil { cmn.Exit(err.Error()) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index b12f3978cc..078eece110 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -209,9 +209,9 @@ func TestAppStateDeterminism(t *testing.T) { []simulation.Invariant{}, 50, 100, - false, + true, ) - app.Commit() + //app.Commit() appHash := app.LastCommitID().Hash appHashList[j] = appHash } diff --git a/cmd/gaia/cmd/gaiadebug/hack.go b/cmd/gaia/cmd/gaiadebug/hack.go index b2f1183b3e..d0a0ad9d72 100644 --- a/cmd/gaia/cmd/gaiadebug/hack.go +++ b/cmd/gaia/cmd/gaiadebug/hack.go @@ -134,6 +134,7 @@ type GaiaApp struct { keyAccount *sdk.KVStoreKey keyIBC *sdk.KVStoreKey keyStake *sdk.KVStoreKey + tkeyStake *sdk.TransientStoreKey keySlashing *sdk.KVStoreKey keyParams *sdk.KVStoreKey @@ -161,6 +162,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.BaseAp keyAccount: sdk.NewKVStoreKey("acc"), keyIBC: sdk.NewKVStoreKey("ibc"), keyStake: sdk.NewKVStoreKey("stake"), + tkeyStake: sdk.NewTransientStoreKey("transient_stake"), keySlashing: sdk.NewKVStoreKey("slashing"), keyParams: sdk.NewKVStoreKey("params"), } @@ -176,7 +178,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.BaseAp app.bankKeeper = bank.NewBaseKeeper(app.accountMapper) app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace)) app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams) - app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace)) + app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.tkeyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace)) app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace)) // register message routes diff --git a/examples/democoin/x/cool/app_test.go b/examples/democoin/x/cool/app_test.go index 8d778045ee..3349928eb2 100644 --- a/examples/democoin/x/cool/app_test.go +++ b/examples/democoin/x/cool/app_test.go @@ -55,7 +55,7 @@ func getMockApp(t *testing.T) *mock.App { mapp.SetInitChainer(getInitChainer(mapp, keeper, "ice-cold")) - require.NoError(t, mapp.CompleteSetup([]*sdk.KVStoreKey{keyCool})) + require.NoError(t, mapp.CompleteSetup(keyCool)) return mapp } diff --git a/examples/democoin/x/pow/app_test.go b/examples/democoin/x/pow/app_test.go index de8642e4c3..0a4f95cf15 100644 --- a/examples/democoin/x/pow/app_test.go +++ b/examples/democoin/x/pow/app_test.go @@ -32,7 +32,7 @@ func getMockApp(t *testing.T) *mock.App { mapp.SetInitChainer(getInitChainer(mapp, keeper)) - require.NoError(t, mapp.CompleteSetup([]*sdk.KVStoreKey{keyPOW})) + require.NoError(t, mapp.CompleteSetup(keyPOW)) mapp.Seal() diff --git a/x/bank/bench_test.go b/x/bank/bench_test.go index 998d4e4bce..2a3cd5e669 100644 --- a/x/bank/bench_test.go +++ b/x/bank/bench_test.go @@ -19,7 +19,7 @@ func getBenchmarkMockApp() (*mock.App, error) { bankKeeper := NewBaseKeeper(mapp.AccountMapper) mapp.Router().AddRoute("bank", NewHandler(bankKeeper)) - err := mapp.CompleteSetup([]*sdk.KVStoreKey{}) + err := mapp.CompleteSetup() return mapp, err } diff --git a/x/bank/simulation/sim_test.go b/x/bank/simulation/sim_test.go index 555dc9a6c5..cd2353c6e7 100644 --- a/x/bank/simulation/sim_test.go +++ b/x/bank/simulation/sim_test.go @@ -21,7 +21,7 @@ func TestBankWithRandomMessages(t *testing.T) { bankKeeper := bank.NewBaseKeeper(mapper) mapp.Router().AddRoute("bank", bank.NewHandler(bankKeeper)) - err := mapp.CompleteSetup([]*sdk.KVStoreKey{}) + err := mapp.CompleteSetup() if err != nil { panic(err) } diff --git a/x/gov/handler.go b/x/gov/handler.go index 5e45571552..c996749265 100644 --- a/x/gov/handler.go +++ b/x/gov/handler.go @@ -115,7 +115,7 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) { resTags.AppendTag(tags.ProposalID, proposalIDBytes) logger.Info( - fmt.Sprintf("proposal %d (%s) didn't meet minimum deposit of %v steak (had only %s steak); deleted", + fmt.Sprintf("proposal %d (%s) didn't meet minimum deposit of %v steak (had only %v steak); deleted", inactiveProposal.GetProposalID(), inactiveProposal.GetTitle(), keeper.GetDepositProcedure(ctx).MinDeposit.AmountOf("steak"), diff --git a/x/gov/simulation/sim_test.go b/x/gov/simulation/sim_test.go index 411dbf0c87..841b4c0f7d 100644 --- a/x/gov/simulation/sim_test.go +++ b/x/gov/simulation/sim_test.go @@ -26,7 +26,8 @@ func TestGovWithRandomMessages(t *testing.T) { mapper := mapp.AccountMapper bankKeeper := bank.NewBaseKeeper(mapper) stakeKey := sdk.NewKVStoreKey("stake") - stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, bankKeeper, stake.DefaultCodespace) + stakeTKey := sdk.NewTransientStoreKey("transient_stake") + stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, stakeTKey, bankKeeper, stake.DefaultCodespace) paramKey := sdk.NewKVStoreKey("params") paramKeeper := params.NewKeeper(mapp.Cdc, paramKey) govKey := sdk.NewKVStoreKey("gov") @@ -37,7 +38,7 @@ func TestGovWithRandomMessages(t *testing.T) { return abci.ResponseEndBlock{} }) - err := mapp.CompleteSetup([]*sdk.KVStoreKey{stakeKey, paramKey, govKey}) + err := mapp.CompleteSetup(stakeKey, stakeTKey, paramKey, govKey) if err != nil { panic(err) } diff --git a/x/gov/test_common.go b/x/gov/test_common.go index a0d5565214..f2f3625e66 100644 --- a/x/gov/test_common.go +++ b/x/gov/test_common.go @@ -28,18 +28,19 @@ func getMockApp(t *testing.T, numGenAccs int) (*mock.App, Keeper, stake.Keeper, keyGlobalParams := sdk.NewKVStoreKey("params") keyStake := sdk.NewKVStoreKey("stake") + tkeyStake := sdk.NewTransientStoreKey("transient_stake") keyGov := sdk.NewKVStoreKey("gov") pk := params.NewKeeper(mapp.Cdc, keyGlobalParams) ck := bank.NewBaseKeeper(mapp.AccountMapper) - sk := stake.NewKeeper(mapp.Cdc, keyStake, ck, mapp.RegisterCodespace(stake.DefaultCodespace)) + sk := stake.NewKeeper(mapp.Cdc, keyStake, tkeyStake, ck, mapp.RegisterCodespace(stake.DefaultCodespace)) keeper := NewKeeper(mapp.Cdc, keyGov, pk.Setter(), ck, sk, DefaultCodespace) mapp.Router().AddRoute("gov", NewHandler(keeper)) mapp.SetEndBlocker(getEndBlocker(keeper)) mapp.SetInitChainer(getInitChainer(mapp, keeper, sk)) - require.NoError(t, mapp.CompleteSetup([]*sdk.KVStoreKey{keyStake, keyGov, keyGlobalParams})) + require.NoError(t, mapp.CompleteSetup(keyStake, keyGov, keyGlobalParams, tkeyStake)) genAccs, addrs, pubKeys, privKeys := mock.CreateGenAccounts(numGenAccs, sdk.Coins{sdk.NewInt64Coin("steak", 42)}) diff --git a/x/ibc/app_test.go b/x/ibc/app_test.go index 07c3616cee..e92e71a8c7 100644 --- a/x/ibc/app_test.go +++ b/x/ibc/app_test.go @@ -24,7 +24,7 @@ func getMockApp(t *testing.T) *mock.App { bankKeeper := bank.NewBaseKeeper(mapp.AccountMapper) mapp.Router().AddRoute("ibc", NewHandler(ibcMapper, bankKeeper)) - require.NoError(t, mapp.CompleteSetup([]*sdk.KVStoreKey{keyIBC})) + require.NoError(t, mapp.CompleteSetup(keyIBC)) return mapp } diff --git a/x/mock/app.go b/x/mock/app.go index 97068a3a51..ebfb97ae5f 100644 --- a/x/mock/app.go +++ b/x/mock/app.go @@ -1,6 +1,7 @@ package mock import ( + "fmt" "math/rand" "os" @@ -75,11 +76,21 @@ func NewApp() *App { // CompleteSetup completes the application setup after the routes have been // registered. -func (app *App) CompleteSetup(newKeys []*sdk.KVStoreKey) error { +func (app *App) CompleteSetup(newKeys ...sdk.StoreKey) error { newKeys = append(newKeys, app.KeyMain) newKeys = append(newKeys, app.KeyAccount) - app.MountStoresIAVL(newKeys...) + for _, key := range newKeys { + switch key.(type) { + case *sdk.KVStoreKey: + app.MountStore(key, sdk.StoreTypeIAVL) + case *sdk.TransientStoreKey: + app.MountStore(key, sdk.StoreTypeTransient) + default: + return fmt.Errorf("unsupported StoreKey: %+v", key) + } + } + err := app.LoadLatestVersion(app.KeyMain) return err diff --git a/x/mock/app_test.go b/x/mock/app_test.go index 460757a043..1319482ca2 100644 --- a/x/mock/app_test.go +++ b/x/mock/app_test.go @@ -41,7 +41,7 @@ func getMockApp(t *testing.T) *App { mApp := NewApp() mApp.Router().AddRoute(msgType, func(ctx sdk.Context, msg sdk.Msg) (res sdk.Result) { return }) - require.NoError(t, mApp.CompleteSetup([]*sdk.KVStoreKey{})) + require.NoError(t, mApp.CompleteSetup()) return mApp } diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index c5bbd2ac12..de78ae0942 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -24,10 +24,11 @@ import ( ) // Simulate tests application by sending random messages. -func Simulate( - t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, ops []WeightedOperation, setups []RandSetup, - invariants []Invariant, numBlocks int, blockSize int, commit bool, -) error { +func Simulate(t *testing.T, app *baseapp.BaseApp, + appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, + ops []WeightedOperation, setups []RandSetup, + invariants []Invariant, numBlocks int, blockSize int, commit bool) error { + time := time.Now().UnixNano() return SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numBlocks, blockSize, commit) } @@ -54,10 +55,11 @@ func randTimestamp(r *rand.Rand) time.Time { // SimulateFromSeed tests an application by running the provided // operations, testing the provided invariants, but using the provided seed. -func SimulateFromSeed( - tb testing.TB, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, seed int64, ops []WeightedOperation, setups []RandSetup, - invariants []Invariant, numBlocks int, blockSize int, commit bool, -) (simError error) { +func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp, + appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, + seed int64, ops []WeightedOperation, setups []RandSetup, invariants []Invariant, + numBlocks int, blockSize int, commit bool) (simError error) { + // in case we have to end early, don't os.Exit so that we can run cleanup code. stopEarly := false testingMode, t, b := getTestingMode(tb) diff --git a/x/slashing/app_test.go b/x/slashing/app_test.go index 4ceeac94db..90e8137e2a 100644 --- a/x/slashing/app_test.go +++ b/x/slashing/app_test.go @@ -26,11 +26,12 @@ func getMockApp(t *testing.T) (*mock.App, stake.Keeper, Keeper) { RegisterWire(mapp.Cdc) keyStake := sdk.NewKVStoreKey("stake") + tkeyStake := sdk.NewTransientStoreKey("transient_stake") keySlashing := sdk.NewKVStoreKey("slashing") keyParams := sdk.NewKVStoreKey("params") bankKeeper := bank.NewBaseKeeper(mapp.AccountMapper) paramsKeeper := params.NewKeeper(mapp.Cdc, keyParams) - stakeKeeper := stake.NewKeeper(mapp.Cdc, keyStake, bankKeeper, mapp.RegisterCodespace(stake.DefaultCodespace)) + stakeKeeper := stake.NewKeeper(mapp.Cdc, keyStake, tkeyStake, bankKeeper, mapp.RegisterCodespace(stake.DefaultCodespace)) keeper := NewKeeper(mapp.Cdc, keySlashing, stakeKeeper, paramsKeeper.Getter(), mapp.RegisterCodespace(DefaultCodespace)) mapp.Router().AddRoute("stake", stake.NewHandler(stakeKeeper)) @@ -38,7 +39,7 @@ func getMockApp(t *testing.T) (*mock.App, stake.Keeper, Keeper) { mapp.SetEndBlocker(getEndBlocker(stakeKeeper)) mapp.SetInitChainer(getInitChainer(mapp, stakeKeeper)) - require.NoError(t, mapp.CompleteSetup([]*sdk.KVStoreKey{keyStake, keySlashing, keyParams})) + require.NoError(t, mapp.CompleteSetup(keyStake, keySlashing, keyParams, tkeyStake)) return mapp, stakeKeeper, keeper } diff --git a/x/slashing/test_common.go b/x/slashing/test_common.go index b10c640f52..a21930ad99 100644 --- a/x/slashing/test_common.go +++ b/x/slashing/test_common.go @@ -52,11 +52,13 @@ func createTestCodec() *wire.Codec { func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, params.Setter, Keeper) { keyAcc := sdk.NewKVStoreKey("acc") keyStake := sdk.NewKVStoreKey("stake") + tkeyStake := sdk.NewTransientStoreKey("transient_stake") keySlashing := sdk.NewKVStoreKey("slashing") keyParams := sdk.NewKVStoreKey("params") db := dbm.NewMemDB() ms := store.NewCommitMultiStore(db) ms.MountStoreWithDB(keyAcc, sdk.StoreTypeIAVL, db) + ms.MountStoreWithDB(tkeyStake, sdk.StoreTypeTransient, nil) ms.MountStoreWithDB(keyStake, sdk.StoreTypeIAVL, db) ms.MountStoreWithDB(keySlashing, sdk.StoreTypeIAVL, db) ms.MountStoreWithDB(keyParams, sdk.StoreTypeIAVL, db) @@ -67,7 +69,7 @@ func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, para accountMapper := auth.NewAccountMapper(cdc, keyAcc, auth.ProtoBaseAccount) ck := bank.NewBaseKeeper(accountMapper) params := params.NewKeeper(cdc, keyParams) - sk := stake.NewKeeper(cdc, keyStake, ck, stake.DefaultCodespace) + sk := stake.NewKeeper(cdc, keyStake, tkeyStake, ck, stake.DefaultCodespace) genesis := stake.DefaultGenesisState() genesis.Pool.LooseTokens = sdk.NewDec(initCoins.MulRaw(int64(len(addrs))).Int64()) diff --git a/x/stake/app_test.go b/x/stake/app_test.go index b5cf904334..a787e5e4d1 100644 --- a/x/stake/app_test.go +++ b/x/stake/app_test.go @@ -34,14 +34,15 @@ func getMockApp(t *testing.T) (*mock.App, Keeper) { RegisterWire(mApp.Cdc) keyStake := sdk.NewKVStoreKey("stake") + tkeyStake := sdk.NewTransientStoreKey("transient_stake") bankKeeper := bank.NewBaseKeeper(mApp.AccountMapper) - keeper := NewKeeper(mApp.Cdc, keyStake, bankKeeper, mApp.RegisterCodespace(DefaultCodespace)) + keeper := NewKeeper(mApp.Cdc, keyStake, tkeyStake, bankKeeper, mApp.RegisterCodespace(DefaultCodespace)) mApp.Router().AddRoute("stake", NewHandler(keeper)) mApp.SetEndBlocker(getEndBlocker(keeper)) mApp.SetInitChainer(getInitChainer(mApp, keeper)) - require.NoError(t, mApp.CompleteSetup([]*sdk.KVStoreKey{keyStake})) + require.NoError(t, mApp.CompleteSetup(keyStake, tkeyStake)) return mApp, keeper } diff --git a/x/stake/handler.go b/x/stake/handler.go index b00db571d2..e7641393db 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -53,7 +53,6 @@ func EndBlocker(ctx sdk.Context, k keeper.Keeper) (ValidatorUpdates []abci.Valid // calculate validator set changes ValidatorUpdates = k.GetValidTendermintUpdates(ctx) - k.ClearTendermintUpdates(ctx) return } diff --git a/x/stake/keeper/_store.md b/x/stake/keeper/_store.md index 818b17ac0c..5c070b9e09 100644 --- a/x/stake/keeper/_store.md +++ b/x/stake/keeper/_store.md @@ -3,6 +3,7 @@ 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`. +# IAVL Store ## Validators - Prefix Key Space: ValidatorsKey @@ -36,10 +37,13 @@ prefixed areas of the staking store which are accessed in `x/stake/keeper.go`. through this set to determine who we've kicked out. retrieving validator by tendermint index +# Transient Store + +The transient store persists between transations but not between blocks + ## Tendermint Updates - - Prefix Key Space: TendermintUpdatesKey + - Prefix Key Space: TendermintUpdatesTKey - 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 - updates are applied then cleared on endblock + - Used For: Informing Tendermint of the validator set updates diff --git a/x/stake/keeper/keeper.go b/x/stake/keeper/keeper.go index c928c97446..cbf6e39e4c 100644 --- a/x/stake/keeper/keeper.go +++ b/x/stake/keeper/keeper.go @@ -11,6 +11,7 @@ import ( // keeper of the stake store type Keeper struct { storeKey sdk.StoreKey + storeTKey sdk.StoreKey cdc *wire.Codec bankKeeper bank.Keeper validatorHooks sdk.ValidatorHooks @@ -19,9 +20,10 @@ type Keeper struct { codespace sdk.CodespaceType } -func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck bank.Keeper, codespace sdk.CodespaceType) Keeper { +func NewKeeper(cdc *wire.Codec, key, tkey sdk.StoreKey, ck bank.Keeper, codespace sdk.CodespaceType) Keeper { keeper := Keeper{ storeKey: key, + storeTKey: tkey, cdc: cdc, bankKeeper: ck, validatorHooks: nil, diff --git a/x/stake/keeper/key.go b/x/stake/keeper/key.go index 9dbf50c03f..c445e25524 100644 --- a/x/stake/keeper/key.go +++ b/x/stake/keeper/key.go @@ -22,14 +22,16 @@ var ( ValidatorsByPowerIndexKey = []byte{0x05} // prefix for each key to a validator index, sorted by power ValidatorCliffIndexKey = []byte{0x06} // key for the validator index of the cliff validator ValidatorPowerCliffKey = []byte{0x07} // key for the power of the validator on the cliff - TendermintUpdatesKey = []byte{0x08} // prefix for each key to a validator which is being updated - IntraTxCounterKey = []byte{0x09} // key for intra-block tx index - DelegationKey = []byte{0x0A} // key for a delegation - UnbondingDelegationKey = []byte{0x0B} // key for an unbonding-delegation - UnbondingDelegationByValIndexKey = []byte{0x0C} // prefix for each key for an unbonding-delegation, by validator operator - RedelegationKey = []byte{0x0D} // key for a redelegation - RedelegationByValSrcIndexKey = []byte{0x0E} // prefix for each key for an redelegation, by source validator operator - RedelegationByValDstIndexKey = []byte{0x0F} // prefix for each key for an redelegation, by destination validator operator + IntraTxCounterKey = []byte{0x08} // key for intra-block tx index + DelegationKey = []byte{0x09} // key for a delegation + UnbondingDelegationKey = []byte{0x0A} // key for an unbonding-delegation + UnbondingDelegationByValIndexKey = []byte{0x0B} // prefix for each key for an unbonding-delegation, by validator operator + RedelegationKey = []byte{0x0C} // key for a redelegation + RedelegationByValSrcIndexKey = []byte{0x0D} // prefix for each key for an redelegation, by source validator operator + RedelegationByValDstIndexKey = []byte{0x0E} // prefix for each key for an redelegation, by destination validator operator + + // Keys for store prefixes (transient) + TendermintUpdatesTKey = []byte{0x00} // prefix for each key to a validator which is being updated ) const maxDigitsForAccount = 12 // ~220,000,000 atoms created at launch @@ -98,8 +100,8 @@ func getValidatorPowerRank(validator types.Validator, pool types.Pool) []byte { // get the key for the accumulated update validators // VALUE: abci.Validator // note records using these keys should never persist between blocks -func GetTendermintUpdatesKey(operatorAddr sdk.ValAddress) []byte { - return append(TendermintUpdatesKey, operatorAddr.Bytes()...) +func GetTendermintUpdatesTKey(operatorAddr sdk.ValAddress) []byte { + return append(TendermintUpdatesTKey, operatorAddr.Bytes()...) } //______________________________________________________________________________ diff --git a/x/stake/keeper/test_common.go b/x/stake/keeper/test_common.go index 247ff262b2..8ebded7bfb 100644 --- a/x/stake/keeper/test_common.go +++ b/x/stake/keeper/test_common.go @@ -90,10 +90,12 @@ func ParamsNoInflation() types.Params { func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context, auth.AccountMapper, Keeper) { keyStake := sdk.NewKVStoreKey("stake") + tkeyStake := sdk.NewTransientStoreKey("transient_stake") keyAcc := sdk.NewKVStoreKey("acc") db := dbm.NewMemDB() ms := store.NewCommitMultiStore(db) + ms.MountStoreWithDB(tkeyStake, sdk.StoreTypeTransient, nil) ms.MountStoreWithDB(keyStake, sdk.StoreTypeIAVL, db) ms.MountStoreWithDB(keyAcc, sdk.StoreTypeIAVL, db) err := ms.LoadLatestVersion() @@ -107,7 +109,7 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context auth.ProtoBaseAccount, // prototype ) ck := bank.NewBaseKeeper(accountMapper) - keeper := NewKeeper(cdc, keyStake, ck, types.DefaultCodespace) + keeper := NewKeeper(cdc, keyStake, tkeyStake, ck, types.DefaultCodespace) keeper.SetPool(ctx, types.InitialPool()) keeper.SetNewParams(ctx, types.DefaultParams()) keeper.InitIntraTxCounter(ctx) diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index aaed74be41..1f65aaa957 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -203,9 +203,9 @@ func (k Keeper) GetValidatorsByPower(ctx sdk.Context) []types.Validator { // at the previous block height or were removed from the validator set entirely // are returned to Tendermint. func (k Keeper) GetValidTendermintUpdates(ctx sdk.Context) (updates []abci.Validator) { - store := ctx.KVStore(k.storeKey) + tstore := ctx.TransientStore(k.storeTKey) - iterator := sdk.KVStorePrefixIterator(store, TendermintUpdatesKey) + iterator := sdk.KVStorePrefixIterator(tstore, TendermintUpdatesTKey) for ; iterator.Valid(); iterator.Next() { var abciVal abci.Validator @@ -233,18 +233,6 @@ func (k Keeper) GetValidTendermintUpdates(ctx sdk.Context) (updates []abci.Valid return } -// remove all validator update entries after applied to Tendermint -func (k Keeper) ClearTendermintUpdates(ctx sdk.Context) { - store := ctx.KVStore(k.storeKey) - - // delete subspace - iterator := sdk.KVStorePrefixIterator(store, TendermintUpdatesKey) - for ; iterator.Valid(); iterator.Next() { - store.Delete(iterator.Key()) - } - iterator.Close() -} - //___________________________________________________________________________ // Perform all the necessary steps for when a validator changes its power. This @@ -255,7 +243,7 @@ func (k Keeper) ClearTendermintUpdates(ctx sdk.Context) { // nolint: gocyclo // TODO: Remove above nolint, function needs to be simplified! func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) types.Validator { - store := ctx.KVStore(k.storeKey) + tstore := ctx.TransientStore(k.storeTKey) pool := k.GetPool(ctx) oldValidator, oldFound := k.GetValidator(ctx, validator.OperatorAddr) @@ -280,7 +268,7 @@ 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.OperatorAddr), bz) + tstore.Set(GetTendermintUpdatesTKey(validator.OperatorAddr), bz) if cliffValExists { cliffAddr := sdk.ValAddress(k.GetCliffValidator(ctx)) @@ -315,7 +303,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.OperatorAddr), bz) + tstore.Set(GetTendermintUpdatesTKey(validator.OperatorAddr), bz) } } @@ -645,7 +633,8 @@ func (k Keeper) beginUnbondingValidator(ctx sdk.Context, validator types.Validat // add to accumulated changes for tendermint bzABCI := k.cdc.MustMarshalBinary(validator.ABCIValidatorZero()) - store.Set(GetTendermintUpdatesKey(validator.OperatorAddr), bzABCI) + tstore := ctx.TransientStore(k.storeTKey) + tstore.Set(GetTendermintUpdatesTKey(validator.OperatorAddr), bzABCI) // also remove from the Bonded types.Validators Store store.Delete(GetValidatorsBondedIndexKey(validator.OperatorAddr)) @@ -682,7 +671,8 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types. // add to accumulated changes for tendermint bzABCI := k.cdc.MustMarshalBinary(validator.ABCIValidator()) - store.Set(GetTendermintUpdatesKey(validator.OperatorAddr), bzABCI) + tstore := ctx.TransientStore(k.storeTKey) + tstore.Set(GetTendermintUpdatesTKey(validator.OperatorAddr), bzABCI) // call the bond hook if present if k.validatorHooks != nil { @@ -717,7 +707,8 @@ func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) { store.Delete(GetValidatorsBondedIndexKey(validator.OperatorAddr)) bz := k.cdc.MustMarshalBinary(validator.ABCIValidatorZero()) - store.Set(GetTendermintUpdatesKey(address), bz) + tstore := ctx.TransientStore(k.storeTKey) + tstore.Set(GetTendermintUpdatesTKey(address), bz) } //__________________________________________________________________________ diff --git a/x/stake/keeper/validator_test.go b/x/stake/keeper/validator_test.go index d9531ae1a7..89dd40677b 100644 --- a/x/stake/keeper/validator_test.go +++ b/x/stake/keeper/validator_test.go @@ -6,12 +6,25 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake/types" - tmtypes "github.com/tendermint/tendermint/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) +// for testing, remove all validator update entries after applied to Tendermint +func clearTendermintUpdates(ctx sdk.Context, k Keeper) { + store := ctx.TransientStore(k.storeTKey) + + // delete subspace + iterator := sdk.KVStorePrefixIterator(store, TendermintUpdatesTKey) + for ; iterator.Valid(); iterator.Next() { + store.Delete(iterator.Key()) + } + iterator.Close() +} + +//_______________________________________________________ + func TestSetValidator(t *testing.T) { ctx, _, keeper := CreateTestInput(t, false, 10) pool := keeper.GetPool(ctx) @@ -636,32 +649,6 @@ func TestFullValidatorSetPowerChange(t *testing.T) { assert.True(ValEq(t, validators[2], resValidators[1])) } -// clear the tracked changes to the gotValidator set -func TestClearTendermintUpdates(t *testing.T) { - ctx, _, keeper := CreateTestInput(t, false, 1000) - - amts := []int64{100, 400, 200} - validators := make([]types.Validator, len(amts)) - for i, amt := range amts { - pool := keeper.GetPool(ctx) - - valPubKey := PKs[i] - valAddr := sdk.ValAddress(valPubKey.Address().Bytes()) - - validators[i] = types.NewValidator(valAddr, valPubKey, types.Description{}) - validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) - - keeper.SetPool(ctx, pool) - keeper.UpdateValidator(ctx, validators[i]) - } - - updates := keeper.GetValidTendermintUpdates(ctx) - require.Equal(t, len(amts), len(updates)) - keeper.ClearTendermintUpdates(ctx) - updates = keeper.GetValidTendermintUpdates(ctx) - require.Equal(t, 0, len(updates)) -} - func TestGetValidTendermintUpdatesAllNone(t *testing.T) { ctx, _, keeper := CreateTestInput(t, false, 1000) @@ -688,21 +675,6 @@ func TestGetValidTendermintUpdatesAllNone(t *testing.T) { assert.Equal(t, 2, len(updates)) assert.Equal(t, validators[0].ABCIValidator(), updates[0]) assert.Equal(t, validators[1].ABCIValidator(), updates[1]) - - // test from something to nothing - // tendermintUpdate set: {} -> {c1, c2, c3, c4} - keeper.ClearTendermintUpdates(ctx) - require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) - - keeper.RemoveValidator(ctx, validators[0].OperatorAddr) - keeper.RemoveValidator(ctx, validators[1].OperatorAddr) - - updates = keeper.GetValidTendermintUpdates(ctx) - assert.Equal(t, 2, len(updates)) - assert.Equal(t, tmtypes.TM2PB.PubKey(validators[0].ConsPubKey), updates[0].PubKey) - assert.Equal(t, tmtypes.TM2PB.PubKey(validators[1].ConsPubKey), updates[1].PubKey) - assert.Equal(t, int64(0), updates[0].Power) - assert.Equal(t, int64(0), updates[1].Power) } func TestGetValidTendermintUpdatesIdentical(t *testing.T) { @@ -718,7 +690,7 @@ func TestGetValidTendermintUpdatesIdentical(t *testing.T) { } validators[0] = keeper.UpdateValidator(ctx, validators[0]) validators[1] = keeper.UpdateValidator(ctx, validators[1]) - keeper.ClearTendermintUpdates(ctx) + clearTendermintUpdates(ctx, keeper) require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) // test identical, @@ -741,7 +713,7 @@ func TestGetValidTendermintUpdatesSingleValueChange(t *testing.T) { } validators[0] = keeper.UpdateValidator(ctx, validators[0]) validators[1] = keeper.UpdateValidator(ctx, validators[1]) - keeper.ClearTendermintUpdates(ctx) + clearTendermintUpdates(ctx, keeper) require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) // test single value change @@ -769,7 +741,7 @@ func TestGetValidTendermintUpdatesMultipleValueChange(t *testing.T) { } validators[0] = keeper.UpdateValidator(ctx, validators[0]) validators[1] = keeper.UpdateValidator(ctx, validators[1]) - keeper.ClearTendermintUpdates(ctx) + clearTendermintUpdates(ctx, keeper) require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) // test multiple value change @@ -800,7 +772,7 @@ func TestGetValidTendermintUpdatesInserted(t *testing.T) { } validators[0] = keeper.UpdateValidator(ctx, validators[0]) validators[1] = keeper.UpdateValidator(ctx, validators[1]) - keeper.ClearTendermintUpdates(ctx) + clearTendermintUpdates(ctx, keeper) require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) // test validtor added at the beginning @@ -812,7 +784,7 @@ func TestGetValidTendermintUpdatesInserted(t *testing.T) { // test validtor added at the beginning // tendermintUpdate set: {} -> {c0} - keeper.ClearTendermintUpdates(ctx) + clearTendermintUpdates(ctx, keeper) validators[3] = keeper.UpdateValidator(ctx, validators[3]) updates = keeper.GetValidTendermintUpdates(ctx) require.Equal(t, 1, len(updates)) @@ -820,7 +792,7 @@ func TestGetValidTendermintUpdatesInserted(t *testing.T) { // test validtor added at the end // tendermintUpdate set: {} -> {c0} - keeper.ClearTendermintUpdates(ctx) + clearTendermintUpdates(ctx, keeper) validators[4] = keeper.UpdateValidator(ctx, validators[4]) updates = keeper.GetValidTendermintUpdates(ctx) require.Equal(t, 1, len(updates)) @@ -843,7 +815,7 @@ func TestGetValidTendermintUpdatesWithCliffValidator(t *testing.T) { } validators[0] = keeper.UpdateValidator(ctx, validators[0]) validators[1] = keeper.UpdateValidator(ctx, validators[1]) - keeper.ClearTendermintUpdates(ctx) + clearTendermintUpdates(ctx, keeper) require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) // test validator added at the end but not inserted in the valset @@ -854,7 +826,7 @@ func TestGetValidTendermintUpdatesWithCliffValidator(t *testing.T) { // test validator change its power and become a gotValidator (pushing out an existing) // tendermintUpdate set: {} -> {c0, c4} - keeper.ClearTendermintUpdates(ctx) + clearTendermintUpdates(ctx, keeper) require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) pool := keeper.GetPool(ctx) @@ -881,7 +853,7 @@ func TestGetValidTendermintUpdatesPowerDecrease(t *testing.T) { } validators[0] = keeper.UpdateValidator(ctx, validators[0]) validators[1] = keeper.UpdateValidator(ctx, validators[1]) - keeper.ClearTendermintUpdates(ctx) + clearTendermintUpdates(ctx, keeper) require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) // check initial power @@ -937,7 +909,7 @@ func TestGetValidTendermintUpdatesNewValidator(t *testing.T) { require.Equal(t, validators[0].ABCIValidator(), updates[0]) require.Equal(t, validators[1].ABCIValidator(), updates[1]) - keeper.ClearTendermintUpdates(ctx) + clearTendermintUpdates(ctx, keeper) require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) // update initial validator set @@ -1013,7 +985,7 @@ func TestGetValidTendermintUpdatesBondTransition(t *testing.T) { require.Equal(t, validators[2].ABCIValidator(), updates[0]) require.Equal(t, validators[1].ABCIValidator(), updates[1]) - keeper.ClearTendermintUpdates(ctx) + clearTendermintUpdates(ctx, keeper) require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) // delegate to validator with lowest power but not enough to bond @@ -1054,6 +1026,6 @@ func TestGetValidTendermintUpdatesBondTransition(t *testing.T) { require.Equal(t, 1, len(updates)) require.Equal(t, validators[1].ABCIValidator(), updates[0]) - keeper.ClearTendermintUpdates(ctx) + clearTendermintUpdates(ctx, keeper) require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) } diff --git a/x/stake/simulation/sim_test.go b/x/stake/simulation/sim_test.go index 7644636047..3bfd665f41 100644 --- a/x/stake/simulation/sim_test.go +++ b/x/stake/simulation/sim_test.go @@ -23,7 +23,8 @@ func TestStakeWithRandomMessages(t *testing.T) { mapper := mapp.AccountMapper bankKeeper := bank.NewBaseKeeper(mapper) stakeKey := sdk.NewKVStoreKey("stake") - stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, bankKeeper, stake.DefaultCodespace) + stakeTKey := sdk.NewTransientStoreKey("transient_stake") + stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, stakeTKey, bankKeeper, stake.DefaultCodespace) mapp.Router().AddRoute("stake", stake.NewHandler(stakeKeeper)) mapp.SetEndBlocker(func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock { validatorUpdates := stake.EndBlocker(ctx, stakeKeeper) @@ -32,7 +33,7 @@ func TestStakeWithRandomMessages(t *testing.T) { } }) - err := mapp.CompleteSetup([]*sdk.KVStoreKey{stakeKey}) + err := mapp.CompleteSetup(stakeKey, stakeTKey) if err != nil { panic(err) } diff --git a/x/stake/stake.go b/x/stake/stake.go index d60e402995..767169f9c9 100644 --- a/x/stake/stake.go +++ b/x/stake/stake.go @@ -33,7 +33,7 @@ var ( GetValidatorByPubKeyIndexKey = keeper.GetValidatorByPubKeyIndexKey GetValidatorsBondedIndexKey = keeper.GetValidatorsBondedIndexKey GetValidatorsByPowerIndexKey = keeper.GetValidatorsByPowerIndexKey - GetTendermintUpdatesKey = keeper.GetTendermintUpdatesKey + GetTendermintUpdatesTKey = keeper.GetTendermintUpdatesTKey GetDelegationKey = keeper.GetDelegationKey GetDelegationsKey = keeper.GetDelegationsKey ParamKey = keeper.ParamKey @@ -44,7 +44,7 @@ var ( ValidatorsByPowerIndexKey = keeper.ValidatorsByPowerIndexKey ValidatorCliffIndexKey = keeper.ValidatorCliffIndexKey ValidatorPowerCliffKey = keeper.ValidatorPowerCliffKey - TendermintUpdatesKey = keeper.TendermintUpdatesKey + TendermintUpdatesTKey = keeper.TendermintUpdatesTKey DelegationKey = keeper.DelegationKey IntraTxCounterKey = keeper.IntraTxCounterKey GetUBDKey = keeper.GetUBDKey