-
assigned issue to
John L. Jegutanis
Permit NuShare custodians and burning transactions
The custodian system will permit NuShare custodians. The process will be exactly the same as with NuBits, except NuShares will be granted to an NSR address.
A new "burn" RPC command will be added. It will send the given amount to an output script containing only "OP_RETURN". This output is not spendable in the current protocol and no future modification should ever change that.
When a node adds a block to its current chain, all the burned amounts will reduce the total supply of the corresponding unit. An amount is considered burned when it is sent to the exact output script "OP_RETURN". Amounts sent to an output script with anything else after the "OP_RETURN" opcode will not be considered as burned because some special protocol rules may make them spendable (the parking process for example).
The mint reward will be adjusted according to the total number of NuShares in the network. Specifically, each time the supply of NuShares reaches 50% and 100% of its original base (1 billion), the mint reward will also increase by 50% and 100%. For example, when NSR supply reaches 1.5 billion, the reward should be 60 NSR. At 2 billion, 80 NSR, at 3 billion, 120 NSR, at 4 billion, 160 NSR, and so on. If the total supply goes below one of these thresholds (because of burning for example) the reward will be reduced accordingly.
Burned NuShares will not be counted in dividend distribution, like any other unrecognized output.
Comments (9)
-
Michael Witrant reporter
-
John L. Jegutanis
Identified 3 places that disable this feature:
- CCustodianVote::IsValid() on the consensus level
- CustodianVoteDialog::accept() in the UI
- CVote ParseVote(const Object& objVote) in datafeed.cpp on the rpc level
CCustodianVote::IsValid() is the blocker and we need a hard
As for the minting reward this function could be used:
int64 GetProofOfStakeReward() { // TODO make constants // Every 250M NSR we increase the stake reward by 10 NSR. int64 PROOF_OF_STAKE_REWARD_BASE = 10 * COIN; int64 PROOF_OF_STAKE_REWARD_STEP = 250e6 * COIN; int64 nSharesSupply = pindexBest->GetMoneySupply('S'); int64 nRewardMultiplier = nSharesSupply / PROOF_OF_STAKE_REWARD_STEP; int64 nStakeReward = nRewardMultiplier * PROOF_OF_STAKE_REWARD_BASE; // Give at least 10 NSR even if we go under 250M NuShares return max(nStakeReward, PROOF_OF_STAKE_REWARD_BASE); }
-
Michael Witrant reporter
There's also an important work to do on the grant transaction. For NBT custodians a special
CurrencyCoinBasetransaction is used and it cannot be used as is on NSR. A standardCoinBasecannot be used as is either.For the block reward, you can't use
pindexBestbecause this function is also used to validate old blocks. One way would be to get theCBlockIndex*as a parameter, but then you cannot validate the reward on a disconnected block anymore. But it's probably the only way to do it anyway.Now that the money supply is protocol data we should also make sure it never overflows (or makes any calculation based on it overflow).
From my understanding of the motion, I think the reward calculation is wrong. There should be no reward value between 40 and 60 NSR, i.e. between the initial base (N) and N*1.5. The step should be
500e6. -
Michael Witrant reporter
- changed milestone to 2.0.0
-
Jordan Lee repo owner
Please do not spend any time right now changing the mint reward as it is low priority. It should be separated into a new issue and handled in accordance with the priorities I have set for the 2.0 protocol changes.
-
John L. Jegutanis
Some updates regarding this issue.
I turns out that using the same code path as the NBT custodian grants works beautifully except that it ultimately fails due to the CTransaction::IsCoinBase() check. The reason is that the NBT custodian grants have the same format as a (NSR) coinbase transaction.
[empty] -> [Coinbase transaction] -> [one or more outputs] cUnit == 'S' && vin.size() == 1 && vin[0].prevout.IsNull() && vout.size() >= 1 [empty] -> [NBT Currency coinbase transaction] -> [one or more outputs] cUnit != 'S' && vin.size() == 1 && vin[0].prevout.IsNull() && vout.size() >= 1
Some workarounds for the NSR currency coinbase:
- Setting the NSR grant in the coinbase or coinstake tx (complicated, a lot of code has to change, not elegant)
- Connecting the input to the coinbase or coinstake tx (same as above)
- Set 2 empty inputs (not possible as the inputs are duplicates)
- Set the first output as empty (it is still detected as a coinbase tx)
- Allow multiple coinbase transactions if an NSR vote pass (haven't tried it yet)
- Chang the definition of the coinbase after the fork (by checking nTime) to
(cUnit == 'S' && vin.size() == 1 && vin[0].prevout.IsNull() && vout.size() == 1 && vout[0].IsEmpty())
The last option to works but some tests fail and I have to debug a bit.
-
Michael Witrant reporter
A standard CoinBase can (and do) have multiple outputs so the last option would not work.
But maybe you meant changing the currency coin base definition?
I think adding a new definition for NSR grants would be the cleanest way.
IsCurrencyCoinBasewould return true if it's a currency coin base or an NSR grant.We can use any definition that does not match a standard transaction, a CoinBase or a CoinStake. For example a
prevoutwithhash == 0andn == -2, or a hard coded signature (but we would have to exclude this signature fromIsCoinBase). Or maybe an emptyvin(but it may be prevented somewhere).And we could rename
IsCurrencyCoinBasetoIsCustodianGrantor something. -
Michael Witrant reporter
A solution was proposed in pull request #225.
-
Michael Witrant reporter
- changed status to resolved
- Log in to comment