Check last 288 block index records at startup.
[novacoin.git] / src / main.cpp
index 1abc1d3..1e68aef 100644 (file)
@@ -179,10 +179,10 @@ void static Inventory(const uint256& hash)
 }
 
 // ask wallets to resend their transactions
-void ResendWalletTransactions()
+void ResendWalletTransactions(bool fForce)
 {
     BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
-        pwallet->ResendWalletTransactions();
+        pwallet->ResendWalletTransactions(fForce);
 }
 
 
@@ -399,25 +399,49 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans)
 
 bool CTransaction::IsStandard() const
 {
-    if (nVersion > CTransaction::CURRENT_VERSION)
+    if (nVersion > CTransaction::CURRENT_VERSION) {
         return false;
+    }
 
     BOOST_FOREACH(const CTxIn& txin, vin)
     {
         // Biggest 'standard' txin is a 3-signature 3-of-3 CHECKMULTISIG
         // pay-to-script-hash, which is 3 ~80-byte signatures, 3
         // ~65-byte public keys, plus a few script ops.
-        if (txin.scriptSig.size() > 500)
+        if (txin.scriptSig.size() > 500) {
             return false;
-        if (!txin.scriptSig.IsPushOnly())
+        }
+        if (!txin.scriptSig.IsPushOnly()) {
             return false;
+        }
+        if (fEnforceCanonical && !txin.scriptSig.HasCanonicalPushes()) {
+            return false;
+        }
     }
+
+    unsigned int nDataOut = 0;
+    txnouttype whichType;
     BOOST_FOREACH(const CTxOut& txout, vout) {
-        if (!::IsStandard(txout.scriptPubKey))
-            return false;
-        if (txout.nValue == 0)
+        if (!::IsStandard(txout.scriptPubKey, whichType)) {
             return false;
+        }
+        if (whichType == TX_NULL_DATA)
+            nDataOut++;
+        else {
+            if (txout.nValue == 0) {
+                return false;
+            }
+            if (fEnforceCanonical && !txout.scriptPubKey.HasCanonicalPushes()) {
+                return false;
+            }
+        }
     }
+
+    // only one OP_RETURN txout is permitted
+    if (nDataOut > 1) {
+        return false;
+    }
+
     return true;
 }
 
@@ -579,6 +603,8 @@ bool CTransaction::CheckTransaction() const
         if (!fTestNet && !IsCoinBase() && !txout.IsEmpty() && nTime < OUTPUT_SWITCH_TIME && txout.nValue < MIN_TXOUT_AMOUNT)
             return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue below minimum"));
 
+        if (txout.nValue < 0)
+            return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue is negative"));
         if (txout.nValue > MAX_MONEY)
             return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue too high"));
         nValueOut += txout.nValue;
@@ -861,27 +887,34 @@ void CTxMemPool::queryHashes(std::vector<uint256>& vtxid)
         vtxid.push_back((*mi).first);
 }
 
-
-
-
+// Return depth of transaction in blockchain:
+// -1  : not in blockchain, and not in memory pool (conflicted transaction)
+//  0  : in memory pool, waiting to be included in a block
+// >=1 : this many blocks deep in the main chain
 int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const
 {
-    if (hashBlock == 0 || nIndex == -1)
-        return 0;
+    bool fInMemPool = mempool.exists(GetHash());
+
+    if (hashBlock == 0 || nIndex == -1) {
+        return fInMemPool ? 0 : -1;
+    }
 
     // Find the block it claims to be in
     map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
-    if (mi == mapBlockIndex.end())
-        return 0;
+    if (mi == mapBlockIndex.end()) {
+        return fInMemPool ? 0 : -1;
+    }
     CBlockIndex* pindex = (*mi).second;
-    if (!pindex || !pindex->IsInMainChain())
-        return 0;
+    if (!pindex || !pindex->IsInMainChain()) {
+        return fInMemPool ? 0 : -1;
+    }
 
     // Make sure the merkle branch connects to this block
     if (!fMerkleVerified)
     {
-        if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot)
-            return 0;
+        if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot) {
+            return fInMemPool ? 0 : -1;
+        }
         fMerkleVerified = true;
     }
 
@@ -2744,6 +2777,28 @@ bool CBlock::CheckLegacySignature() const
     return false;
 }
 
+// entropy bit for stake modifier if chosen by modifier
+unsigned int CBlock::GetStakeEntropyBit(unsigned int nTime) const
+{
+    // Protocol switch at novacoin block #9689
+    if (nTime >= ENTROPY_SWITCH_TIME || fTestNet)
+    {
+        // Take last bit of block hash as entropy bit
+        unsigned int nEntropyBit = ((GetHash().Get64()) & 1llu);
+        if (fDebug && GetBoolArg("-printstakemodifier"))
+            printf("GetStakeEntropyBit: nTime=%u hashBlock=%s nEntropyBit=%u\n", nTime, GetHash().ToString().c_str(), nEntropyBit);
+        return nEntropyBit;
+    }
+    // Before novacoin block #9689 - old protocol
+    uint160 hashSig = Hash160(vchBlockSig);
+    if (fDebug && GetBoolArg("-printstakemodifier"))
+        printf("GetStakeEntropyBit: hashSig=%s", hashSig.ToString().c_str());
+    hashSig >>= 159; // take the first bit of the hash
+    if (fDebug && GetBoolArg("-printstakemodifier"))
+        printf(" entropybit=%"PRI64d"\n", hashSig.Get64());
+    return hashSig.Get64();
+}
+
 bool CheckDiskSpace(uint64 nAdditionalBytes)
 {
     uint64 nFreeBytesAvailable = filesystem::space(GetDataDir()).available;
@@ -2890,7 +2945,7 @@ bool static LoadBlockIndexDB()
 
     // Verify blocks in the best chain
     int nCheckLevel = GetArg("-checklevel", 1);
-    int nCheckDepth = GetArg( "-checkblocks", 2500);
+    int nCheckDepth = GetArg( "-checkblocks", 288);
     if (nCheckDepth == 0)
         nCheckDepth = 1000000000; // suffices until the year 19000
     if (nCheckDepth > nBestHeight)