aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core.cpp3
-rw-r--r--src/core.h277
-rw-r--r--src/init.cpp1
-rw-r--r--src/main.cpp276
-rw-r--r--src/main.h406
-rw-r--r--src/qt/transactiondesc.cpp4
-rw-r--r--src/qt/transactionrecord.cpp4
-rw-r--r--src/rpcrawtransaction.cpp2
-rw-r--r--src/rpcwallet.cpp10
-rw-r--r--src/script.h2
-rw-r--r--src/test/data/tx_invalid.json2
-rw-r--r--src/test/data/tx_valid.json2
-rw-r--r--src/test/script_P2SH_tests.cpp18
-rw-r--r--src/test/transaction_tests.cpp24
-rw-r--r--src/wallet.cpp14
-rw-r--r--src/wallet.h4
-rw-r--r--src/walletdb.cpp2
17 files changed, 527 insertions, 524 deletions
diff --git a/src/core.cpp b/src/core.cpp
index cb1053b69d..b12c90efe8 100644
--- a/src/core.cpp
+++ b/src/core.cpp
@@ -3,4 +3,5 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "core.h" \ No newline at end of file
+#include "core.h"
+
diff --git a/src/core.h b/src/core.h
index bd1ddbf5a4..21ca6618a2 100644
--- a/src/core.h
+++ b/src/core.h
@@ -8,6 +8,7 @@
#include "uint256.h"
#include "serialize.h"
#include "util.h"
+#include "script.h"
#include <stdio.h>
@@ -65,4 +66,278 @@ public:
bool IsNull() const { return (ptx == NULL && n == (unsigned int) -1); }
};
-#endif \ No newline at end of file
+/** An input of a transaction. It contains the location of the previous
+ * transaction's output that it claims and a signature that matches the
+ * output's public key.
+ */
+class CTxIn
+{
+public:
+ COutPoint prevout;
+ CScript scriptSig;
+ unsigned int nSequence;
+
+ CTxIn()
+ {
+ nSequence = std::numeric_limits<unsigned int>::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=std::numeric_limits<unsigned int>::max())
+ {
+ prevout = COutPoint(hashPrevTx, nOut);
+ scriptSig = scriptSigIn;
+ nSequence = nSequenceIn;
+ }
+
+ IMPLEMENT_SERIALIZE
+ (
+ READWRITE(prevout);
+ READWRITE(scriptSig);
+ READWRITE(nSequence);
+ )
+
+ bool IsFinal() const
+ {
+ return (nSequence == std::numeric_limits<unsigned int>::max());
+ }
+
+ friend bool operator==(const CTxIn& a, const CTxIn& b)
+ {
+ return (a.prevout == b.prevout &&
+ a.scriptSig == b.scriptSig &&
+ a.nSequence == b.nSequence);
+ }
+
+ friend bool operator!=(const CTxIn& a, const CTxIn& b)
+ {
+ return !(a == b);
+ }
+
+ std::string ToString() const
+ {
+ std::string str;
+ str += "CTxIn(";
+ str += prevout.ToString();
+ if (prevout.IsNull())
+ str += strprintf(", coinbase %s", HexStr(scriptSig).c_str());
+ else
+ str += strprintf(", scriptSig=%s", scriptSig.ToString().substr(0,24).c_str());
+ if (nSequence != std::numeric_limits<unsigned int>::max())
+ str += strprintf(", nSequence=%u", nSequence);
+ str += ")";
+ return str;
+ }
+
+ void print() const
+ {
+ printf("%s\n", ToString().c_str());
+ }
+};
+
+
+
+
+/** An output of a transaction. It contains the public key that the next input
+ * must be able to sign with to claim it.
+ */
+class CTxOut
+{
+public:
+ int64 nValue;
+ CScript scriptPubKey;
+
+ CTxOut()
+ {
+ SetNull();
+ }
+
+ CTxOut(int64 nValueIn, CScript scriptPubKeyIn)
+ {
+ nValue = nValueIn;
+ scriptPubKey = scriptPubKeyIn;
+ }
+
+ IMPLEMENT_SERIALIZE
+ (
+ READWRITE(nValue);
+ READWRITE(scriptPubKey);
+ )
+
+ void SetNull()
+ {
+ nValue = -1;
+ scriptPubKey.clear();
+ }
+
+ bool IsNull() const
+ {
+ return (nValue == -1);
+ }
+
+ uint256 GetHash() const
+ {
+ return SerializeHash(*this);
+ }
+
+ bool IsDust(int64 nMinRelayTxFee) const
+ {
+ // "Dust" is defined in terms of CTransaction::nMinRelayTxFee,
+ // which has units satoshis-per-kilobyte.
+ // If you'd pay more than 1/3 in fees
+ // to spend something, then we consider it dust.
+ // A typical txout is 33 bytes big, and will
+ // need a CTxIn of at least 148 bytes to spend,
+ // so dust is a txout less than 54 uBTC
+ // (5430 satoshis) with default nMinRelayTxFee
+ return ((nValue*1000)/(3*((int)GetSerializeSize(SER_DISK,0)+148)) < nMinRelayTxFee);
+ }
+
+ friend bool operator==(const CTxOut& a, const CTxOut& b)
+ {
+ return (a.nValue == b.nValue &&
+ a.scriptPubKey == b.scriptPubKey);
+ }
+
+ friend bool operator!=(const CTxOut& a, const CTxOut& b)
+ {
+ return !(a == b);
+ }
+
+ std::string ToString() const
+ {
+ if (scriptPubKey.size() < 6)
+ return "CTxOut(error)";
+ return strprintf("CTxOut(nValue=%"PRI64d".%08"PRI64d", scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,30).c_str());
+ }
+
+ void print() const
+ {
+ printf("%s\n", ToString().c_str());
+ }
+};
+
+
+/** The basic transaction that is broadcasted on the network and contained in
+ * blocks. A transaction can contain multiple inputs and outputs.
+ */
+class CTransaction
+{
+public:
+ static int64 nMinTxFee;
+ static int64 nMinRelayTxFee;
+ static const int CURRENT_VERSION=1;
+ int nVersion;
+ std::vector<CTxIn> vin;
+ std::vector<CTxOut> vout;
+ unsigned int nLockTime;
+
+ CTransaction()
+ {
+ SetNull();
+ }
+
+ IMPLEMENT_SERIALIZE
+ (
+ READWRITE(this->nVersion);
+ nVersion = this->nVersion;
+ READWRITE(vin);
+ READWRITE(vout);
+ READWRITE(nLockTime);
+ )
+
+ void SetNull()
+ {
+ nVersion = CTransaction::CURRENT_VERSION;
+ vin.clear();
+ vout.clear();
+ nLockTime = 0;
+ }
+
+ bool IsNull() const
+ {
+ return (vin.empty() && vout.empty());
+ }
+
+ uint256 GetHash() const
+ {
+ return SerializeHash(*this);
+ }
+
+ bool IsNewerThan(const CTransaction& old) const
+ {
+ if (vin.size() != old.vin.size())
+ return false;
+ 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 = std::numeric_limits<unsigned int>::max();
+ for (unsigned int i = 0; i < vin.size(); i++)
+ {
+ if (vin[i].nSequence != old.vin[i].nSequence)
+ {
+ if (vin[i].nSequence <= nLowest)
+ {
+ fNewer = false;
+ nLowest = vin[i].nSequence;
+ }
+ if (old.vin[i].nSequence < nLowest)
+ {
+ fNewer = true;
+ nLowest = old.vin[i].nSequence;
+ }
+ }
+ }
+ return fNewer;
+ }
+
+ bool IsCoinBase() const
+ {
+ return (vin.size() == 1 && vin[0].prevout.IsNull());
+ }
+
+ friend bool operator==(const CTransaction& a, const CTransaction& b)
+ {
+ return (a.nVersion == b.nVersion &&
+ a.vin == b.vin &&
+ a.vout == b.vout &&
+ a.nLockTime == b.nLockTime);
+ }
+
+ friend bool operator!=(const CTransaction& a, const CTransaction& b)
+ {
+ return !(a == b);
+ }
+
+
+ std::string ToString() const
+ {
+ std::string str;
+ str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%"PRIszu", vout.size=%"PRIszu", nLockTime=%u)\n",
+ GetHash().ToString().substr(0,10).c_str(),
+ nVersion,
+ vin.size(),
+ vout.size(),
+ nLockTime);
+ for (unsigned int i = 0; i < vin.size(); i++)
+ str += " " + vin[i].ToString() + "\n";
+ for (unsigned int i = 0; i < vout.size(); i++)
+ str += " " + vout[i].ToString() + "\n";
+ return str;
+ }
+
+ void print() const
+ {
+ printf("%s", ToString().c_str());
+ }
+};
+
+#endif
diff --git a/src/init.cpp b/src/init.cpp
index 1eee4d2470..a1dbfd2a5f 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -5,6 +5,7 @@
#include "init.h"
#include "main.h"
+#include "core.h"
#include "txdb.h"
#include "walletdb.h"
#include "bitcoinrpc.h"
diff --git a/src/main.cpp b/src/main.cpp
index 5a1345d414..28b32101d3 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -357,41 +357,23 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans)
-//////////////////////////////////////////////////////////////////////////////
-//
-// CTransaction / CTxOut
-//
-
-bool CTxOut::IsDust() const
+bool IsStandardTx(const CTransaction& tx)
{
- // "Dust" is defined in terms of CTransaction::nMinRelayTxFee,
- // which has units satoshis-per-kilobyte.
- // If you'd pay more than 1/3 in fees
- // to spend something, then we consider it dust.
- // A typical txout is 33 bytes big, and will
- // need a CTxIn of at least 148 bytes to spend,
- // so dust is a txout less than 54 uBTC
- // (5430 satoshis) with default nMinRelayTxFee
- return ((nValue*1000)/(3*((int)GetSerializeSize(SER_DISK,0)+148)) < CTransaction::nMinRelayTxFee);
-}
-
-bool CTransaction::IsStandard() const
-{
- if (nVersion > CTransaction::CURRENT_VERSION)
+ if (tx.nVersion > CTransaction::CURRENT_VERSION)
return false;
- if (!IsFinal())
+ if (!IsFinalTx(tx))
return false;
// Extremely large transactions with lots of inputs can cost the network
// almost as much to process as they cost the sender in fees, because
// computing signature hashes is O(ninputs*txsize). Limiting transactions
// to MAX_STANDARD_TX_SIZE mitigates CPU exhaustion attacks.
- unsigned int sz = this->GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION);
+ unsigned int sz = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION);
if (sz >= MAX_STANDARD_TX_SIZE)
return false;
- BOOST_FOREACH(const CTxIn& txin, vin)
+ BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
// Biggest 'standard' txin is a 3-signature 3-of-3 CHECKMULTISIG
// pay-to-script-hash, which is 3 ~80-byte signatures, 3
@@ -401,15 +383,47 @@ bool CTransaction::IsStandard() const
if (!txin.scriptSig.IsPushOnly())
return false;
}
- BOOST_FOREACH(const CTxOut& txout, vout) {
+ BOOST_FOREACH(const CTxOut& txout, tx.vout) {
if (!::IsStandard(txout.scriptPubKey))
return false;
- if (txout.IsDust())
+ if (txout.IsDust(CTransaction::nMinRelayTxFee))
return false;
}
return true;
}
+bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64 nBlockTime)
+{
+ // Time based nLockTime implemented in 0.1.6
+ if (tx.nLockTime == 0)
+ return true;
+ if (nBlockHeight == 0)
+ nBlockHeight = nBestHeight;
+ if (nBlockTime == 0)
+ nBlockTime = GetAdjustedTime();
+ if ((int64)tx.nLockTime < ((int64)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64)nBlockHeight : nBlockTime))
+ return true;
+ BOOST_FOREACH(const CTxIn& txin, tx.vin)
+ if (!txin.IsFinal())
+ return false;
+ return true;
+}
+
+/** Amount of bitcoins spent by the transaction.
+ @return sum of all outputs (note: does not include fees)
+ */
+int64 GetValueOut(const CTransaction& tx)
+{
+ int64 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
@@ -421,14 +435,14 @@ bool CTransaction::IsStandard() const
// expensive-to-check-upon-redemption script like:
// DUP CHECKSIG DROP ... repeated 100 times... OP_1
//
-bool CTransaction::AreInputsStandard(CCoinsViewCache& mapInputs) const
+bool AreInputsStandard(const CTransaction& tx, CCoinsViewCache& mapInputs)
{
- if (IsCoinBase())
+ if (tx.IsCoinBase())
return true; // Coinbases don't use vin normally
- for (unsigned int i = 0; i < vin.size(); i++)
+ for (unsigned int i = 0; i < tx.vin.size(); i++)
{
- const CTxOut& prev = GetOutputFor(vin[i], mapInputs);
+ const CTxOut& prev = mapInputs.GetOutputFor(tx.vin[i]);
vector<vector<unsigned char> > vSolutions;
txnouttype whichType;
@@ -446,7 +460,7 @@ bool CTransaction::AreInputsStandard(CCoinsViewCache& mapInputs) const
// beside "push data" in the scriptSig the
// IsStandard() call returns false
vector<vector<unsigned char> > stack;
- if (!EvalScript(stack, vin[i].scriptSig, *this, i, false, 0))
+ if (!EvalScript(stack, tx.vin[i].scriptSig, tx, i, false, 0))
return false;
if (whichType == TX_SCRIPTHASH)
@@ -475,20 +489,34 @@ bool CTransaction::AreInputsStandard(CCoinsViewCache& mapInputs) const
return true;
}
-unsigned int CTransaction::GetLegacySigOpCount() const
+unsigned int GetLegacySigOpCount(const CTransaction& tx)
{
unsigned int nSigOps = 0;
- BOOST_FOREACH(const CTxIn& txin, vin)
+ BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
nSigOps += txin.scriptSig.GetSigOpCount(false);
}
- BOOST_FOREACH(const CTxOut& txout, vout)
+ BOOST_FOREACH(const CTxOut& txout, tx.vout)
{
nSigOps += txout.scriptPubKey.GetSigOpCount(false);
}
return nSigOps;
}
+unsigned int GetP2SHSigOpCount(const CTransaction& tx, CCoinsViewCache& inputs)
+{
+ if (tx.IsCoinBase())
+ return 0;
+
+ unsigned int nSigOps = 0;
+ for (unsigned int i = 0; i < tx.vin.size(); i++)
+ {
+ const CTxOut &prevout = inputs.GetOutputFor(tx.vin[i]);
+ if (prevout.scriptPubKey.IsPayToScriptHash())
+ nSigOps += prevout.scriptPubKey.GetSigOpCount(tx.vin[i].scriptSig);
+ }
+ return nSigOps;
+}
int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
{
@@ -543,25 +571,25 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
-bool CTransaction::CheckTransaction(CValidationState &state) const
+bool CheckTransaction(const CTransaction& tx, CValidationState &state)
{
// Basic checks that don't depend on any context
- if (vin.empty())
- return state.DoS(10, error("CTransaction::CheckTransaction() : vin empty"));
- if (vout.empty())
- return state.DoS(10, error("CTransaction::CheckTransaction() : vout empty"));
+ if (tx.vin.empty())
+ return state.DoS(10, error("CheckTransaction() : vin empty"));
+ if (tx.vout.empty())
+ return state.DoS(10, error("CheckTransaction() : vout empty"));
// Size limits
- if (::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
+ if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
return state.DoS(100, error("CTransaction::CheckTransaction() : size limits failed"));
// Check for negative or overflow output values
int64 nValueOut = 0;
- BOOST_FOREACH(const CTxOut& txout, vout)
+ BOOST_FOREACH(const CTxOut& txout, tx.vout)
{
if (txout.nValue < 0)
- return state.DoS(100, error("CTransaction::CheckTransaction() : txout.nValue negative"));
+ return state.DoS(100, error("CheckTransaction() : txout.nValue negative"));
if (txout.nValue > MAX_MONEY)
- return state.DoS(100, error("CTransaction::CheckTransaction() : txout.nValue too high"));
+ return state.DoS(100, error("CheckTransaction() : txout.nValue too high"));
nValueOut += txout.nValue;
if (!MoneyRange(nValueOut))
return state.DoS(100, error("CTransaction::CheckTransaction() : txout total out of range"));
@@ -569,23 +597,23 @@ bool CTransaction::CheckTransaction(CValidationState &state) const
// Check for duplicate inputs
set<COutPoint> vInOutPoints;
- BOOST_FOREACH(const CTxIn& txin, vin)
+ BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
if (vInOutPoints.count(txin.prevout))
return state.DoS(100, error("CTransaction::CheckTransaction() : duplicate inputs"));
vInOutPoints.insert(txin.prevout);
}
- if (IsCoinBase())
+ if (tx.IsCoinBase())
{
- if (vin[0].scriptSig.size() < 2 || vin[0].scriptSig.size() > 100)
- return state.DoS(100, error("CTransaction::CheckTransaction() : coinbase script size"));
+ if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 100)
+ return state.DoS(100, error("CheckTransaction() : coinbase script size"));
}
else
{
- BOOST_FOREACH(const CTxIn& txin, vin)
+ BOOST_FOREACH(const CTxIn& txin, tx.vin)
if (txin.prevout.IsNull())
- return state.DoS(10, error("CTransaction::CheckTransaction() : prevout is null"));
+ return state.DoS(10, error("CheckTransaction() : prevout is null"));
}
return true;
@@ -657,7 +685,7 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckIn
if (pfMissingInputs)
*pfMissingInputs = false;
- if (!tx.CheckTransaction(state))
+ if (!CheckTransaction(tx, state))
return error("CTxMemPool::accept() : CheckTransaction failed");
// Coinbase is only valid in a block, not as a loose transaction
@@ -669,7 +697,7 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckIn
return error("CTxMemPool::accept() : not accepting nLockTime beyond 2038 yet");
// Rather not work on nonstandard transactions (unless -testnet)
- if (!fTestNet && !tx.IsStandard())
+ if (!fTestNet && !IsStandardTx(tx))
return error("CTxMemPool::accept() : nonstandard transaction type");
// is it already in the memory pool?
@@ -694,7 +722,7 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckIn
if (i != 0)
return false;
ptxOld = mapNextTx[outpoint].ptx;
- if (ptxOld->IsFinal())
+ if (IsFinalTx(*ptxOld))
return false;
if (!tx.IsNewerThan(*ptxOld))
return false;
@@ -734,7 +762,7 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckIn
}
// are the actual inputs available?
- if (!tx.HaveInputs(view))
+ if (!view.HaveInputs(tx))
return state.Invalid(error("CTxMemPool::accept() : inputs already spent"));
// Bring the best block into scope
@@ -745,14 +773,14 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckIn
}
// Check for non-standard pay-to-script-hash in inputs
- if (!tx.AreInputsStandard(view) && !fTestNet)
+ if (!AreInputsStandard(tx, view) && !fTestNet)
return error("CTxMemPool::accept() : nonstandard transaction input");
// Note: if you modify this code to accept non-standard transactions, then
// you should add code here to check that the transaction does a
// reasonable number of ECDSA signature verifications.
- int64 nFees = tx.GetValueIn(view)-tx.GetValueOut();
+ int64 nFees = view.GetValueIn(tx)-GetValueOut(tx);
unsigned int nSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
// Don't accept it if it can't get into a block
@@ -787,7 +815,7 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckIn
// Check against previous transactions
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
- if (!tx.CheckInputs(state, view, true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC))
+ if (!CheckInputs(tx, state, view, true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC))
{
return error("CTxMemPool::accept() : ConnectInputs failed %s", hash.ToString().c_str());
}
@@ -816,14 +844,6 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckIn
return true;
}
-bool CTransaction::AcceptToMemoryPool(CValidationState &state, bool fCheckInputs, bool fLimitFree, bool* pfMissingInputs)
-{
- try {
- return mempool.accept(state, *this, fCheckInputs, fLimitFree, pfMissingInputs);
- } catch(std::runtime_error &e) {
- return state.Abort(_("System error: ") + e.what());
- }
-}
bool CTxMemPool::addUnchecked(const uint256& hash, CTransaction &tx)
{
@@ -936,7 +956,7 @@ int CMerkleTx::GetBlocksToMaturity() const
bool CMerkleTx::AcceptToMemoryPool(bool fCheckInputs, bool fLimitFree)
{
CValidationState state;
- return CTransaction::AcceptToMemoryPool(state, fCheckInputs, fLimitFree);
+ return mempool.accept(state, *this, fCheckInputs, fLimitFree, NULL);
}
@@ -1299,45 +1319,30 @@ void CBlockHeader::UpdateTime(const CBlockIndex* pindexPrev)
-const CTxOut &CTransaction::GetOutputFor(const CTxIn& input, CCoinsViewCache& view)
+const CTxOut &CCoinsViewCache::GetOutputFor(const CTxIn& input)
{
- const CCoins &coins = view.GetCoins(input.prevout.hash);
+ const CCoins &coins = GetCoins(input.prevout.hash);
assert(coins.IsAvailable(input.prevout.n));
return coins.vout[input.prevout.n];
}
-int64 CTransaction::GetValueIn(CCoinsViewCache& inputs) const
+int64 CCoinsViewCache::GetValueIn(const CTransaction& tx)
{
- if (IsCoinBase())
+ if (tx.IsCoinBase())
return 0;
int64 nResult = 0;
- for (unsigned int i = 0; i < vin.size(); i++)
- nResult += GetOutputFor(vin[i], inputs).nValue;
+ for (unsigned int i = 0; i < tx.vin.size(); i++)
+ nResult += GetOutputFor(tx.vin[i]).nValue;
return nResult;
}
-unsigned int CTransaction::GetP2SHSigOpCount(CCoinsViewCache& inputs) const
-{
- if (IsCoinBase())
- return 0;
-
- unsigned int nSigOps = 0;
- for (unsigned int i = 0; i < vin.size(); i++)
- {
- const CTxOut &prevout = GetOutputFor(vin[i], inputs);
- if (prevout.scriptPubKey.IsPayToScriptHash())
- nSigOps += prevout.scriptPubKey.GetSigOpCount(vin[i].scriptSig);
- }
- return nSigOps;
-}
-
-void CTransaction::UpdateCoins(CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight, const uint256 &txhash) const
+void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight, const uint256 &txhash)
{
// mark inputs spent
- if (!IsCoinBase()) {
- BOOST_FOREACH(const CTxIn &txin, vin) {
+ if (!tx.IsCoinBase()) {
+ BOOST_FOREACH(const CTxIn &txin, tx.vin) {
CCoins &coins = inputs.GetCoins(txin.prevout.hash);
CTxInUndo undo;
assert(coins.Spend(txin.prevout, undo));
@@ -1346,23 +1351,23 @@ void CTransaction::UpdateCoins(CValidationState &state, CCoinsViewCache &inputs,
}
// add outputs
- assert(inputs.SetCoins(txhash, CCoins(*this, nHeight)));
+ assert(inputs.SetCoins(txhash, CCoins(tx, nHeight)));
}
-bool CTransaction::HaveInputs(CCoinsViewCache &inputs) const
+bool CCoinsViewCache::HaveInputs(const CTransaction& tx)
{
- if (!IsCoinBase()) {
+ if (!tx.IsCoinBase()) {
// first check whether information about the prevout hash is available
- for (unsigned int i = 0; i < vin.size(); i++) {
- const COutPoint &prevout = vin[i].prevout;
- if (!inputs.HaveCoins(prevout.hash))
+ for (unsigned int i = 0; i < tx.vin.size(); i++) {
+ const COutPoint &prevout = tx.vin[i].prevout;
+ if (!HaveCoins(prevout.hash))
return false;
}
// then check whether the actual outputs are available
- for (unsigned int i = 0; i < vin.size(); i++) {
- const COutPoint &prevout = vin[i].prevout;
- const CCoins &coins = inputs.GetCoins(prevout.hash);
+ for (unsigned int i = 0; i < tx.vin.size(); i++) {
+ const COutPoint &prevout = tx.vin[i].prevout;
+ const CCoins &coins = GetCoins(prevout.hash);
if (!coins.IsAvailable(prevout.n))
return false;
}
@@ -1382,26 +1387,26 @@ bool VerifySignature(const CCoins& txFrom, const CTransaction& txTo, unsigned in
return CScriptCheck(txFrom, txTo, nIn, flags, nHashType)();
}
-bool CTransaction::CheckInputs(CValidationState &state, CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, std::vector<CScriptCheck> *pvChecks) const
+bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, std::vector<CScriptCheck> *pvChecks)
{
- if (!IsCoinBase())
+ if (!tx.IsCoinBase())
{
if (pvChecks)
- pvChecks->reserve(vin.size());
+ pvChecks->reserve(tx.vin.size());
// This doesn't trigger the DoS code on purpose; if it did, it would make it easier
// for an attacker to attempt to split the network.
- if (!HaveInputs(inputs))
- return state.Invalid(error("CheckInputs() : %s inputs unavailable", GetHash().ToString().c_str()));
+ if (!inputs.HaveInputs(tx))
+ return state.Invalid(error("CheckInputs() : %s inputs unavailable", tx.GetHash().ToString().c_str()));
// While checking, GetBestBlock() refers to the parent block.
// This is also true for mempool checks.
int nSpendHeight = inputs.GetBestBlock()->nHeight + 1;
int64 nValueIn = 0;
int64 nFees = 0;
- for (unsigned int i = 0; i < vin.size(); i++)
+ for (unsigned int i = 0; i < tx.vin.size(); i++)
{
- const COutPoint &prevout = vin[i].prevout;
+ const COutPoint &prevout = tx.vin[i].prevout;
const CCoins &coins = inputs.GetCoins(prevout.hash);
// If prev is coinbase, check that it's matured
@@ -1417,13 +1422,13 @@ bool CTransaction::CheckInputs(CValidationState &state, CCoinsViewCache &inputs,
}
- if (nValueIn < GetValueOut())
- return state.DoS(100, error("CheckInputs() : %s value in < value out", GetHash().ToString().c_str()));
+ if (nValueIn < GetValueOut(tx))
+ return state.DoS(100, error("CheckInputs() : %s value in < value out", tx.GetHash().ToString().c_str()));
// Tally transaction fees
- int64 nTxFee = nValueIn - GetValueOut();
+ int64 nTxFee = nValueIn - GetValueOut(tx);
if (nTxFee < 0)
- return state.DoS(100, error("CheckInputs() : %s nTxFee < 0", GetHash().ToString().c_str()));
+ return state.DoS(100, error("CheckInputs() : %s nTxFee < 0", tx.GetHash().ToString().c_str()));
nFees += nTxFee;
if (!MoneyRange(nFees))
return state.DoS(100, error("CheckInputs() : nFees out of range"));
@@ -1436,12 +1441,12 @@ bool CTransaction::CheckInputs(CValidationState &state, CCoinsViewCache &inputs,
// before the last block chain checkpoint. This is safe because block merkle hashes are
// still computed and checked, and any change will be caught at the next checkpoint.
if (fScriptChecks) {
- for (unsigned int i = 0; i < vin.size(); i++) {
- const COutPoint &prevout = vin[i].prevout;
+ for (unsigned int i = 0; i < tx.vin.size(); i++) {
+ const COutPoint &prevout = tx.vin[i].prevout;
const CCoins &coins = inputs.GetCoins(prevout.hash);
// Verify signature
- CScriptCheck check(coins, *this, i, flags, 0);
+ CScriptCheck check(coins, tx, i, flags, 0);
if (pvChecks) {
pvChecks->push_back(CScriptCheck());
check.swap(pvChecks->back());
@@ -1449,7 +1454,7 @@ bool CTransaction::CheckInputs(CValidationState &state, CCoinsViewCache &inputs,
if (flags & SCRIPT_VERIFY_STRICTENC) {
// For now, check whether the failure was caused by non-canonical
// encodings or not; if so, don't trigger DoS protection.
- CScriptCheck check(coins, *this, i, flags & (~SCRIPT_VERIFY_STRICTENC), 0);
+ CScriptCheck check(coins, tx, i, flags & (~SCRIPT_VERIFY_STRICTENC), 0);
if (check())
return state.Invalid();
}
@@ -1464,7 +1469,6 @@ bool CTransaction::CheckInputs(CValidationState &state, CCoinsViewCache &inputs,
-
bool CBlock::DisconnectBlock(CValidationState &state, CBlockIndex *pindex, CCoinsViewCache &view, bool *pfClean)
{
assert(pindex == view.GetBestBlock());
@@ -1644,13 +1648,13 @@ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsVi
const CTransaction &tx = vtx[i];
nInputs += tx.vin.size();
- nSigOps += tx.GetLegacySigOpCount();
+ nSigOps += GetLegacySigOpCount(tx);
if (nSigOps > MAX_BLOCK_SIGOPS)
return state.DoS(100, error("ConnectBlock() : too many sigops"));
if (!tx.IsCoinBase())
{
- if (!tx.HaveInputs(view))
+ if (!view.HaveInputs(tx))
return state.DoS(100, error("ConnectBlock() : inputs missing/spent"));
if (fStrictPayToScriptHash)
@@ -1658,21 +1662,21 @@ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsVi
// Add in sigops done by pay-to-script-hash inputs;
// this is to prevent a "rogue miner" from creating
// an incredibly-expensive-to-validate block.
- nSigOps += tx.GetP2SHSigOpCount(view);
+ nSigOps += GetP2SHSigOpCount(tx, view);
if (nSigOps > MAX_BLOCK_SIGOPS)
return state.DoS(100, error("ConnectBlock() : too many sigops"));
}
- nFees += tx.GetValueIn(view)-tx.GetValueOut();
+ nFees += view.GetValueIn(tx)-GetValueOut(tx);
std::vector<CScriptCheck> vChecks;
- if (!tx.CheckInputs(state, view, fScriptChecks, flags, nScriptCheckThreads ? &vChecks : NULL))
+ if (!CheckInputs(tx, state, view, fScriptChecks, flags, nScriptCheckThreads ? &vChecks : NULL))
return false;
control.Add(vChecks);
}
CTxUndo txundo;
- tx.UpdateCoins(state, view, txundo, pindex->nHeight, GetTxHash(i));
+ UpdateCoins(tx, state, view, txundo, pindex->nHeight, GetTxHash(i));
if (!tx.IsCoinBase())
blockundo.vtxundo.push_back(txundo);
@@ -1683,8 +1687,8 @@ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsVi
if (fBenchmark)
printf("- Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin)\n", (unsigned)vtx.size(), 0.001 * nTime, 0.001 * nTime / vtx.size(), nInputs <= 1 ? 0 : 0.001 * nTime / (nInputs-1));
- if (vtx[0].GetValueOut() > GetBlockValue(pindex->nHeight, nFees))
- return state.DoS(100, error("ConnectBlock() : coinbase pays too much (actual=%"PRI64d" vs limit=%"PRI64d")", vtx[0].GetValueOut(), GetBlockValue(pindex->nHeight, nFees)));
+ if (GetValueOut(vtx[0]) > GetBlockValue(pindex->nHeight, nFees))
+ return state.DoS(100, error("ConnectBlock() : coinbase pays too much (actual=%"PRI64d" vs limit=%"PRI64d")", GetValueOut(vtx[0]), GetBlockValue(pindex->nHeight, nFees)));
if (!control.Wait())
return state.DoS(100, false);
@@ -1846,7 +1850,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
BOOST_FOREACH(CTransaction& tx, vResurrect) {
// ignore validation errors in resurrected transactions
CValidationState stateDummy;
- tx.AcceptToMemoryPool(stateDummy, true, false);
+ mempool.accept(stateDummy, tx, true, false, NULL);
}
// Delete redundant memory transactions that are in the connected branch
@@ -2076,7 +2080,7 @@ bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerk
// Check transactions
BOOST_FOREACH(const CTransaction& tx, vtx)
- if (!tx.CheckTransaction(state))
+ if (!CheckTransaction(tx, state))
return error("CheckBlock() : CheckTransaction failed");
// Build the merkle tree already. We need it anyway later, and it makes the
@@ -2096,7 +2100,7 @@ bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerk
unsigned int nSigOps = 0;
BOOST_FOREACH(const CTransaction& tx, vtx)
{
- nSigOps += tx.GetLegacySigOpCount();
+ nSigOps += GetLegacySigOpCount(tx);
}
if (nSigOps > MAX_BLOCK_SIGOPS)
return state.DoS(100, error("CheckBlock() : out-of-bounds SigOpCount"));
@@ -2135,7 +2139,7 @@ bool CBlock::AcceptBlock(CValidationState &state, CDiskBlockPos *dbp)
// Check that all transactions are finalized
BOOST_FOREACH(const CTransaction& tx, vtx)
- if (!tx.IsFinal(nHeight, GetBlockTime()))
+ if (!IsFinalTx(tx, nHeight, GetBlockTime()))
return state.DoS(10, error("AcceptBlock() : contains a non-final transaction"));
// Check that the block chain matches the known block chain up to a checkpoint
@@ -3488,7 +3492,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
bool fMissingInputs = false;
CValidationState state;
- if (tx.AcceptToMemoryPool(state, true, true, &fMissingInputs))
+ if (mempool.accept(state, tx, true, true, &fMissingInputs))
{
RelayTransaction(tx, inv.hash, vMsg);
mapAlreadyAskedFor.erase(inv);
@@ -3511,7 +3515,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
// Use a dummy CValidationState so someone can't setup nodes to counter-DoS based on orphan resolution (that is, feeding people an invalid transaction based on LegitTxX in order to get anyone relaying LegitTxX banned)
CValidationState stateDummy;
- if (tx.AcceptToMemoryPool(stateDummy, true, true, &fMissingInputs2))
+ if (mempool.accept(stateDummy, tx, true, true, &fMissingInputs2))
{
printf(" accepted orphan tx %s\n", inv.hash.ToString().c_str());
RelayTransaction(tx, inv.hash, vMsg);
@@ -4194,7 +4198,7 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
for (map<uint256, CTransaction>::iterator mi = mempool.mapTx.begin(); mi != mempool.mapTx.end(); ++mi)
{
CTransaction& tx = (*mi).second;
- if (tx.IsCoinBase() || !tx.IsFinal())
+ if (tx.IsCoinBase() || !IsFinalTx(tx))
continue;
COrphan* porphan = NULL;
@@ -4249,7 +4253,7 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
// 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-tx.GetValueOut()) / (double(nTxSize)/1000.0);
+ double dFeePerKb = double(nTotalIn-GetValueOut(tx)) / (double(nTxSize)/1000.0);
if (porphan)
{
@@ -4285,7 +4289,7 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
continue;
// Legacy limits on sigOps:
- unsigned int nTxSigOps = tx.GetLegacySigOpCount();
+ unsigned int nTxSigOps = GetLegacySigOpCount(tx);
if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
continue;
@@ -4303,22 +4307,22 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
}
- if (!tx.HaveInputs(view))
+ if (!view.HaveInputs(tx))
continue;
- int64 nTxFees = tx.GetValueIn(view)-tx.GetValueOut();
+ int64 nTxFees = view.GetValueIn(tx)-GetValueOut(tx);
- nTxSigOps += tx.GetP2SHSigOpCount(view);
+ nTxSigOps += GetP2SHSigOpCount(tx, view);
if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
continue;
CValidationState state;
- if (!tx.CheckInputs(state, view, true, SCRIPT_VERIFY_P2SH))
+ if (!CheckInputs(tx, state, view, true, SCRIPT_VERIFY_P2SH))
continue;
CTxUndo txundo;
uint256 hash = tx.GetHash();
- tx.UpdateCoins(state, view, txundo, pindexPrev->nHeight+1, hash);
+ UpdateCoins(tx, state, view, txundo, pindexPrev->nHeight+1, hash);
// Added
pblock->vtx.push_back(tx);
@@ -4366,7 +4370,7 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock);
pblock->nNonce = 0;
pblock->vtx[0].vin[0].scriptSig = CScript() << OP_0 << OP_0;
- pblocktemplate->vTxSigOps[0] = pblock->vtx[0].GetLegacySigOpCount();
+ pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
CBlockIndex indexDummy(*pblock);
indexDummy.pprev = pindexPrev;
diff --git a/src/main.h b/src/main.h
index c3c7ee3966..7069d4bab3 100644
--- a/src/main.h
+++ b/src/main.h
@@ -254,155 +254,6 @@ struct CDiskTxPos : public CDiskBlockPos
-
-/** An input of a transaction. It contains the location of the previous
- * transaction's output that it claims and a signature that matches the
- * output's public key.
- */
-class CTxIn
-{
-public:
- COutPoint prevout;
- CScript scriptSig;
- unsigned int nSequence;
-
- CTxIn()
- {
- nSequence = std::numeric_limits<unsigned int>::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=std::numeric_limits<unsigned int>::max())
- {
- prevout = COutPoint(hashPrevTx, nOut);
- scriptSig = scriptSigIn;
- nSequence = nSequenceIn;
- }
-
- IMPLEMENT_SERIALIZE
- (
- READWRITE(prevout);
- READWRITE(scriptSig);
- READWRITE(nSequence);
- )
-
- bool IsFinal() const
- {
- return (nSequence == std::numeric_limits<unsigned int>::max());
- }
-
- friend bool operator==(const CTxIn& a, const CTxIn& b)
- {
- return (a.prevout == b.prevout &&
- a.scriptSig == b.scriptSig &&
- a.nSequence == b.nSequence);
- }
-
- friend bool operator!=(const CTxIn& a, const CTxIn& b)
- {
- return !(a == b);
- }
-
- std::string ToString() const
- {
- std::string str;
- str += "CTxIn(";
- str += prevout.ToString();
- if (prevout.IsNull())
- str += strprintf(", coinbase %s", HexStr(scriptSig).c_str());
- else
- str += strprintf(", scriptSig=%s", scriptSig.ToString().substr(0,24).c_str());
- if (nSequence != std::numeric_limits<unsigned int>::max())
- str += strprintf(", nSequence=%u", nSequence);
- str += ")";
- return str;
- }
-
- void print() const
- {
- printf("%s\n", ToString().c_str());
- }
-};
-
-
-
-
-/** An output of a transaction. It contains the public key that the next input
- * must be able to sign with to claim it.
- */
-class CTxOut
-{
-public:
- int64 nValue;
- CScript scriptPubKey;
-
- CTxOut()
- {
- SetNull();
- }
-
- CTxOut(int64 nValueIn, CScript scriptPubKeyIn)
- {
- nValue = nValueIn;
- scriptPubKey = scriptPubKeyIn;
- }
-
- IMPLEMENT_SERIALIZE
- (
- READWRITE(nValue);
- READWRITE(scriptPubKey);
- )
-
- void SetNull()
- {
- nValue = -1;
- scriptPubKey.clear();
- }
-
- bool IsNull() const
- {
- return (nValue == -1);
- }
-
- uint256 GetHash() const
- {
- return SerializeHash(*this);
- }
-
- friend bool operator==(const CTxOut& a, const CTxOut& b)
- {
- return (a.nValue == b.nValue &&
- a.scriptPubKey == b.scriptPubKey);
- }
-
- friend bool operator!=(const CTxOut& a, const CTxOut& b)
- {
- return !(a == b);
- }
-
- bool IsDust() const;
-
- std::string ToString() const
- {
- if (scriptPubKey.size() < 6)
- return "CTxOut(error)";
- return strprintf("CTxOut(nValue=%"PRI64d".%08"PRI64d", scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,30).c_str());
- }
-
- void print() const
- {
- printf("%s\n", ToString().c_str());
- }
-};
-
-
-
enum GetMinFee_mode
{
GMF_BLOCK,
@@ -412,215 +263,71 @@ enum GetMinFee_mode
int64 GetMinFee(const CTransaction& tx, unsigned int nBlockSize = 1, bool fAllowFree = true, enum GetMinFee_mode mode = GMF_BLOCK);
-/** The basic transaction that is broadcasted on the network and contained in
- * blocks. A transaction can contain multiple inputs and outputs.
- */
-class CTransaction
-{
-public:
- static int64 nMinTxFee;
- static int64 nMinRelayTxFee;
- static const int CURRENT_VERSION=1;
- int nVersion;
- std::vector<CTxIn> vin;
- std::vector<CTxOut> vout;
- unsigned int nLockTime;
-
- CTransaction()
- {
- SetNull();
- }
-
- IMPLEMENT_SERIALIZE
- (
- READWRITE(this->nVersion);
- nVersion = this->nVersion;
- READWRITE(vin);
- READWRITE(vout);
- READWRITE(nLockTime);
- )
-
- void SetNull()
- {
- nVersion = CTransaction::CURRENT_VERSION;
- vin.clear();
- vout.clear();
- nLockTime = 0;
- }
-
- bool IsNull() const
- {
- return (vin.empty() && vout.empty());
- }
-
- uint256 GetHash() const
- {
- return SerializeHash(*this);
- }
-
- bool IsFinal(int nBlockHeight=0, int64 nBlockTime=0) const
- {
- // Time based nLockTime implemented in 0.1.6
- if (nLockTime == 0)
- return true;
- if (nBlockHeight == 0)
- nBlockHeight = nBestHeight;
- if (nBlockTime == 0)
- nBlockTime = GetAdjustedTime();
- if ((int64)nLockTime < ((int64)nLockTime < LOCKTIME_THRESHOLD ? (int64)nBlockHeight : nBlockTime))
- return true;
- BOOST_FOREACH(const CTxIn& txin, vin)
- if (!txin.IsFinal())
- return false;
- return true;
- }
-
- bool IsNewerThan(const CTransaction& old) const
- {
- if (vin.size() != old.vin.size())
- return false;
- 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 = std::numeric_limits<unsigned int>::max();
- for (unsigned int i = 0; i < vin.size(); i++)
- {
- if (vin[i].nSequence != old.vin[i].nSequence)
- {
- if (vin[i].nSequence <= nLowest)
- {
- fNewer = false;
- nLowest = vin[i].nSequence;
- }
- if (old.vin[i].nSequence < nLowest)
- {
- fNewer = true;
- nLowest = old.vin[i].nSequence;
- }
- }
- }
- return fNewer;
- }
-
- bool IsCoinBase() const
- {
- return (vin.size() == 1 && vin[0].prevout.IsNull());
- }
-
- /** Check for standard transaction types
- @return True if all outputs (scriptPubKeys) use only standard transaction forms
- */
- bool IsStandard() const;
+//
+// Check transaction inputs, and make sure any
+// pay-to-script-hash transactions are evaluating IsStandard scripts
+//
+// Why bother? To avoid denial-of-service attacks; an attacker
+// can submit a standard HASH... OP_EQUAL transaction,
+// which will get accepted into blocks. The redemption
+// script can be anything; an attacker could use a very
+// expensive-to-check-upon-redemption script like:
+// DUP CHECKSIG DROP ... repeated 100 times... OP_1
+//
/** Check for standard transaction types
- @param[in] mapInputs Map of previous transactions that have outputs we're spending
+ @param[in] mapInputs Map of previous transactions that have outputs we're spending
@return True if all inputs (scriptSigs) use only standard transaction forms
*/
- bool AreInputsStandard(CCoinsViewCache& mapInputs) const;
+bool AreInputsStandard(const CTransaction& tx, CCoinsViewCache& mapInputs);
- /** Count ECDSA signature operations the old-fashioned (pre-0.6) way
- @return number of sigops this transaction's outputs will produce when spent
- */
- unsigned int GetLegacySigOpCount() 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
+*/
+unsigned int GetLegacySigOpCount(const CTransaction& tx);
- /** 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
- */
- unsigned int GetP2SHSigOpCount(CCoinsViewCache& 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;
- 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;
- }
-
- /** 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)
- */
- int64 GetValueIn(CCoinsViewCache& mapInputs) const;
-
- static bool AllowFree(double dPriority)
- {
- // Large (in bytes) low-priority (new, small-coin) transactions
- // need a fee.
- return dPriority > COIN * 144 / 250;
- }
-
- friend bool operator==(const CTransaction& a, const CTransaction& b)
- {
- return (a.nVersion == b.nVersion &&
- a.vin == b.vin &&
- a.vout == b.vout &&
- a.nLockTime == b.nLockTime);
- }
-
- friend bool operator!=(const CTransaction& a, const CTransaction& b)
- {
- return !(a == b);
- }
+/** 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
+ */
+unsigned int GetP2SHSigOpCount(const CTransaction& tx, CCoinsViewCache& mapInputs);
- std::string ToString() const
- {
- std::string str;
- str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%"PRIszu", vout.size=%"PRIszu", nLockTime=%u)\n",
- GetHash().ToString().c_str(),
- nVersion,
- vin.size(),
- vout.size(),
- nLockTime);
- for (unsigned int i = 0; i < vin.size(); i++)
- str += " " + vin[i].ToString() + "\n";
- for (unsigned int i = 0; i < vout.size(); i++)
- str += " " + vout[i].ToString() + "\n";
- return str;
- }
- void print() const
- {
- printf("%s", ToString().c_str());
- }
+inline bool AllowFree(double dPriority)
+{
+ // Large (in bytes) low-priority (new, small-coin) transactions
+ // need a fee.
+ return dPriority > COIN * 144 / 250;
+}
+// Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts)
+// This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it
+// instead of being performed inline.
+bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCache &view, bool fScriptChecks = true,
+ unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC,
+ std::vector<CScriptCheck> *pvChecks = NULL);
- // Check whether all prevouts of this transaction are present in the UTXO set represented by view
- bool HaveInputs(CCoinsViewCache &view) const;
+// Apply the effects of this transaction on the UTXO set represented by view
+bool UpdateCoins(const CTransaction& tx, CCoinsViewCache &view, CTxUndo &txundo, int nHeight, const uint256 &txhash);
- // Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts)
- // This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it
- // instead of being performed inline.
- bool CheckInputs(CValidationState &state, CCoinsViewCache &view, bool fScriptChecks = true,
- unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC,
- std::vector<CScriptCheck> *pvChecks = NULL) const;
+// Context-independent validity checks
+bool CheckTransaction(const CTransaction& tx, CValidationState& state);
- // Apply the effects of this transaction on the UTXO set represented by view
- void UpdateCoins(CValidationState &state, CCoinsViewCache &view, CTxUndo &txundo, int nHeight, const uint256 &txhash) const;
+/** Check for standard transaction types
+ @return True if all outputs (scriptPubKeys) use only standard transaction forms
+*/
+bool IsStandardTx(const CTransaction& tx);
- // Context-independent validity checks
- bool CheckTransaction(CValidationState &state) const;
+bool IsFinalTx(const CTransaction &tx, int nBlockHeight = 0, int64 nBlockTime = 0);
- // Try to accept this transaction into the memory pool
- bool AcceptToMemoryPool(CValidationState &state, bool fCheckInputs=true, bool fLimitFree = true, bool* pfMissingInputs=NULL);
+/** Amount of bitcoins spent by the transaction.
+ @return sum of all outputs (note: does not include fees)
+ */
+int64 GetValueOut(const CTransaction& tx);
-protected:
- static const CTxOut &GetOutputFor(const CTxIn& input, CCoinsViewCache& mapInputs);
-};
/** wrapper for CTxOut that provides a more compact serialization */
class CTxOutCompressor
@@ -2132,6 +1839,21 @@ public:
// Calculate the size of the cache (in number of transactions)
unsigned int GetCacheSize();
+ /** Amount of bitcoins coming in to a 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] tx transaction for which we are checking input total
+ @return Sum of value of all inputs (scriptSigs)
+ @see CTransaction::FetchInputs
+ */
+ int64 GetValueIn(const CTransaction& tx);
+
+ // Check whether all prevouts of the transaction are present in the UTXO set represented by this view
+ bool HaveInputs(const CTransaction& tx);
+
+ const CTxOut &GetOutputFor(const CTxIn& input);
+
private:
std::map<uint256,CCoins>::iterator FetchCoins(const uint256 &txid);
};
diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp
index e4dbf9c0d9..aeef721ce5 100644
--- a/src/qt/transactiondesc.cpp
+++ b/src/qt/transactiondesc.cpp
@@ -12,7 +12,7 @@
QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
{
- if (!wtx.IsFinal())
+ if (!IsFinalTx(wtx))
{
if (wtx.nLockTime < LOCKTIME_THRESHOLD)
return tr("Open for %n more block(s)", "", wtx.nLockTime - nBestHeight + 1);
@@ -186,7 +186,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nValue) + "<br>";
}
- int64 nTxFee = nDebit - wtx.GetValueOut();
+ int64 nTxFee = nDebit - GetValueOut(wtx);
if (nTxFee > 0)
strHTML += "<b>" + tr("Transaction fee") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -nTxFee) + "<br>";
}
diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp
index 40a5f735cd..e954508769 100644
--- a/src/qt/transactionrecord.cpp
+++ b/src/qt/transactionrecord.cpp
@@ -89,7 +89,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
//
// Debit
//
- int64 nTxFee = nDebit - wtx.GetValueOut();
+ int64 nTxFee = nDebit - GetValueOut(wtx);
for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++)
{
@@ -162,7 +162,7 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
status.depth = wtx.GetDepthInMainChain();
status.cur_num_blocks = nBestHeight;
- if (!wtx.IsFinal())
+ if (!IsFinalTx(wtx))
{
if (wtx.nLockTime < LOCKTIME_THRESHOLD)
{
diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index c1e05466e5..917c2f5de9 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -555,7 +555,7 @@ Value sendrawtransaction(const Array& params, bool fHelp)
if (!fHave) {
// push to local node
CValidationState state;
- if (!tx.AcceptToMemoryPool(state, true, false))
+ if (!mempool.accept(state, tx, true, false, NULL))
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX rejected"); // TODO: report validation state
}
}
diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp
index fbad1944de..585bdb2bfb 100644
--- a/src/rpcwallet.cpp
+++ b/src/rpcwallet.cpp
@@ -408,7 +408,7 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
- if (wtx.IsCoinBase() || !wtx.IsFinal())
+ if (wtx.IsCoinBase() || !IsFinalTx(wtx))
continue;
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
@@ -454,7 +454,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
- if (wtx.IsCoinBase() || !wtx.IsFinal())
+ if (wtx.IsCoinBase() || !IsFinalTx(wtx))
continue;
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
@@ -478,7 +478,7 @@ int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinD
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
- if (!wtx.IsFinal())
+ if (!IsFinalTx(wtx))
continue;
int64 nReceived, nSent, nFee;
@@ -839,7 +839,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
{
const CWalletTx& wtx = (*it).second;
- if (wtx.IsCoinBase() || !wtx.IsFinal())
+ if (wtx.IsCoinBase() || !IsFinalTx(wtx))
continue;
int nDepth = wtx.GetDepthInMainChain();
@@ -1220,7 +1220,7 @@ Value gettransaction(const Array& params, bool fHelp)
int64 nCredit = wtx.GetCredit();
int64 nDebit = wtx.GetDebit();
int64 nNet = nCredit - nDebit;
- int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
+ int64 nFee = (wtx.IsFromMe() ? GetValueOut(wtx) - nDebit : 0);
entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
if (wtx.IsFromMe())
diff --git a/src/script.h b/src/script.h
index 3cbb2cf322..f963467c94 100644
--- a/src/script.h
+++ b/src/script.h
@@ -533,7 +533,7 @@ public:
bool IsPayToScriptHash() const;
- // Called by CTransaction::IsStandard
+ // Called by IsStandardTx
bool IsPushOnly() const
{
const_iterator pc = begin();
diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json
index 81e77b7df8..a26f4a87db 100644
--- a/src/test/data/tx_invalid.json
+++ b/src/test/data/tx_invalid.json
@@ -23,7 +23,7 @@
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]],
"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", true],
-["Tests for CTransaction::CheckTransaction()"],
+["Tests for CheckTransaction()"],
["No inputs"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]],
"0100000000010000000000000000015100000000", true],
diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json
index 8aeb30f35b..faf911a97f 100644
--- a/src/test/data/tx_valid.json
+++ b/src/test/data/tx_valid.json
@@ -50,7 +50,7 @@
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x8febbed40483661de6958d957412f82deed8e2f7 EQUAL"]],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100c66c9cdf4c43609586d15424c54707156e316d88b0a1534c9e6b0d4f311406310221009c0fe51dbc9c4ab7cc25d3fdbeccf6679fe6827f08edf2b4a9f16ee3eb0e438a0123210338e8034509af564c62644c07691942e0c056752008a173c89f60ab2a88ac2ebfacffffffff010000000000000000015100000000", true],
-["Tests for CTransaction::CheckTransaction()"],
+["Tests for CheckTransaction()"],
["MAX_MONEY output"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x32afac281462b822adbec5094b8d4d337dd5bd6a EQUAL"]],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010040075af0750700015100000000", true],
diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp
index 65f0ad0cdc..23cb3a8e0a 100644
--- a/src/test/script_P2SH_tests.cpp
+++ b/src/test/script_P2SH_tests.cpp
@@ -82,7 +82,7 @@ BOOST_AUTO_TEST_CASE(sign)
txFrom.vout[i+4].scriptPubKey = standardScripts[i];
txFrom.vout[i+4].nValue = COIN;
}
- BOOST_CHECK(txFrom.IsStandard());
+ BOOST_CHECK(IsStandardTx(txFrom));
CTransaction txTo[8]; // Spending transactions
for (int i = 0; i < 8; i++)
@@ -173,7 +173,7 @@ BOOST_AUTO_TEST_CASE(set)
txFrom.vout[i].scriptPubKey = outer[i];
txFrom.vout[i].nValue = CENT;
}
- BOOST_CHECK(txFrom.IsStandard());
+ BOOST_CHECK(IsStandardTx(txFrom));
CTransaction txTo[4]; // Spending transactions
for (int i = 0; i < 4; i++)
@@ -189,7 +189,7 @@ BOOST_AUTO_TEST_CASE(set)
for (int i = 0; i < 4; i++)
{
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
- BOOST_CHECK_MESSAGE(txTo[i].IsStandard(), strprintf("txTo[%d].IsStandard", i));
+ BOOST_CHECK_MESSAGE(IsStandardTx(txTo[i]), strprintf("txTo[%d].IsStandard", i));
}
}
@@ -305,15 +305,15 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
txTo.vin[2].prevout.hash = txFrom.GetHash();
BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 2));
- BOOST_CHECK(txTo.AreInputsStandard(coins));
- BOOST_CHECK_EQUAL(txTo.GetP2SHSigOpCount(coins), 1U);
+ BOOST_CHECK(::AreInputsStandard(txTo, coins));
+ BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txTo, coins), 1U);
// Make sure adding crap to the scriptSigs makes them non-standard:
for (int i = 0; i < 3; i++)
{
CScript t = txTo.vin[i].scriptSig;
txTo.vin[i].scriptSig = (CScript() << 11) + t;
- BOOST_CHECK(!txTo.AreInputsStandard(coins));
+ BOOST_CHECK(!::AreInputsStandard(txTo, coins));
txTo.vin[i].scriptSig = t;
}
@@ -329,11 +329,11 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
txToNonStd.vin[1].prevout.hash = txFrom.GetHash();
txToNonStd.vin[1].scriptSig << OP_0 << Serialize(oneOfEleven);
- BOOST_CHECK(!txToNonStd.AreInputsStandard(coins));
- BOOST_CHECK_EQUAL(txToNonStd.GetP2SHSigOpCount(coins), 11U);
+ BOOST_CHECK(!::AreInputsStandard(txToNonStd, coins));
+ BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txToNonStd, coins), 11U);
txToNonStd.vin[0].scriptSig.clear();
- BOOST_CHECK(!txToNonStd.AreInputsStandard(coins));
+ BOOST_CHECK(!::AreInputsStandard(txToNonStd, coins));
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index ddff2acd4e..53d1307b69 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -67,7 +67,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
stream >> tx;
CValidationState state;
- BOOST_CHECK_MESSAGE(tx.CheckTransaction(state), strTest);
+ BOOST_CHECK_MESSAGE(CheckTransaction(tx, state), strTest);
BOOST_CHECK(state.IsValid());
for (unsigned int i = 0; i < tx.vin.size(); i++)
@@ -136,7 +136,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
stream >> tx;
CValidationState state;
- fValid = tx.CheckTransaction(state) && state.IsValid();
+ fValid = CheckTransaction(tx, state) && state.IsValid();
for (unsigned int i = 0; i < tx.vin.size() && fValid; i++)
{
@@ -163,11 +163,11 @@ BOOST_AUTO_TEST_CASE(basic_transaction_tests)
CTransaction tx;
stream >> tx;
CValidationState state;
- BOOST_CHECK_MESSAGE(tx.CheckTransaction(state) && state.IsValid(), "Simple deserialized transaction should be valid.");
+ BOOST_CHECK_MESSAGE(CheckTransaction(tx, state) && state.IsValid(), "Simple deserialized transaction should be valid.");
// Check that duplicate txins fail
tx.vin.push_back(tx.vin[0]);
- BOOST_CHECK_MESSAGE(!tx.CheckTransaction(state) || !state.IsValid(), "Transaction with duplicate txins should be invalid.");
+ BOOST_CHECK_MESSAGE(!CheckTransaction(tx, state) || !state.IsValid(), "Transaction with duplicate txins should be invalid.");
}
//
@@ -230,16 +230,16 @@ BOOST_AUTO_TEST_CASE(test_Get)
t1.vout[0].nValue = 90*CENT;
t1.vout[0].scriptPubKey << OP_1;
- BOOST_CHECK(t1.AreInputsStandard(coins));
- BOOST_CHECK_EQUAL(t1.GetValueIn(coins), (50+21+22)*CENT);
+ BOOST_CHECK(AreInputsStandard(t1, coins));
+ BOOST_CHECK_EQUAL(coins.GetValueIn(t1), (50+21+22)*CENT);
// Adding extra junk to the scriptSig should make it non-standard:
t1.vin[0].scriptSig << OP_11;
- BOOST_CHECK(!t1.AreInputsStandard(coins));
+ BOOST_CHECK(!AreInputsStandard(t1, coins));
// ... as should not having enough:
t1.vin[0].scriptSig = CScript();
- BOOST_CHECK(!t1.AreInputsStandard(coins));
+ BOOST_CHECK(!AreInputsStandard(t1, coins));
}
BOOST_AUTO_TEST_CASE(test_IsStandard)
@@ -260,16 +260,16 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
key.MakeNewKey(true);
t.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
- BOOST_CHECK(t.IsStandard());
+ BOOST_CHECK(IsStandardTx(t));
t.vout[0].nValue = 5011; // dust
- BOOST_CHECK(!t.IsStandard());
+ BOOST_CHECK(!IsStandardTx(t));
t.vout[0].nValue = 6011; // not dust
- BOOST_CHECK(t.IsStandard());
+ BOOST_CHECK(IsStandardTx(t));
t.vout[0].scriptPubKey = CScript() << OP_1;
- BOOST_CHECK(!t.IsStandard());
+ BOOST_CHECK(!IsStandardTx(t));
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/wallet.cpp b/src/wallet.cpp
index da75752bb4..7041d49dab 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -643,7 +643,7 @@ void CWalletTx::GetAmounts(list<pair<CTxDestination, int64> >& listReceived,
int64 nDebit = GetDebit();
if (nDebit > 0) // debit>0 means we signed/sent this transaction
{
- int64 nValueOut = GetValueOut();
+ int64 nValueOut = GetValueOut(*this);
nFee = nDebit - nValueOut;
}
@@ -933,7 +933,7 @@ int64 CWallet::GetUnconfirmedBalance() const
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
- if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
+ if (!IsFinalTx(*pcoin) || !pcoin->IsConfirmed())
nTotal += pcoin->GetAvailableCredit();
}
}
@@ -965,7 +965,7 @@ void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed) const
{
const CWalletTx* pcoin = &(*it).second;
- if (!pcoin->IsFinal())
+ if (!IsFinalTx(*pcoin))
continue;
if (fOnlyConfirmed && !pcoin->IsConfirmed())
@@ -1178,7 +1178,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend,
BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
{
CTxOut txout(s.second, s.first);
- if (txout.IsDust())
+ if (txout.IsDust(CTransaction::nMinRelayTxFee))
{
strFailReason = _("Transaction amount too small");
return false;
@@ -1237,7 +1237,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend,
// Never create dust outputs; if we would, just
// add the dust to the fee.
- if (newTxOut.IsDust())
+ if (newTxOut.IsDust(CTransaction::nMinRelayTxFee))
{
nFeeRet += nChange;
reservekey.ReturnKey();
@@ -1276,7 +1276,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend,
// Check that enough fee is included
int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
- bool fAllowFree = CTransaction::AllowFree(dPriority);
+ bool fAllowFree = AllowFree(dPriority);
int64 nMinFee = GetMinFee(wtxNew, 1, fAllowFree, GMF_SEND);
if (nFeeRet < max(nPayFee, nMinFee))
{
@@ -1657,7 +1657,7 @@ std::map<CTxDestination, int64> CWallet::GetAddressBalances()
{
CWalletTx *pcoin = &walletEntry.second;
- if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
+ if (!IsFinalTx(*pcoin) || !pcoin->IsConfirmed())
continue;
if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
diff --git a/src/wallet.h b/src/wallet.h
index 22dce78e91..674bae66dd 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -641,7 +641,7 @@ public:
bool IsConfirmed() const
{
// Quick answer in most cases
- if (!IsFinal())
+ if (!IsFinalTx(*this))
return false;
if (GetDepthInMainChain() >= 1)
return true;
@@ -658,7 +658,7 @@ public:
{
const CMerkleTx* ptx = vWorkQueue[i];
- if (!ptx->IsFinal())
+ if (!IsFinalTx(*ptx))
return false;
if (ptx->GetDepthInMainChain() >= 1)
continue;
diff --git a/src/walletdb.cpp b/src/walletdb.cpp
index 4a73413d26..8910cac4bc 100644
--- a/src/walletdb.cpp
+++ b/src/walletdb.cpp
@@ -204,7 +204,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
CWalletTx& wtx = pwallet->mapWallet[hash];
ssValue >> wtx;
CValidationState state;
- if (wtx.CheckTransaction(state) && (wtx.GetHash() == hash) && state.IsValid())
+ if (CheckTransaction(wtx, state) && (wtx.GetHash() == hash) && state.IsValid())
wtx.BindWallet(pwallet);
else
{