Skip to content

Commit 9ddc8c6

Browse files
committed
Merge pull request #5394
307f7d4 Report script evaluation failures in log and reject messages (Pieter Wuille)
2 parents 4d2ecc4 + 307f7d4 commit 9ddc8c6

File tree

2 files changed

+19
-12
lines changed

2 files changed

+19
-12
lines changed

src/main.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,7 +1334,7 @@ void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state
13341334
if (state.IsInvalid(nDoS)) {
13351335
std::map<uint256, NodeId>::iterator it = mapBlockSource.find(pindex->GetBlockHash());
13361336
if (it != mapBlockSource.end() && State(it->second)) {
1337-
CBlockReject reject = {state.GetRejectCode(), state.GetRejectReason(), pindex->GetBlockHash()};
1337+
CBlockReject reject = {state.GetRejectCode(), state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), pindex->GetBlockHash()};
13381338
State(it->second)->rejects.push_back(reject);
13391339
if (nDoS > 0)
13401340
Misbehaving(it->second, nDoS);
@@ -1364,10 +1364,11 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach
13641364
inputs.ModifyCoins(tx.GetHash())->FromTx(tx, nHeight);
13651365
}
13661366

1367-
bool CScriptCheck::operator()() const {
1367+
bool CScriptCheck::operator()() {
13681368
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
1369-
if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingSignatureChecker(*ptxTo, nIn, cacheStore)))
1370-
return error("CScriptCheck() : %s:%d VerifySignature failed", ptxTo->GetHash().ToString(), nIn);
1369+
if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingSignatureChecker(*ptxTo, nIn, cacheStore), &error)) {
1370+
return ::error("CScriptCheck() : %s:%d VerifySignature failed: %s", ptxTo->GetHash().ToString(), nIn, ScriptErrorString(error));
1371+
}
13711372
return true;
13721373
}
13731374

@@ -1455,7 +1456,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
14551456
CScriptCheck check(*coins, tx, i,
14561457
flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore);
14571458
if (check())
1458-
return state.Invalid(false, REJECT_NONSTANDARD, "non-mandatory-script-verify-flag");
1459+
return state.Invalid(false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError())));
14591460
}
14601461
// Failures of other flags indicate a transaction that is
14611462
// invalid in new blocks, e.g. a invalid P2SH. We DoS ban
@@ -1464,7 +1465,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
14641465
// as to the correct behavior - we may want to continue
14651466
// peering with non-upgraded nodes even after a soft-fork
14661467
// super-majority vote has passed.
1467-
return state.DoS(100,false, REJECT_INVALID, "mandatory-script-verify-flag-failed");
1468+
return state.DoS(100,false, REJECT_INVALID, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(check.GetScriptError())));
14681469
}
14691470
}
14701471
}
@@ -3990,7 +3991,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
39903991
pfrom->id, pfrom->cleanSubVer,
39913992
state.GetRejectReason());
39923993
pfrom->PushMessage("reject", strCommand, state.GetRejectCode(),
3993-
state.GetRejectReason(), inv.hash);
3994+
state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash);
39943995
if (nDoS > 0)
39953996
Misbehaving(pfrom->GetId(), nDoS);
39963997
}
@@ -4064,7 +4065,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
40644065
int nDoS;
40654066
if (state.IsInvalid(nDoS)) {
40664067
pfrom->PushMessage("reject", strCommand, state.GetRejectCode(),
4067-
state.GetRejectReason(), inv.hash);
4068+
state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash);
40684069
if (nDoS > 0) {
40694070
LOCK(cs_main);
40704071
Misbehaving(pfrom->GetId(), nDoS);
@@ -4271,7 +4272,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
42714272
if (fDebug) {
42724273
try {
42734274
string strMsg; unsigned char ccode; string strReason;
4274-
vRecv >> LIMITED_STRING(strMsg, CMessageHeader::COMMAND_SIZE) >> ccode >> LIMITED_STRING(strReason, 111);
4275+
vRecv >> LIMITED_STRING(strMsg, CMessageHeader::COMMAND_SIZE) >> ccode >> LIMITED_STRING(strReason, MAX_REJECT_MESSAGE_LENGTH);
42754276

42764277
ostringstream ss;
42774278
ss << strMsg << " code " << itostr(ccode) << ": " << strReason;

src/main.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ static const unsigned int MAX_HEADERS_RESULTS = 2000;
9696
static const unsigned int BLOCK_DOWNLOAD_WINDOW = 1024;
9797
/** Time to wait (in seconds) between writing blockchain state to disk. */
9898
static const unsigned int DATABASE_WRITE_INTERVAL = 3600;
99+
/** Maximum length of reject messages. */
100+
static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111;
99101

100102
/** "reject" message codes */
101103
static const unsigned char REJECT_MALFORMED = 0x01;
@@ -334,22 +336,26 @@ class CScriptCheck
334336
unsigned int nIn;
335337
unsigned int nFlags;
336338
bool cacheStore;
339+
ScriptError error;
337340

338341
public:
339-
CScriptCheck(): ptxTo(0), nIn(0), nFlags(0), cacheStore(false) {}
342+
CScriptCheck(): ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
340343
CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn) :
341344
scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey),
342-
ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn) { }
345+
ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR) { }
343346

344-
bool operator()() const;
347+
bool operator()();
345348

346349
void swap(CScriptCheck &check) {
347350
scriptPubKey.swap(check.scriptPubKey);
348351
std::swap(ptxTo, check.ptxTo);
349352
std::swap(nIn, check.nIn);
350353
std::swap(nFlags, check.nFlags);
351354
std::swap(cacheStore, check.cacheStore);
355+
std::swap(error, check.error);
352356
}
357+
358+
ScriptError GetScriptError() const { return error; }
353359
};
354360

355361
/** Data structure that represents a partial merkle tree.

0 commit comments

Comments
 (0)