Author

Topic: Fixing negative rewards with high staking coins. (Read 315 times)

legendary
Activity: 1638
Merit: 1036
So it seems that Hi-POS has revealed another limit to generic coin code.

When uint64 nCoinAge becomes too large, it can cause int64 nSubsidy to overflow into a negative value, then because negative rewards are generally not accepteed, this prevents that input from ever staking.
(nCoinAge being unsigned, and nSubsidy being signed)

the basic, and truncated, code in question is
Code:
bool CTransaction::GetCoinAge(CTxDB& txdb, uint64_t& nCoinAge) const
{
    CBigNum bnCentSecond = 0;  // coin age in the unit of cent-seconds
    nCoinAge = 0;

        int64_t nValueIn = txPrev.vout[txin.prevout.n].nValue;
        bnCentSecond += CBigNum(nValueIn) * (nTime-txPrev.nTime) / CENT;

    CBigNum bnCoinDay = bnCentSecond * CENT / COIN / (24 * 60 * 60);

    nCoinAge = bnCoinDay.getuint64();
}

Code:
static const int64_t COIN_YEAR_REWARD = 1000 * CENT;


int64_t GetProofOfStakeReward(int nHeight, int64_t nCoinAge, int64_t nFees)
{
    int64_t nSubsidy = nCoinAge * COIN_YEAR_REWARD * 33 / (365 * 33 + 8);

    return nSubsidy + nFees;
}



I'm pondering different options to "fix" this.

1. modify nCoinAge
- it were based on CoinYear rather than CoinDay, the possibility would be diminished but would still exist.
- if it were given an upper limit then it would be possible for nSubsidy to never exceed upper limit of being int64.


2. modify nSubsidy
- ignoring the -ve and getting absolute value as is , not sure of correct usage but something along lines of
Code:
    int64_t nSubsidy = abs(nCoinAge * COIN_YEAR_REWARD * 33 / (365 * 33 + 8));
- i cant think of any reason why it needs to be signed ? so converting to uint64, would never have a -ve return, and overflows would just be ignored
- does it even need to be uint64? give it more bits? eg converting to CBigNum which is 256 bit?




.

another variable of interest in this is MAX_MONEY, as it defines maximum possible size of input, it then sets some idea where nCoinAge becomes an issue
maximum value of int64 / MAX_MONEY = age at which larges possible input will cause problems

Code:
static const int64_t MAX_MONEY = 700000000 * COIN;


.

other possibilities include auto splitting the input if it is obviously an issue.
when nCoinAge of the input exceeds some value, then split it.

this would be interesting because it's only a client update, where the others seem to requiring forks.
Jump to: