// 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.
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_MAIN_H
#define BITCOIN_MAIN_H
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;
};
+typedef std::map<uint256, std::pair<CTxIndex, CTransaction> > MapPrevTx;
//
{
if (vin.size() != old.vin.size())
return false;
- for (int i = 0; i < vin.size(); i++)
+ for (unsigned int i = 0; i < vin.size(); i++)
if (vin[i].prevout != old.vin[i].prevout)
return false;
bool fNewer = false;
unsigned int nLowest = UINT_MAX;
- for (int i = 0; i < vin.size(); i++)
+ for (unsigned int i = 0; i < vin.size(); i++)
{
if (vin[i].nSequence != old.vin[i].nSequence)
{
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
{
BOOST_FOREACH(const CTxIn& txin, vin)
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
// 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 = nBaseFee;
+ }
// Raise the price as the block approaches full
if (nBlockSize != 1 && nNewBlockSize >= MAX_BLOCK_SIZE_GEN/2)
// Read transaction
if (fseek(filein, pos.nTxPos, SEEK_SET) != 0)
return error("CTransaction::ReadFromDisk() : fseek failed");
- filein >> *this;
+
+ try {
+ filein >> *this;
+ }
+ catch (std::exception &e) {
+ return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__);
+ }
// Return file pointer
if (pfileRet)
vin.size(),
vout.size(),
nLockTime);
- for (int i = 0; i < vin.size(); i++)
+ for (unsigned int i = 0; i < vin.size(); i++)
str += " " + vin[i].ToString() + "\n";
- for (int i = 0; i < vout.size(); i++)
+ for (unsigned int i = 0; i < vout.size(); i++)
str += " " + vout[i].ToString() + "\n";
return str;
}
bool ReadFromDisk(CTxDB& txdb, COutPoint prevout);
bool ReadFromDisk(COutPoint prevout);
bool DisconnectInputs(CTxDB& txdb);
- bool ConnectInputs(CTxDB& txdb, std::map<uint256, CTxIndex>& mapTestPool, CDiskTxPos posThisTx,
- CBlockIndex* pindexBlock, int64& nFees, bool fBlock, bool fMiner, int64 nMinFee,
- bool& fInvalid);
+
+ /** 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);
protected:
+ const CTxOut& GetOutputFor(const CTxIn& input, const MapPrevTx& inputs) const;
bool AddToMemoryPoolUnchecked();
public:
bool RemoveFromMemoryPool();
return n;
}
+ void UpdateTime(const CBlockIndex* pindexPrev);
+
uint256 BuildMerkleTree() const
{
fileout << FLATDATA(pchMessageStart) << nSize;
// Write block
- nBlockPosRet = ftell(fileout);
- if (nBlockPosRet == -1)
+ long fileOutPos = ftell(fileout);
+ if (fileOutPos < 0)
return error("CBlock::WriteToDisk() : ftell failed");
+ nBlockPosRet = fileOutPos;
fileout << *this;
// Flush stdio buffers and commit to disk before returning
filein.nType |= SER_BLOCKHEADERONLY;
// Read block
- filein >> *this;
+ try {
+ filein >> *this;
+ }
+ catch (std::exception &e) {
+ return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__);
+ }
// Check the header
if (!CheckProofOfWork(GetHash(), nBits))
hashMerkleRoot.ToString().substr(0,10).c_str(),
nTime, nBits, nNonce,
vtx.size());
- for (int i = 0; i < vtx.size(); i++)
+ for (unsigned int i = 0; i < vtx.size(); i++)
{
printf(" ");
vtx[i].print();
}
printf(" vMerkleTree: ");
- for (int i = 0; i < vMerkleTree.size(); i++)
+ for (unsigned int i = 0; i < vMerkleTree.size(); i++)
printf("%s ", vMerkleTree[i].ToString().substr(0,10).c_str());
printf("\n");
}