diff --git a/src/coins.h b/src/coins.h index 2c72ee88e..409d5713f 100644 --- a/src/coins.h +++ b/src/coins.h @@ -340,7 +340,6 @@ public: @param[in] tx transaction for which we are checking input total @return Sum of value of all inputs (scriptSigs) - @see CTransaction::FetchInputs */ int64_t GetValueIn(const CTransaction& tx); diff --git a/src/core.cpp b/src/core.cpp index 7a1c90e58..5da6f11b5 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -106,6 +106,18 @@ bool CTransaction::IsNewerThan(const CTransaction& old) const return fNewer; } +int64_t CTransaction::GetValueOut() const +{ + int64_t nValueOut = 0; + BOOST_FOREACH(const CTxOut& txout, vout) + { + nValueOut += txout.nValue; + if (!MoneyRange(txout.nValue) || !MoneyRange(nValueOut)) + throw std::runtime_error("CTransaction::GetValueOut() : value out of range"); + } + return nValueOut; +} + std::string CTransaction::ToString() const { std::string str; diff --git a/src/core.h b/src/core.h index e31a7e658..7b4c6af31 100644 --- a/src/core.h +++ b/src/core.h @@ -14,6 +14,10 @@ class CTransaction; +/** No amount larger than this (in satoshi) is valid */ +static const int64_t MAX_MONEY = 21000000 * COIN; +inline bool MoneyRange(int64_t nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); } + /** An outpoint - a combination of a transaction hash and an index n into its vout */ class COutPoint { @@ -217,6 +221,11 @@ public: uint256 GetHash() const; bool IsNewerThan(const CTransaction& old) const; + // Return sum of txouts. + int64_t GetValueOut() const; + // GetValueIn() is a method on CCoinsViewCache, because + // inputs must be known to compute value in. + bool IsCoinBase() const { return (vin.size() == 1 && vin[0].prevout.IsNull()); diff --git a/src/main.cpp b/src/main.cpp index db8f72f94..0cc134b8f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -379,21 +379,6 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime) return true; } -/** Amount of bitcoins spent by the transaction. - @return sum of all outputs (note: does not include fees) - */ -int64_t GetValueOut(const CTransaction& tx) -{ - int64_t nValueOut = 0; - BOOST_FOREACH(const CTxOut& txout, tx.vout) - { - nValueOut += txout.nValue; - if (!MoneyRange(txout.nValue) || !MoneyRange(nValueOut)) - throw std::runtime_error("GetValueOut() : value out of range"); - } - return nValueOut; -} - // // Check transaction inputs, and make sure any // pay-to-script-hash transactions are evaluating IsStandard scripts @@ -717,7 +702,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // you should add code here to check that the transaction does a // reasonable number of ECDSA signature verifications. - int64_t nFees = view.GetValueIn(tx)-GetValueOut(tx); + int64_t nFees = view.GetValueIn(tx)-tx.GetValueOut(); unsigned int nSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); // Don't accept it if it can't get into a block @@ -1342,12 +1327,12 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCach } - if (nValueIn < GetValueOut(tx)) + if (nValueIn < tx.GetValueOut()) return state.DoS(100, error("CheckInputs() : %s value in < value out", tx.GetHash().ToString().c_str()), REJECT_INVALID, "in < out"); // Tally transaction fees - int64_t nTxFee = nValueIn - GetValueOut(tx); + int64_t nTxFee = nValueIn - tx.GetValueOut(); if (nTxFee < 0) return state.DoS(100, error("CheckInputs() : %s nTxFee < 0", tx.GetHash().ToString().c_str()), REJECT_INVALID, "fee < 0"); @@ -1600,7 +1585,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C REJECT_INVALID, "too many sigops"); } - nFees += view.GetValueIn(tx)-GetValueOut(tx); + nFees += view.GetValueIn(tx)-tx.GetValueOut(); std::vector vChecks; if (!CheckInputs(tx, state, view, fScriptChecks, flags, nScriptCheckThreads ? &vChecks : NULL)) @@ -1620,10 +1605,10 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C if (fBenchmark) LogPrintf("- Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin)\n", (unsigned)block.vtx.size(), 0.001 * nTime, 0.001 * nTime / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * nTime / (nInputs-1)); - if (GetValueOut(block.vtx[0]) > GetBlockValue(pindex->nHeight, nFees)) + if (block.vtx[0].GetValueOut() > GetBlockValue(pindex->nHeight, nFees)) return state.DoS(100, error("ConnectBlock() : coinbase pays too much (actual=%"PRId64" vs limit=%"PRId64")", - GetValueOut(block.vtx[0]), GetBlockValue(pindex->nHeight, nFees)), + block.vtx[0].GetValueOut(), GetBlockValue(pindex->nHeight, nFees)), REJECT_INVALID, "coinbase too large"); if (!control.Wait()) diff --git a/src/main.h b/src/main.h index 1d3ac1cdb..c4e183944 100644 --- a/src/main.h +++ b/src/main.h @@ -49,9 +49,6 @@ static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; // 16 MiB /** The pre-allocation chunk size for rev?????.dat files (since 0.8) */ static const unsigned int UNDOFILE_CHUNK_SIZE = 0x100000; // 1 MiB -/** No amount larger than this (in satoshi) is valid */ -static const int64_t MAX_MONEY = 21000000 * COIN; -inline bool MoneyRange(int64_t nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); } /** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */ static const int COINBASE_MATURITY = 100; /** Threshold for nLockTime: below this value it is interpreted as block number, otherwise as UNIX timestamp. */ @@ -320,11 +317,6 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason); bool IsFinalTx(const CTransaction &tx, int nBlockHeight = 0, int64_t nBlockTime = 0); -/** Amount of bitcoins spent by the transaction. - @return sum of all outputs (note: does not include fees) - */ -int64_t GetValueOut(const CTransaction& tx); - /** Undo information for a CBlock */ class CBlockUndo { diff --git a/src/miner.cpp b/src/miner.cpp index b01b60cc3..5661037ac 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -261,7 +261,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) // This is a more accurate fee-per-kilobyte than is used by the client code, because the // client code rounds up the size to the nearest 1K. That's good, because it gives an // incentive to create smaller transactions. - double dFeePerKb = double(nTotalIn-GetValueOut(tx)) / (double(nTxSize)/1000.0); + double dFeePerKb = double(nTotalIn-tx.GetValueOut()) / (double(nTxSize)/1000.0); if (porphan) { @@ -318,7 +318,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) if (!view.HaveInputs(tx)) continue; - int64_t nTxFees = view.GetValueIn(tx)-GetValueOut(tx); + int64_t nTxFees = view.GetValueIn(tx)-tx.GetValueOut(); nTxSigOps += GetP2SHSigOpCount(tx, view); if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS) diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 8bd2bf564..c0c4d5373 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -194,7 +194,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, int vout, int u strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, nValue) + "
"; } - int64_t nTxFee = nDebit - GetValueOut(wtx); + int64_t nTxFee = nDebit - wtx.GetValueOut(); if (nTxFee > 0) strHTML += "" + tr("Transaction fee") + ": " + BitcoinUnits::formatWithUnit(unit, -nTxFee) + "
"; } diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 675daa9c9..6823557eb 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -95,7 +95,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * // // Debit // - int64_t nTxFee = nDebit - GetValueOut(wtx); + int64_t nTxFee = nDebit - wtx.GetValueOut(); for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++) { diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 1fd061547..b4e522de8 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -1673,7 +1673,7 @@ Value gettransaction(const Array& params, bool fHelp) int64_t nCredit = wtx.GetCredit(); int64_t nDebit = wtx.GetDebit(); int64_t nNet = nCredit - nDebit; - int64_t nFee = (wtx.IsFromMe() ? GetValueOut(wtx) - nDebit : 0); + int64_t nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0); entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee))); if (wtx.IsFromMe()) diff --git a/src/wallet.cpp b/src/wallet.cpp index db957cbd0..46d6cc566 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -655,7 +655,7 @@ void CWalletTx::GetAmounts(list >& listReceived, int64_t nDebit = GetDebit(); if (nDebit > 0) // debit>0 means we signed/sent this transaction { - int64_t nValueOut = GetValueOut(*this); + int64_t nValueOut = GetValueOut(); nFee = nDebit - nValueOut; }