df6d458b85
* Remove orphan state wipe from UnloadBlockIndex. As orphan state is now "network state", like in d6ea737be19a0001e69e4e854eb1cef21523ea7a, UnloadBlockIndex is only used during init if we end up reindexing to clear our block state so that we can start over. However, at that time no connections have been brought up as CConnman hasn't been started yet, so all of the network processing state logic is empty when its called. * Move network-msg-processing code out of main to its own file * Rename the remaining main.{h,cpp} to validation.{h,cpp}
156 lines
5.3 KiB
C++
156 lines
5.3 KiB
C++
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|
// Copyright (c) 2009-2015 The Bitcoin developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
// NOTE: This file is intended to be customised by the end user, and includes only local node policy logic
|
|
|
|
#include "policy/policy.h"
|
|
|
|
#include "validation.h"
|
|
#include "tinyformat.h"
|
|
#include "util.h"
|
|
#include "utilstrencodings.h"
|
|
|
|
#include <boost/foreach.hpp>
|
|
|
|
/**
|
|
* Check transaction inputs to mitigate two
|
|
* potential denial-of-service attacks:
|
|
*
|
|
* 1. scriptSigs with extra data stuffed into them,
|
|
* not consumed by scriptPubKey (or P2SH script)
|
|
* 2. P2SH scripts with a crazy number of expensive
|
|
* CHECKSIG/CHECKMULTISIG operations
|
|
*
|
|
* Check transaction inputs, and make sure any
|
|
* pay-to-script-hash transactions are evaluating IsStandard scripts
|
|
*
|
|
* Why bother? To avoid denial-of-service attacks; an attacker
|
|
* can submit a standard HASH... OP_EQUAL transaction,
|
|
* which will get accepted into blocks. The redemption
|
|
* script can be anything; an attacker could use a very
|
|
* expensive-to-check-upon-redemption script like:
|
|
* DUP CHECKSIG DROP ... repeated 100 times... OP_1
|
|
*/
|
|
|
|
bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
|
|
{
|
|
std::vector<std::vector<unsigned char> > vSolutions;
|
|
if (!Solver(scriptPubKey, whichType, vSolutions))
|
|
return false;
|
|
|
|
if (whichType == TX_MULTISIG)
|
|
{
|
|
unsigned char m = vSolutions.front()[0];
|
|
unsigned char n = vSolutions.back()[0];
|
|
// Support up to x-of-3 multisig txns as standard
|
|
if (n < 1 || n > 3)
|
|
return false;
|
|
if (m < 1 || m > n)
|
|
return false;
|
|
} else if (whichType == TX_NULL_DATA &&
|
|
(!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes))
|
|
return false;
|
|
|
|
return whichType != TX_NONSTANDARD;
|
|
}
|
|
|
|
bool IsStandardTx(const CTransaction& tx, std::string& reason)
|
|
{
|
|
if (tx.nVersion > CTransaction::MAX_STANDARD_VERSION || tx.nVersion < 1) {
|
|
reason = "version";
|
|
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 = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION);
|
|
if (sz >= MAX_STANDARD_TX_SIZE) {
|
|
reason = "tx-size";
|
|
return false;
|
|
}
|
|
|
|
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
|
{
|
|
// Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed
|
|
// keys. (remember the 520 byte limit on redeemScript size) That works
|
|
// out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)+3=1627
|
|
// bytes of scriptSig, which we round off to 1650 bytes for some minor
|
|
// future-proofing. That's also enough to spend a 20-of-20
|
|
// CHECKMULTISIG scriptPubKey, though such a scriptPubKey is not
|
|
// considered standard)
|
|
if (txin.scriptSig.size() > 1650) {
|
|
reason = "scriptsig-size";
|
|
return false;
|
|
}
|
|
if (!txin.scriptSig.IsPushOnly()) {
|
|
reason = "scriptsig-not-pushonly";
|
|
return false;
|
|
}
|
|
}
|
|
|
|
unsigned int nDataOut = 0;
|
|
txnouttype whichType;
|
|
BOOST_FOREACH(const CTxOut& txout, tx.vout) {
|
|
if (!::IsStandard(txout.scriptPubKey, whichType)) {
|
|
reason = "scriptpubkey";
|
|
return false;
|
|
}
|
|
|
|
if (whichType == TX_NULL_DATA)
|
|
nDataOut++;
|
|
else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) {
|
|
reason = "bare-multisig";
|
|
return false;
|
|
} else if (txout.IsDust(::minRelayTxFee)) {
|
|
reason = "dust";
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// only one OP_RETURN txout is permitted
|
|
if (nDataOut > 1) {
|
|
reason = "multi-op-return";
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
|
|
{
|
|
if (tx.IsCoinBase())
|
|
return true; // Coinbases don't use vin normally
|
|
|
|
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
|
{
|
|
const CTxOut& prev = mapInputs.GetOutputFor(tx.vin[i]);
|
|
|
|
std::vector<std::vector<unsigned char> > vSolutions;
|
|
txnouttype whichType;
|
|
// get the scriptPubKey corresponding to this input:
|
|
const CScript& prevScript = prev.scriptPubKey;
|
|
if (!Solver(prevScript, whichType, vSolutions))
|
|
return false;
|
|
|
|
if (whichType == TX_SCRIPTHASH)
|
|
{
|
|
std::vector<std::vector<unsigned char> > stack;
|
|
// convert the scriptSig into a stack, so we can inspect the redeemScript
|
|
if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), 0))
|
|
return false;
|
|
if (stack.empty())
|
|
return false;
|
|
CScript subscript(stack.back().begin(), stack.back().end());
|
|
if (subscript.GetSigOpCount(true) > MAX_P2SH_SIGOPS) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|