Skip to content

Commit 19007cf

Browse files
committed
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)
2 parents 2df5e34 + c117d9e commit 19007cf

File tree

2 files changed

+47
-45
lines changed

2 files changed

+47
-45
lines changed

src/main.cpp

Lines changed: 43 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -637,29 +637,29 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
637637
// Basic checks that don't depend on any context
638638
if (tx.vin.empty())
639639
return state.DoS(10, error("CheckTransaction() : vin empty"),
640-
REJECT_INVALID, "vin empty");
640+
REJECT_INVALID, "bad-txns-vin-empty");
641641
if (tx.vout.empty())
642642
return state.DoS(10, error("CheckTransaction() : vout empty"),
643-
REJECT_INVALID, "vout empty");
643+
REJECT_INVALID, "bad-txns-vout-empty");
644644
// Size limits
645645
if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
646646
return state.DoS(100, error("CheckTransaction() : size limits failed"),
647-
REJECT_INVALID, "oversize");
647+
REJECT_INVALID, "bad-txns-oversize");
648648

649649
// Check for negative or overflow output values
650650
int64_t nValueOut = 0;
651651
BOOST_FOREACH(const CTxOut& txout, tx.vout)
652652
{
653653
if (txout.nValue < 0)
654654
return state.DoS(100, error("CheckTransaction() : txout.nValue negative"),
655-
REJECT_INVALID, "vout negative");
655+
REJECT_INVALID, "bad-txns-vout-negative");
656656
if (txout.nValue > MAX_MONEY)
657657
return state.DoS(100, error("CheckTransaction() : txout.nValue too high"),
658-
REJECT_INVALID, "vout too large");
658+
REJECT_INVALID, "bad-txns-vout-toolarge");
659659
nValueOut += txout.nValue;
660660
if (!MoneyRange(nValueOut))
661661
return state.DoS(100, error("CheckTransaction() : txout total out of range"),
662-
REJECT_INVALID, "txout total too large");
662+
REJECT_INVALID, "bad-txns-txouttotal-toolarge");
663663
}
664664

665665
// Check for duplicate inputs
@@ -668,22 +668,22 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
668668
{
669669
if (vInOutPoints.count(txin.prevout))
670670
return state.DoS(100, error("CheckTransaction() : duplicate inputs"),
671-
REJECT_INVALID, "duplicate inputs");
671+
REJECT_INVALID, "bad-txns-inputs-duplicate");
672672
vInOutPoints.insert(txin.prevout);
673673
}
674674

675675
if (tx.IsCoinBase())
676676
{
677677
if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 100)
678678
return state.DoS(100, error("CheckTransaction() : coinbase script size"),
679-
REJECT_INVALID, "coinbase script too large");
679+
REJECT_INVALID, "bad-cb-length");
680680
}
681681
else
682682
{
683683
BOOST_FOREACH(const CTxIn& txin, tx.vin)
684684
if (txin.prevout.IsNull())
685685
return state.DoS(10, error("CheckTransaction() : prevout is null"),
686-
REJECT_INVALID, "prevout null");
686+
REJECT_INVALID, "bad-txns-prevout-null");
687687
}
688688

689689
return true;
@@ -791,7 +791,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
791791
// are the actual inputs available?
792792
if (!view.HaveInputs(tx))
793793
return state.Invalid(error("AcceptToMemoryPool : inputs already spent"),
794-
REJECT_DUPLICATE, "inputs spent");
794+
REJECT_DUPLICATE, "bad-txns-inputs-spent");
795795

796796
// Bring the best block into scope
797797
view.GetBestBlock();
@@ -1410,30 +1410,30 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCach
14101410
if (nSpendHeight - coins.nHeight < COINBASE_MATURITY)
14111411
return state.Invalid(
14121412
error("CheckInputs() : tried to spend coinbase at depth %d", nSpendHeight - coins.nHeight),
1413-
REJECT_INVALID, "premature spend of coinbase");
1413+
REJECT_INVALID, "bad-txns-premature-spend-of-coinbase");
14141414
}
14151415

14161416
// Check for negative or overflow input values
14171417
nValueIn += coins.vout[prevout.n].nValue;
14181418
if (!MoneyRange(coins.vout[prevout.n].nValue) || !MoneyRange(nValueIn))
14191419
return state.DoS(100, error("CheckInputs() : txin values out of range"),
1420-
REJECT_INVALID, "input values out of range");
1420+
REJECT_INVALID, "bad-txns-inputvalues-outofrange");
14211421

