diff --git a/src/consensus/validation.h b/src/consensus/validation.h index 362c0be0b..6e34837a3 100644 --- a/src/consensus/validation.h +++ b/src/consensus/validation.h @@ -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 diff --git a/src/gtest/test_checkblock.cpp b/src/gtest/test_checkblock.cpp index 140813a62..3a61e5945 100644 --- a/src/gtest/test_checkblock.cpp +++ b/src/gtest/test_checkblock.cpp @@ -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 diff --git a/src/gtest/test_checktransaction.cpp b/src/gtest/test_checktransaction.cpp index 9c569e4ff..82b05e42e 100644 --- a/src/gtest/test_checktransaction.cpp +++ b/src/gtest/test_checktransaction.cpp @@ -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(); diff --git a/src/gtest/test_validation.cpp b/src/gtest/test_validation.cpp index 8e89b2b49..21833fb63 100644 --- a/src/gtest/test_validation.cpp +++ b/src/gtest/test_validation.cpp @@ -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));