Bitcoin Forum
October 21, 2018, 06:12:54 PM
 News: Make sure you are not using versions of Bitcoin Core other than 0.17.0 [Torrent], 0.16.3, 0.15.2, or 0.14.3. More info.
 Home Help Search Donate Login Register
 Pages: [1]
 Author Topic: PPCoin: stake reward logic (GetProofOfStakeReward)  (Read 2902 times)
Jutarul
Donator
Legendary

Offline

Activity: 994
Merit: 1000

 September 12, 2012, 11:52:34 PM

I am currently digging through the ppcoin source code to understand the reward mechanism.

Stake rewards are calculated based on the following equation (code below)

CENT=10000;
int64 nSubsidy = nCoinAge * 33 / (365 * 33 + * CENT;

Thus a CoinAge of 30000 (1000PPC at 30 days) provides a reward of about 0.8PPC (which corresponds to about 0.08% interest per month or about 1% per year)

Questions:
1) what the purpose of the 33?
2) Is there another limit to the money generation I overlooked? Right now it looks like PPCoin is inflationary in nature (1% per year).
3) What is the rationale for the choice for rewards? Why 1% and not 0.5% return on stake per year?

Code:
// ppcoin: miner's coin stake is rewarded based on coin age spent (coin-days)
int64 GetProofOfStakeReward(int64 nCoinAge)
{
static int64 nRewardCoinYear = CENT;  // creation amount per coin-year
int64 nSubsidy = nCoinAge * 33 / (365 * 33 + 8) * nRewardCoinYear;
if (fDebug && GetBoolArg("-printcreation"))
printf("GetProofOfStakeReward(): create=%s nCoinAge=%"PRI64d"\n", FormatMoney(nSubsidy).c_str(), nCoinAge);
return nSubsidy;
}

The ASICMINER Project https://bitcointalk.org/index.php?topic=99497.0
"The way you solve things is by making it politically profitable for the wrong people to do the right thing.", Milton Friedman
1540145574
Hero Member

Offline

Posts: 1540145574

Ignore
 1540145574

1540145574
 Report to moderator
1540145574
Hero Member

Offline

Posts: 1540145574

Ignore
 1540145574

1540145574
 Report to moderator
1540145574
Hero Member

Offline

Posts: 1540145574

Ignore
 1540145574

1540145574
 Report to moderator
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction. Advertise here.
Sunny King
Legendary

Offline

Activity: 1203
Merit: 1001

 September 13, 2012, 12:28:52 AM

I am currently digging through the ppcoin source code to understand the reward mechanism.

Stake rewards are calculated based on the following equation (code below)

CENT=10000;
int64 nSubsidy = nCoinAge * 33 / (365 * 33 + * CENT;

Thus a CoinAge of 30000 (1000PPC at 30 days) provides a reward of about 0.8PPC (which corresponds to about 0.08% interest per month or about 1% per year)

Questions:
1) what the purpose of the 33?
2) Is there another limit to the money generation I overlooked? Right now it looks like PPCoin is inflationary in nature (1% per year).
3) What is the rationale for the choice for rewards? Why 1% and not 0.5% return on stake per year?

Code:
// ppcoin: miner's coin stake is rewarded based on coin age spent (coin-days)
int64 GetProofOfStakeReward(int64 nCoinAge)
{
static int64 nRewardCoinYear = CENT;  // creation amount per coin-year
int64 nSubsidy = nCoinAge * 33 / (365 * 33 + 8) * nRewardCoinYear;
if (fDebug && GetBoolArg("-printcreation"))
printf("GetProofOfStakeReward(): create=%s nCoinAge=%"PRI64d"\n", FormatMoney(nSubsidy).c_str(), nCoinAge);
return nSubsidy;
}

Good to see people researching the code. 365+8/33 is an approximation of number of days in a year.
1% is chosen as it's a round number and low inflation rate. Not all coin age would generate block so the actual rate is likely lower than 1%.

Following info is from our FAQ:

Is there a cap on total money supply like Bitcoin's 21 million?

There is no hard cap other than a 2 billion coin max put into the code for now. But that should not be interpreted as an approachable cap, as it might never get anywhere close to that. It should not be considered a hard cap either as it may get lifted but that's likely not needed in a very very long time. Due to the nature of the mint rate design it's not possible to predict a final limit as it depends heavily on market participation, as well as the influences between proof-of-stake minting and fee destruction (there may not even be a mathematical limit if minting continues to outpace fee destruction). What we do know is that the proof-of-work minting would slow down exponentially according to Moore's Law (we are aware that Moore's Law eventually would stop to apply), and proof-of-stake minting introduces at most 1% annual inflation. So generally speaking it is still a very low future-inflation design comparable to Bitcoin.

In 0.2 release a 'moneysupply' stat is included in the getinfo output so everyone can see how many coins are in the market.
Jutarul
Donator
Legendary

Offline

Activity: 994
Merit: 1000

 September 13, 2012, 12:44:58 AM

