Add wallet dump functionality and key creation timestamps
[novacoin.git] / src / main.cpp
index 6e897fd..af4e190 100644 (file)
@@ -37,6 +37,7 @@ CBigNum bnProofOfWorkLimit(~uint256(0) >> 20); // "standard" scrypt target limit
 CBigNum bnProofOfStakeLegacyLimit(~uint256(0) >> 24); // proof of stake target limit from block #15000 and until 20 June 2013, results with 0,00390625 proof of stake difficulty
 CBigNum bnProofOfStakeLimit(~uint256(0) >> 27); // proof of stake target limit since 20 June 2013, equal to 0.03125  proof of stake difficulty
 CBigNum bnProofOfStakeHardLimit(~uint256(0) >> 30); // disabled temporarily, will be used in the future to fix minimal proof of stake difficulty at 0.25
+CBigNum bnPoWBase = CBigNum(uint256("0x00000000ffff0000000000000000000000000000000000000000000000000000")); // difficulty-1 target
 
 CBigNum bnProofOfWorkLimitTestNet(~uint256(0) >> 16);
 
@@ -939,7 +940,7 @@ uint256 WantedByOrphan(const CBlock* pblockOrphan)
 }
 
 // select stake target limit according to hard-coded conditions
-CBigNum static GetProofOfStakeLimit(int nHeight, unsigned int nTime)
+CBigNum inline GetProofOfStakeLimit(int nHeight, unsigned int nTime)
 {
     if(fTestNet) // separate proof of stake target limit for testnet
         return bnProofOfStakeLimit;
@@ -993,9 +994,9 @@ int64 GetProofOfWorkReward(unsigned int nBits)
 }
 
 // miner's coin stake reward based on nBits and coin age spent (coin-days)
