Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 721 Lines • ▼ Show 20 Lines | for (const CTxIn &txin : tx.vin) { | ||||
PrecomputedTransactionData txdata(tx); | PrecomputedTransactionData txdata(tx); | ||||
int nSigChecksStandard; | int nSigChecksStandard; | ||||
if (!CheckInputs(tx, state, view, true, scriptVerifyFlags, true, false, | if (!CheckInputs(tx, state, view, true, scriptVerifyFlags, true, false, | ||||
txdata, nSigChecksStandard)) { | txdata, nSigChecksStandard)) { | ||||
// State filled in by CheckInputs. | // State filled in by CheckInputs. | ||||
return false; | return false; | ||||
} | } | ||||
// After the sigchecks activation we repurpose the 'sigops' tracking in | |||||
// mempool/mining to actually track sigchecks instead. (Proper SigOps | |||||
// will not need to be counted any more since it's getting deactivated.) | |||||
auto nSigChecksOrOps = | |||||
(nextBlockScriptVerifyFlags & SCRIPT_REPORT_SIGCHECKS) | |||||
? nSigChecksStandard | |||||
: nSigOpsCount; | |||||
CTxMemPoolEntry entry(ptx, nFees, nAcceptTime, chainActive.Height(), | CTxMemPoolEntry entry(ptx, nFees, nAcceptTime, chainActive.Height(), | ||||
fSpendsCoinbase, nSigOpsCount, lp); | fSpendsCoinbase, nSigChecksOrOps, lp); | ||||
unsigned int nVirtualSize = entry.GetTxVirtualSize(); | unsigned int nVirtualSize = entry.GetTxVirtualSize(); | ||||
Amount mempoolRejectFee = | Amount mempoolRejectFee = | ||||
pool.GetMinFee( | pool.GetMinFee( | ||||
gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * | gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * | ||||
1000000) | 1000000) | ||||
.GetFee(nVirtualSize); | .GetFee(nVirtualSize); | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | for (const CTxIn &txin : tx.vin) { | ||||
// This can occur under some circumstances, if the node receives an | // This can occur under some circumstances, if the node receives an | ||||
// unrequested tx which is invalid due to new consensus rules not | // unrequested tx which is invalid due to new consensus rules not | ||||
// being activated yet (during IBD). | // being activated yet (during IBD). | ||||
return error("%s: BUG! PLEASE REPORT THIS! CheckInputs failed " | return error("%s: BUG! PLEASE REPORT THIS! CheckInputs failed " | ||||
"against next-block but not STANDARD flags %s, %s", | "against next-block but not STANDARD flags %s, %s", | ||||
__func__, txid.ToString(), FormatStateMessage(state)); | __func__, txid.ToString(), FormatStateMessage(state)); | ||||
} | } | ||||
if (nSigChecksStandard != nSigChecksConsensus) { | |||||
// We can't accept this transaction as we've used the standard count | |||||
// for the mempool/mining, but the consensus count will be enforced | |||||
// in validation (we don't want to produce bad block templates). | |||||
return error( | |||||
"%s: BUG! PLEASE REPORT THIS! SigChecks count differed between " | |||||
"standard and consensus flags in %s", | |||||
__func__, txid.ToString()); | |||||
} | |||||
if (test_accept) { | if (test_accept) { | ||||
// Tx was accepted, but not added | // Tx was accepted, but not added | ||||
return true; | return true; | ||||
} | } | ||||
// Store transaction in memory. | // Store transaction in memory. | ||||
pool.addUnchecked(entry, setAncestors); | pool.addUnchecked(entry, setAncestors); | ||||
▲ Show 20 Lines • Show All 873 Lines • ▼ Show 20 Lines | static uint32_t GetNextBlockScriptFlags(const Consensus::Params ¶ms, | ||||
if (IsGravitonEnabled(params, pindex)) { | if (IsGravitonEnabled(params, pindex)) { | ||||
flags |= SCRIPT_ENABLE_SCHNORR_MULTISIG; | flags |= SCRIPT_ENABLE_SCHNORR_MULTISIG; | ||||
flags |= SCRIPT_VERIFY_MINIMALDATA; | flags |= SCRIPT_VERIFY_MINIMALDATA; | ||||
} | } | ||||
if (IsPhononEnabled(params, pindex)) { | if (IsPhononEnabled(params, pindex)) { | ||||
flags |= SCRIPT_ENABLE_OP_REVERSEBYTES; | flags |= SCRIPT_ENABLE_OP_REVERSEBYTES; | ||||
flags |= SCRIPT_REPORT_SIGCHECKS; | |||||
flags |= SCRIPT_ZERO_SIGOPS; | flags |= SCRIPT_ZERO_SIGOPS; | ||||
} | } | ||||
// We make sure this node will have replay protection during the next hard | // We make sure this node will have replay protection during the next hard | ||||
// fork. | // fork. | ||||
if (IsReplayProtectionEnabled(params, pindex)) { | if (IsReplayProtectionEnabled(params, pindex)) { | ||||
flags |= SCRIPT_ENABLE_REPLAY_PROTECTION; | flags |= SCRIPT_ENABLE_REPLAY_PROTECTION; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 191 Lines • ▼ Show 20 Lines | bool CChainState::ConnectBlock(const CBlock &block, CValidationState &state, | ||||
int nInputs = 0; | int nInputs = 0; | ||||
// Sigops counting. We need to do it again because of P2SH. | // Sigops counting. We need to do it again because of P2SH. | ||||
uint64_t nSigOpsCount = 0; | uint64_t nSigOpsCount = 0; | ||||
const uint64_t currentBlockSize = | const uint64_t currentBlockSize = | ||||
::GetSerializeSize(block, PROTOCOL_VERSION); | ::GetSerializeSize(block, PROTOCOL_VERSION); | ||||
const uint64_t nMaxSigOpsCount = GetMaxBlockSigOpsCount(currentBlockSize); | const uint64_t nMaxSigOpsCount = GetMaxBlockSigOpsCount(currentBlockSize); | ||||
// Limit the total executed signature operations in the block, a consensus | |||||
// rule. Tracking during the CPU-consuming part (validation of uncached | |||||
// inputs) is per-input atomic and validation in each thread stops very | |||||
// quickly after the limit is exceeded, so an adversary cannot cause us to | |||||
// exceed the limit by much at all. | |||||
CheckInputsLimiter nSigChecksBlockLimiter( | |||||
GetMaxBlockSigChecksCount(options.getExcessiveBlockSize())); | |||||
blockundo.vtxundo.reserve(block.vtx.size() - 1); | blockundo.vtxundo.reserve(block.vtx.size() - 1); | ||||
// Add all outputs | // Add all outputs | ||||
try { | try { | ||||
for (const auto &ptx : block.vtx) { | for (const auto &ptx : block.vtx) { | ||||
AddCoins(view, *ptx, pindex->nHeight); | AddCoins(view, *ptx, pindex->nHeight); | ||||
} | } | ||||
} catch (const std::logic_error &e) { | } catch (const std::logic_error &e) { | ||||
▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | for (const auto &ptx : block.vtx) { | ||||
bool fCacheResults = fJustCheck; | bool fCacheResults = fJustCheck; | ||||
std::vector<CScriptCheck> vChecks; | std::vector<CScriptCheck> vChecks; | ||||
// nSigChecksRet may be accurate (found in cache) or 0 (checks were | // nSigChecksRet may be accurate (found in cache) or 0 (checks were | ||||
// deferred into vChecks). | // deferred into vChecks). | ||||
int nSigChecksRet; | int nSigChecksRet; | ||||
if (!CheckInputs(tx, state, view, fScriptChecks, flags, fCacheResults, | if (!CheckInputs(tx, state, view, fScriptChecks, flags, fCacheResults, | ||||
fCacheResults, PrecomputedTransactionData(tx), | fCacheResults, PrecomputedTransactionData(tx), | ||||
nSigChecksRet, &vChecks)) { | nSigChecksRet, &vChecks, &nSigChecksBlockLimiter)) { | ||||
// Parallel CheckInputs shouldn't fail except for this reason, which | |||||
// is banworthy. Use "blk-bad-inputs" to mimic the parallel script | |||||
// check error. | |||||
if (!nSigChecksBlockLimiter.check()) { | |||||
return state.DoS(100, false, REJECT_INVALID, "blk-bad-inputs", | |||||
false, "CheckInputs exceeded SigChecks limit"); | |||||
} | |||||
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); | ||||
blockundo.vtxundo.push_back(CTxUndo()); | blockundo.vtxundo.push_back(CTxUndo()); | ||||
// Note: this must execute in the same iteration as CheckTxInputs (not | // Note: this must execute in the same iteration as CheckTxInputs (not | ||||
▲ Show 20 Lines • Show All 3,838 Lines • Show Last 20 Lines |