14221422
}
14231423

14241424
if (nValueIn < tx.GetValueOut())
14251425
return state.DoS(100, error("CheckInputs() : %s value in < value out", tx.GetHash().ToString()),
1426-
REJECT_INVALID, "in < out");
1426+
REJECT_INVALID, "bad-txns-in-belowout");
14271427

14281428
// Tally transaction fees
14291429
int64_t nTxFee = nValueIn - tx.GetValueOut();
14301430
if (nTxFee < 0)
14311431
return state.DoS(100, error("CheckInputs() : %s nTxFee < 0", tx.GetHash().ToString()),
1432-
REJECT_INVALID, "fee < 0");
1432+
REJECT_INVALID, "bad-txns-fee-negative");
14331433
nFees += nTxFee;
14341434
if (!MoneyRange(nFees))
14351435
return state.DoS(100, error("CheckInputs() : nFees out of range"),
1436-
REJECT_INVALID, "fee out of range");
1436+
REJECT_INVALID, "bad-txns-fee-outofrange");
14371437

14381438
// The first loop above does all the inexpensive checks.
14391439
// 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
16301630
uint256 hash = block.GetTxHash(i);
16311631
if (view.HaveCoins(hash) && !view.GetCoins(hash).IsPruned())
16321632
return state.DoS(100, error("ConnectBlock() : tried to overwrite transaction"),
1633-
REJECT_INVALID, "BIP30");
1633+
REJECT_INVALID, "bad-txns-BIP30");
16341634
}
16351635
}
16361636

@@ -1660,13 +1660,13 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
16601660
nSigOps += GetLegacySigOpCount(tx);
16611661
if (nSigOps > MAX_BLOCK_SIGOPS)
16621662
return state.DoS(100, error("ConnectBlock() : too many sigops"),
1663-
REJECT_INVALID, "too many sigops");
1663+
REJECT_INVALID, "bad-blk-sigops");
16641664

16651665
if (!tx.IsCoinBase())
16661666
{
16671667
if (!view.HaveInputs(tx))
16681668
return state.DoS(100, error("ConnectBlock() : inputs missing/spent"),
1669-
REJECT_INVALID, "inputs missing/spent");
1669+
REJECT_INVALID, "bad-txns-inputs-missingorspent");
16701670

16711671
if (fStrictPayToScriptHash)
16721672
{
@@ -1676,7 +1676,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
16761676
nSigOps += GetP2SHSigOpCount(tx, view);
16771677
if (nSigOps > MAX_BLOCK_SIGOPS)
16781678
return state.DoS(100, error("ConnectBlock() : too many sigops"),
1679-
REJECT_INVALID, "too many sigops");
1679+
REJECT_INVALID, "bad-blk-sigops");
16801680
}
16811681

16821682
nFees += view.GetValueIn(tx)-tx.GetValueOut();
@@ -1703,7 +1703,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
17031703
return state.DoS(100,
17041704
error("ConnectBlock() : coinbase pays too much (actual=%"PRId64" vs limit=%"PRId64")",
17051705
block.vtx[0].GetValueOut(), GetBlockValue(pindex->nHeight, nFees)),
1706-
REJECT_INVALID, "coinbase too large");
1706+
REJECT_INVALID, "bad-cb-amount");
17071707

17081708
if (!control.Wait())
17091709
return state.DoS(100, false);
@@ -1762,7 +1762,7 @@ bool static WriteChainState(CValidationState &state) {
17621762
// an overestimation, as most will delete an existing entry or
17631763
// overwrite one. Still, use a conservative safety factor of 2.
17641764
if (!CheckDiskSpace(100 * 2 * 2 * pcoinsTip->GetCacheSize()))
1765-
return state.Error();
1765+
return state.Error("out of disk space");
17661766
FlushBlockFile();
17671767
pblocktree->Sync();
17681768
if (!pcoinsTip->Flush())
@@ -1987,7 +1987,7 @@ bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos
19871987
// Check for duplicate
19881988
uint256 hash = block.GetHash();
19891989
if (mapBlockIndex.count(hash))
1990-
return state.Invalid(error("AddToBlockIndex() : %s already exists", hash.ToString()));
1990+
return state.Invalid(error("AddToBlockIndex() : %s already exists", hash.ToString()), 0, "duplicate");
19911991

19921992
// Construct new block index object
19931993
CBlockIndex* pindexNew = new CBlockIndex(block);
@@ -2082,7 +2082,7 @@ bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAdd
20822082
}
20832083
}
20842084
else
2085-
return state.Error();
2085+
return state.Error("out of disk space");
20862086
}
20872087
}
20882088

