Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Small double voting vulnerability (5%) in power down event at depleted voting strength. #2539

Closed
pibara opened this issue Jun 8, 2018 · 3 comments
Assignees

Comments

@pibara
Copy link

pibara commented Jun 8, 2018

This issue is related to #2428 in the way that I believe both vulnerabilities to stem from what I believe is the same underlying idiomatic design shortcoming.

This is a smaller double voting vulnerability than the one with a delegation.

Basically, the same problem that exists with a delegation at close to zero % VS also applies to the following sequence:

  • Deplete VS
  • Power-down event
  • Power up with powered down amount to a different account.

Where the resulting double voting with delegation could be as big as 42%, the power down scenario only allows a little over 5% double voting.

The below blog post describes:

  • The problem scenario
  • Why the two scenario's are actually the same underlying problem
  • How potentially making all operations "sum of the product of SP and VS" constant could lay the foundation for weeding out any such issues at a fundamental level

https://steemit.com/steem/@mattockfs/an-other-double-voting-bug-truly-fixing-steem-double-voting-issues

@mvandeberg
Copy link
Contributor

mvandeberg commented Jun 12, 2018

We have discussed this issue internally and agree it is a problem. We have a counter proposal that should not only address the problem, but solve it in a much more consistent and desirable manner.

The Problem

I want to walk through the problem with numbers assigned to everything so that we are clear we understand the math.

The two scenarios you are referring to are the following:

Alice has 13,000 SP and Bob has 12,000 SP. They both vote maximally every day.
Alice has 13,000 SP and Bob has 12,000 SP. Alice withdraws 1,000 SP to Bob and then Bob withdraws it to Alice.
I actually think this problem is fairly straightforward, but let's walk through it.

The period for the attack is 2 weeks. After that it can repeat ad infinitum.

Over 2 weeks Alice can regenerate 280% VP. Assuming she uses it all, she consumes 36,400 power shares (VP * SP). Bob can regenerate the same amount of VP but only consumes 33,600 power shares due to only having 12,000 SP. The total is 70,000 power shares.

The trick here is that Alice and Bob both want to maximize votes when they have 13,000 SP. In order to do this optimally they will vote down to 0% immediately before power down. Because of a 7 day power down the most VP they can use is 240% (100% burned immediately after acquiring SP, and regenerate 140%). When the account has 12,000 SP then they will only use 40% to allow the remaining 240% to be used with maximal SP. For a single account you have 240% * 13,000 SP + 40% * 12,000 = 36,000 power shares. Each account can do this, however, so the total is double that for 72,000 SP.

This is an increase of 2.857% to use the second method.

The nature of the bug you've described is that through a series of interactions an account can earn Power Shares (Voting Power * Vesting Shares) at a faster rate than normal. The current number of Power Shares an account has can be derived currently by multiplying voting power and SP together. On the blockchain, we denote everything in Vesting Shares (VESTS). VESTS are claims against a shared Vesting STEEM pool. The ratio of an accounts VESTS to the total VESTS times the Vesting STEEM pool is the amount of STEEM Power the account has. It is easier to do our calculations using VESTS because an account's VESTS remain constant block to block even though their SP can increase.

There are two ways we can treat liquid STEEM:

  1. It is implicitly at 0% power.
  2. It is implicitly at 100% power.

If it is at 0% power then when you power up you should not gain Power Shares, effectively lowering Voting Power.

If it is at 100% power then when you power up you should gain Power Shares, effectively increasing Voting Power.

The current power up system is actually neither of these as we let voting power remain constant. Because of this, we must assume that we are working with the second option that liquid STEEM is at 100% power but that we don't always enforce this. For the system to not be exploitable, the long term behavior must not create more Power Shares than the system will allow.

This breaks on power down because voting power remains constant. If you have 0% voting power when SP is powered down and it instantly goes to another account then the STEEM has powered back up instantly. That is where the additional 2000 power shares come from. There are two instant power up events in two weeks for 1000 SP.

This is good. We've empirically walked through the problem and shown it's existence. We also have a framework for understanding why the problem occurs which happens to spit out the exact same numerical answer!

The Solution

  • We are going to start tracking remaining voting power as Power Shares instead. condenser_api will continue to return voting_power on the account objects as it is easily calculated if you know an account's vesting shares and power shares. Power shares will still generate to 100% * SP over 5 days. There is no impact on how votes are cast, only how their weight is stored.

  • When STEEM is powered up into an account, 100% * STEEM Power Shares will be added to the account. This is an increase from what happens today and is 100% fair under this system!

  • When STEEM powers down, the week before the power down it will not generate power shares for the account. The 7 days for a chunk of STEEM to power down is greater than the 5 day regeneration and allows the STEEM to reach 100% power before it becomes liquid.

  • When delegating SP, you have to have the excess Power Shares needed to transfer the SP at 100% power. For example, if you have 1000 SP and 50% Power (500 Power Shares), you will only be able to delegate 500 SP until your power increases. This will also let us reduce the delegation return period back to 5 days (changed in HF 20 but not deployed) to let the returning delegation power back up before returning the owner.

@mvandeberg mvandeberg self-assigned this Jun 14, 2018
mvandeberg added a commit that referenced this issue Jun 22, 2018
@LKNX
Copy link

LKNX commented Jul 3, 2018

Instant delegation - Instant undelegation

We expect a smart solution for Instant undelegation. It cannot be that hard to move a delegation back home with the remaining % voting-power leftover on both accounts to a factual correct vote % average.

If you are afraid of someone gaming it, just set a -2% to 0% penalty so that a 100% comes back at 98% while a 0% vote power comes back as a 0% vote power.

Instant delegation and Instant undelegation should be a minimum requirement in the near future. All this time-traps do is halting businesses and projects, got to think longer than that.

@mvandeberg
Copy link
Contributor

@LKNX Instant delegation has always been the behavior.

Instant undelegation could be an extension to this assuming there is sufficient mana in the returned VESTS. As it stands, the changes being implemented will reduce the delegation return time from 7 days to 5 while still removing the exploit. This is not a promise the develop instant undelegation, only a confirmation that the solution we have implemented does not rule out a similar behavior entirely.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants