Browse Source

Merge pull request #3592

c117d9e Support for error messages and a few more rejection reasons (Luke Dashjr)
14e7ffc Use standard BIP 22 rejection reasons where applicable (Luke Dashjr)
0.10
Wladimir J. van der Laan 11 years ago
parent
commit
19007cf552
No known key found for this signature in database
GPG Key ID: 74810B012346C9A6
  1. 86
      src/main.cpp
  2. 6
      src/main.h

86
src/main.cpp

@ -637,14 +637,14 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
// Basic checks that don't depend on any context // Basic checks that don't depend on any context
if (tx.vin.empty()) if (tx.vin.empty())
return state.DoS(10, error("CheckTransaction() : vin empty"), return state.DoS(10, error("CheckTransaction() : vin empty"),
REJECT_INVALID, "vin empty"); REJECT_INVALID, "bad-txns-vin-empty");
if (tx.vout.empty()) if (tx.vout.empty())
return state.DoS(10, error("CheckTransaction() : vout empty"), return state.DoS(10, error("CheckTransaction() : vout empty"),
REJECT_INVALID, "vout empty"); REJECT_INVALID, "bad-txns-vout-empty");
// Size limits // Size limits
if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE) if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
return state.DoS(100, error("CheckTransaction() : size limits failed"), return state.DoS(100, error("CheckTransaction() : size limits failed"),
REJECT_INVALID, "oversize"); REJECT_INVALID, "bad-txns-oversize");
// Check for negative or overflow output values // Check for negative or overflow output values
int64_t nValueOut = 0; int64_t nValueOut = 0;
@ -652,14 +652,14 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
{ {
if (txout.nValue < 0) if (txout.nValue < 0)
return state.DoS(100, error("CheckTransaction() : txout.nValue negative"), return state.DoS(100, error("CheckTransaction() : txout.nValue negative"),
REJECT_INVALID, "vout negative"); REJECT_INVALID, "bad-txns-vout-negative");
if (txout.nValue > MAX_MONEY) if (txout.nValue > MAX_MONEY)
return state.DoS(100, error("CheckTransaction() : txout.nValue too high"), return state.DoS(100, error("CheckTransaction() : txout.nValue too high"),
REJECT_INVALID, "vout too large"); REJECT_INVALID, "bad-txns-vout-toolarge");
nValueOut += txout.nValue; nValueOut += txout.nValue;
if (!MoneyRange(nValueOut)) if (!MoneyRange(nValueOut))
return state.DoS(100, error("CheckTransaction() : txout total out of range"), return state.DoS(100, error("CheckTransaction() : txout total out of range"),
REJECT_INVALID, "txout total too large"); REJECT_INVALID, "bad-txns-txouttotal-toolarge");
} }
// Check for duplicate inputs // Check for duplicate inputs
@ -668,7 +668,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
{ {
if (vInOutPoints.count(txin.prevout)) if (vInOutPoints.count(txin.prevout))
return state.DoS(100, error("CheckTransaction() : duplicate inputs"), return state.DoS(100, error("CheckTransaction() : duplicate inputs"),
REJECT_INVALID, "duplicate inputs"); REJECT_INVALID, "bad-txns-inputs-duplicate");
vInOutPoints.insert(txin.prevout); vInOutPoints.insert(txin.prevout);
} }
@ -676,14 +676,14 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
{ {
if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 100) if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 100)
return state.DoS(100, error("CheckTransaction() : coinbase script size"), return state.DoS(100, error("CheckTransaction() : coinbase script size"),
REJECT_INVALID, "coinbase script too large"); REJECT_INVALID, "bad-cb-length");
} }
else else
{ {
BOOST_FOREACH(const CTxIn& txin, tx.vin) BOOST_FOREACH(const CTxIn& txin, tx.vin)
if (txin.prevout.IsNull()) if (txin.prevout.IsNull())
return state.DoS(10, error("CheckTransaction() : prevout is null"), return state.DoS(10, error("CheckTransaction() : prevout is null"),
REJECT_INVALID, "prevout null"); REJECT_INVALID, "bad-txns-prevout-null");
} }
return true; return true;
@ -791,7 +791,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// are the actual inputs available? // are the actual inputs available?
if (!view.HaveInputs(tx)) if (!view.HaveInputs(tx))
return state.Invalid(error("AcceptToMemoryPool : inputs already spent"), return state.Invalid(error("AcceptToMemoryPool : inputs already spent"),
REJECT_DUPLICATE, "inputs spent"); REJECT_DUPLICATE, "bad-txns-inputs-spent");
// Bring the best block into scope // Bring the best block into scope
view.GetBestBlock(); view.GetBestBlock();
@ -1410,30 +1410,30 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCach
if (nSpendHeight - coins.nHeight < COINBASE_MATURITY) if (nSpendHeight - coins.nHeight < COINBASE_MATURITY)
return state.Invalid( return state.Invalid(
error("CheckInputs() : tried to spend coinbase at depth %d", nSpendHeight - coins.nHeight), error("CheckInputs() : tried to spend coinbase at depth %d", nSpendHeight - coins.nHeight),
REJECT_INVALID, "premature spend of coinbase"); REJECT_INVALID, "bad-txns-premature-spend-of-coinbase");
} }
// Check for negative or overflow input values // Check for negative or overflow input values
nValueIn += coins.vout[prevout.n].nValue; nValueIn += coins.vout[prevout.n].nValue;
if (!MoneyRange(coins.vout[prevout.n].nValue) || !MoneyRange(nValueIn)) if (!MoneyRange(coins.vout[prevout.n].nValue) || !MoneyRange(nValueIn))
return state.DoS(100, error("CheckInputs() : txin values out of range"), return state.DoS(100, error("CheckInputs() : txin values out of range"),
REJECT_INVALID, "input values out of range"); REJECT_INVALID, "bad-txns-inputvalues-outofrange");
} }
if (nValueIn < tx.GetValueOut()) if (nValueIn < tx.GetValueOut())
return state.DoS(100, error("CheckInputs() : %s value in < value out", tx.GetHash().ToString()), return state.DoS(100, error("CheckInputs() : %s value in < value out", tx.GetHash().ToString()),
REJECT_INVALID, "in < out"); REJECT_INVALID, "bad-txns-in-belowout");
// Tally transaction fees // Tally transaction fees
int64_t nTxFee = nValueIn - tx.GetValueOut(); int64_t nTxFee = nValueIn - tx.GetValueOut();
if (nTxFee < 0) if (nTxFee < 0)
return state.DoS(100, error("CheckInputs() : %s nTxFee < 0", tx.GetHash().ToString()), return state.DoS(100, error("CheckInputs() : %s nTxFee < 0", tx.GetHash().ToString()),
REJECT_INVALID, "fee < 0"); REJECT_INVALID, "bad-txns-fee-negative");
nFees += nTxFee; nFees += nTxFee;
if (!MoneyRange(nFees)) if (!MoneyRange(nFees))
return state.DoS(100, error("CheckInputs() : nFees out of range"), return state.DoS(100, error("CheckInputs() : nFees out of range"),
REJECT_INVALID, "fee out of range"); REJECT_INVALID, "bad-txns-fee-outofrange");
// The first loop above does all the inexpensive checks. // The first loop above does all the inexpensive checks.
// Only if ALL inputs pass do we perform expensive ECDSA signature checks. // Only if ALL inputs pass do we perform expensive ECDSA signature checks.
@ -1630,7 +1630,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
uint256 hash = block.GetTxHash(i); uint256 hash = block.GetTxHash(i);
if (view.HaveCoins(hash) && !view.GetCoins(hash).IsPruned()) if (view.HaveCoins(hash) && !view.GetCoins(hash).IsPruned())
return state.DoS(100, error("ConnectBlock() : tried to overwrite transaction"), return state.DoS(100, error("ConnectBlock() : tried to overwrite transaction"),
REJECT_INVALID, "BIP30"); REJECT_INVALID, "bad-txns-BIP30");
} }
} }
@ -1660,13 +1660,13 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
nSigOps += GetLegacySigOpCount(tx); nSigOps += GetLegacySigOpCount(tx);
if (nSigOps > MAX_BLOCK_SIGOPS) if (nSigOps > MAX_BLOCK_SIGOPS)
return state.DoS(100, error("ConnectBlock() : too many sigops"), return state.DoS(100, error("ConnectBlock() : too many sigops"),
REJECT_INVALID, "too many sigops"); REJECT_INVALID, "bad-blk-sigops");
if (!tx.IsCoinBase()) if (!tx.IsCoinBase())
{ {
if (!view.HaveInputs(tx)) if (!view.HaveInputs(tx))
return state.DoS(100, error("ConnectBlock() : inputs missing/spent"), return state.DoS(100, error("ConnectBlock() : inputs missing/spent"),
REJECT_INVALID, "inputs missing/spent"); REJECT_INVALID, "bad-txns-inputs-missingorspent");
if (fStrictPayToScriptHash) if (fStrictPayToScriptHash)
{ {
@ -1676,7 +1676,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
nSigOps += GetP2SHSigOpCount(tx, view); nSigOps += GetP2SHSigOpCount(tx, view);
if (nSigOps > MAX_BLOCK_SIGOPS) if (nSigOps > MAX_BLOCK_SIGOPS)
return state.DoS(100, error("ConnectBlock() : too many sigops"), return state.DoS(100, error("ConnectBlock() : too many sigops"),
REJECT_INVALID, "too many sigops"); REJECT_INVALID, "bad-blk-sigops");
} }
nFees += view.GetValueIn(tx)-tx.GetValueOut(); nFees += view.GetValueIn(tx)-tx.GetValueOut();
@ -1703,7 +1703,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
return state.DoS(100, return state.DoS(100,
error("ConnectBlock() : coinbase pays too much (actual=%"PRId64" vs limit=%"PRId64")", error("ConnectBlock() : coinbase pays too much (actual=%"PRId64" vs limit=%"PRId64")",
block.vtx[0].GetValueOut(), GetBlockValue(pindex->nHeight, nFees)), block.vtx[0].GetValueOut(), GetBlockValue(pindex->nHeight, nFees)),
REJECT_INVALID, "coinbase too large"); REJECT_INVALID, "bad-cb-amount");
if (!control.Wait()) if (!control.Wait())
return state.DoS(100, false); return state.DoS(100, false);
@ -1762,7 +1762,7 @@ bool static WriteChainState(CValidationState &state) {
// an overestimation, as most will delete an existing entry or // an overestimation, as most will delete an existing entry or
// overwrite one. Still, use a conservative safety factor of 2. // overwrite one. Still, use a conservative safety factor of 2.
if (!CheckDiskSpace(100 * 2 * 2 * pcoinsTip->GetCacheSize())) if (!CheckDiskSpace(100 * 2 * 2 * pcoinsTip->GetCacheSize()))
return state.Error(); return state.Error("out of disk space");
FlushBlockFile(); FlushBlockFile();
pblocktree->Sync(); pblocktree->Sync();
if (!pcoinsTip->Flush()) if (!pcoinsTip->Flush())
@ -1987,7 +1987,7 @@ bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos
// Check for duplicate // Check for duplicate
uint256 hash = block.GetHash(); uint256 hash = block.GetHash();
if (mapBlockIndex.count(hash)) if (mapBlockIndex.count(hash))
return state.Invalid(error("AddToBlockIndex() : %s already exists", hash.ToString())); return state.Invalid(error("AddToBlockIndex() : %s already exists", hash.ToString()), 0, "duplicate");
// Construct new block index object // Construct new block index object
CBlockIndex* pindexNew = new CBlockIndex(block); CBlockIndex* pindexNew = new CBlockIndex(block);
@ -2082,7 +2082,7 @@ bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAdd
} }
} }
else else
return state.Error(); return state.Error("out of disk space");
} }
} }
@ -2128,7 +2128,7 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne
} }
} }
else else
return state.Error(); return state.Error("out of disk space");
} }
return true; return true;
@ -2143,26 +2143,26 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
// Size limits // Size limits
if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE) if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
return state.DoS(100, error("CheckBlock() : size limits failed"), return state.DoS(100, error("CheckBlock() : size limits failed"),
REJECT_INVALID, "block size too large"); REJECT_INVALID, "bad-blk-length");
// Check proof of work matches claimed amount // Check proof of work matches claimed amount
if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits)) if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits))
return state.DoS(50, error("CheckBlock() : proof of work failed"), return state.DoS(50, error("CheckBlock() : proof of work failed"),
REJECT_INVALID, "invalid pow"); REJECT_INVALID, "high-hash");
// Check timestamp // Check timestamp
if (block.GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60) if (block.GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60)
return state.Invalid(error("CheckBlock() : block timestamp too far in the future"), return state.Invalid(error("CheckBlock() : block timestamp too far in the future"),
REJECT_INVALID, "time in future"); REJECT_INVALID, "time-too-new");
// First transaction must be coinbase, the rest must not be // First transaction must be coinbase, the rest must not be
if (block.vtx.empty() || !block.vtx[0].IsCoinBase()) if (block.vtx.empty() || !block.vtx[0].IsCoinBase())
return state.DoS(100, error("CheckBlock() : first tx is not coinbase"), return state.DoS(100, error("CheckBlock() : first tx is not coinbase"),
REJECT_INVALID, "no coinbase"); REJECT_INVALID, "bad-cb-missing");
for (unsigned int i = 1; i < block.vtx.size(); i++) for (unsigned int i = 1; i < block.vtx.size(); i++)
if (block.vtx[i].IsCoinBase()) if (block.vtx[i].IsCoinBase())
return state.DoS(100, error("CheckBlock() : more than one coinbase"), return state.DoS(100, error("CheckBlock() : more than one coinbase"),
REJECT_INVALID, "duplicate coinbase"); REJECT_INVALID, "bad-cb-multiple");
// Check transactions // Check transactions
BOOST_FOREACH(const CTransaction& tx, block.vtx) BOOST_FOREACH(const CTransaction& tx, block.vtx)
@ -2182,7 +2182,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
} }
if (uniqueTx.size() != block.vtx.size()) if (uniqueTx.size() != block.vtx.size())
return state.DoS(100, error("CheckBlock() : duplicate transaction"), return state.DoS(100, error("CheckBlock() : duplicate transaction"),
REJECT_INVALID, "duplicate transaction", true); REJECT_INVALID, "bad-txns-duplicate", true);
unsigned int nSigOps = 0; unsigned int nSigOps = 0;
BOOST_FOREACH(const CTransaction& tx, block.vtx) BOOST_FOREACH(const CTransaction& tx, block.vtx)
@ -2191,12 +2191,12 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
} }
if (nSigOps > MAX_BLOCK_SIGOPS) if (nSigOps > MAX_BLOCK_SIGOPS)
return state.DoS(100, error("CheckBlock() : out-of-bounds SigOpCount"), return state.DoS(100, error("CheckBlock() : out-of-bounds SigOpCount"),
REJECT_INVALID, "sig op count", true); REJECT_INVALID, "bad-blk-sigops", true);
// Check merkle root // Check merkle root
if (fCheckMerkleRoot && block.hashMerkleRoot != block.vMerkleTree.back()) if (fCheckMerkleRoot && block.hashMerkleRoot != block.vMerkleTree.back())
return state.DoS(100, error("CheckBlock() : hashMerkleRoot mismatch"), return state.DoS(100, error("CheckBlock() : hashMerkleRoot mismatch"),
REJECT_INVALID, "bad merkle root", true); REJECT_INVALID, "bad-txnmrklroot", true);
return true; return true;
} }
@ -2206,7 +2206,7 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp)
// Check for duplicate // Check for duplicate
uint256 hash = block.GetHash(); uint256 hash = block.GetHash();
if (mapBlockIndex.count(hash)) if (mapBlockIndex.count(hash))
return state.Invalid(error("AcceptBlock() : block already in mapBlockIndex")); return state.Invalid(error("AcceptBlock() : block already in mapBlockIndex"), 0, "duplicate");
// Get prev block index // Get prev block index
CBlockIndex* pindexPrev = NULL; CBlockIndex* pindexPrev = NULL;
@ -2214,25 +2214,25 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp)
if (hash != Params().HashGenesisBlock()) { if (hash != Params().HashGenesisBlock()) {
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(block.hashPrevBlock); map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
if (mi == mapBlockIndex.end()) if (mi == mapBlockIndex.end())
return state.DoS(10, error("AcceptBlock() : prev block not found")); return state.DoS(10, error("AcceptBlock() : prev block not found"), 0, "bad-prevblk");
pindexPrev = (*mi).second; pindexPrev = (*mi).second;
nHeight = pindexPrev->nHeight+1; nHeight = pindexPrev->nHeight+1;
// Check proof of work // Check proof of work
if (block.nBits != GetNextWorkRequired(pindexPrev, &block)) if (block.nBits != GetNextWorkRequired(pindexPrev, &block))
return state.DoS(100, error("AcceptBlock() : incorrect proof of work"), return state.DoS(100, error("AcceptBlock() : incorrect proof of work"),
REJECT_INVALID, "bad pow"); REJECT_INVALID, "bad-diffbits");
// Check timestamp against prev // Check timestamp against prev
if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast()) if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast())
return state.Invalid(error("AcceptBlock() : block's timestamp is too early"), return state.Invalid(error("AcceptBlock() : block's timestamp is too early"),
REJECT_INVALID, "timestamp too early"); REJECT_INVALID, "time-too-old");
// Check that all transactions are finalized // Check that all transactions are finalized
BOOST_FOREACH(const CTransaction& tx, block.vtx) BOOST_FOREACH(const CTransaction& tx, block.vtx)
if (!IsFinalTx(tx, nHeight, block.GetBlockTime())) if (!IsFinalTx(tx, nHeight, block.GetBlockTime()))
return state.DoS(10, error("AcceptBlock() : contains a non-final transaction"), return state.DoS(10, error("AcceptBlock() : contains a non-final transaction"),
REJECT_INVALID, "non-final tx"); REJECT_INVALID, "bad-txns-nonfinal");
// Check that the block chain matches the known block chain up to a checkpoint // Check that the block chain matches the known block chain up to a checkpoint
if (!Checkpoints::CheckBlock(nHeight, hash)) if (!Checkpoints::CheckBlock(nHeight, hash))
@ -2246,7 +2246,7 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp)
(TestNet() && CBlockIndex::IsSuperMajority(2, pindexPrev, 75, 100))) (TestNet() && CBlockIndex::IsSuperMajority(2, pindexPrev, 75, 100)))
{ {
return state.Invalid(error("AcceptBlock() : rejected nVersion=1 block"), return state.Invalid(error("AcceptBlock() : rejected nVersion=1 block"),
REJECT_OBSOLETE, "version 1 blocks obsolete"); REJECT_OBSOLETE, "bad-version");
} }
} }
// Enforce block.nVersion=2 rule that the coinbase starts with serialized block height // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height
@ -2260,7 +2260,7 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp)
if (block.vtx[0].vin[0].scriptSig.size() < expect.size() || if (block.vtx[0].vin[0].scriptSig.size() < expect.size() ||
!std::equal(expect.begin(), expect.end(), block.vtx[0].vin[0].scriptSig.begin())) !std::equal(expect.begin(), expect.end(), block.vtx[0].vin[0].scriptSig.begin()))
return state.DoS(100, error("AcceptBlock() : block height mismatch in coinbase"), return state.DoS(100, error("AcceptBlock() : block height mismatch in coinbase"),
REJECT_INVALID, "height incorrect in coinbase"); REJECT_INVALID, "bad-cb-height");
} }
} }
} }
@ -2337,9 +2337,9 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
// Check for duplicate // Check for duplicate
uint256 hash = pblock->GetHash(); uint256 hash = pblock->GetHash();
if (mapBlockIndex.count(hash)) if (mapBlockIndex.count(hash))
return state.Invalid(error("ProcessBlock() : already have block %d %s", mapBlockIndex[hash]->nHeight, hash.ToString())); return state.Invalid(error("ProcessBlock() : already have block %d %s", mapBlockIndex[hash]->nHeight, hash.ToString()), 0, "duplicate");
if (mapOrphanBlocks.count(hash)) if (mapOrphanBlocks.count(hash))
return state.Invalid(error("ProcessBlock() : already have block (orphan) %s", hash.ToString())); return state.Invalid(error("ProcessBlock() : already have block (orphan) %s", hash.ToString()), 0, "duplicate");
// Preliminary checks // Preliminary checks
if (!CheckBlock(*pblock, state)) { if (!CheckBlock(*pblock, state)) {
@ -2356,7 +2356,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
if (deltaTime < 0) if (deltaTime < 0)
{ {
return state.DoS(100, error("ProcessBlock() : block with timestamp before last checkpoint"), return state.DoS(100, error("ProcessBlock() : block with timestamp before last checkpoint"),
REJECT_CHECKPOINT, "timestamp before checkpoint"); REJECT_CHECKPOINT, "time-too-old");
} }
CBigNum bnNewBlock; CBigNum bnNewBlock;
bnNewBlock.SetCompact(pblock->nBits); bnNewBlock.SetCompact(pblock->nBits);
@ -2365,7 +2365,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
if (bnNewBlock > bnRequired) if (bnNewBlock > bnRequired)
{ {
return state.DoS(100, error("ProcessBlock() : block with too little proof-of-work"), return state.DoS(100, error("ProcessBlock() : block with too little proof-of-work"),
REJECT_INVALID, "invalid pow"); REJECT_INVALID, "bad-diffbits");
} }
} }

6
src/main.h

@ -952,13 +952,15 @@ public:
unsigned char _chRejectCode=0, std::string _strRejectReason="") { unsigned char _chRejectCode=0, std::string _strRejectReason="") {
return DoS(0, ret, _chRejectCode, _strRejectReason); return DoS(0, ret, _chRejectCode, _strRejectReason);
} }
bool Error() { bool Error(std::string strRejectReasonIn="") {
if (mode == MODE_VALID)
strRejectReason = strRejectReasonIn;
mode = MODE_ERROR; mode = MODE_ERROR;
return false; return false;
} }
bool Abort(const std::string &msg) { bool Abort(const std::string &msg) {
AbortNode(msg); AbortNode(msg);
return Error(); return Error(msg);
} }
bool IsValid() const { bool IsValid() const {
return mode == MODE_VALID; return mode == MODE_VALID;

Loading…
Cancel
Save