From 54c15e7161027bdf56d3f360b96479b64ea2e395 Mon Sep 17 00:00:00 2001 From: furszy Date: Tue, 8 Dec 2020 15:05:55 -0300 Subject: [PATCH] [Test] Adding sapling transaction validation unit test coverage. --- src/test/CMakeLists.txt | 1 + src/test/validation_tests.cpp | 95 +++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 51aa21c3ca00..4a420606f5ed 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -127,6 +127,7 @@ set(BITCOIN_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/uint256_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/univalue_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/util_tests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/validation_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/sha256compress_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/upgrades_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/librust/sapling_rpc_wallet_tests.cpp diff --git a/src/test/validation_tests.cpp b/src/test/validation_tests.cpp index 56fee4d2da40..ad7be364874d 100644 --- a/src/test/validation_tests.cpp +++ b/src/test/validation_tests.cpp @@ -4,6 +4,7 @@ #include "test/test_pivx.h" #include "primitives/transaction.h" +#include "sapling/sapling_validation.h" #include "tiertwo/specialtx_validation.h" #include "test/librust/utiltest.h" @@ -58,4 +59,98 @@ BOOST_AUTO_TEST_CASE(special_tx_validation_test) RegtestDeactivateSapling(); } +void test_simple_sapling_invalidity(CMutableTransaction& tx) +{ + CAmount nDummyValueOut; + { + CMutableTransaction newTx(tx); + CValidationState state; + + BOOST_CHECK(!CheckTransaction(newTx, false, false, state, false)); + BOOST_CHECK(state.GetRejectReason() == "bad-txns-vin-empty"); + } + { + CMutableTransaction newTx(tx); + CValidationState state; + + newTx.sapData->vShieldedSpend.emplace_back(); + newTx.sapData->vShieldedSpend[0].nullifier = GetRandHash(); + + BOOST_CHECK(!CheckTransaction(newTx, false, false, state, false)); + BOOST_CHECK(state.GetRejectReason() == "bad-txns-vout-empty"); + } + { + // Ensure that nullifiers are never duplicated within a transaction. + CMutableTransaction newTx(tx); + CValidationState state; + + newTx.sapData->vShieldedSpend.emplace_back(); + newTx.sapData->vShieldedSpend[0].nullifier = GetRandHash(); + + newTx.sapData->vShieldedOutput.emplace_back(); + + newTx.sapData->vShieldedSpend.emplace_back(); + newTx.sapData->vShieldedSpend[1].nullifier = newTx.sapData->vShieldedSpend[0].nullifier; + + BOOST_CHECK(!SaplingValidation::CheckTransactionWithoutProofVerification(newTx, state, nDummyValueOut)); + BOOST_CHECK(state.GetRejectReason() == "bad-spend-description-nullifiers-duplicate"); + + newTx.sapData->vShieldedSpend[1].nullifier = GetRandHash(); + + BOOST_CHECK(SaplingValidation::CheckTransactionWithoutProofVerification(newTx, state, nDummyValueOut)); + } + { + CMutableTransaction newTx(tx); + CValidationState state; + + // Create a coinbase transaction + CTxIn vin; + vin.prevout = COutPoint(); + newTx.vin.emplace_back(vin); + CTxOut vout; + vout.nValue = 2; + newTx.vout.emplace_back(vout); + + newTx.sapData->vShieldedSpend.emplace_back(); + + BOOST_CHECK(!CheckTransaction(newTx, false, false, state, false, false, true)); + BOOST_CHECK(state.GetRejectReason() == "bad-txns-invalid-sapling"); + } + { + CMutableTransaction newTx(tx); + CValidationState state; + + // Create a coinstake transaction + CTxIn vin; + vin.prevout = COutPoint(UINT256_ZERO, 0); + newTx.vin.emplace_back(vin); + CTxOut vout; + vout.nValue = 0; + newTx.vout.emplace_back(vout); + vout.nValue = 2; + newTx.vout.emplace_back(vout); + + newTx.sapData->vShieldedSpend.emplace_back(); + + BOOST_CHECK(!CheckTransaction(newTx, false, false, state, false, false, true)); + BOOST_CHECK(state.GetRejectReason() == "bad-txns-invalid-sapling"); + } +} + +BOOST_AUTO_TEST_CASE(test_simple_shielded_invalid) +{ + // Switch to regtest parameters so we can activate Sapling + SelectParams(CBaseChainParams::REGTEST); + + CMutableTransaction mtx; + mtx.nVersion = CTransaction::TxVersion::SAPLING; + + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_V5_0, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); + test_simple_sapling_invalidity(mtx); + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_V5_0, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); + + // Switch back to mainnet parameters as originally selected in test fixture + SelectParams(CBaseChainParams::MAIN); +} + BOOST_AUTO_TEST_SUITE_END()