class CInv;
class CRequestTracker;
class CNode;
-class CBlockIndex;
+
+static const int CLIENT_VERSION = 60000;
+static const bool VERSION_IS_BETA = true;
+extern const std::string CLIENT_NAME;
static const unsigned int MAX_BLOCK_SIZE = 1000000;
static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2;
#endif
+extern CScript COINBASE_FLAGS;
+
+
extern CBigNum bnBestInvalidWork;
extern uint256 hashBestChain;
extern CBlockIndex* pindexBest;
+extern uint64 nPooledTx;
extern unsigned int nTransactionsUpdated;
+extern uint64 nLastBlockTx;
+extern uint64 nLastBlockSize;
+extern const std::string strMessageMagic;
extern double dHashesPerSec;
extern int64 nHPSTimerStart;
extern int64 nTimeBestReceived;
CTxIn()
{
- nSequence = UINT_MAX;
+ nSequence = std::numeric_limits<unsigned int>::max();
}
- explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=UINT_MAX)
+ explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits<unsigned int>::max())
{
prevout = prevoutIn;
scriptSig = scriptSigIn;
nSequence = nSequenceIn;
}
- CTxIn(uint256 hashPrevTx, unsigned int nOut, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=UINT_MAX)
+ CTxIn(uint256 hashPrevTx, unsigned int nOut, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits<unsigned int>::max())
{
prevout = COutPoint(hashPrevTx, nOut);
scriptSig = scriptSigIn;
bool IsFinal() const
{
- return (nSequence == UINT_MAX);
+ return (nSequence == std::numeric_limits<unsigned int>::max());
}
friend bool operator==(const CTxIn& a, const CTxIn& b)
str += strprintf(", coinbase %s", HexStr(scriptSig).c_str());
else
str += strprintf(", scriptSig=%s", scriptSig.ToString().substr(0,24).c_str());
- if (nSequence != UINT_MAX)
+ if (nSequence != std::numeric_limits<unsigned int>::max())
str += strprintf(", nSequence=%u", nSequence);
str += ")";
return str;
+enum GetMinFee_mode
+{
+ GMF_BLOCK,
+ GMF_RELAY,
+ GMF_SEND,
+};
+
+typedef std::map<uint256, std::pair<CTxIndex, CTransaction> > MapPrevTx;
+
//
// The basic transaction that is broadcasted on the network and contained in
// blocks. A transaction can contain multiple inputs and outputs.
return false;
bool fNewer = false;
- unsigned int nLowest = UINT_MAX;
+ unsigned int nLowest = std::numeric_limits<unsigned int>::max();
for (int i = 0; i < vin.size(); i++)
{
if (vin[i].nSequence != old.vin[i].nSequence)
return (vin.size() == 1 && vin[0].prevout.IsNull());
}
- int GetSigOpCount() const
- {
- int n = 0;
- BOOST_FOREACH(const CTxIn& txin, vin)
- n += txin.scriptSig.GetSigOpCount();
- BOOST_FOREACH(const CTxOut& txout, vout)
- n += txout.scriptPubKey.GetSigOpCount();
- return n;
- }
+ /** Check for standard transaction types
+ @return True if all outputs (scriptPubKeys) use only standard transaction forms
+ */
+ bool IsStandard() const;
- bool IsStandard() const
- {
- BOOST_FOREACH(const CTxIn& txin, vin)
- if (!txin.scriptSig.IsPushOnly())
- return error("nonstandard txin: %s", txin.scriptSig.ToString().c_str());
- BOOST_FOREACH(const CTxOut& txout, vout)
- if (!::IsStandard(txout.scriptPubKey))
- return error("nonstandard txout: %s", txout.scriptPubKey.ToString().c_str());
- return true;
- }
+ /** Check for standard transaction types
+ @param[in] mapInputs Map of previous transactions that have outputs we're spending
+ @return True if all inputs (scriptSigs) use only standard transaction forms
+ @see CTransaction::FetchInputs
+ */
+ bool AreInputsStandard(const MapPrevTx& mapInputs) const;
+
+ /** Count ECDSA signature operations the old-fashioned (pre-0.6) way
+ @return number of sigops this transaction's outputs will produce when spent
+ @see CTransaction::FetchInputs
+ */
+ int GetLegacySigOpCount() const;
+
+ /** Count ECDSA signature operations in pay-to-script-hash inputs.
+ @param[in] mapInputs Map 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;
+
+ /** Amount of bitcoins spent by this transaction.
+ @return sum of all outputs (note: does not include fees)
+ */
int64 GetValueOut() const
{
int64 nValueOut = 0;
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] mapInputs Map of previous transactions that have outputs we're spending
+ @return Sum 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, bool fForRelay=false) const
+ int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=true, enum GetMinFee_mode mode=GMF_BLOCK) const
{
// Base fee is either MIN_TX_FEE or MIN_RELAY_TX_FEE
- int64 nBaseFee = fForRelay ? MIN_RELAY_TX_FEE : MIN_TX_FEE;
+ int64 nBaseFee = (mode == GMF_RELAY) ? MIN_RELAY_TX_FEE : MIN_TX_FEE;
unsigned int nBytes = ::GetSerializeSize(*this, SER_NETWORK);
unsigned int nNewBlockSize = nBlockSize + nBytes;
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=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] inputs Previous transactions (from FetchInputs)
+ @param[out] mapTestPool Keeps track of inputs that need to be updated on disk
+ @param[in] posThisTx Position 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();
int SetMerkleBranch(const CBlock* pblock=NULL);
- int GetDepthInMainChain(int& nHeightRet) const;
- int GetDepthInMainChain() const { int nHeight; return GetDepthInMainChain(nHeight); }
+ int GetDepthInMainChain(CBlockIndex* &pindexRet) const;
+ int GetDepthInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); }
bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
int GetBlocksToMaturity() const;
bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true);
return !(a == b);
}
int GetDepthInMainChain() const;
+
};
return (int64)nTime;
}
- int GetSigOpCount() const
- {
- int n = 0;
- BOOST_FOREACH(const CTransaction& tx, vtx)
- n += tx.GetSigOpCount();
- return n;
- }
uint256 BuildMerkleTree() const
Set((*mi).second);
}
+ CBlockLocator(const std::vector<uint256>& vHaveIn)
+ {
+ vHave = vHaveIn;
+ }
+
IMPLEMENT_SERIALIZE
(
if (!(nType & SER_GETHASH))
bool AppliesTo(int nVersion, std::string strSubVerIn) const
{
+ // TODO: rework for client-version-embedded-in-strSubVer ?
return (IsInEffect() &&
nMinVer <= nVersion && nVersion <= nMaxVer &&
(setSubVer.empty() || setSubVer.count(strSubVerIn)));
bool AppliesToMe() const
{
- return AppliesTo(VERSION, ::pszSubVer);
+ return AppliesTo(PROTOCOL_VERSION, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<std::string>()));
}
bool RelayTo(CNode* pnode) const