-int64 GetProofOfStakeReward(int64 nCoinAge, unsigned int nBits, unsigned int nTime)
+int64 GetProofOfStakeReward(int64 nCoinAge, unsigned int nBits, unsigned int nTime, bool bCoinYearOnly)
 {
-    int64 nRewardCoinYear;
+    int64 nRewardCoinYear, nSubsidy;
 
     if(fTestNet || nTime > STAKE_SWITCH_TIME)
     {
@@ -1007,22 +1008,46 @@ int64 GetProofOfStakeReward(int64 nCoinAge, unsigned int nBits, unsigned int nTi
         CBigNum bnTargetLimit = GetProofOfStakeLimit(0, nTime);
         bnTargetLimit.SetCompact(bnTargetLimit.GetCompact());
 
-        // NovaCoin: reward for coin-year is cut in half every 64x multiply of PoS difficulty
-        // A reasonably continuous curve is used to avoid shock to market
-        // (nRewardCoinYearLimit / nRewardCoinYear) ** 6 == bnProofOfStakeLimit / bnTarget
-        //
-        // Human readable form:
-        //
-        // nRewardCoinYear = 1 / (posdiff ^ 1/6)
+        // NovaCoin: A reasonably continuous curve is used to avoid shock to market
+
+        CBigNum bnLowerBound = 1 * CENT, // Lower interest bound is 1% per year
+            bnUpperBound = bnRewardCoinYearLimit, // Upper interest bound is 100% per year
+            bnMidPart, bnRewardPart;
 
-        CBigNum bnLowerBound = 1 * CENT; // Lower interest bound is 1% per year
-        CBigNum bnUpperBound = bnRewardCoinYearLimit;
         while (bnLowerBound + CENT <= bnUpperBound)
         {
             CBigNum bnMidValue = (bnLowerBound + bnUpperBound) / 2;
             if (fDebug && GetBoolArg("-printcreation"))
                 printf("GetProofOfStakeReward() : lower=%"PRI64d" upper=%"PRI64d" mid=%"PRI64d"\n", bnLowerBound.getuint64(), bnUpperBound.getuint64(), bnMidValue.getuint64());
-            if (bnMidValue * bnMidValue * bnMidValue * bnMidValue * bnMidValue * bnMidValue * bnTargetLimit > bnRewardCoinYearLimit * bnRewardCoinYearLimit * bnRewardCoinYearLimit * bnRewardCoinYearLimit * bnRewardCoinYearLimit * bnRewardCoinYearLimit * bnTarget)
+
+            if(!fTestNet && nTime < STAKECURVE_SWITCH_TIME)
+            {
+                //
+                // Until 20 Oct 2013: reward for coin-year is cut in half every 64x multiply of PoS difficulty
+                //
+                // (nRewardCoinYearLimit / nRewardCoinYear) ** 6 == bnProofOfStakeLimit / bnTarget
+                //
+                // Human readable form: nRewardCoinYear = 1 / (posdiff ^ 1/6)
+                //
+
+                bnMidPart = bnMidValue * bnMidValue * bnMidValue * bnMidValue * bnMidValue * bnMidValue * bnTargetLimit;
+                bnRewardPart = bnRewardCoinYearLimit * bnRewardCoinYearLimit * bnRewardCoinYearLimit * bnRewardCoinYearLimit * bnRewardCoinYearLimit * bnRewardCoinYearLimit * bnTarget;
+            }
+            else
+            {
+                //
+                // Since 20 Oct 2013: reward for coin-year is cut in half every 8x multiply of PoS difficulty
+                //
+                // (nRewardCoinYearLimit / nRewardCoinYear) ** 3 == bnProofOfStakeLimit / bnTarget
+                //
+                // Human readable form: nRewardCoinYear = 1 / (posdiff ^ 1/3)
+                //
+
+                bnMidPart = bnMidValue * bnMidValue * bnMidValue * bnTargetLimit;
+                bnRewardPart = bnRewardCoinYearLimit * bnRewardCoinYearLimit * bnRewardCoinYearLimit * bnTarget;
+            }
+
+            if (bnMidPart > bnRewardPart)
                 bnUpperBound = bnMidValue;
             else
                 bnLowerBound = bnMidValue;
@@ -1037,7 +1062,15 @@ int64 GetProofOfStakeReward(int64 nCoinAge, unsigned int nBits, unsigned int nTi
         nRewardCoinYear = 5 * CENT;
     }
 
-    int64 nSubsidy = nCoinAge * 33 / (365 * 33 + 8) * nRewardCoinYear;
+    if(bCoinYearOnly)
+        return nRewardCoinYear;
+
+    // Fix problem with proof-of-stake rewards calculation since 20 Sep 2013
+    if(nTime < CHAINCHECKS_SWITCH_TIME)
+        nSubsidy = nCoinAge * 33 / (365 * 33 + 8) * nRewardCoinYear;
+    else
+        nSubsidy = nCoinAge * nRewardCoinYear * 33 / (365 * 33 + 8);
+
     if (fDebug && GetBoolArg("-printcreation"))
         printf("GetProofOfStakeReward(): create=%s nCoinAge=%"PRI64d" nBits=%d\n", FormatMoney(nSubsidy).c_str(), nCoinAge, nBits);
     return nSubsidy;
@@ -1046,7 +1079,7 @@ int64 GetProofOfStakeReward(int64 nCoinAge, unsigned int nBits, unsigned int nTi
 static const int64 nTargetTimespan = 7 * 24 * 60 * 60;  // one week
 
 // get proof of work blocks max spacing according to hard-coded conditions
-int64 static GetTargetSpacingWorkMax(int nHeight, unsigned int nTime)
+int64 inline GetTargetSpacingWorkMax(int nHeight, unsigned int nTime)
 {
     if(nTime > TARGETS_SWITCH_TIME)
         return 3 * nStakeTargetSpacing; // 30 minutes on mainNet since 20 Jul 2013 00:00:00
@@ -2249,30 +2282,32 @@ bool CBlock::AcceptBlock()
 CBigNum CBlockIndex::GetBlockTrust() const
 {
     CBigNum bnTarget;
+    bnTarget.SetCompact(nBits);
 
-    // Old protocol
-    if (!fTestNet && GetBlockTime() < CHAINCHECKS_SWITCH_TIME)
-    {
-        CBigNum bnTarget;
-        bnTarget.SetCompact(nBits);
+    if (bnTarget <= 0)
+        return 0;
 
-        if (bnTarget <= 0)
-            return 0;
+    /* Old protocol, will be removed later */
+    if (!fTestNet && GetBlockTime() < CHAINCHECKS_SWITCH_TIME)
         return (IsProofOfStake()? (CBigNum(1)<<256) / (bnTarget+1) : 1);
-    }
 
-    // New protocol
+    /* New protocol */
+
+    // Calculate work amount for block
+    CBigNum bnPoWTrust = bnPoWBase / (bnTarget+1);
+
+    // Set bnPowTrust to 1 if we are checking PoS block or PoW difficulty is too low
+    bnPoWTrust = (IsProofOfStake() || bnPoWTrust < 1) ? 1 : bnPoWTrust;
+
+    // Return bnPoWTrust for the first 12 blocks
     if (pprev == NULL || pprev->nHeight < 12)
-        return 1;
+        return bnPoWTrust;
 
     const CBlockIndex* currentIndex = pprev;
 
     if(IsProofOfStake())
     {
-        bnTarget.SetCompact(nBits);
-        if (bnTarget <= 0)
-            return 0;
-
+        // Return 1/3 of score if parent block is not the PoW block
         if (!pprev->IsProofOfWork())
             return (CBigNum(1)<<256) / (3 * (bnTarget+1));
 
@@ -2294,8 +2329,9 @@ CBigNum CBlockIndex::GetBlockTrust() const
     }
     else
     {
+        // Return bnPoWTrust + 2/3 of previous block score if two parent blocks are not PoS blocks
         if (!(pprev->IsProofOfStake() && pprev->pprev->IsProofOfStake()))
-            return 1 + (2 * (pprev->bnChainTrust - pprev->pprev->bnChainTrust) / 3);
+            return bnPoWTrust + (2 * (pprev->bnChainTrust - pprev->pprev->bnChainTrust) / 3);
 
         int nPoSCount = 0;
 
@@ -2307,11 +2343,17 @@ CBigNum CBlockIndex::GetBlockTrust() const
             currentIndex = currentIndex->pprev;
         }
 
-        // Return 2/3 of previous block score if less than 7 PoS blocks found
+        // Return bnPoWTrust + 2/3 of previous block score if less than 7 PoS blocks found
         if (nPoSCount < 7)
-            return 1 + (2 * (pprev->bnChainTrust - pprev->pprev->bnChainTrust) / 3);
+            return bnPoWTrust + (2 * (pprev->bnChainTrust - pprev->pprev->bnChainTrust) / 3);
+
+        bnTarget.SetCompact(pprev->nBits);
+
+        if (bnTarget <= 0)
+            return 0;
 
-        return (pprev->bnChainTrust - pprev->pprev->bnChainTrust);
+        // Return bnPoWTrust + full trust score for previous block nBits
+        return bnPoWTrust + (CBigNum(1)<<256) / (bnTarget+1);
     }
 }