Add debug message to CValidationState for optional extra information

Add a field `strDebugMessage` which can be passed to DoS or Invalid,
and queried using GetDebugMessage() to add extra troubleshooting
information to the validation state.

(cherry picked from commit bitcoin/bitcoin@fbf44e6f3e)
This commit is contained in:
Wladimir J. van der Laan 2015-08-06 09:47:01 +02:00 committed by Jack Grigg
parent e65733e032
commit 36c70c01a1
4 changed files with 98 additions and 84 deletions

View File

@ -30,14 +30,17 @@ private:
std::string strRejectReason;
unsigned int chRejectCode;
bool corruptionPossible;
std::string strDebugMessage;
public:
CValidationState() : mode(MODE_VALID), nDoS(0), chRejectCode(0), corruptionPossible(false) {}
virtual bool DoS(int level, bool ret = false,
unsigned int chRejectCodeIn=0, std::string strRejectReasonIn="",
bool corruptionIn=false) {
unsigned int chRejectCodeIn=0, const std::string &strRejectReasonIn="",
bool corruptionIn=false,
const std::string &strDebugMessageIn="") {
chRejectCode = chRejectCodeIn;
strRejectReason = strRejectReasonIn;
corruptionPossible = corruptionIn;
strDebugMessage = strDebugMessageIn;
if (mode == MODE_ERROR)
return ret;
nDoS += level;
@ -45,8 +48,9 @@ public:
return ret;
}
virtual bool Invalid(bool ret = false,
unsigned int _chRejectCode=0, std::string _strRejectReason="") {
return DoS(0, ret, _chRejectCode, _strRejectReason);
unsigned int _chRejectCode=0, const std::string &_strRejectReason="",
const std::string &_strDebugMessage="") {
return DoS(0, ret, _chRejectCode, _strRejectReason, false, _strDebugMessage);
}
virtual bool Error(const std::string& strRejectReasonIn) {
if (mode == MODE_VALID)
@ -75,6 +79,7 @@ public:
}
virtual unsigned int GetRejectCode() const { return chRejectCode; }
virtual std::string GetRejectReason() const { return strRejectReason; }
virtual std::string GetDebugMessage() const { return strDebugMessage; }
};
#endif // BITCOIN_CONSENSUS_VALIDATION_H

View File

@ -11,11 +11,13 @@
class MockCValidationState : public CValidationState {
public:
MOCK_METHOD5(DoS, bool(int level, bool ret,
unsigned int chRejectCodeIn, std::string strRejectReasonIn,
bool corruptionIn));
MOCK_METHOD3(Invalid, bool(bool ret,
unsigned int _chRejectCode, std::string _strRejectReason));
MOCK_METHOD6(DoS, bool(int level, bool ret,
unsigned int chRejectCodeIn, const std::string strRejectReasonIn,
bool corruptionIn,
const std::string &strDebugMessageIn));
MOCK_METHOD4(Invalid, bool(bool ret,
unsigned int _chRejectCode, const std::string _strRejectReason,
const std::string &_strDebugMessage));
MOCK_METHOD1(Error, bool(std::string strRejectReasonIn));
MOCK_CONST_METHOD0(IsValid, bool());
MOCK_CONST_METHOD0(IsInvalid, bool());
@ -24,6 +26,7 @@ public:
MOCK_CONST_METHOD0(CorruptionPossible, bool());
MOCK_CONST_METHOD0(GetRejectCode, unsigned int());
MOCK_CONST_METHOD0(GetRejectReason, std::string());
MOCK_CONST_METHOD0(GetDebugMessage, std::string());
};
TEST(CheckBlock, VersionTooLow) {
@ -34,7 +37,7 @@ TEST(CheckBlock, VersionTooLow) {
block.nVersion = 1;
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "version-too-low", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "version-too-low", false, "")).Times(1);
EXPECT_FALSE(CheckBlock(block, state, Params(), verifier, orchardAuth, false, false, true));
}
@ -77,7 +80,7 @@ TEST(CheckBlock, BlockSproutRejectsBadVersion) {
auto verifier = ProofVerifier::Strict();
auto orchardAuth = orchard::AuthValidator::Batch();
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-version-too-low", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-version-too-low", false, "")).Times(1);
EXPECT_FALSE(CheckBlock(block, state, Params(), verifier, orchardAuth, false, false, true));
}
@ -149,7 +152,7 @@ protected:
// We now expect this to be an invalid block, for the given reason.
MockCValidationState state;
EXPECT_CALL(state, DoS(level, false, REJECT_INVALID, reason, false)).Times(1);
EXPECT_CALL(state, DoS(level, false, REJECT_INVALID, reason, false, "")).Times(1);
EXPECT_FALSE(ContextualCheckBlock(block, state, Params(), &indexPrev, true));
}
@ -180,14 +183,14 @@ TEST_F(ContextualCheckBlockTest, BadCoinbaseHeight) {
CBlock prev;
CBlockIndex indexPrev {prev};
indexPrev.nHeight = 0;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-height", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-height", false, "")).Times(1);
EXPECT_FALSE(ContextualCheckBlock(block, state, Params(), &indexPrev, true));
// Setting to an incorrect height should fail
mtx.vin[0].scriptSig = CScript() << 2 << OP_0;
CTransaction tx3 {mtx};
block.vtx[0] = tx3;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-height", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-height", false, "")).Times(1);
EXPECT_FALSE(ContextualCheckBlock(block, state, Params(), &indexPrev, true));
// After correcting the scriptSig, should pass

View File

@ -41,11 +41,13 @@ TEST(ChecktransactionTests, CheckVpubNotBothNonzero) {
class MockCValidationState : public CValidationState {
public:
MOCK_METHOD5(DoS, bool(int level, bool ret,
unsigned int chRejectCodeIn, std::string strRejectReasonIn,
bool corruptionIn));
MOCK_METHOD3(Invalid, bool(bool ret,
unsigned int _chRejectCode, std::string _strRejectReason));
MOCK_METHOD6(DoS, bool(int level, bool ret,
unsigned int chRejectCodeIn, const std::string &strRejectReasonIn,
bool corruptionIn,
const std::string &strDebugMessageIn));
MOCK_METHOD4(Invalid, bool(bool ret,
unsigned int _chRejectCode, const std::string _strRejectReason,
const std::string &_strDebugMessage));
MOCK_METHOD1(Error, bool(std::string strRejectReasonIn));
MOCK_CONST_METHOD0(IsValid, bool());
MOCK_CONST_METHOD0(IsInvalid, bool());
@ -54,6 +56,7 @@ public:
MOCK_CONST_METHOD0(CorruptionPossible, bool());
MOCK_CONST_METHOD0(GetRejectCode, unsigned int());
MOCK_CONST_METHOD0(GetRejectReason, std::string());
MOCK_CONST_METHOD0(GetDebugMessage, std::string());
};
void CreateJoinSplitSignature(CMutableTransaction& mtx, uint32_t consensusBranchId);
@ -135,7 +138,7 @@ TEST(ChecktransactionTests, BadVersionTooLow) {
EXPECT_THROW((CTransaction(mtx)), std::ios_base::failure);
UNSAFE_CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-version-too-low", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-version-too-low", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -146,7 +149,7 @@ TEST(ChecktransactionTests, BadTxnsVinEmpty) {
CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(10, false, REJECT_INVALID, "bad-txns-no-source-of-funds", false)).Times(1);
EXPECT_CALL(state, DoS(10, false, REJECT_INVALID, "bad-txns-no-source-of-funds", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -158,7 +161,7 @@ TEST(ChecktransactionTests, BadTxnsVoutEmpty) {
CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(10, false, REJECT_INVALID, "bad-txns-no-sink-of-funds", false)).Times(1);
EXPECT_CALL(state, DoS(10, false, REJECT_INVALID, "bad-txns-no-sink-of-funds", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -192,7 +195,7 @@ TEST(ChecktransactionTests, BadTxnsOversize) {
EXPECT_TRUE(CheckTransactionWithoutProofVerification(tx, state));
// ... but fails contextual ones!
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-oversize", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-oversize", false, "")).Times(1);
EXPECT_FALSE(ContextualCheckTransaction(tx, state, Params(), 1, true));
}
@ -270,7 +273,7 @@ TEST(ChecktransactionTests, OversizeSaplingTxns) {
EXPECT_EQ(::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION), MAX_TX_SIZE_AFTER_SAPLING + 1);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-oversize", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-oversize", false, "")).Times(1);
EXPECT_FALSE(CheckTransactionWithoutProofVerification(tx, state));
}
@ -286,7 +289,7 @@ TEST(ChecktransactionTests, BadTxnsVoutNegative) {
UNSAFE_CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-vout-negative", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-vout-negative", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -298,7 +301,7 @@ TEST(ChecktransactionTests, BadTxnsVoutToolarge) {
UNSAFE_CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-vout-toolarge", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-vout-toolarge", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -310,7 +313,7 @@ TEST(ChecktransactionTests, BadTxnsTxouttotalToolargeOutputs) {
CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -321,7 +324,7 @@ TEST(ChecktransactionTests, ValueBalanceNonZero) {
CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-valuebalance-nonzero", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-valuebalance-nonzero", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -333,7 +336,7 @@ TEST(ChecktransactionTests, PositiveValueBalanceTooLarge) {
CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-valuebalance-toolarge", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-valuebalance-toolarge", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -345,7 +348,7 @@ TEST(ChecktransactionTests, NegativeValueBalanceTooLarge) {
CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-valuebalance-toolarge", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-valuebalance-toolarge", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -358,7 +361,7 @@ TEST(ChecktransactionTests, ValueBalanceOverflowsTotal) {
CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -370,7 +373,7 @@ TEST(ChecktransactionTests, BadTxnsTxouttotalToolargeJoinsplit) {
CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -382,7 +385,7 @@ TEST(ChecktransactionTests, BadTxnsTxintotalToolargeJoinsplit) {
CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-txintotal-toolarge", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-txintotal-toolarge", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -393,7 +396,7 @@ TEST(ChecktransactionTests, BadTxnsVpubOldNegative) {
CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-vpub_old-negative", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-vpub_old-negative", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -404,7 +407,7 @@ TEST(ChecktransactionTests, BadTxnsVpubNewNegative) {
CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-vpub_new-negative", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-vpub_new-negative", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -415,7 +418,7 @@ TEST(ChecktransactionTests, BadTxnsVpubOldToolarge) {
CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-vpub_old-toolarge", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-vpub_old-toolarge", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -426,7 +429,7 @@ TEST(ChecktransactionTests, BadTxnsVpubNewToolarge) {
CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-vpub_new-toolarge", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-vpub_new-toolarge", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -438,7 +441,7 @@ TEST(ChecktransactionTests, BadTxnsVpubsBothNonzero) {
CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-vpubs-both-nonzero", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-vpubs-both-nonzero", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -450,7 +453,7 @@ TEST(ChecktransactionTests, BadTxnsInputsDuplicate) {
CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-inputs-duplicate", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-inputs-duplicate", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -462,7 +465,7 @@ TEST(ChecktransactionTests, BadJoinsplitsNullifiersDuplicateSameJoinsplit) {
CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-joinsplits-nullifiers-duplicate", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-joinsplits-nullifiers-duplicate", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -474,7 +477,7 @@ TEST(ChecktransactionTests, BadJoinsplitsNullifiersDuplicateDifferentJoinsplit)
CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-joinsplits-nullifiers-duplicate", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-joinsplits-nullifiers-duplicate", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -490,7 +493,7 @@ TEST(ChecktransactionTests, BadCbHasJoinsplits) {
EXPECT_TRUE(tx.IsCoinBase());
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-has-joinsplits", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-has-joinsplits", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -506,7 +509,7 @@ TEST(ChecktransactionTests, BadCbEmptyScriptsig) {
EXPECT_TRUE(tx.IsCoinBase());
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-length", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-length", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -518,7 +521,7 @@ TEST(ChecktransactionTests, BadTxnsPrevoutNull) {
EXPECT_FALSE(tx.IsCoinBase());
MockCValidationState state;
EXPECT_CALL(state, DoS(10, false, REJECT_INVALID, "bad-txns-prevout-null", false)).Times(1);
EXPECT_CALL(state, DoS(10, false, REJECT_INVALID, "bad-txns-prevout-null", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -533,15 +536,15 @@ TEST(ChecktransactionTests, BadTxnsInvalidJoinsplitSignature) {
MockCValidationState state;
// during initial block download, for transactions being accepted into the
// mempool (and thus not mined), DoS ban score should be zero, else 10
EXPECT_CALL(state, DoS(0, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1);
EXPECT_CALL(state, DoS(0, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
ContextualCheckTransaction(tx, state, chainparams, 0, false, [](const Consensus::Params&) { return true; });
EXPECT_CALL(state, DoS(10, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1);
EXPECT_CALL(state, DoS(10, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
ContextualCheckTransaction(tx, state, chainparams, 0, false, [](const Consensus::Params&) { return false; });
// for transactions that have been mined in a block, DoS ban score should
// always be 100.
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
ContextualCheckTransaction(tx, state, chainparams, 0, true, [](const Consensus::Params&) { return true; });
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
ContextualCheckTransaction(tx, state, chainparams, 0, true, [](const Consensus::Params&) { return false; });
}
@ -573,7 +576,7 @@ TEST(ChecktransactionTests, JoinsplitSignatureDetectsOldBranchId) {
strprintf("old-consensus-branch-id (Expected %s, found %s)",
HexInt(blossomBranchId),
HexInt(saplingBranchId)),
false)).Times(1);
false, "")).Times(1);
EXPECT_FALSE(ContextualCheckTransaction(
tx, state, chainparams, 15, false,
[](const Consensus::Params&) { return false; }));
@ -583,7 +586,7 @@ TEST(ChecktransactionTests, JoinsplitSignatureDetectsOldBranchId) {
// network upgrade back.
EXPECT_CALL(state, DoS(
10, false, REJECT_INVALID,
"bad-txns-invalid-joinsplit-signature", false)).Times(1);
"bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
EXPECT_FALSE(ContextualCheckTransaction(
tx, state, chainparams, 25, false,
[](const Consensus::Params&) { return false; }));
@ -625,15 +628,15 @@ TEST(ChecktransactionTests, NonCanonicalEd25519Signature) {
MockCValidationState state;
// during initial block download, for transactions being accepted into the
// mempool (and thus not mined), DoS ban score should be zero, else 10
EXPECT_CALL(state, DoS(0, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1);
EXPECT_CALL(state, DoS(0, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
ContextualCheckTransaction(tx, state, chainparams, 0, false, [](const Consensus::Params&) { return true; });
EXPECT_CALL(state, DoS(10, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1);
EXPECT_CALL(state, DoS(10, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
ContextualCheckTransaction(tx, state, chainparams, 0, false, [](const Consensus::Params&) { return false; });
// for transactions that have been mined in a block, DoS ban score should
// always be 100.
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
ContextualCheckTransaction(tx, state, chainparams, 0, true, [](const Consensus::Params&) { return true; });
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
ContextualCheckTransaction(tx, state, chainparams, 0, true, [](const Consensus::Params&) { return false; });
}
@ -769,7 +772,7 @@ TEST(ChecktransactionTests, OverwinterExpiryHeight) {
CTransaction tx(mtx);
MockCValidationState state;
EXPECT_TRUE(CheckTransactionWithoutProofVerification(tx, state));
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-tx-expiry-height-too-high", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-tx-expiry-height-too-high", false, "")).Times(1);
ContextualCheckTransaction(tx, state, params, 1, true);
}
@ -778,7 +781,7 @@ TEST(ChecktransactionTests, OverwinterExpiryHeight) {
CTransaction tx(mtx);
MockCValidationState state;
EXPECT_TRUE(CheckTransactionWithoutProofVerification(tx, state));
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-tx-expiry-height-too-high", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-tx-expiry-height-too-high", false, "")).Times(1);
ContextualCheckTransaction(tx, state, params, 1, true);
}
@ -805,7 +808,7 @@ TEST(ChecktransactionTests, SproutTxVersionTooLow) {
EXPECT_THROW((CTransaction(mtx)), std::ios_base::failure);
UNSAFE_CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-version-too-low", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-version-too-low", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -860,7 +863,7 @@ TEST(ChecktransactionTests, SaplingSproutInputSumsTooLarge) {
{
UNSAFE_CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-txintotal-toolarge", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-txintotal-toolarge", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
}
@ -877,7 +880,7 @@ TEST(ChecktransactionTests, OverwinterVersionNumberLow) {
EXPECT_THROW((CTransaction(mtx)), std::ios_base::failure);
UNSAFE_CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-tx-overwinter-version-too-low", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-tx-overwinter-version-too-low", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -896,7 +899,7 @@ TEST(ChecktransactionTests, OverwinterVersionNumberHigh) {
EXPECT_THROW((CTransaction(mtx)), std::ios_base::failure);
UNSAFE_CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-tx-overwinter-version-too-high", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-tx-overwinter-version-too-high", false, "")).Times(1);
ContextualCheckTransaction(tx, state, Params(), 1, true);
// Revert to default
@ -916,7 +919,7 @@ TEST(ChecktransactionTests, OverwinterBadVersionGroupId) {
EXPECT_THROW((CTransaction(mtx)), std::ios_base::failure);
UNSAFE_CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-tx-version-group-id", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-tx-version-group-id", false, "")).Times(1);
CheckTransactionWithoutProofVerification(tx, state);
}
@ -935,15 +938,15 @@ TEST(ChecktransactionTests, OverwinterNotActive) {
MockCValidationState state;
// during initial block download, for transactions being accepted into the
// mempool (and thus not mined), DoS ban score should be zero, else 10
EXPECT_CALL(state, DoS(0, false, REJECT_INVALID, "tx-overwinter-not-active", false)).Times(1);
EXPECT_CALL(state, DoS(0, false, REJECT_INVALID, "tx-overwinter-not-active", false, "")).Times(1);
ContextualCheckTransaction(tx, state, chainparams, 0, false, [](const Consensus::Params&) { return true; });
EXPECT_CALL(state, DoS(10, false, REJECT_INVALID, "tx-overwinter-not-active", false)).Times(1);
EXPECT_CALL(state, DoS(10, false, REJECT_INVALID, "tx-overwinter-not-active", false, "")).Times(1);
ContextualCheckTransaction(tx, state, chainparams, 0, false, [](const Consensus::Params&) { return false; });
// for transactions that have been mined in a block, DoS ban score should
// always be 100.
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "tx-overwinter-not-active", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "tx-overwinter-not-active", false, "")).Times(1);
ContextualCheckTransaction(tx, state, chainparams, 0, true, [](const Consensus::Params&) { return true; });
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "tx-overwinter-not-active", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "tx-overwinter-not-active", false, "")).Times(1);
ContextualCheckTransaction(tx, state, chainparams, 0, true, [](const Consensus::Params&) { return false; });
}
@ -960,7 +963,7 @@ TEST(ChecktransactionTests, OverwinterFlagNotSet) {
CTransaction tx(mtx);
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "tx-overwintered-flag-not-set", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "tx-overwintered-flag-not-set", false, "")).Times(1);
ContextualCheckTransaction(tx, state, Params(), 1, true);
// Revert to default
@ -1125,13 +1128,13 @@ TEST(ChecktransactionTests, InvalidShieldedCoinbase) {
// Before Heartwood, output descriptions are rejected.
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-has-output-description", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-has-output-description", false, "")).Times(1);
ContextualCheckTransaction(tx, state, Params(), 10, 57);
RegtestActivateHeartwood(false, Consensus::NetworkUpgrade::ALWAYS_ACTIVE);
// From Heartwood, the output description is allowed but invalid (undecryptable).
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-output-desc-invalid-outct", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-output-desc-invalid-outct", false, "")).Times(1);
ContextualCheckTransaction(tx, state, Params(), 10, 57);
RegtestDeactivateHeartwood();
@ -1168,7 +1171,7 @@ TEST(ChecktransactionTests, HeartwoodAcceptsShieldedCoinbase) {
EXPECT_TRUE(tx.IsCoinBase());
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-output-desc-invalid-outct", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-output-desc-invalid-outct", false, "")).Times(1);
ContextualCheckTransaction(tx, state, chainparams, 10, 57);
mtx.vShieldedOutput[0].cmu = cmOrig;
@ -1182,7 +1185,7 @@ TEST(ChecktransactionTests, HeartwoodAcceptsShieldedCoinbase) {
EXPECT_TRUE(tx.IsCoinBase());
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-output-desc-invalid-outct", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-output-desc-invalid-outct", false, "")).Times(1);
ContextualCheckTransaction(tx, state, chainparams, 10, 57);
mtx.vShieldedOutput[0].outCiphertext = outCtOrig;
@ -1196,7 +1199,7 @@ TEST(ChecktransactionTests, HeartwoodAcceptsShieldedCoinbase) {
EXPECT_TRUE(tx.IsCoinBase());
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-output-desc-invalid-encct", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-output-desc-invalid-encct", false, "")).Times(1);
ContextualCheckTransaction(tx, state, chainparams, 10, 57);
mtx.vShieldedOutput[0].encCiphertext = encCtOrig;
@ -1210,7 +1213,7 @@ TEST(ChecktransactionTests, HeartwoodAcceptsShieldedCoinbase) {
EXPECT_TRUE(tx.IsCoinBase());
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-sapling-binding-signature-invalid", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-sapling-binding-signature-invalid", false, "")).Times(1);
ContextualCheckTransaction(tx, state, chainparams, 10, 57);
}
@ -1247,7 +1250,7 @@ TEST(ChecktransactionTests, HeartwoodEnforcesSaplingRulesOnShieldedCoinbase) {
EXPECT_TRUE(tx.IsCoinBase());
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-valuebalance-nonzero", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-valuebalance-nonzero", false, "")).Times(1);
EXPECT_FALSE(CheckTransactionWithoutProofVerification(tx, state));
}
@ -1266,7 +1269,7 @@ TEST(ChecktransactionTests, HeartwoodEnforcesSaplingRulesOnShieldedCoinbase) {
EXPECT_TRUE(tx.IsCoinBase());
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-valuebalance-toolarge", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-valuebalance-toolarge", false, "")).Times(1);
EXPECT_FALSE(CheckTransactionWithoutProofVerification(tx, state));
}
{
@ -1276,7 +1279,7 @@ TEST(ChecktransactionTests, HeartwoodEnforcesSaplingRulesOnShieldedCoinbase) {
EXPECT_TRUE(tx.IsCoinBase());
MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-valuebalance-toolarge", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-valuebalance-toolarge", false, "")).Times(1);
EXPECT_FALSE(CheckTransactionWithoutProofVerification(tx, state));
}
@ -1290,7 +1293,7 @@ TEST(ChecktransactionTests, HeartwoodEnforcesSaplingRulesOnShieldedCoinbase) {
// Coinbase transaction does not pass contextual checks, as bindingSig
// consensus rule is enforced.
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-sapling-binding-signature-invalid", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-sapling-binding-signature-invalid", false, "")).Times(1);
ContextualCheckTransaction(tx, state, chainparams, 10, 57);
RegtestDeactivateHeartwood();
@ -1320,7 +1323,7 @@ TEST(ChecktransactionTests, CanopyRejectsNonzeroVPubOld) {
// After Canopy, nonzero vpub_old is accepted in non-contextual checks but rejected in contextual checks
EXPECT_TRUE(CheckTransactionWithoutProofVerification(tx, state));
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-vpub_old-nonzero", false)).Times(1);
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-vpub_old-nonzero", false, "")).Times(1);
EXPECT_FALSE(ContextualCheckTransaction(tx, state, Params(), 10, true));
RegtestDeactivateCanopy();

View File

@ -97,11 +97,13 @@ public:
class MockCValidationState : public CValidationState {
public:
MOCK_METHOD5(DoS, bool(int level, bool ret,
unsigned int chRejectCodeIn, std::string strRejectReasonIn,
bool corruptionIn));
MOCK_METHOD3(Invalid, bool(bool ret,
unsigned int _chRejectCode, std::string _strRejectReason));
MOCK_METHOD6(DoS, bool(int level, bool ret,
unsigned int chRejectCodeIn, const std::string strRejectReasonIn,
bool corruptionIn,
const std::string &strDebugMessageIn));
MOCK_METHOD4(Invalid, bool(bool ret,
unsigned int _chRejectCode, const std::string _strRejectReason,
const std::string &_strDebugMessage));
MOCK_METHOD1(Error, bool(std::string strRejectReasonIn));
MOCK_CONST_METHOD0(IsValid, bool());
MOCK_CONST_METHOD0(IsInvalid, bool());
@ -110,6 +112,7 @@ public:
MOCK_CONST_METHOD0(CorruptionPossible, bool());
MOCK_CONST_METHOD0(GetRejectCode, unsigned int());
MOCK_CONST_METHOD0(GetRejectReason, std::string());
MOCK_CONST_METHOD0(GetDebugMessage, std::string());
};
TEST(Validation, ContextualCheckInputsPassesWithCoinbase) {
@ -190,7 +193,7 @@ TEST(Validation, ContextualCheckInputsDetectsOldBranchId) {
strprintf("old-consensus-branch-id (Expected %s, found %s)",
HexInt(saplingBranchId),
HexInt(overwinterBranchId)),
false)).Times(1);
false, "")).Times(1);
EXPECT_FALSE(ContextualCheckInputs(
tx, mockState, view, true, 0, false, txdata,
consensusParams, saplingBranchId));
@ -201,7 +204,7 @@ TEST(Validation, ContextualCheckInputsDetectsOldBranchId) {
EXPECT_CALL(mockState, DoS(
100, false, REJECT_INVALID,
"mandatory-script-verify-flag-failed (Script evaluated without error but finished with a false/empty top stack element)",
false)).Times(1);
false, "")).Times(1);
EXPECT_FALSE(ContextualCheckInputs(
tx, mockState, view, true, 0, false, txdata,
consensusParams, blossomBranchId));