Good to see people researching the code. 365+8/33 is an approximation of number of days in a year.
Ah. good. So you're accounting for the additional day every 4 years...

1% is chosen as it's a round number and low inflation rate. Not all coin age would generate block so the actual rate is likely lower than 1%.
Makes sense. So 1% seems to be the "worst" case.

Following info is from our FAQ:
Is there a cap on total money supply like Bitcoin's 21 million?
...
There is no hard cap other than a 2 billion coin max put into the code for now. But that should not be interpreted as an approachable cap, ... (there may not even be a mathematical limit if minting continues to outpace fee destruction). ...
Thanks for pointing that out. So the transaction fee in ppcoin works different than in bitcoin? In bitcoin its voluntary and is redistributed to the miner as an incentive. Based on what you're suggesting is that ppcoin's transaction fees actually affect the money supply!

The ASICMINER Project https://bitcointalk.org/index.php?topic=99497.0
"The way you solve things is by making it politically profitable for the wrong people to do the right thing.", Milton Friedman
Sunny King
Legendary

Offline

Activity: 1203
Merit: 1001

 September 13, 2012, 01:08:50 AM

Thanks for pointing that out. So the transaction fee in ppcoin works different than in bitcoin? In bitcoin its voluntary and is redistributed to the miner as an incentive. Based on what you're suggesting is that ppcoin's transaction fees actually affect the money supply!

Yes. Transaction fees are destroyed and act as a deflationary force in ppcoin.
Jutarul
Donator
Legendary

Offline

Activity: 994
Merit: 1000

 September 13, 2012, 01:36:50 AM

Thanks for pointing that out. So the transaction fee in ppcoin works different than in bitcoin? In bitcoin its voluntary and is redistributed to the miner as an incentive. Based on what you're suggesting is that ppcoin's transaction fees actually affect the money supply!

Yes. Transaction fees are destroyed and act as a deflationary force in ppcoin.

Wow. That gives it a totally different dynamic! Would be interesting to determine the half-time of the money.. that is the number of transactions necessary that it only has half of the nominal value.

The ASICMINER Project https://bitcointalk.org/index.php?topic=99497.0
"The way you solve things is by making it politically profitable for the wrong people to do the right thing.", Milton Friedman
Etlase2
Hero Member

Offline

Activity: 798
Merit: 1000

 September 13, 2012, 01:48:42 AM

In all honesty,

Code:
int64 nSubsidy = nCoinAge * 33 / (365 * 33 + 8) * nRewardCoinYear;

this is some scary code. Is there something I am missing, or is compiler-dependent rounding part of your network protocol?
This may work in C++ across all implementations, may, assuming they all adhere to the same standard, which is not a given.

This may work in java or other implementations, but there is no guarantee. This may work in future programming languages.

But all in all it is a not a good design decision. It has Y2K written all over it.

markm
Legendary

Offline

Activity: 2114
Merit: 1000

 September 13, 2012, 02:17:52 AM

In all honesty,

Code:
int64 nSubsidy = nCoinAge * 33 / (365 * 33 + 8) * nRewardCoinYear;

this is some scary code. Is there something I am missing, or is compiler-dependent rounding part of your network protocol?
This may work in C++ across all implementations, may, assuming they all adhere to the same standard, which is not a given.

This may work in java or other implementations, but there is no guarantee. This may work in future programming languages.

But all in all it is a not a good design decision. It has Y2K written all over it.

Since the variables are all presumably integers of a known number of bits, how is integer arithmetic compiler-dependent? That sounds like a really bad compiler design more than a code problem?

tl;dr integers do not round, they truncate...

-MarkM-

Browser-launched Crossfire client now online (select CrossCiv server for Galactic  Milieu)
Free website hosting with PHP, MySQL etc: http://hosting.knotwork.com/
Jutarul
Donator
Legendary

Offline

Activity: 994
Merit: 1000

 September 13, 2012, 02:22:01 AM

In all honesty,

Code:
int64 nSubsidy = nCoinAge * 33 / (365 * 33 + 8) * nRewardCoinYear;

this is some scary code. Is there something I am missing, or is compiler-dependent rounding part of your network protocol?
This may work in C++ across all implementations, may, assuming they all adhere to the same standard, which is not a given.

This may work in java or other implementations, but there is no guarantee. This may work in future programming languages.

But all in all it is a not a good design decision. It has Y2K written all over it.

lol. good catch.
As far as I understand C++, it is not doing any "rounding", because it never is converted to a different datatype. (as opposed to e.g. python)  But what is problematic is the order by which the expression is evaluated. If the convention would be simply from right to left, then nSubsidy would always yield 0.

Code:
proof:
(365 * 33 + 8) * 10000 = 120530000
33/120530000 = 0
nCoinAge * 0 = 0
nSubsidy = 0

However, most compilers have operator associativity left to right, which yields the correct value IN THIS CASE.

The ASICMINER Project https://bitcointalk.org/index.php?topic=99497.0
"The way you solve things is by making it politically profitable for the wrong people to do the right thing.", Milton Friedman
markm
Legendary

