// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
+#ifndef BITCOIN_MAIN_H
+#define BITCOIN_MAIN_H
+
+#include "bignum.h"
+#include "net.h"
+#include "key.h"
+#include "script.h"
+#include "db.h"
+
+#include <list>
-class COutPoint;
-class CInPoint;
-class CDiskTxPos;
-class CCoinBase;
-class CTxIn;
-class CTxOut;
-class CTransaction;
class CBlock;
class CBlockIndex;
class CWalletTx;
+class CWallet;
class CKeyItem;
+class CReserveKey;
+class CWalletDB;
+
+class CAddress;
+class CInv;
+class CRequestTracker;
+class CNode;
+class CBlockIndex;
static const unsigned int MAX_BLOCK_SIZE = 1000000;
static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2;
static const int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
+static const int MAX_ORPHAN_TRANSACTIONS = MAX_BLOCK_SIZE/100;
static const int64 COIN = 100000000;
static const int64 CENT = 1000000;
+static const int64 MIN_TX_FEE = 50000;
+static const int64 MIN_RELAY_TX_FEE = 10000;
static const int64 MAX_MONEY = 21000000 * COIN;
inline bool MoneyRange(int64 nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
static const int COINBASE_MATURITY = 100;
+// Threshold for nLockTime: below this value it is interpreted as block number, otherwise as UNIX timestamp.
+static const int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC
#ifdef USE_UPNP
static const int fHaveUPnP = true;
#else
extern CCriticalSection cs_main;
-extern map<uint256, CBlockIndex*> mapBlockIndex;
+extern std::map<uint256, CBlockIndex*> mapBlockIndex;
extern uint256 hashGenesisBlock;
-extern CBigNum bnProofOfWorkLimit;
extern CBlockIndex* pindexGenesisBlock;
extern int nBestHeight;
extern CBigNum bnBestChainWork;
extern uint256 hashBestChain;
extern CBlockIndex* pindexBest;
extern unsigned int nTransactionsUpdated;
-extern map<uint256, int> mapRequestCount;
-extern CCriticalSection cs_mapRequestCount;
-extern map<string, string> mapAddressBook;
-extern CCriticalSection cs_mapAddressBook;
-extern vector<unsigned char> vchDefaultKey;
extern double dHashesPerSec;
extern int64 nHPSTimerStart;
+extern int64 nTimeBestReceived;
+extern CCriticalSection cs_setpwalletRegistered;
+extern std::set<CWallet*> setpwalletRegistered;
// Settings
extern int fGenerateBitcoins;
extern int64 nTransactionFee;
-extern CAddress addrIncoming;
extern int fLimitProcessors;
extern int nLimitProcessors;
extern int fMinimizeToTray;
+class CReserveKey;
+class CTxDB;
+class CTxIndex;
-
+void RegisterWallet(CWallet* pwalletIn);
+void UnregisterWallet(CWallet* pwalletIn);
+bool ProcessBlock(CNode* pfrom, CBlock* pblock);
bool CheckDiskSpace(uint64 nAdditionalBytes=0);
FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb");
FILE* AppendBlockFile(unsigned int& nFileRet);
-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();
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);
-string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
-string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
-void GenerateBitcoins(bool fGenerate);
-void ThreadBitcoinMiner(void* parg);
+void GenerateBitcoins(bool fGenerate, CWallet* pwallet);
CBlock* CreateNewBlock(CReserveKey& reservekey);
-void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce, int64& nPrevTime);
+void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1);
-bool CheckWork(CBlock* pblock, CReserveKey& reservekey);
-void BitcoinMiner();
+bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey);
bool CheckProofOfWork(uint256 hash, unsigned int nBits);
+unsigned int ComputeMinWork(unsigned int nBase, int64 nTime);
+int GetNumBlocksOfPeers();
bool IsInitialBlockDownload();
-string GetWarnings(string strFor);
+std::string GetWarnings(std::string strFor);
+bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut);
+
+template<typename T>
+bool WriteSetting(const std::string& strKey, const T& value)
+{
+ bool fOk = false;
+ BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+ {
+ std::string strWalletFile;
+ if (!GetWalletFile(pwallet, strWalletFile))
+ continue;
+ fOk |= CWalletDB(strWalletFile).WriteSetting(strKey, value);
+ }
+ return fOk;
+}
+
+
class CDiskTxPos
{
public:
return !(a == b);
}
- string ToString() const
+ std::string ToString() const
{
if (IsNull())
return strprintf("null");
return !(a == b);
}
- string ToString() const
+ std::string ToString() const
{
return strprintf("COutPoint(%s, %d)", hash.ToString().substr(0,10).c_str(), n);
}
return !(a == b);
}
- string ToString() const
+ std::string ToString() const
{
- string str;
+ std::string str;
str += strprintf("CTxIn(");
str += prevout.ToString();
if (prevout.IsNull())
{
printf("%s\n", ToString().c_str());
}
-
- bool IsMine() const;
- int64 GetDebit() const;
};
return SerializeHash(*this);
}
- bool IsMine() const
- {
- return ::IsMine(scriptPubKey);
- }
-
- int64 GetCredit() const
- {
- if (!MoneyRange(nValue))
- throw runtime_error("CTxOut::GetCredit() : value out of range");
- return (IsMine() ? nValue : 0);
- }
-
- bool IsChange() const
- {
- // On a debit transaction, a txout that's mine but isn't in the address book is change
- vector<unsigned char> vchPubKey;
- if (ExtractPubKey(scriptPubKey, true, vchPubKey))
- CRITICAL_BLOCK(cs_mapAddressBook)
- if (!mapAddressBook.count(PubKeyToAddress(vchPubKey)))
- return true;
- return false;
- }
-
- int64 GetChange() const
- {
- if (!MoneyRange(nValue))
- throw runtime_error("CTxOut::GetChange() : value out of range");
- return (IsChange() ? nValue : 0);
- }
-
friend bool operator==(const CTxOut& a, const CTxOut& b)
{
return (a.nValue == b.nValue &&
return !(a == b);
}
- string ToString() const
+ std::string ToString() const
{
if (scriptPubKey.size() < 6)
return "CTxOut(error)";
};
+typedef std::map<uint256, std::pair<CTxIndex, CTransaction> > MapPrevTx;
//
{
public:
int nVersion;
- vector<CTxIn> vin;
- vector<CTxOut> vout;
+ std::vector<CTxIn> vin;
+ std::vector<CTxOut> vout;
unsigned int nLockTime;
+ // Denial-of-service detection:
+ mutable int nDoS;
+ bool DoS(int nDoSIn, bool fIn) const { nDoS += nDoSIn; return fIn; }
CTransaction()
{
vin.clear();
vout.clear();
nLockTime = 0;
+ nDoS = 0; // Denial-of-service prevention
}
bool IsNull() const
nBlockHeight = nBestHeight;
if (nBlockTime == 0)
nBlockTime = GetAdjustedTime();
- if ((int64)nLockTime < (nLockTime < 500000000 ? (int64)nBlockHeight : nBlockTime))
+ if ((int64)nLockTime < (nLockTime < LOCKTIME_THRESHOLD ? (int64)nBlockHeight : nBlockTime))
return true;
- foreach(const CTxIn& txin, vin)
+ BOOST_FOREACH(const CTxIn& txin, vin)
if (!txin.IsFinal())
return false;
return true;
int GetSigOpCount() const
{
int n = 0;
- foreach(const CTxIn& txin, vin)
+ BOOST_FOREACH(const CTxIn& txin, vin)
n += txin.scriptSig.GetSigOpCount();
- foreach(const CTxOut& txout, vout)
+ BOOST_FOREACH(const CTxOut& txout, vout)
n += txout.scriptPubKey.GetSigOpCount();
return n;
}
+ /** Count ECDSA signature operations in pay-to-script-hash inputs.
+ This is a better measure of how expensive it is to process this transaction.
+
+ @param[in] mapInputsMap of previous transactions that have outputs we're spending
+ @return maximum number of sigops required to validate this transaction's inputs
+ @see CTransaction::FetchInputs
+ */
+ int GetP2SHSigOpCount(const MapPrevTx& mapInputs) const;
+
bool IsStandard() const
{
- foreach(const CTxIn& txin, vin)
+ BOOST_FOREACH(const CTxIn& txin, vin)
if (!txin.scriptSig.IsPushOnly())
return error("nonstandard txin: %s", txin.scriptSig.ToString().c_str());
- foreach(const CTxOut& txout, vout)
+ BOOST_FOREACH(const CTxOut& txout, vout)
if (!::IsStandard(txout.scriptPubKey))
return error("nonstandard txout: %s", txout.scriptPubKey.ToString().c_str());
return true;
}
- bool IsMine() const
- {
- foreach(const CTxOut& txout, vout)
- if (txout.IsMine())
- return true;
- return false;
- }
-
- bool IsFromMe() const
- {
- return (GetDebit() > 0);
- }
-
- int64 GetDebit() const
- {
- int64 nDebit = 0;
- foreach(const CTxIn& txin, vin)
- {
- nDebit += txin.GetDebit();
- if (!MoneyRange(nDebit))
- throw runtime_error("CTransaction::GetDebit() : value out of range");
- }
- return nDebit;
- }
-
- int64 GetCredit() const
- {
- int64 nCredit = 0;
- foreach(const CTxOut& txout, vout)
- {
- nCredit += txout.GetCredit();
- if (!MoneyRange(nCredit))
- throw runtime_error("CTransaction::GetCredit() : value out of range");
- }
- return nCredit;
- }
-
- int64 GetChange() const
- {
- if (IsCoinBase())
- return 0;
- int64 nChange = 0;
- foreach(const CTxOut& txout, vout)
- {
- nChange += txout.GetChange();
- if (!MoneyRange(nChange))
- throw runtime_error("CTransaction::GetChange() : value out of range");
- }
- return nChange;
- }
-
int64 GetValueOut() const
{
int64 nValueOut = 0;
- foreach(const CTxOut& txout, vout)
+ BOOST_FOREACH(const CTxOut& txout, vout)
{
nValueOut += txout.nValue;
if (!MoneyRange(txout.nValue) || !MoneyRange(nValueOut))
- throw runtime_error("CTransaction::GetValueOut() : value out of range");
+ throw std::runtime_error("CTransaction::GetValueOut() : value out of range");
}
return nValueOut;
}
+ /** Amount of bitcoins coming in to this transaction
+ Note that lightweight clients may not know anything besides the hash of previous transactions,
+ so may not be able to calculate this.
+
+ @param[in] mapInputsMap of previous transactions that have outputs we're spending
+ @returnSum of value of all inputs (scriptSigs)
+ @see CTransaction::FetchInputs
+ */
+ int64 GetValueIn(const MapPrevTx& mapInputs) const;
+
static bool AllowFree(double dPriority)
{
// Large (in bytes) low-priority (new, small-coin) transactions
return dPriority > COIN * 144 / 250;
}
- int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=true) const
+ int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=true, bool fForRelay=false) const
{
- // Base fee is 1 cent per kilobyte
+ // Base fee is either MIN_TX_FEE or MIN_RELAY_TX_FEE
+ int64 nBaseFee = fForRelay ? MIN_RELAY_TX_FEE : MIN_TX_FEE;
+
unsigned int nBytes = ::GetSerializeSize(*this, SER_NETWORK);
unsigned int nNewBlockSize = nBlockSize + nBytes;
- int64 nMinFee = (1 + (int64)nBytes / 1000) * CENT;
+ int64 nMinFee = (1 + (int64)nBytes / 1000) * nBaseFee;
if (fAllowFree)
{
}
}
- // To limit dust spam, require a 0.01 fee if any output is less than 0.01
- if (nMinFee < CENT)
- foreach(const CTxOut& txout, vout)
+ // To limit dust spam, require MIN_TX_FEE/MIN_RELAY_TX_FEE if any output is less than 0.01
+ if (nMinFee < nBaseFee)
+ BOOST_FOREACH(const CTxOut& txout, vout)
if (txout.nValue < CENT)
- nMinFee = CENT;
+ nMinFee = nBaseFee;
// Raise the price as the block approaches full
if (nBlockSize != 1 && nNewBlockSize >= MAX_BLOCK_SIZE_GEN/2)
}
- string ToString() const
+ std::string ToString() const
{
- string str;
+ std::string str;
str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%d, vout.size=%d, nLockTime=%d)\n",
GetHash().ToString().substr(0,10).c_str(),
nVersion,
bool ReadFromDisk(CTxDB& txdb, COutPoint prevout);
bool ReadFromDisk(COutPoint prevout);
bool DisconnectInputs(CTxDB& txdb);
- bool ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPool, CDiskTxPos posThisTx,
- CBlockIndex* pindexBlock, int64& nFees, bool fBlock, bool fMiner, int64 nMinFee=0);
+
+ /** Fetch from memory and/or disk. inputsRet keys are transaction hashes.
+
+ @param[in] txdb Transaction database
+ @param[in] mapTestPool List of pending changes to the transaction index database
+ @param[in] fBlock True if being called to add a new best-block to the chain
+ @param[in] fMiner True if being called by CreateNewBlock
+ @param[out] inputsRet Pointers to this transaction's inputs
+ @param[out] fInvalid returns true if transaction is invalid
+ @return Returns true if all inputs are in txdb or mapTestPool
+ */
+ bool FetchInputs(CTxDB& txdb, const std::map<uint256, CTxIndex>& mapTestPool,
+ bool fBlock, bool fMiner, MapPrevTx& inputsRet, bool& fInvalid);
+
+ /** Sanity check previous transactions, then, if all checks succeed,
+ mark them as spent by this transaction.
+
+ @param[in] inputsPrevious transactions (from FetchInputs)
+ @param[out] mapTestPoolKeeps track of inputs that need to be updated on disk
+ @param[in] posThisTxPosition of this transaction on disk
+ @param[in] pindexBlock
+ @param[in] fBlock true if called from ConnectBlock
+ @param[in] fMiner true if called from CreateNewBlock
+ @param[in] fStrictPayToScriptHash true if fully validating p2sh transactions
+ @return Returns true if all checks succeed
+ */
+ bool ConnectInputs(MapPrevTx inputs,
+ std::map<uint256, CTxIndex>& mapTestPool, const CDiskTxPos& posThisTx,
+ const CBlockIndex* pindexBlock, bool fBlock, bool fMiner, bool fStrictPayToScriptHash=true);
bool ClientConnectInputs();
bool CheckTransaction() const;
bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true, bool* pfMissingInputs=NULL);
- bool AcceptToMemoryPool(bool fCheckInputs=true, bool* pfMissingInputs=NULL)
- {
- CTxDB txdb("r");
- return AcceptToMemoryPool(txdb, fCheckInputs, pfMissingInputs);
- }
+ bool AcceptToMemoryPool(bool fCheckInputs=true, bool* pfMissingInputs=NULL);
protected:
+ const CTxOut& GetOutputFor(const CTxIn& input, const MapPrevTx& inputs) const;
bool AddToMemoryPoolUnchecked();
public:
bool RemoveFromMemoryPool();
{
public:
uint256 hashBlock;
- vector<uint256> vMerkleBranch;
+ std::vector<uint256> vMerkleBranch;
int nIndex;
// memory only
bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
int GetBlocksToMaturity() const;
bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true);
- bool AcceptToMemoryPool() { CTxDB txdb("r"); return AcceptToMemoryPool(txdb); }
-};
-
-
-
-
-//
-// A transaction with a bunch of additional info that only the owner cares
-// about. It includes any unrecorded transactions needed to link it back
-// to the block chain.
-//
-class CWalletTx : public CMerkleTx
-{
-public:
- vector<CMerkleTx> vtxPrev;
- map<string, string> mapValue;
- vector<pair<string, string> > vOrderForm;
- unsigned int fTimeReceivedIsTxTime;
- unsigned int nTimeReceived; // time received by this node
- char fFromMe;
- 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
- mutable unsigned int nTimeDisplayed;
- mutable int nLinesDisplayed;
- mutable char fConfirmedDisplayed;
-
-
- CWalletTx()
- {
- Init();
- }
-
- CWalletTx(const CMerkleTx& txIn) : CMerkleTx(txIn)
- {
- Init();
- }
-
- CWalletTx(const CTransaction& txIn) : CMerkleTx(txIn)
- {
- Init();
- }
-
- void Init()
- {
- vtxPrev.clear();
- mapValue.clear();
- vOrderForm.clear();
- fTimeReceivedIsTxTime = false;
- nTimeReceived = 0;
- fFromMe = 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;
- fConfirmedDisplayed = false;
- }
-
- IMPLEMENT_SERIALIZE
- (
- CWalletTx* pthis = const_cast<CWalletTx*>(this);
- if (fRead)
- pthis->Init();
- char fSpent = false;
-
- 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())
- return 0;
- if (fDebitCached)
- return nDebitCached;
- nDebitCached = CTransaction::GetDebit();
- fDebitCached = true;
- return nDebitCached;
- }
-
- int64 GetCredit(bool fUseCache=true) const
- {
- // Must wait until coinbase is safely deep enough in the chain before valuing it
- if (IsCoinBase() && GetBlocksToMaturity() > 0)
- return 0;
-
- // GetBalance can assume transactions in mapWallet won't change
- if (fUseCache && fCreditCached)
- return nCreditCached;
- nCreditCached = CTransaction::GetCredit();
- fCreditCached = true;
- 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)
- return nChangeCached;
- nChangeCached = CTransaction::GetChange();
- fChangeCached = true;
- return nChangeCached;
- }
-
- void GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, list<pair<string /* address */, int64> >& listReceived,
- list<pair<string /* address */, int64> >& listSent, int64& nFee, string& strSentAccount) const;
-
- void GetAccountAmounts(const string& strAccount, int64& nGenerated, int64& nReceived,
- int64& nSent, int64& nFee) const;
-
- bool IsFromMe() const
- {
- return (GetDebit() > 0);
- }
-
- bool IsConfirmed() const
- {
- // Quick answer in most cases
- if (!IsFinal())
- return false;
- if (GetDepthInMainChain() >= 1)
- return true;
- if (!IsFromMe()) // using wtx's cached debit
- return false;
-
- // If no confirmations but it's from us, we can still
- // consider it confirmed if all dependencies are confirmed
- map<uint256, const CMerkleTx*> mapPrev;
- vector<const CMerkleTx*> vWorkQueue;
- vWorkQueue.reserve(vtxPrev.size()+1);
- vWorkQueue.push_back(this);
- for (int i = 0; i < vWorkQueue.size(); i++)
- {
- const CMerkleTx* ptx = vWorkQueue[i];
-
- if (!ptx->IsFinal())
- return false;
- if (ptx->GetDepthInMainChain() >= 1)
- return true;
- if (!ptx->IsFromMe())
- return false;
-
- if (mapPrev.empty())
- foreach(const CMerkleTx& tx, vtxPrev)
- mapPrev[tx.GetHash()] = &tx;
-
- foreach(const CTxIn& txin, ptx->vin)
- {
- if (!mapPrev.count(txin.prevout.hash))
- return false;
- vWorkQueue.push_back(mapPrev[txin.prevout.hash]);
- }
- }
- return true;
- }
-
- bool WriteToDisk()
- {
- return CWalletDB().WriteTx(GetHash(), *this);
- }
-
-
- int64 GetTxTime() const;
- int GetRequestCount() const;
-
- void AddSupportingTransactions(CTxDB& txdb);
-
- bool AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs=true);
- bool AcceptWalletTransaction() { CTxDB txdb("r"); return AcceptWalletTransaction(txdb); }
-
- void RelayWalletTransaction(CTxDB& txdb);
- void RelayWalletTransaction() { CTxDB txdb("r"); RelayWalletTransaction(txdb); }
+ bool AcceptToMemoryPool();
};
{
public:
CDiskTxPos pos;
- vector<CDiskTxPos> vSpent;
+ std::vector<CDiskTxPos> vSpent;
CTxIndex()
{
unsigned int nNonce;
// network and disk
- vector<CTransaction> vtx;
+ std::vector<CTransaction> vtx;
// memory only
- mutable vector<uint256> vMerkleTree;
+ mutable std::vector<uint256> vMerkleTree;
+ // Denial-of-service detection:
+ mutable int nDoS;
+ bool DoS(int nDoSIn, bool fIn) const { nDoS += nDoSIn; return fIn; }
CBlock()
{
nNonce = 0;
vtx.clear();
vMerkleTree.clear();
+ nDoS = 0;
}
bool IsNull() const
int GetSigOpCount() const
{
int n = 0;
- foreach(const CTransaction& tx, vtx)
+ BOOST_FOREACH(const CTransaction& tx, vtx)
n += tx.GetSigOpCount();
return n;
}
+ void UpdateTime(const CBlockIndex* pindexPrev);
+
uint256 BuildMerkleTree() const
{
vMerkleTree.clear();
- foreach(const CTransaction& tx, vtx)
+ BOOST_FOREACH(const CTransaction& tx, vtx)
vMerkleTree.push_back(tx.GetHash());
int j = 0;
for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
{
for (int i = 0; i < nSize; i += 2)
{
- int i2 = min(i+1, nSize-1);
+ int i2 = std::min(i+1, nSize-1);
vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]), END(vMerkleTree[j+i]),
BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
}
return (vMerkleTree.empty() ? 0 : vMerkleTree.back());
}
- vector<uint256> GetMerkleBranch(int nIndex) const
+ std::vector<uint256> GetMerkleBranch(int nIndex) const
{
if (vMerkleTree.empty())
BuildMerkleTree();
- vector<uint256> vMerkleBranch;
+ std::vector<uint256> vMerkleBranch;
int j = 0;
for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
{
- int i = min(nIndex^1, nSize-1);
+ int i = std::min(nIndex^1, nSize-1);
vMerkleBranch.push_back(vMerkleTree[j+i]);
nIndex >>= 1;
j += nSize;
return vMerkleBranch;
}
- static uint256 CheckMerkleBranch(uint256 hash, const vector<uint256>& vMerkleBranch, int nIndex)
+ static uint256 CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex)
{
if (nIndex == -1)
return 0;
- foreach(const uint256& otherside, vMerkleBranch)
+ BOOST_FOREACH(const uint256& otherside, vMerkleBranch)
{
if (nIndex & 1)
hash = Hash(BEGIN(otherside), END(otherside), BEGIN(hash), END(hash));
fflush(fileout);
if (!IsInitialBlockDownload() || (nBestHeight+1) % 500 == 0)
{
-#ifdef __WXMSW__
+#ifdef WIN32
_commit(_fileno(fileout));
#else
fsync(fileno(fileout));
for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
*(--pbegin) = pindex->GetBlockTime();
- sort(pbegin, pend);
+ std::sort(pbegin, pend);
return pbegin[(pend - pbegin)/2];
}
- string ToString() const
+ std::string ToString() const
{
return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nHeight=%d, merkle=%s, hashBlock=%s)",
pprev, pnext, nFile, nBlockPos, nHeight,
}
- string ToString() const
+ std::string ToString() const
{
- string str = "CDiskBlockIndex(";
+ std::string str = "CDiskBlockIndex(";
str += CBlockIndex::ToString();
str += strprintf("\n hashBlock=%s, hashPrev=%s, hashNext=%s)",
GetBlockHash().ToString().c_str(),
class CBlockLocator
{
protected:
- vector<uint256> vHave;
+ std::vector<uint256> vHave;
public:
CBlockLocator()
explicit CBlockLocator(uint256 hashBlock)
{
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
+ std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
if (mi != mapBlockIndex.end())
Set((*mi).second);
}
// Retrace how far back it was in the sender's branch
int nDistance = 0;
int nStep = 1;
- foreach(const uint256& hash, vHave)
+ BOOST_FOREACH(const uint256& hash, vHave)
{
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
+ std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
if (mi != mapBlockIndex.end())
{
CBlockIndex* pindex = (*mi).second;
CBlockIndex* GetBlockIndex()
{
// Find the first block the caller has in the main chain
- foreach(const uint256& hash, vHave)
+ BOOST_FOREACH(const uint256& hash, vHave)
{
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
+ std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
if (mi != mapBlockIndex.end())
{
CBlockIndex* pindex = (*mi).second;
uint256 GetBlockHash()
{
// Find the first block the caller has in the main chain
- foreach(const uint256& hash, vHave)
+ BOOST_FOREACH(const uint256& hash, vHave)
{
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
+ std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
if (mi != mapBlockIndex.end())
{
CBlockIndex* pindex = (*mi).second;
-//
-// Private key that includes an expiration date in case it never gets used.
-//
-class CWalletKey
-{
-public:
- CPrivKey vchPrivKey;
- int64 nTimeCreated;
- int64 nTimeExpires;
- string strComment;
- //// todo: add something to note what created it (user, getnewaddress, change)
- //// maybe should have a map<string, string> property map
-
- CWalletKey(int64 nExpires=0)
- {
- nTimeCreated = (nExpires ? GetTime() : 0);
- nTimeExpires = nExpires;
- }
-
- IMPLEMENT_SERIALIZE
- (
- if (!(nType & SER_GETHASH))
- READWRITE(nVersion);
- READWRITE(vchPrivKey);
- READWRITE(nTimeCreated);
- READWRITE(nTimeExpires);
- READWRITE(strComment);
- )
-};
-
-
-
-
-
-
-//
-// Account information.
-// Stored in wallet with key "acc"+string account name
-//
-class CAccount
-{
-public:
- vector<unsigned char> vchPubKey;
-
- CAccount()
- {
- SetNull();
- }
-
- void SetNull()
- {
- vchPubKey.clear();
- }
-
- IMPLEMENT_SERIALIZE
- (
- if (!(nType & SER_GETHASH))
- READWRITE(nVersion);
- READWRITE(vchPubKey);
- )
-};
-
-
-
-//
-// Internal transfers.
-// Database key is acentry<account><counter>
-//
-class CAccountingEntry
-{
-public:
- string strAccount;
- int64 nCreditDebit;
- int64 nTime;
- string strOtherAccount;
- string strComment;
-
- CAccountingEntry()
- {
- SetNull();
- }
-
- void SetNull()
- {
- nCreditDebit = 0;
- nTime = 0;
- strAccount.clear();
- strOtherAccount.clear();
- strComment.clear();
- }
-
- IMPLEMENT_SERIALIZE
- (
- if (!(nType & SER_GETHASH))
- READWRITE(nVersion);
- // Note: strAccount is serialized as part of the key, not here.
- READWRITE(nCreditDebit);
- READWRITE(nTime);
- READWRITE(strOtherAccount);
- READWRITE(strComment);
- )
-};
-
-
-
-
-
-
int64 nExpiration;
int nID;
int nCancel;
- set<int> setCancel;
+ std::set<int> setCancel;
int nMinVer; // lowest version inclusive
int nMaxVer; // highest version inclusive
- set<string> setSubVer; // empty matches all
+ std::set<std::string> setSubVer; // empty matches all
int nPriority;
// Actions
- string strComment;
- string strStatusBar;
- string strReserved;
+ std::string strComment;
+ std::string strStatusBar;
+ std::string strReserved;
IMPLEMENT_SERIALIZE
(
strReserved.clear();
}
- string ToString() const
+ std::string ToString() const
{
- string strSetCancel;
- foreach(int n, setCancel)
+ std::string strSetCancel;
+ BOOST_FOREACH(int n, setCancel)
strSetCancel += strprintf("%d ", n);
- string strSetSubVer;
- foreach(string str, setSubVer)
+ std::string strSetSubVer;
+ BOOST_FOREACH(std::string str, setSubVer)
strSetSubVer += "\"" + str + "\" ";
return strprintf(
"CAlert(\n"
class CAlert : public CUnsignedAlert
{
public:
- vector<unsigned char> vchMsg;
- vector<unsigned char> vchSig;
+ std::vector<unsigned char> vchMsg;
+ std::vector<unsigned char> vchSig;
CAlert()
{
return (alert.nID <= nCancel || setCancel.count(alert.nID));
}
- bool AppliesTo(int nVersion, string strSubVerIn) const
+ bool AppliesTo(int nVersion, std::string strSubVerIn) const
{
return (IsInEffect() &&
nMinVer <= nVersion && nVersion <= nMaxVer &&
bool ProcessAlert();
};
-
-
-
-
-
-
-
-
-
-extern map<uint256, CTransaction> mapTransactions;
-extern map<uint256, CWalletTx> mapWallet;
-extern vector<uint256> vWalletUpdated;
-extern CCriticalSection cs_mapWallet;
-extern map<vector<unsigned char>, CPrivKey> mapKeys;
-extern map<uint160, vector<unsigned char> > mapPubKeys;
-extern CCriticalSection cs_mapKeys;
-extern CKey keyUser;
+#endif