Better wording for transaction fee notification messages
[novacoin.git] / main.h
diff --git a/main.h b/main.h
index 088e286..355ef53 100644 (file)
--- a/main.h
+++ b/main.h
@@ -22,6 +22,11 @@ static const int64 CENT = 1000000;
 static const int64 MAX_MONEY = 21000000 * COIN;
 inline bool MoneyRange(int64 nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
 static const int COINBASE_MATURITY = 100;
+#ifdef USE_UPNP
+static const int fHaveUPnP = true;
+#else
+static const int fHaveUPnP = false;
+#endif
 
 
 
@@ -55,6 +60,7 @@ extern int fLimitProcessors;
 extern int nLimitProcessors;
 extern int fMinimizeToTray;
 extern int fMinimizeOnClose;
+extern int fUseUPnP;
 
 
 
@@ -69,6 +75,7 @@ bool AddKey(const CKey& key);
 vector<unsigned char> GenerateNewKey();
 bool AddToWallet(const CWalletTx& wtxIn);
 void WalletUpdateSpent(const COutPoint& prevout);
+int ScanForWalletTransactions(CBlockIndex* pindexStart);
 void ReacceptWalletTransactions();
 bool LoadBlockIndex(bool fAllowNew=true);
 void PrintBlockTree();
@@ -76,6 +83,7 @@ bool ProcessMessages(CNode* pfrom);
 bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv);
 bool SendMessages(CNode* pto, bool fSendTrickle);
 int64 GetBalance();
+bool CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
 bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
 bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
 bool BroadcastTransaction(CWalletTx& wtxNew);
@@ -573,6 +581,13 @@ public:
         return nValueOut;
     }
 
+    static bool AllowFree(double dPriority)
+    {
+        // Large (in bytes) low-priority (new, small-coin) transactions
+        // need a fee.
+        return dPriority > COIN * 144 / 250;
+    }
+
     int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=true) const
     {
         // Base fee is 1 cent per kilobyte
@@ -729,6 +744,7 @@ public:
         fMerkleVerified = false;
     }
 
+
     IMPLEMENT_SERIALIZE
     (
         nSerSize += SerReadWrite(s, *(CTransaction*)this, nType, nVersion, ser_action);
@@ -765,15 +781,17 @@ public:
     unsigned int fTimeReceivedIsTxTime;
     unsigned int nTimeReceived;  // time received by this node
     char fFromMe;
-    char fSpent;
     string strFromAccount;
+    vector<char> vfSpent;
 
     // memory only
     mutable char fDebitCached;
     mutable char fCreditCached;
+    mutable char fAvailableCreditCached;
     mutable char fChangeCached;
     mutable int64 nDebitCached;
     mutable int64 nCreditCached;
+    mutable int64 nAvailableCreditCached;
     mutable int64 nChangeCached;
 
     // memory only UI hints
@@ -805,13 +823,15 @@ public:
         fTimeReceivedIsTxTime = false;
         nTimeReceived = 0;
         fFromMe = false;
-        fSpent = false;
         strFromAccount.clear();
+        vfSpent.clear();
         fDebitCached = false;
         fCreditCached = false;
+        fAvailableCreditCached = false;
         fChangeCached = false;
         nDebitCached = 0;
         nCreditCached = 0;
+        nAvailableCreditCached = 0;
         nChangeCached = 0;
         nTimeDisplayed = 0;
         nLinesDisplayed = 0;
@@ -823,22 +843,96 @@ public:
         CWalletTx* pthis = const_cast<CWalletTx*>(this);
         if (fRead)
             pthis->Init();
-        nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion, ser_action);
-        READWRITE(vtxPrev);
+        char fSpent = false;
 
-        pthis->mapValue["fromaccount"] = pthis->strFromAccount;
-        READWRITE(mapValue);
-        pthis->strFromAccount = pthis->mapValue["fromaccount"];
-        pthis->mapValue.erase("fromaccount");
-        pthis->mapValue.erase("version");
+        if (!fRead)
+        {
+            pthis->mapValue["fromaccount"] = pthis->strFromAccount;
+
+            string str;
+            foreach(char f, vfSpent)
+            {
+                str += (f ? '1' : '0');
+                if (f)
+                    fSpent = true;
+            }
+            pthis->mapValue["spent"] = str;
+        }
 
+        nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion,ser_action);
+        READWRITE(vtxPrev);
+        READWRITE(mapValue);
         READWRITE(vOrderForm);
         READWRITE(fTimeReceivedIsTxTime);
         READWRITE(nTimeReceived);
         READWRITE(fFromMe);
         READWRITE(fSpent);
+
+        if (fRead)
+        {
+            pthis->strFromAccount = pthis->mapValue["fromaccount"];
+
+            if (mapValue.count("spent"))
+                foreach(char c, pthis->mapValue["spent"])
+                    pthis->vfSpent.push_back(c != '0');
+            else
+                pthis->vfSpent.assign(vout.size(), fSpent);
+        }
+
+        pthis->mapValue.erase("fromaccount");
+        pthis->mapValue.erase("version");
+        pthis->mapValue.erase("spent");
     )
 