@@ -2128,7 +2128,7 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne
21282128
}
21292129
}
21302130
else
2131-
return state.Error();
2131+
return state.Error("out of disk space");
21322132
}
21332133

21342134
return true;
@@ -2143,26 +2143,26 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
21432143
// Size limits
21442144
if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
21452145
return state.DoS(100, error("CheckBlock() : size limits failed"),
2146-
REJECT_INVALID, "block size too large");
2146+
REJECT_INVALID, "bad-blk-length");
21472147

21482148
// Check proof of work matches claimed amount
21492149
if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits))
21502150
return state.DoS(50, error("CheckBlock() : proof of work failed"),
2151-
REJECT_INVALID, "invalid pow");
2151+
REJECT_INVALID, "high-hash");
21522152

21532153
// Check timestamp
21542154
if (block.GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60)
21552155
return state.Invalid(error("CheckBlock() : block timestamp too far in the future"),
2156-
REJECT_INVALID, "time in future");
2156+
REJECT_INVALID, "time-too-new");
21572157

21582158
// First transaction must be coinbase, the rest must not be
21592159
if (block.vtx.empty() || !block.vtx[0].IsCoinBase())
21602160
return state.DoS(100, error("CheckBlock() : first tx is not coinbase"),
2161-
REJECT_INVALID, "no coinbase");
2161+
REJECT_INVALID, "bad-cb-missing");
21622162
for (unsigned int i = 1; i < block.vtx.size(); i++)
21632163
if (block.vtx[i].IsCoinBase())
21642164
return state.DoS(100, error("CheckBlock() : more than one coinbase"),
2165-
REJECT_INVALID, "duplicate coinbase");
2165+
REJECT_INVALID, "bad-cb-multiple");
21662166

21672167
// Check transactions
21682168
BOOST_FOREACH(const CTransaction& tx, block.vtx)
@@ -2182,7 +2182,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
21822182
}
21832183
if (uniqueTx.size() != block.vtx.size())
21842184
return state.DoS(100, error("CheckBlock() : duplicate transaction"),
2185-
REJECT_INVALID, "duplicate transaction", true);
2185+
REJECT_INVALID, "bad-txns-duplicate", true);
21862186

21872187
unsigned int nSigOps = 0;
21882188
BOOST_FOREACH(const CTransaction& tx, block.vtx)
@@ -2191,12 +2191,12 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
21912191
}
21922192
if (nSigOps > MAX_BLOCK_SIGOPS)
21932193
return state.DoS(100, error("CheckBlock() : out-of-bounds SigOpCount"),
2194-
REJECT_INVALID, "sig op count", true);
2194+
REJECT_INVALID, "bad-blk-sigops", true);
21952195

21962196
// Check merkle root
21972197
if (fCheckMerkleRoot && block.hashMerkleRoot != block.vMerkleTree.back())
21982198
return state.DoS(100, error("CheckBlock() : hashMerkleRoot mismatch"),
2199-
REJECT_INVALID, "bad merkle root", true);
2199+
REJECT_INVALID, "bad-txnmrklroot", true);
22002200

22012201
return true;
22022202
}
@@ -2206,33 +2206,33 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp)
22062206
// Check for duplicate
22072207
uint256 hash = block.GetHash();
22082208
if (mapBlockIndex.count(hash))
2209-
return state.Invalid(error("AcceptBlock() : block already in mapBlockIndex"));
2209+
return state.Invalid(error("AcceptBlock() : block already in mapBlockIndex"), 0, "duplicate");
22102210

22112211
// Get prev block index
22122212
CBlockIndex* pindexPrev = NULL;
22132213
int nHeight = 0;
22142214
if (hash != Params().HashGenesisBlock()) {
22152215
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
22162216
if (mi == mapBlockIndex.end())
2217-
return state.DoS(10, error("AcceptBlock() : prev block not found"));
2217+
return state.DoS(10, error("AcceptBlock() : prev block not found"), 0, "bad-prevblk");
22182218
pindexPrev = (*mi).second;
22192219
nHeight = pindexPrev->nHeight+1;
22202220

22212221
// Check proof of work
22222222
if (block.nBits != GetNextWorkRequired(pindexPrev, &block))
22232223
return state.DoS(100, error("AcceptBlock() : incorrect proof of work"),
2224-
REJECT_INVALID, "bad pow");
2224+
REJECT_INVALID, "bad-diffbits");
22252225

