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

[Staking][Wallet] Add Multi-Split functionality to stake output splitting #968

Merged
merged 2 commits into from
Sep 17, 2019

Conversation

CaveSpectre11
Copy link

Release notes

  • [Staking] Staking inputs are now split into 2 or more outputs based on the stake split threshold

Note

For ease of rebasing; and for cleaner testing; this PR is built on top of PR #952 and will need adjustments if PR #952 has changes.

Background

The common function of stakesplitthreshold is to break a stake that has grown large into two outputs, splitting them in half. It is assumed the size of the split is based on the users amount of coins they are staking, and they desire their staking UTXOs to be sized between their stake split threshold and 2 times that stake split threshold.

This design falters when a stake UTXO is a multiple of the stake split threshold; causing repetitive halving until all outputs reach below twice the stake split threshold.

For example, with a stake split threshold of 2000; a UTXO will grow until it hits 4000 coins, at which point it will split to 2000 coins. However if the UTXO was 10,000 coins; it would split to two 5000 coin UTXOs, which would then split on the next stake for each of them; to 2500 coins.

This becomes more problematic when considering the impact to the coin owners staking odds. After a split; the coins will not stake until they mature. So when that 10k splits into two 5k blocks, they won't stake for another 101 transactions. After 101 transactions, the 10k is now being staked, until the next split; at which point only 5k is staking for the next 101 transactions.

This issue comes up in a variety of scenarios; A large transaction from an exchange or a payment received, Unlocking a masternode for staking, auto combine rewards (especially with PR #953) sweeping up a lot of dust bunnies into a big UTXO; just to name a few.

Multi-Split

Multi-Split will now use the stake split threshold to determine how many multiples of the threshold is contained in the input transaction; and split accordingly. In the theoretical example above; that first stake of 10k will now be split into 5 outputs of 2000.4. When one of those outputs receives a stake, instead of only the other 5k being staked for the 101 transactions to maturity; now 8k will remain staked for the maturity period of the UTXO (post split) being unavailable for staking.

For a real example, with a stake split threshold of 1500, and a UTXO of 4708.1557; the current stake split algorithm would break that into two outputs of approximately 2355.07785. With this new logic; it will be broken into 3 outputs instead of two; each sized 1570.0519 (4708.1557 input + 2 stake = 4710.1557 / 3 outputs = 1570.0519.

See this test transaction in testnet block 1171496

In order to limit the potential size growth of the staking transaction; the number of splits is limited. This limit is a calculation based on the MAX_STANDARD_TX_SIZE, and is meant to limit the staking transaction to less than 10% of that size. With an assumed per vout size of 190, rounded up, and converted to a bit shift for speed; MAX_STANDARD_TX_SIZE is shifted right 11 bits. In simpler math:
The limit is effectively MAX_STANDARD_TX_SIZE divided by 2048, creating a maximum limit of outputs for the stake split to 48 (with the current MAX_STANDARD_TX_SIZE of 100k).

An example of this test can be seen in testblock 1171785, where a UTXO of 13114.83882369 coins was used for a stake; and the stake split threshold was set to 100. The logic would have split this into 131 outputs of 131.116 and change, however the maximum threshold is reached, and thus it is split into 47 outputs of 273.26747549, with the 48th output having the .17 uPiv remainder added and resulting in that final output of 273.26747566.

As the stake splitting is contained within the wallet software itself; there is no protocol change with this PR; the consensus is already built to look at the last vout for the masternode payment, and look at the total value of a variable number of outputs to confirm that an overmint is not occurring.

@CaveSpectre11 CaveSpectre11 changed the title [Staking] Add Multi-Split functionality to stake output splitting [Staking][Wallet] Add Multi-Split functionality to stake output splitting Jul 30, 2019
@Fuzzbawls Fuzzbawls added this to In progress in Community Developer Contributions via automation Aug 1, 2019
@random-zebra random-zebra added this to the 4.0.0 milestone Aug 6, 2019
@Fuzzbawls Fuzzbawls added Block Generation Mining/Staking related issues Wallet labels Sep 1, 2019
Copy link

@random-zebra random-zebra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Community Developer Contributions automation moved this from In progress to Reviewer approved Sep 17, 2019
Copy link
Collaborator

@Fuzzbawls Fuzzbawls left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK 2e41db5

@furszy furszy self-requested a review September 17, 2019 23:46
Copy link

@furszy furszy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Finally here, great PR description, code looking good.

utACK 2e41db5

random-zebra added a commit that referenced this pull request Sep 17, 2019
…output splitting

2e41db5 [Staking] Revise stakesplit to multi-split (Cave Spectre)

Pull request description:

  ### **Release notes**
  - [Staking] Staking inputs are now split into 2 or more outputs based on the stake split threshold

  ### **Note**
  For ease of rebasing; and for cleaner testing; this PR is built on top of PR #952 and will need adjustments if PR #952 has changes.

  ### **Background**
  The common function of `stakesplitthreshold` is to break a stake that has grown large into two outputs, splitting them in half.  It is assumed the size of the split is based on the users amount of coins they are staking, and they desire their staking UTXOs to be sized between their stake split threshold and 2 times that stake split threshold.

  This design falters when a stake UTXO is a multiple of the stake split threshold; causing repetitive halving until all outputs reach below twice the stake split threshold.

  For example, with a stake split threshold of 2000; a UTXO will grow until it hits 4000 coins, at which point it will split to 2000 coins.  However if the UTXO was 10,000 coins; it would split to two 5000 coin UTXOs, which would then split on the next stake for each of them; to 2500 coins.

  This becomes more problematic when considering the impact to the coin owners staking odds.  After a split; the coins will not stake until they mature.  So when that 10k splits into two 5k blocks, they won't stake for another 101 transactions.   After 101 transactions, the 10k is now being staked, until the next split; at which point only 5k is staking for the next 101 transactions.

  This issue comes up in a variety of scenarios;  A large transaction from an exchange or a payment received, Unlocking a masternode for staking, auto combine rewards (especially with PR #953) sweeping up a lot of dust bunnies into a big UTXO; just to name a few.

  ### **Multi-Split**
  Multi-Split will now use the stake split threshold to determine how many multiples of the threshold is contained in the input transaction; and split accordingly.  In the theoretical example above; that first stake of 10k will now be split into 5 outputs of 2000.4.  When one of those outputs receives a stake, instead of only the other 5k being staked for the 101 transactions to maturity; now 8k will remain staked for the maturity period of the UTXO (post split) being unavailable for staking.

  For a real example, with a stake split threshold of 1500, and a UTXO of 4708.1557; the current stake split algorithm would break that into two outputs of approximately 2355.07785.  With this new logic; it will be broken into 3 outputs instead of two; each sized 1570.0519 (4708.1557 input + 2 stake = 4710.1557 / 3 outputs = 1570.0519.

  _See this test transaction in [testnet block 1171496](https://testnet.pivx.link/block/1171496)_

  In order to limit the potential size growth of the staking transaction; the number of splits is limited.  This limit is a calculation based on the MAX_STANDARD_TX_SIZE, and is meant to limit the staking transaction to less than 10% of that size.  With an assumed per vout size of 190, rounded up, and converted to a bit shift for speed; MAX_STANDARD_TX_SIZE is shifted right 11 bits.  In simpler math:
   The limit is effectively MAX_STANDARD_TX_SIZE divided by 2048, creating a maximum limit of outputs for the stake split to 48 (with the current MAX_STANDARD_TX_SIZE of 100k).

  An example of this test can be seen in [testblock 1171785](https://testnet.pivx.link/block/1171785), where a UTXO of 13114.83882369 coins was used for a stake; and the stake split threshold was set to 100.  The logic would have split this into 131 outputs of 131.116 and change, however the maximum threshold is reached, and thus it is split into 47 outputs of 273.26747549, with the 48th output having the .17 uPiv remainder added and resulting in that final output of 273.26747566.

  As the stake splitting is contained within the wallet software itself; there is **no protocol change with this PR**; the consensus is already built to look at the last vout for the masternode payment, and look at the total value of a variable number of outputs to confirm that an overmint is not occurring.

ACKs for top commit:
  random-zebra:
    ACK 2e41db5
  Fuzzbawls:
    utACK 2e41db5
  furszy:
    utACK [2e41db5](2e41db5)

Tree-SHA512: 35f612a5042de964bd3fda040ff2e3ea24de81300ecdc7d9d322757471df45cc4c7cb3d7905554ec41b607bb8364a94ced372c93ac7963c7729653d88cf32765
@random-zebra random-zebra merged commit 2e41db5 into PIVX-Project:master Sep 17, 2019
Community Developer Contributions automation moved this from Reviewer approved to Accepted Sep 17, 2019
@CaveSpectre11 CaveSpectre11 deleted the MultiSplit branch September 30, 2019 11:47
@Fuzzbawls Fuzzbawls added the Needs Release Notes Placeholder tag for anything needing mention in the "Notable Changes" section of release notes label Dec 3, 2019
@Fuzzbawls Fuzzbawls removed the Needs Release Notes Placeholder tag for anything needing mention in the "Notable Changes" section of release notes label Dec 14, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Block Generation Mining/Staking related issues Wallet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants