Post
Topic
Board Announcements (Altcoins)
Re: DNotes 2.0 - Bridging the Gap Between the Centralized and Decentralized World
by
DNotes
on 28/02/2018, 20:09:50 UTC
Found the issue -- it's a floating point bug in GetBlockValue()


Thanks flound1129! That is correct, some blocks like 2103797 reward 20.36265624 rather than (25*math.pow(0.95,4)) 20.36265625. The mystery remains, why your node rejects it and all the others seem fine with it.

It's not really a mystery, pow(0.95,4)*25 at https://github.com/DNotesCoin/DNotes/blob/master/src/main.cpp#L851-L853 evaluates to 20.362656249999997 on my system, which evaluates to False in the comparison at https://github.com/DNotesCoin/DNotes/blob/master/src/main.cpp#L1431 when the coinbase transaction vtx[0].getValueOut() == 20.36265625 and thus the block is considered invalid.

Minor correction, since nSubsidy starts out as an int64, the math should be pow(0.95,4)*2500000000 == 2036265624.9999998, which is being cast back to an int64 type at https://github.com/DNotesCoin/DNotes/blob/master/src/main.cpp#L853

Expected behavior when casting a floating point value to an int is that the number is truncated (not rounded).  See https://stackoverflow.com/questions/9695329/c-how-to-round-a-double-to-an-int

Patching main.cpp in the following manner (assuming rounding is the desired behavior) appears to fix the issue:

Code:
diff --git a/src/main.cpp b/src/main.cpp
index 4773964..48d7b3c 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -850,7 +850,7 @@ int64 static GetBlockValue(int nHeight, int64 nFees)
        {
                int yearsElapsed = nHeight / 525949;
                double nReductionPercentage = pow(0.95,yearsElapsed);
-               nSubsidy = nSubsidy * nReductionPercentage;
+               nSubsidy = (int64) ((nSubsidy * nReductionPercentage)+0.5);
        }
     return nSubsidy + nFees;
 }


Appreciate it flound1129! There was 8 or so blocks that reported 20.36265624 reward after the reward change, all of the rest have been 20.36265625, and at the point where it was 20.36265625 is the block your node started rejecting blocks. There have been no other reports of incident since, so I assume the problem is isolated to your specific setup, or as for on the network your machine. The problem is to make changes to the block reward would require forking the network, which creates an even bigger problem and across the entire network. I'll have to check, but I don't believe this can be changed just on your side without impacting the rest of the network.