+    // marks certain txout's as spent
+    // returns true if any update took place
+    bool UpdateSpent(const vector<char>& vfNewSpent)
+    {
+        bool fReturn = false;
+        for (int i=0; i < vfNewSpent.size(); i++)
+        {
+            if (i == vfSpent.size())
+                break;
+
+            if (vfNewSpent[i] && !vfSpent[i])
+            {
+                vfSpent[i] = true;
+                fReturn = true;
+                fAvailableCreditCached = false;
+            }
+        }
+        return fReturn;
+    }
+
+    void MarkDirty()
+    {
+        fCreditCached = false;
+        fAvailableCreditCached = false;
+        fDebitCached = false;
+        fChangeCached = false;
+    }
+
+    void MarkSpent(unsigned int nOut)
+    {
+        if (nOut >= vout.size())
+            throw runtime_error("CWalletTx::MarkSpent() : nOut out of range");
+        vfSpent.resize(vout.size());
+        if (!vfSpent[nOut])
+        {
+            vfSpent[nOut] = true;
+            fAvailableCreditCached = false;
+        }
+    }
+
+    bool IsSpent(unsigned int nOut) const
+    {
+        if (nOut >= vout.size())
+            throw runtime_error("CWalletTx::IsSpent() : nOut out of range");
+        if (nOut >= vfSpent.size())
+            return false;
+        return (!!vfSpent[nOut]);
+    }
+
     int64 GetDebit() const
     {
         if (vin.empty())
@@ -864,6 +958,33 @@ public:
         return nCreditCached;
     }
 
+    int64 GetAvailableCredit(bool fUseCache=true) const
+    {
+        // Must wait until coinbase is safely deep enough in the chain before valuing it
+        if (IsCoinBase() && GetBlocksToMaturity() > 0)
+            return 0;
+
+        if (fUseCache && fAvailableCreditCached)
+            return nAvailableCreditCached;
+
+        int64 nCredit = 0;
+        for (int i = 0; i < vout.size(); i++)
+        {
+            if (!IsSpent(i))
+            {
+                const CTxOut &txout = vout[i];
+                nCredit += txout.GetCredit();
+                if (!MoneyRange(nCredit))
+                    throw runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
+            }
+        }
+
+        nAvailableCreditCached = nCredit;
+        fAvailableCreditCached = true;
+        return nCredit;
+    }
+
+
     int64 GetChange() const
     {
         if (fChangeCached)
@@ -873,36 +994,11 @@ public:
         return nChangeCached;
     }
 
-    void GetAccountAmounts(string strAccount, const set<CScript>& setPubKey,
-                           int64& nGenerated, int64& nReceived, int64& nSent, int64& nFee) const
-    {
-        nGenerated = nReceived = nSent = nFee = 0;
+    void GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, list<pair<string /* address */, int64> >& listReceived,
+                    list<pair<string /* address */, int64> >& listSent, int64& nFee, string& strSentAccount) const;
 
-        // Generated blocks count to account ""
-        if (IsCoinBase())
-        {
-            if (strAccount == "" && GetBlocksToMaturity() == 0)
-                nGenerated = GetCredit();
-            return;
-        }
-
-        // Received
-        foreach(const CTxOut& txout, vout)
-            if (setPubKey.count(txout.scriptPubKey))
-                nReceived += txout.nValue;
-
-        // Sent
-        if (strFromAccount == strAccount)
-        {
-            int64 nDebit = GetDebit();
-            if (nDebit > 0)
-            {
-                int64 nValueOut = GetValueOut();
-                nFee = nDebit - nValueOut;
-                nSent = nValueOut - GetChange();
-            }
-        }
-    }
+    void GetAccountAmounts(const string& strAccount, int64& nGenerated, int64& nReceived, 
+                           int64& nSent, int64& nFee) const;
 
     bool IsFromMe() const
     {
@@ -1022,6 +1118,7 @@ public:
     {
         return !(a == b);
     }
+    int GetDepthInMainChain() const;
 };
 
 
@@ -1695,6 +1792,7 @@ public:
 class CAccountingEntry
 {
 public:
+    string strAccount;
     int64 nCreditDebit;
     int64 nTime;
     string strOtherAccount;
@@ -1709,6 +1807,7 @@ public:
     {
         nCreditDebit = 0;
         nTime = 0;
+        strAccount.clear();
         strOtherAccount.clear();
         strComment.clear();
     }
@@ -1717,6 +1816,7 @@ public:
     (
         if (!(nType & SER_GETHASH))
             READWRITE(nVersion);
+        // Note: strAccount is serialized as part of the key, not here.
         READWRITE(nCreditDebit);
         READWRITE(nTime);
         READWRITE(strOtherAccount);
@@ -1733,6 +1833,8 @@ public:
 
 
 //
+// Alerts are for notifying old versions if they become too obsolete and
+// need to upgrade.  The message is displayed in the status bar.
 // Alert messages are broadcast as a vector of signed data.  Unserializing may
 // not read the entire buffer if the alert is for a newer version, but older
 // versions can still relay the original data.