From 8926263dde10bed3f42e21e5f106365f1192e6c0 Mon Sep 17 00:00:00 2001 From: Eric Lombrozo Date: Mon, 7 Jan 2013 06:39:53 -0800 Subject: Moved PushGetBlocks to main.cpp to eliminate dependence of net.cpp on CBlockLocator. --- src/main.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index b8b777161..65ae78a13 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2208,6 +2208,17 @@ bool CBlockIndex::IsSuperMajority(int minVersion, const CBlockIndex* pstart, uns return (nFound >= nRequired); } +void PushGetBlocks(CNode* pnode, CBlockIndex* pindexBegin, uint256 hashEnd) +{ + // Filter out duplicate requests + if (pindexBegin == pnode->pindexLastGetBlocksBegin && hashEnd == pnode->hashLastGetBlocksEnd) + return; + pnode->pindexLastGetBlocksBegin = pindexBegin; + pnode->hashLastGetBlocksEnd = hashEnd; + + pnode->PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd); +} + bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp) { // Check for duplicate @@ -2253,7 +2264,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl mapOrphanBlocksByPrev.insert(make_pair(pblock2->hashPrevBlock, pblock2)); // Ask this guy to fill in what we're missing - pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(pblock2)); + PushGetBlocks(pfrom, pindexBest, GetOrphanRoot(pblock2)); } return true; } @@ -3357,12 +3368,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) if (!fImporting && !fReindex) pfrom->AskFor(inv); } else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash)) { - pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash])); + PushGetBlocks(pfrom, pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash])); } else if (nInv == nLastBlock) { // In case we are on a very long side-chain, it is possible that we already have // the last block in an inv bundle sent in response to getblocks. Try to detect // this situation and push another getblocks to continue. - pfrom->PushGetBlocks(mapBlockIndex[inv.hash], uint256(0)); + PushGetBlocks(pfrom, mapBlockIndex[inv.hash], uint256(0)); if (fDebug) printf("force request: %s\n", inv.ToString().c_str()); } @@ -3839,7 +3850,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) // Start block sync if (pto->fStartSync && !fImporting && !fReindex) { pto->fStartSync = false; - pto->PushGetBlocks(pindexBest, uint256(0)); + PushGetBlocks(pto, pindexBest, uint256(0)); } // Resend wallet transactions that haven't gotten in a block yet -- cgit v1.2.3 From 788536f1755c6a9ea81394a2199ca27c9e90944e Mon Sep 17 00:00:00 2001 From: Eric Lombrozo Date: Tue, 8 Jan 2013 03:42:22 -0800 Subject: Moved CInPoint to core. Removed GetMinFee from CTransaction and made it a regular function in main. --- src/main.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 65ae78a13..5a1345d41 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -591,13 +591,12 @@ bool CTransaction::CheckTransaction(CValidationState &state) const return true; } -int64 CTransaction::GetMinFee(unsigned int nBlockSize, bool fAllowFree, - enum GetMinFee_mode mode) const +int64 GetMinFee(const CTransaction& tx, unsigned int nBlockSize, bool fAllowFree, enum GetMinFee_mode mode) { // Base fee is either nMinTxFee or nMinRelayTxFee - int64 nBaseFee = (mode == GMF_RELAY) ? nMinRelayTxFee : nMinTxFee; + int64 nBaseFee = (mode == GMF_RELAY) ? tx.nMinRelayTxFee : tx.nMinTxFee; - unsigned int nBytes = ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION); + unsigned int nBytes = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); unsigned int nNewBlockSize = nBlockSize + nBytes; int64 nMinFee = (1 + (int64)nBytes / 1000) * nBaseFee; @@ -621,7 +620,7 @@ int64 CTransaction::GetMinFee(unsigned int nBlockSize, bool fAllowFree, // To limit dust spam, require base fee if any output is less than 0.01 if (nMinFee < nBaseFee) { - BOOST_FOREACH(const CTxOut& txout, vout) + BOOST_FOREACH(const CTxOut& txout, tx.vout) if (txout.nValue < CENT) nMinFee = nBaseFee; } @@ -757,7 +756,7 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckIn unsigned int nSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); // Don't accept it if it can't get into a block - int64 txMinFee = tx.GetMinFee(1000, true, GMF_RELAY); + int64 txMinFee = GetMinFee(tx, 1000, true, GMF_RELAY); if (fLimitFree && nFees < txMinFee) return error("CTxMemPool::accept() : not enough fees %s, %"PRI64d" < %"PRI64d, hash.ToString().c_str(), -- cgit v1.2.3 From 05df3fc68d68e87415ed9e534db3ea3160dc3092 Mon Sep 17 00:00:00 2001 From: Eric Lombrozo Date: Tue, 8 Jan 2013 04:17:15 -0800 Subject: 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. --- src/main.cpp | 276 ++++++++++++++++++++++++++++++----------------------------- 1 file changed, 140 insertions(+), 136 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 5a1345d41..28b32101d 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 > 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 > 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 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 *pvChecks) const +bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, std::vector *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 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::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; -- cgit v1.2.3 From aabdf9e899e9024927c26c194ad38142495f80bf Mon Sep 17 00:00:00 2001 From: Eric Lombrozo Date: Tue, 8 Jan 2013 14:58:06 -0800 Subject: Moved UpdateTime out of CBlockHeader and moved CBlockHeader into core. --- src/main.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 28b32101d..bd40476d4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1300,13 +1300,13 @@ bool ConnectBestBlock(CValidationState &state) { } while(true); } -void CBlockHeader::UpdateTime(const CBlockIndex* pindexPrev) +void UpdateTime(CBlockHeader& block, const CBlockIndex* pindexPrev) { - nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); + block.nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); // Updating time can change work required on testnet: if (fTestNet) - nBits = GetNextWorkRequired(pindexPrev, this); + block.nBits = GetNextWorkRequired(pindexPrev, &block); } @@ -4366,7 +4366,7 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey) // Fill in header pblock->hashPrevBlock = pindexPrev->GetBlockHash(); - pblock->UpdateTime(pindexPrev); + UpdateTime(*pblock, pindexPrev); pblock->nBits = GetNextWorkRequired(pindexPrev, pblock); pblock->nNonce = 0; pblock->vtx[0].vin[0].scriptSig = CScript() << OP_0 << OP_0; @@ -4606,7 +4606,7 @@ void static BitcoinMiner(CWallet *pwallet) break; // Update nTime every few seconds - pblock->UpdateTime(pindexPrev); + UpdateTime(*pblock, pindexPrev); nBlockTime = ByteReverse(pblock->nTime); if (fTestNet) { -- cgit v1.2.3 From 501da2503a39dd88470df89ccc923c696fe6b111 Mon Sep 17 00:00:00 2001 From: Eric Lombrozo Date: Wed, 5 Jun 2013 20:21:41 -0700 Subject: Using boost::signals2 to message main from net.cpp. --- src/main.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index bd40476d4..98921e142 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -160,7 +160,22 @@ void static ResendWalletTransactions() +////////////////////////////////////////////////////////////////////////////// +// +// Registration of network node signals. +// + +void RegisterNodeSignals(CNodeSignals& nodeSignals) +{ + nodeSignals.ProcessMessages.connect(&ProcessMessages); + nodeSignals.SendMessages.connect(&SendMessages); +} +void UnregisterNodeSignals(CNodeSignals& nodeSignals) +{ + nodeSignals.ProcessMessages.disconnect(&ProcessMessages); + nodeSignals.SendMessages.disconnect(&SendMessages); +} -- cgit v1.2.3