Cosmos-sdk: Run mint.BeginBlocker before distr.BeginBlocker

Created on 30 Nov 2018  路  9Comments  路  Source: cosmos/cosmos-sdk

Presently we run distr.BeginBlocker before mint.BeginBlocker - this means that if a large-stake validator unbonds, inflationary rewards proportional to their stake will be paid at the start of the next block (since they're just added to the collected fees in x/mint, not yet distributed). Can we swap the ordering so said validator will be able to withdraw the fees (which they deserve, since they signed the block)?

Any problems with doing this (other than needing to change a few invariants) @rigelrozanski?

proposal distribution

Most helpful comment

even mint.BeginBlocker before distr.BeginBlocker,this situation will still happen,because Inflation/AnnualProvisions calculate every 1 hour.Only if a large-stake validator unbonds at Inflation/AnnualProvisions calculate block

All 9 comments

nope that sounds fine, I don't foresee any issues

I'm not sure whether this will completely fix the problem since in x/mint we are inflating and then calculating the inflation amount for the next block.

https://github.com/cosmos/cosmos-sdk/blob/a55f4490f9b663cce9a7387b336290e355bcfe42/x/mint/abci_app.go#L15-L30

So with both of these things combined we could currently have a 2 block lag of inflation. Even though I'm wondering because in the block after the unbonding the calculation/TotalPower should be correct.

image

This is a guess of how this went in Gaia-9002.

After the genesis validators were unbonded the inflation was still lagging 2 blocks.

In the first of these we autobonded and consequently were the ones with the by far highest weight. So we accumulated almost 100% of the Accum in the FeePool in the 2nd block and could get almost all of the inflation which was still extremely large because the inflation module was "lagging behind".

That way not only inflation was extremely high for 2 rounds but we were also able to claim almost 100% of the rewards in one of the blocks.

even mint.BeginBlocker before distr.BeginBlocker,this situation will still happen,because Inflation/AnnualProvisions calculate every 1 hour.Only if a large-stake validator unbonds at Inflation/AnnualProvisions calculate block

With all these things in mind.

I don't think this change is plausible as recalculation of the AnnualProvisions after a large bonded stake change would open a potential DoS vector.

I can only imagine that calculating the inflation rate rather than the amount every hour would solve this even though that increases the effective inflation.

even mint.BeginBlocker before distr.BeginBlocker,this situation will still happen,because Inflation/AnnualProvisions calculate every 1 hour.Only if a large-stake validator unbonds at Inflation/AnnualProvisions calculate block

Yes, you are quite correct. In normal situations (no single massive validator unbonding), this doesn't seem too problematic, but in this case it definitely is.

I don't think this change is plausible as recalculation of the AnnualProvisions after a large bonded stake change would open a potential DoS vector.

I don't think this matters, calculating the annual provisions is not very expensive at all (a few multiplications) compared to lots of other things we do every block (tracking signing info, for example).

I suggest we make this BeginBlocker change and additionally recalculate inflation each block.

Thoughts @rigelrozanski?

I want to point out about the global pool distribution logic behind the scene.

  1. The fee pool has 100 stake and every validator's DelAccum is 100(suppose there are 4 validators)
  2. If node0 withdraws, he gets 100 * 100/400 = 25
    ( If the distribution is fair, node0's distribution on 100 stake is DONE. There should be no more rewards to node0 from current pool )
  3. Time passes, 4 validator's DelAccum increased by 100 each
    ( Pool stays at 75 stake )
  4. node0 withdraws again, he gets 75 * 100/700 = 10.7
  5. node1 withdraws, he gets 64.3 * 200/600 = 21.4
  6. node2 withdraws, he gets 42.9 * 200/400 = 21.4
  7. node3 withdraws, he gets 21.4 * 200/200 = 21.4

Therefore, total rewards for each node is 35.7/21.4/21.4/21.4

Considering the same DelAccum at step 1, the distribution result is somewhat different.
I suspect this logic impacted on gaia-9002. If node0 delegate his withdrawal amount(25) right after step 2, he would get more total reward than 35.7, result in larger distribution difference. And if the reward pool is very huge, the difference will explode since node0's power will increase with huge magnitude.

Is it a reasonable thing to happen in distribution logic? This logic makes all the validators to withdraw more frequently, result in heavy tx and network costs.

  • OPINION
    For the design perspective, I think the distribution design should be fixed. The distribution should not be affected by the DelAccum of future times, which is later of the reward happened time.

This logic will finally lead to an equillibrium that all the validators withdraw their rewards when their share is greater than 1 stake. It will be eventually a very competitively withdrawing network.

This logic will finally lead to an equillibrium that all the validators withdraw their rewards when their share is greater than 1 stake. It will be eventually a very competitively withdrawing network.

I also think this is likely - can we discuss on https://github.com/cosmos/cosmos-sdk/issues/2764 instead?

ok. thanks for the link! I can see your reply with similar argument already there.

Was this page helpful?
0 / 5 - 0 ratings