Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 1,266 Lines • ▼ Show 20 Lines | void UpdateCoins(const CTransaction &tx, CCoinsViewCache &inputs, int nHeight) { | ||||
CTxUndo txundo; | CTxUndo txundo; | ||||
UpdateCoins(tx, inputs, txundo, nHeight); | UpdateCoins(tx, inputs, txundo, nHeight); | ||||
} | } | ||||
bool CScriptCheck::operator()() { | bool CScriptCheck::operator()() { | ||||
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig; | const CScript &scriptSig = ptxTo->vin[nIn].scriptSig; | ||||
if (!VerifyScript(scriptSig, scriptPubKey, nFlags, | if (!VerifyScript(scriptSig, scriptPubKey, nFlags, | ||||
CachingTransactionSignatureChecker(ptxTo, nIn, amount, | CachingTransactionSignatureChecker(ptxTo, nIn, amount, | ||||
cacheStore, *txdata), | cacheStore, txdata), | ||||
&error)) { | &error)) { | ||||
return false; | return false; | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
int GetSpendHeight(const CCoinsViewCache &inputs) { | int GetSpendHeight(const CCoinsViewCache &inputs) { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | if (!MoneyRange(nFees)) | ||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-fee-outofrange"); | return state.DoS(100, false, REJECT_INVALID, "bad-txns-fee-outofrange"); | ||||
return true; | return true; | ||||
} | } | ||||
} // namespace Consensus | } // namespace Consensus | ||||
bool CheckInputs(const CTransaction &tx, CValidationState &state, | bool CheckInputs(const CTransaction &tx, CValidationState &state, | ||||
const CCoinsViewCache &inputs, bool fScriptChecks, | const CCoinsViewCache &inputs, bool fScriptChecks, | ||||
unsigned int flags, bool cacheStore, | unsigned int flags, bool cacheStore, | ||||
PrecomputedTransactionData &txdata, | const PrecomputedTransactionData &txdata, | ||||
std::vector<CScriptCheck> *pvChecks) { | std::vector<CScriptCheck> *pvChecks) { | ||||
assert(!tx.IsCoinBase()); | assert(!tx.IsCoinBase()); | ||||
if (!Consensus::CheckTxInputs(tx, state, inputs, GetSpendHeight(inputs))) { | if (!Consensus::CheckTxInputs(tx, state, inputs, GetSpendHeight(inputs))) { | ||||
return false; | return false; | ||||
} | } | ||||
if (pvChecks) { | if (pvChecks) { | ||||
Show All 14 Lines | bool CheckInputs(const CTransaction &tx, CValidationState &state, | ||||
} | } | ||||
for (unsigned int i = 0; i < tx.vin.size(); i++) { | for (unsigned int i = 0; i < tx.vin.size(); i++) { | ||||
const COutPoint &prevout = tx.vin[i].prevout; | const COutPoint &prevout = tx.vin[i].prevout; | ||||
const CCoins *coins = inputs.AccessCoins(prevout.hash); | const CCoins *coins = inputs.AccessCoins(prevout.hash); | ||||
assert(coins); | assert(coins); | ||||
// Verify signature | // Verify signature | ||||
CScriptCheck check(*coins, tx, i, flags, cacheStore, &txdata); | CScriptCheck check(*coins, tx, i, flags, cacheStore, txdata); | ||||
if (pvChecks) { | if (pvChecks) { | ||||
pvChecks->push_back(CScriptCheck()); | pvChecks->push_back(std::move(check)); | ||||
check.swap(pvChecks->back()); | |||||
} else if (!check()) { | } else if (!check()) { | ||||
if (flags & STANDARD_NOT_MANDATORY_VERIFY_FLAGS) { | if (flags & STANDARD_NOT_MANDATORY_VERIFY_FLAGS) { | ||||
// Check whether the failure was caused by a non-mandatory | // Check whether the failure was caused by a non-mandatory | ||||
// script verification check, such as non-standard DER encodings | // script verification check, such as non-standard DER encodings | ||||
// or non-null dummy arguments; if so, don't trigger DoS | // or non-null dummy arguments; if so, don't trigger DoS | ||||
// protection to avoid splitting the network between upgraded | // protection to avoid splitting the network between upgraded | ||||
// and non-upgraded nodes. | // and non-upgraded nodes. | ||||
CScriptCheck check2( | CScriptCheck check2( | ||||
*coins, tx, i, flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, | *coins, tx, i, flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, | ||||
cacheStore, &txdata); | cacheStore, txdata); | ||||
if (check2()) { | if (check2()) { | ||||
return state.Invalid( | return state.Invalid( | ||||
false, REJECT_NONSTANDARD, | false, REJECT_NONSTANDARD, | ||||
strprintf("non-mandatory-script-verify-flag (%s)", | strprintf("non-mandatory-script-verify-flag (%s)", | ||||
ScriptErrorString(check.GetScriptError()))); | ScriptErrorString(check.GetScriptError()))); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 470 Lines • ▼ Show 20 Lines | const uint64_t currentBlockSize = | ||||
::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION); | ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION); | ||||
const uint64_t nMaxSigOpsCount = GetMaxBlockSigOpsCount(currentBlockSize); | const uint64_t nMaxSigOpsCount = GetMaxBlockSigOpsCount(currentBlockSize); | ||||
CDiskTxPos pos(pindex->GetBlockPos(), | CDiskTxPos pos(pindex->GetBlockPos(), | ||||
GetSizeOfCompactSize(block.vtx.size())); | GetSizeOfCompactSize(block.vtx.size())); | ||||
std::vector<std::pair<uint256, CDiskTxPos>> vPos; | std::vector<std::pair<uint256, CDiskTxPos>> vPos; | ||||
vPos.reserve(block.vtx.size()); | vPos.reserve(block.vtx.size()); | ||||
blockundo.vtxundo.reserve(block.vtx.size() - 1); | blockundo.vtxundo.reserve(block.vtx.size() - 1); | ||||
std::vector<PrecomputedTransactionData> txdata; | |||||
// Required so that pointers to individual PrecomputedTransactionData don't | |||||
// get invalidated. | |||||
txdata.reserve(block.vtx.size()); | |||||
for (unsigned int i = 0; i < block.vtx.size(); i++) { | for (unsigned int i = 0; i < block.vtx.size(); i++) { | ||||
const CTransaction &tx = *(block.vtx[i]); | const CTransaction &tx = *(block.vtx[i]); | ||||
nInputs += tx.vin.size(); | nInputs += tx.vin.size(); | ||||
if (!tx.IsCoinBase()) { | if (!tx.IsCoinBase()) { | ||||
if (!view.HaveInputs(tx)) | if (!view.HaveInputs(tx)) | ||||
Show All 27 Lines | for (unsigned int i = 0; i < block.vtx.size(); i++) { | ||||
} | } | ||||
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"); | ||||
} | } | ||||
txdata.emplace_back(tx); | |||||
if (!tx.IsCoinBase()) { | if (!tx.IsCoinBase()) { | ||||
nFees += view.GetValueIn(tx) - tx.GetValueOut(); | nFees += view.GetValueIn(tx) - tx.GetValueOut(); | ||||
// 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, | if (!CheckInputs(tx, state, view, fScriptChecks, flags, | ||||
fCacheResults, txdata[i], | fCacheResults, PrecomputedTransactionData(tx), | ||||
nScriptCheckThreads ? &vChecks : nullptr)) { | nScriptCheckThreads ? &vChecks : nullptr)) { | ||||
return error("ConnectBlock(): CheckInputs on %s failed with %s", | return error("ConnectBlock(): CheckInputs on %s failed with %s", | ||||
tx.GetId().ToString(), FormatStateMessage(state)); | tx.GetId().ToString(), FormatStateMessage(state)); | ||||
} | } | ||||
control.Add(vChecks); | control.Add(vChecks); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 495 Lines • ▼ Show 20 Lines | static bool ConnectTip(const Config &config, CValidationState &state, | ||||
LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", | LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", | ||||
(nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001); | (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001); | ||||
LogPrint("bench", "- Connect block: %.2fms [%.2fs]\n", | LogPrint("bench", "- Connect block: %.2fms [%.2fs]\n", | ||||
(nTime6 - nTime1) * 0.001, nTimeTotal * 0.000001); | (nTime6 - nTime1) * 0.001, nTimeTotal * 0.000001); | ||||
return true; | return true; | ||||
} | } | ||||
/** | /** | ||||
* Return the tip of the chain with the most work in it, that isn't | * Return the tip of the chain with the most work in it, that isn't known to be | ||||
* known to be invalid (it's however far from certain to be valid). | * invalid (it's however far from certain to be valid). | ||||
*/ | */ | ||||
static CBlockIndex *FindMostWorkChain() { | static CBlockIndex *FindMostWorkChain() { | ||||
do { | do { | ||||
CBlockIndex *pindexNew = NULL; | CBlockIndex *pindexNew = NULL; | ||||
// Find the best candidate header. | // Find the best candidate header. | ||||
{ | { | ||||
std::set<CBlockIndex *, CBlockIndexWorkComparator>::reverse_iterator | std::set<CBlockIndex *, CBlockIndexWorkComparator>::reverse_iterator | ||||
▲ Show 20 Lines • Show All 2,350 Lines • Show Last 20 Lines |