diff options
author | Eric Lombrozo <elombrozo@gmail.com> | 2013-01-08 04:17:15 -0800 |
---|---|---|
committer | Eric Lombrozo <elombrozo@gmail.com> | 2013-06-05 23:15:20 -0700 |
commit | 05df3fc68d68e87415ed9e534db3ea3160dc3092 (patch) | |
tree | 50e1da470312d2300da4a1ec0ae2c1941f681b29 /src/main.cpp | |
parent | 788536f1755c6a9ea81394a2199ca27c9e90944e (diff) |
Removed AcceptToMemoryPool method from CTransaction. This method belongs to the mempool instance.
Removed AreInputsStandard from CTransaction, made it a regular function in main.
Moved CTransaction::GetOutputFor to CCoinsViewCache.
Moved GetLegacySigOpCount and GetP2SHSigOpCount out of CTransaction into regular functions in main.
Moved GetValueIn and HaveInputs from CTransaction into CCoinsViewCache.
Moved AllowFree, ClientCheckInputs, CheckInputs, UpdateCoins, and CheckTransaction out of CTransaction and into main.
Moved IsStandard and IsFinal out of CTransaction and put them in main as IsStandardTx and IsFinalTx. Moved GetValueOut out of CTransaction into main. Moved CTxIn, CTxOut, and CTransaction into core.
Added minimum fee parameter to CTxOut::IsDust() temporarily until CTransaction is moved to core.h so that CTxOut needn't know about CTransaction.
Diffstat (limited to 'src/main.cpp')
-rw-r--r-- | src/main.cpp | 276 |
1 files changed, 140 insertions, 136 deletions
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; |