-
Notifications
You must be signed in to change notification settings - Fork 36
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
Implement Stake Pre-Splitting #444
base: master
Are you sure you want to change the base?
Conversation
This was causing change to be computed incorrectly if the actual `valueOut` differed from the user's `value` due to automated differences (i.e: Stake Split remainders)
✅ Deploy Preview for cheery-moxie-4f1121 ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a few comments, but overall I like the feature
scripts/wallet.js
Outdated
@@ -1062,7 +1062,7 @@ export class Wallet { | |||
} | |||
|
|||
const fee = transactionBuilder.getFee(); | |||
const changeValue = transactionBuilder.valueIn - value - fee; | |||
const changeValue = transactionBuilder.valueIn - transactionBuilder.valueOut - fee; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert that value === transcationBuilder.valueOut
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a couple of comments
// The per-output target for maximum staking efficiency | ||
const nTarget = cChainParams.current.stakeSplitTarget; | ||
// Generate optimal staking outputs | ||
for (let i = 0; i <= Math.floor(value / nTarget); i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see the problem here, but I would prefer that the whole value
is staked... what about something like this?
for (let i = 0; i <= Math.floor(value / nTarget); i++) { | |
if(value < COIN) { | |
throw new Error("below consensus); | |
} else if (value < nTarget) { | |
transactionBuilder.addColdStakeOutput({ | |
address: returnAddress, | |
addressColdStake: address, | |
value, | |
}); | |
} else { | |
for (let i = 0; i < Math.floor(value / nTarget); i++) { | |
transactionBuilder.addColdStakeOutput({ | |
address: returnAddress, | |
addressColdStake: address, | |
value: i == 0 ? nTarget + (value % nTarget) : nTarget, | |
}); | |
} | |
} |
@@ -165,6 +165,7 @@ describe('Wallet transaction tests', () => { | |||
}); | |||
|
|||
it('Creates a cold stake tx correctly', async () => { | |||
// TODO: rewrite this test over >1 PIV to match PIVX Consensus, and to also test Stake Splitting |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
update the test in this PR
Abstract
This PR adds a simple but very useful improvement to staking efficiency for MPW, by pre-splitting large delegations, we allow each output to confirm and start staking individually without causing one stake to put the entire balance in to a long maturation period.
Take these two examples of how this change could improve the user experience:
Example 1: unusually large 'immature balances' confusing users
If a user delegates 10,000 PIVX (their entire balance), and it hits a stake, their entire balance is going to be considered immature, and thus unusable, which is not ideal - this situation can be prevented by pre-splitting delegated UTXOs.
Example 2: slower stake rewards, shortly after delegating
In the same example of staking 10,000 PIV: if you delegate a single UTXO of 10,000, which hits a stake - then that entire UTXO will not be staking until it re-matures, and the Cold Address splits this automatically with PIVX Core's
stakesplitthreshold
, this wasted time ends up reducing the rewards you could potentially earn in the short-term.With pre-splitting in to, say, 20x 500 PIV UTXOs, hitting a stake means only 500 PIV is immature, and the other 9,500 PIV continues staking, which means you could earn more stakes in the same time period that it takes for your initial 10k to re-mature and become stakeable again.
Note
The PR's suggested split target is 500 PIV - the same setting that the PIVX Labs Cold Pool uses for it's
stakesplitthreshold
.Mainnet Example
Using this PR, configured at a 5 PIV split threshold, a new large delegation looks like:
https://explorer2.duddino.com/tx/295a547273879d744d5cd34a0cf09ba973842aa53023a0425407f0a9d91b5390
Testing
To test this PR, it's suggested to attempt these user flows, or variations of these:
vout
) on the explorer.If any errors are found, the PR works unexpectedly, or you have viable suggestions to improve the UX or functionality of the PR, let me know!