Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 517 Lines • ▼ Show 20 Lines | for (const CTxIn &txin : tx.vin) { | ||||
"txn-mempool-conflict"); | "txn-mempool-conflict"); | ||||
} | } | ||||
} | } | ||||
{ | { | ||||
CCoinsView dummy; | CCoinsView dummy; | ||||
CCoinsViewCache view(&dummy); | CCoinsViewCache view(&dummy); | ||||
Amount nValueIn = Amount::zero(); | |||||
LockPoints lp; | LockPoints lp; | ||||
CCoinsViewMemPool viewMemPool(pcoinsTip.get(), pool); | CCoinsViewMemPool viewMemPool(pcoinsTip.get(), pool); | ||||
view.SetBackend(viewMemPool); | view.SetBackend(viewMemPool); | ||||
// Do all inputs exist? | // Do all inputs exist? | ||||
for (const CTxIn txin : tx.vin) { | for (const CTxIn txin : tx.vin) { | ||||
if (!pcoinsTip->HaveCoinInCache(txin.prevout)) { | if (!pcoinsTip->HaveCoinInCache(txin.prevout)) { | ||||
coins_to_uncache.push_back(txin.prevout); | coins_to_uncache.push_back(txin.prevout); | ||||
Show All 26 Lines | for (const CTxIn &txin : tx.vin) { | ||||
if (!view.HaveInputs(tx)) { | if (!view.HaveInputs(tx)) { | ||||
return state.Invalid(false, REJECT_DUPLICATE, | return state.Invalid(false, REJECT_DUPLICATE, | ||||
"bad-txns-inputs-spent"); | "bad-txns-inputs-spent"); | ||||
} | } | ||||
// Bring the best block into scope. | // Bring the best block into scope. | ||||
view.GetBestBlock(); | view.GetBestBlock(); | ||||
nValueIn = view.GetValueIn(tx); | |||||
// We have all inputs cached now, so switch back to dummy, so we don't | // We have all inputs cached now, so switch back to dummy, so we don't | ||||
// need to keep lock on mempool. | // need to keep lock on mempool. | ||||
view.SetBackend(dummy); | view.SetBackend(dummy); | ||||
// Only accept BIP68 sequence locked transactions that can be mined in | // Only accept BIP68 sequence locked transactions that can be mined in | ||||
// the next block; we don't want our mempool filled up with transactions | // the next block; we don't want our mempool filled up with transactions | ||||
// that can't be mined yet. Must keep pool.cs for this unless we change | // that can't be mined yet. Must keep pool.cs for this unless we change | ||||
// CheckSequenceLocks to take a CoinsViewCache instead of create its | // CheckSequenceLocks to take a CoinsViewCache instead of create its | ||||
// own. | // own. | ||||
if (!CheckSequenceLocks(tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp)) { | if (!CheckSequenceLocks(tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp)) { | ||||
return state.DoS(0, false, REJECT_NONSTANDARD, "non-BIP68-final"); | return state.DoS(0, false, REJECT_NONSTANDARD, "non-BIP68-final"); | ||||
} | } | ||||
Amount nFees = Amount::zero(); | |||||
if (!Consensus::CheckTxInputs(tx, state, view, GetSpendHeight(view), | |||||
nFees)) { | |||||
return error("%s: Consensus::CheckTxInputs: %s, %s", __func__, | |||||
tx.GetId().ToString(), FormatStateMessage(state)); | |||||
} | |||||
// Check for non-standard pay-to-script-hash in inputs | // Check for non-standard pay-to-script-hash in inputs | ||||
if (fRequireStandard && !AreInputsStandard(tx, view)) { | if (fRequireStandard && !AreInputsStandard(tx, view)) { | ||||
return state.Invalid(false, REJECT_NONSTANDARD, | return state.Invalid(false, REJECT_NONSTANDARD, | ||||
"bad-txns-nonstandard-inputs"); | "bad-txns-nonstandard-inputs"); | ||||
} | } | ||||
int64_t nSigOpsCount = | int64_t nSigOpsCount = | ||||
GetTransactionSigOpCount(tx, view, STANDARD_SCRIPT_VERIFY_FLAGS); | GetTransactionSigOpCount(tx, view, STANDARD_SCRIPT_VERIFY_FLAGS); | ||||
Amount nValueOut = tx.GetValueOut(); | |||||
Amount nFees = nValueIn - nValueOut; | |||||
// nModifiedFees includes any fee deltas from PrioritiseTransaction | // nModifiedFees includes any fee deltas from PrioritiseTransaction | ||||
Amount nModifiedFees = nFees; | Amount nModifiedFees = nFees; | ||||
double nPriorityDummy = 0; | double nPriorityDummy = 0; | ||||
pool.ApplyDeltas(txid, nPriorityDummy, nModifiedFees); | pool.ApplyDeltas(txid, nPriorityDummy, nModifiedFees); | ||||
Amount inChainInputValue; | Amount inChainInputValue; | ||||
double dPriority = | double dPriority = | ||||
view.GetPriority(tx, chainActive.Height(), inChainInputValue); | view.GetPriority(tx, chainActive.Height(), inChainInputValue); | ||||
▲ Show 20 Lines • Show All 570 Lines • ▼ Show 20 Lines | |||||
bool CheckInputs(const CTransaction &tx, CValidationState &state, | bool CheckInputs(const CTransaction &tx, CValidationState &state, | ||||
const CCoinsViewCache &inputs, bool fScriptChecks, | const CCoinsViewCache &inputs, bool fScriptChecks, | ||||
const uint32_t flags, bool sigCacheStore, | const uint32_t flags, bool sigCacheStore, | ||||
bool scriptCacheStore, | bool scriptCacheStore, | ||||
const PrecomputedTransactionData &txdata, | const PrecomputedTransactionData &txdata, | ||||
std::vector<CScriptCheck> *pvChecks) { | std::vector<CScriptCheck> *pvChecks) { | ||||
assert(!tx.IsCoinBase()); | assert(!tx.IsCoinBase()); | ||||
// This call does all the inexpensive checks on all the inputs. Only if ALL | |||||
// inputs pass do we perform expensive ECDSA signature checks. Helps prevent | |||||
// CPU exhaustion attacks. | |||||
if (!Consensus::CheckTxInputs(tx, state, inputs, GetSpendHeight(inputs))) { | |||||
return false; | |||||
} | |||||
if (pvChecks) { | if (pvChecks) { | ||||
pvChecks->reserve(tx.vin.size()); | pvChecks->reserve(tx.vin.size()); | ||||
} | } | ||||
// Skip script verification when connecting blocks under the assumevalid | // Skip script verification when connecting blocks under the assumevalid | ||||
// block. Assuming the assumevalid block is valid this is safe because | // block. Assuming the assumevalid block is valid this is safe because | ||||
// block merkle hashes are still computed and checked, of course, if an | // block merkle hashes are still computed and checked, of course, if an | ||||
// assumed valid block is invalid due to false scriptSigs this optimization | // assumed valid block is invalid due to false scriptSigs this optimization | ||||
▲ Show 20 Lines • Show All 622 Lines • ▼ Show 20 Lines | bool CChainState::ConnectBlock(const Config &config, const CBlock &block, | ||||
} | } | ||||
for (const auto &ptx : block.vtx) { | for (const auto &ptx : block.vtx) { | ||||
const CTransaction &tx = *ptx; | const CTransaction &tx = *ptx; | ||||
if (tx.IsCoinBase()) { | if (tx.IsCoinBase()) { | ||||
continue; | continue; | ||||
} | } | ||||
if (!view.HaveInputs(tx)) { | Amount txfee = Amount::zero(); | ||||
return state.DoS(100, error("ConnectBlock(): inputs missing/spent"), | if (!Consensus::CheckTxInputs(tx, state, view, pindex->nHeight, | ||||
REJECT_INVALID, "bad-txns-inputs-missingorspent"); | txfee)) { | ||||
return error("%s: Consensus::CheckTxInputs: %s, %s", __func__, | |||||
tx.GetId().ToString(), FormatStateMessage(state)); | |||||
} | |||||
nFees += txfee; | |||||
if (!MoneyRange(nFees)) { | |||||
return state.DoS( | |||||
100, | |||||
error("%s: accumulated fee in the block out of range.", | |||||
__func__), | |||||
REJECT_INVALID, "bad-txns-accumulated-fee-outofrange"); | |||||
} | } | ||||
// Check that transaction is BIP68 final BIP68 lock checks (as | // Check that transaction is BIP68 final BIP68 lock checks (as | ||||
// opposed to nLockTime checks) must be in ConnectBlock because they | // opposed to nLockTime checks) must be in ConnectBlock because they | ||||
// require the UTXO set. | // require the UTXO set. | ||||
prevheights.resize(tx.vin.size()); | prevheights.resize(tx.vin.size()); | ||||
for (size_t j = 0; j < tx.vin.size(); j++) { | for (size_t j = 0; j < tx.vin.size(); j++) { | ||||
prevheights[j] = view.AccessCoin(tx.vin[j].prevout).GetHeight(); | prevheights[j] = view.AccessCoin(tx.vin[j].prevout).GetHeight(); | ||||
Show All 15 Lines | for (const auto &ptx : block.vtx) { | ||||
} | } | ||||
nSigOpsCount += txSigOpsCount; | nSigOpsCount += txSigOpsCount; | ||||
if (nSigOpsCount > nMaxSigOpsCount) { | if (nSigOpsCount > nMaxSigOpsCount) { | ||||
return state.DoS(100, error("ConnectBlock(): too many sigops"), | return state.DoS(100, error("ConnectBlock(): too many sigops"), | ||||
REJECT_INVALID, "bad-blk-sigops"); | REJECT_INVALID, "bad-blk-sigops"); | ||||
} | } | ||||
Amount fee = view.GetValueIn(tx) - tx.GetValueOut(); | |||||
nFees += fee; | |||||
// Don't cache results if we're actually connecting blocks (still | // Don't cache results if we're actually connecting blocks (still | ||||
// consult the cache, though). | // consult the cache, though). | ||||
bool fCacheResults = fJustCheck; | bool fCacheResults = fJustCheck; | ||||
std::vector<CScriptCheck> vChecks; | std::vector<CScriptCheck> vChecks; | ||||
if (!CheckInputs(tx, state, view, fScriptChecks, flags, fCacheResults, | if (!CheckInputs(tx, state, view, fScriptChecks, flags, fCacheResults, | ||||
fCacheResults, PrecomputedTransactionData(tx), | fCacheResults, PrecomputedTransactionData(tx), | ||||
&vChecks)) { | &vChecks)) { | ||||
▲ Show 20 Lines • Show All 3,754 Lines • Show Last 20 Lines |