Offline

Activity: 2114
Merit: 1000

 September 13, 2012, 02:41:24 AM

However, most compilers have operator associativity left to right, which yields the correct value IN THIS CASE.

Most compilers?

That associativity is part of the language itself isn't it? So that a compiler that does not do it that way would be a different language's compiler.

So again, back to it being a problem compiler rather than problem code.

Could run into the problem though maybe if someone who does not bother to pay close attention to the associativity of the language they are porting from tries to port it though I suppose.

-MarkM-

Browser-launched Crossfire client now online (select CrossCiv server for Galactic  Milieu)
Free website hosting with PHP, MySQL etc: http://hosting.knotwork.com/
Jutarul
Donator
Legendary

Offline

Activity: 994
Merit: 1000

 September 13, 2012, 03:05:43 AM

Most compilers?
That associativity is part of the language itself isn't it? So that a compiler that does not do it that way would be a different language's compiler.
So again, back to it being a problem compiler rather than problem code.

Could run into the problem though maybe if someone who does not bother to pay close attention to the associativity of the language they are porting from tries to port it though I suppose.

-MarkM-

You're right. My bad. So problem will occur when somebody wants to port this or runs into a compiler bug.

However, back to the original problem. I don't think the code works as INTENDED.
E.g.
CoinAge=365 -> nSubsidy= 0.
CoinAge=366 -> nSubsidy= 10000.

Which is due to operator associativity...

I think the intent was:
CoinAge=365 -> nSubsidy= 9993
CoinAge=366 -> nSubsidy= 10020

which translates into code:
Code:
int64 nSubsidy = (nRewardCoinYear * nCoinAge * 33) / (365 * 33 + 8) ;

The ASICMINER Project https://bitcointalk.org/index.php?topic=99497.0
"The way you solve things is by making it politically profitable for the wrong people to do the right thing.", Milton Friedman
Etlase2
Hero Member

Offline

Activity: 798
Merit: 1000

 September 13, 2012, 04:36:26 AM

So again, back to it being a problem compiler rather than problem code.

Not an associativity problem that I brought up, but indeed a rounding problem. When you get 1258.83752 or whatever there is no set standard across all implementations that says the number should be 1258 or 1259. C did not standardize this until many, many years after it was originally designed. If you're familiar with a company called Microsoft and a software called Visual Studio, you'll be perhaps not so surprised to know that not everybody complies with ANSI C standards with their compilers. And again, there is nothing that says this will be the same standard for other languages.

edit: more derpage

markm
Legendary

Offline

Activity: 2114
Merit: 1000

 September 13, 2012, 04:48:13 AM

There is no rounding if all the variables are integers. There is nothing to round as there are no decimals in the first place.

In fact it is the processor hardware that does this I think, only some language that does not distinguish integers from reals could even get around it maybe. In C you'd have to cast to real somewhere in there or something like that.

Maybe you are imagining that the eight decimals you see displayed imply decimals exist in the code? The code uses integers, the display routines stick a decimal in before the last eight digits of the actual integer value used internally.

-MarkM-

Browser-launched Crossfire client now online (select CrossCiv server for Galactic  Milieu)
Free website hosting with PHP, MySQL etc: http://hosting.knotwork.com/
Etlase2
Hero Member

Offline

Activity: 798
Merit: 1000

 September 13, 2012, 05:04:21 AM

There is no rounding if all the variables are integers. There is nothing to round as there are no decimals in the first place.

You know what, I derped on this. This was a problem in the past if one of the operands was negative. The behavior could be truncate closest to zero, or be the smallest integer (e.g. -5.5 would be -6). This used to be implementation-specific behavior in C and does allude to there being more going on than just what the processor decides or that it is universally truncated. But in unsigned ints I don't believe it was ever an issue and I was mistaken there. Some old crusty nugget of misremembered information led me astray.

The original formula is apt to lose precision (if it was correct) for no particular reason though.

AndyRossy
Sr. Member

Offline

Activity: 448
Merit: 250

 September 13, 2012, 09:02:15 AM

Code:
//  int64 nSubsidy = nCoinAge * 33 / (365 * 33 + 8) * nRewardCoinYear;
int64 nCoEff     = 0.00273790757487762;
int64 nSubsidy = nCoinAge * nRewardCoinYear * nCoEff ;
Just calc the division yourself? Next.
Jutarul
Donator
Legendary

Offline

Activity: 994
Merit: 1000

 September 13, 2012, 09:07:47 AM

int64 nCoEff     = 0.00273790757487762;
lol. I pretend I didn't see that

The ASICMINER Project https://bitcointalk.org/index.php?topic=99497.0
"The way you solve things is by making it politically profitable for the wrong people to do the right thing.", Milton Friedman
AndyRossy
Sr. Member

Offline

Activity: 448
Merit: 250

 September 13, 2012, 09:17:32 AM

int64 nCoEff     = 0.00273790757487762;
lol. I pretend I didn't see that

oops xD even worse, my var name woooop good morning world.
 Pages: [1]