22262226
// Check timestamp against prev
22272227
if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast())
22282228
return state.Invalid(error("AcceptBlock() : block's timestamp is too early"),
2229-
REJECT_INVALID, "timestamp too early");
2229+
REJECT_INVALID, "time-too-old");
22302230

22312231
// Check that all transactions are finalized
22322232
BOOST_FOREACH(const CTransaction& tx, block.vtx)
22332233
if (!IsFinalTx(tx, nHeight, block.GetBlockTime()))
22342234
return state.DoS(10, error("AcceptBlock() : contains a non-final transaction"),
2235-
REJECT_INVALID, "non-final tx");
2235+
REJECT_INVALID, "bad-txns-nonfinal");
22362236

22372237
// Check that the block chain matches the known block chain up to a checkpoint
22382238
if (!Checkpoints::CheckBlock(nHeight, hash))
@@ -2246,7 +2246,7 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp)
22462246
(TestNet() && CBlockIndex::IsSuperMajority(2, pindexPrev, 75, 100)))
22472247
{
22482248
return state.Invalid(error("AcceptBlock() : rejected nVersion=1 block"),
2249-
REJECT_OBSOLETE, "version 1 blocks obsolete");
2249+
REJECT_OBSOLETE, "bad-version");
22502250
}
22512251
}
22522252
// 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)
22602260
if (block.vtx[0].vin[0].scriptSig.size() < expect.size() ||
22612261
!std::equal(expect.begin(), expect.end(), block.vtx[0].vin[0].scriptSig.begin()))
22622262
return state.DoS(100, error("AcceptBlock() : block height mismatch in coinbase"),
2263-
REJECT_INVALID, "height incorrect in coinbase");
2263+
REJECT_INVALID, "bad-cb-height");
22642264
}
22652265
}
22662266
}
@@ -2337,9 +2337,9 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
23372337
// Check for duplicate
23382338
uint256 hash = pblock->GetHash();
23392339
if (mapBlockIndex.count(hash))
2340-
return state.Invalid(error("ProcessBlock() : already have block %d %s", mapBlockIndex[hash]->nHeight, hash.ToString()));
2340+
return state.Invalid(error("ProcessBlock() : already have block %d %s", mapBlockIndex[hash]->nHeight, hash.ToString()), 0, "duplicate");
23412341
if (mapOrphanBlocks.count(hash))
2342-
return state.Invalid(error("ProcessBlock() : already have block (orphan) %s", hash.ToString()));
2342+
return state.Invalid(error("ProcessBlock() : already have block (orphan) %s", hash.ToString()), 0, "duplicate");
23432343

23442344
// Preliminary checks
23452345
if (!CheckBlock(*pblock, state)) {
@@ -2356,7 +2356,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
23562356
if (deltaTime < 0)
23572357
{
23582358
return state.DoS(100, error("ProcessBlock() : block with timestamp before last checkpoint"),
2359-
REJECT_CHECKPOINT, "timestamp before checkpoint");
2359+
REJECT_CHECKPOINT, "time-too-old");
23602360
}
23612361
CBigNum bnNewBlock;
23622362
bnNewBlock.SetCompact(pblock->nBits);
@@ -2365,7 +2365,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
23652365
if (bnNewBlock > bnRequired)
23662366
{
23672367
return state.DoS(100, error("ProcessBlock() : block with too little proof-of-work"),
2368-
REJECT_INVALID, "invalid pow");
2368+
REJECT_INVALID, "bad-diffbits");
23692369
}
23702370
}
23712371

src/main.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -952,13 +952,15 @@ class CValidationState {
952952
unsigned char _chRejectCode=0, std::string _strRejectReason="") {
953953
return DoS(0, ret, _chRejectCode, _strRejectReason);
954954
}
955-
bool Error() {
955+
bool Error(std::string strRejectReasonIn="") {
956+
if (mode == MODE_VALID)
957+
strRejectReason = strRejectReasonIn;
956958
mode = MODE_ERROR;
957959
return false;
958960
}
959961
bool Abort(const std::string &msg) {
960962
AbortNode(msg);
961-
return Error();
963+
return Error(msg);
962964
}
963965
bool IsValid() const {
964966
return mode == MODE_VALID;

0 commit comments

Comments
 (0)