Add scrypt+sha512 key derivation method.
[novacoin.git] / src / wallet.cpp
index 35d24b5..aecb227 100644 (file)
@@ -247,7 +247,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
     vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
     RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
 
-    CMasterKey kMasterKey;
+    CMasterKey kMasterKey(nDerivationMethodIndex);
 
     RandAddSeedPerfmon();
     kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
@@ -1368,8 +1368,8 @@ bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& w
     return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet);
 }
 
-// NovaCoin: get current stake generation power
-uint64 CWallet::GetStakeMintPower(const CKeyStore& keystore, enum StakeWeightMode mode)
+// NovaCoin: get current stake weight
+uint64 CWallet::GetStakeWeight(const CKeyStore& keystore, enum StakeWeightMode mode)
 {
     LOCK2(cs_main, cs_wallet);
 
@@ -1380,7 +1380,7 @@ uint64 CWallet::GetStakeMintPower(const CKeyStore& keystore, enum StakeWeightMod
 
     if (mapArgs.count("-reservebalance") && !ParseMoney(mapArgs["-reservebalance"], nReserveBalance))
     {
-        error("GetStakeMintPower : invalid reserve balance amount");
+        error("GetStakeWeight : invalid reserve balance amount");
         return 0;
     }
 
@@ -1402,41 +1402,53 @@ uint64 CWallet::GetStakeMintPower(const CKeyStore& keystore, enum StakeWeightMod
         if (!txdb.ReadTxIndex(pcoin.first->GetHash(), txindex))
             continue;
 
+        unsigned int nTime = pcoin.first->nTime;
+
         switch(mode)
         {
             case STAKE_NORMAL:
                 // Do not count input that is still less than 30 days old
-                if (pcoin.first->nTime + nStakeMinAge > GetTime())
+                if (nTime + nStakeMinAge > GetTime())
                     continue;
             break;
             case STAKE_MAXWEIGHT:
                 // Do not count input that is still less than 90 days old
-                if (pcoin.first->nTime + nStakeMaxAge > GetTime())
+                if (nTime + nStakeMaxAge > GetTime())
                     continue;
             break;
             case STAKE_MINWEIGHT:
                 // Count only inputs with suitable age (from 30 to 90 days old)
-                if (pcoin.first->nTime + nStakeMaxAge < GetTime())
-                    continue;
-                if (pcoin.first->nTime + nStakeMinAge > GetTime())
+                if (nTime + nStakeMaxAge < GetTime())
                     continue;
-            break;
-            case STAKE_BELOWMIN:
-                // Count only inputs with suitable age (less than 30 days old)
-                if (pcoin.first->nTime + nStakeMinAge < GetTime())
+                if (nTime + nStakeMinAge > GetTime())
                     continue;
             break;
         }
 
-        CBigNum bnCentSecond = CBigNum(pcoin.first->vout[pcoin.second].nValue) * (GetTime()-pcoin.first->nTime) / CENT;
-        CBigNum bnCoinDay = bnCentSecond * CENT / COIN / (24 * 60 * 60);
+        int64 nTimeWeight;
+
+        // Kernel hash weight starts from 0 at the 30-day min age
+        // this change increases active coins participating the hash and helps
+        // to secure the network when proof-of-stake difficulty is low
+        //
+        if(fTestNet || (STAKEWEIGHT_SWITCH_TIME < nTime))
+        {
+            // New rule since 01 Jan 2014: Maximum TimeWeight is 90 days.
+            nTimeWeight = min((int64)GetTime() - nTime - nStakeMinAge, (int64)nStakeMaxAge);
+        }
+        else
+        {
+            // Current rule: Maximum TimeWeight is 60 days.
+            nTimeWeight = min((int64)GetTime() - nTime, (int64)nStakeMaxAge) - nStakeMinAge;
+        }
 
+        CBigNum bnCoinDayWeight = CBigNum(pcoin.first->vout[pcoin.second].nValue) * nTimeWeight / COIN / (24 * 60 * 60);
 
-        nCoinAge += bnCoinDay.getuint64();
+        nCoinAge += bnCoinDayWeight.getuint64();
     }
 
     if (fDebug && GetBoolArg("-printcoinage"))
-        printf("StakePower bnCoinDay=%"PRI64d"\n", nCoinAge);
+        printf("StakeWeight bnCoinDay=%"PRI64d"\n", nCoinAge);
 
     return nCoinAge;
 }
@@ -1495,9 +1507,9 @@ bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int
         {
             // Search backward in time from the given txNew timestamp 
             // Search nSearchInterval seconds back up to nMaxStakeSearchInterval
-            uint256 hashProofOfStake = 0;
+            uint256 hashProofOfStake = 0, targetProofOfStake = 0;
             COutPoint prevoutStake = COutPoint(pcoin.first->GetHash(), pcoin.second);
-            if (CheckStakeKernelHash(nBits, block, txindex.pos.nTxPos - txindex.pos.nBlockPos, *pcoin.first, prevoutStake, txNew.nTime - n, hashProofOfStake))
+            if (CheckStakeKernelHash(nBits, block, txindex.pos.nTxPos - txindex.pos.nBlockPos, *pcoin.first, prevoutStake, txNew.nTime - n, hashProofOfStake, targetProofOfStake))
             {
                 // Found a kernel
                 if (fDebug && GetBoolArg("-printcoinstake"))
@@ -1595,6 +1607,19 @@ bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int
         // Set output amount
         if (txNew.vout.size() == 3)
         {
+            // Should we use keys from pool for the last coinstake output?
+            if (fStakeUsePooledKeys)
+            {
+                CReserveKey reservekey((CWallet*) &keystore);
+
+                // Replace current key with the new one
+                txNew.vout[2].SetNull();
+                txNew.vout[2].scriptPubKey << reservekey.GetReservedKey() << OP_CHECKSIG;
+
+                // Remove key from pool
+                reservekey.KeepKey();
+            }
+
             txNew.vout[1].nValue = ((nCredit - nMinFee) / 2 / CENT) * CENT;
             txNew.vout[2].nValue = nCredit - nMinFee - txNew.vout[1].nValue;
         }
@@ -1868,7 +1893,7 @@ bool CWallet::NewKeyPool()
     return true;
 }
 
-bool CWallet::TopUpKeyPool()
+bool CWallet::TopUpKeyPool(unsigned int nSize)
 {
     {
         LOCK(cs_wallet);
@@ -1879,7 +1904,12 @@ bool CWallet::TopUpKeyPool()
         CWalletDB walletdb(strWalletFile);
 
         // Top up key pool
-        unsigned int nTargetSize = max(GetArg("-keypool", 100), 0LL);
+        unsigned int nTargetSize;
+        if (nSize > 0)
+            nTargetSize = nSize;
+        else
+            nTargetSize = max(GetArg("-keypool", 100), 0LL);
+
         while (setKeyPool.size() < (nTargetSize + 1))
         {
             int64 nEnd = 1;