Prevent coinbases from being spent to transparent outputs.
This commit is contained in:
@@ -1629,7 +1629,12 @@ bool NonContextualCheckInputs(const CTransaction& tx, CValidationState &state, c
|
|||||||
assert(coins);
|
assert(coins);
|
||||||
|
|
||||||
if (coins->IsCoinBase()) {
|
if (coins->IsCoinBase()) {
|
||||||
|
// Ensure that coinbases cannot be spent to transparent outputs
|
||||||
|
if (!tx.vout.empty()) {
|
||||||
|
return state.Invalid(
|
||||||
|
error("CheckInputs(): tried to spend coinbase with transparent outputs"),
|
||||||
|
REJECT_INVALID, "bad-txns-coinbase-spend-has-transparent-outputs");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for negative or overflow input values
|
// Check for negative or overflow input values
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
#include "random.h"
|
#include "random.h"
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
#include "test/test_bitcoin.h"
|
#include "test/test_bitcoin.h"
|
||||||
|
#include "consensus/validation.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "undo.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -475,4 +478,48 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test)
|
|||||||
BOOST_CHECK(missed_an_entry);
|
BOOST_CHECK(missed_an_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(coins_coinbase_spends)
|
||||||
|
{
|
||||||
|
CCoinsViewTest base;
|
||||||
|
CCoinsViewCacheTest cache(&base);
|
||||||
|
|
||||||
|
// Create coinbase transaction
|
||||||
|
CMutableTransaction mtx;
|
||||||
|
mtx.vin.resize(1);
|
||||||
|
mtx.vin[0].scriptSig = CScript() << OP_1;
|
||||||
|
mtx.vin[0].nSequence = 0;
|
||||||
|
mtx.vout.resize(1);
|
||||||
|
mtx.vout[0].nValue = 500;
|
||||||
|
mtx.vout[0].scriptPubKey = CScript() << OP_1;
|
||||||
|
|
||||||
|
CTransaction tx(mtx);
|
||||||
|
|
||||||
|
BOOST_CHECK(tx.IsCoinBase());
|
||||||
|
|
||||||
|
CValidationState state;
|
||||||
|
UpdateCoins(tx, state, cache, 100);
|
||||||
|
|
||||||
|
// Create coinbase spend
|
||||||
|
CMutableTransaction mtx2;
|
||||||
|
mtx2.vin.resize(1);
|
||||||
|
mtx2.vin[0].prevout = COutPoint(tx.GetHash(), 0);
|
||||||
|
mtx2.vin[0].scriptSig = CScript() << OP_1;
|
||||||
|
mtx2.vin[0].nSequence = 0;
|
||||||
|
|
||||||
|
{
|
||||||
|
CTransaction tx2(mtx2);
|
||||||
|
BOOST_CHECK(NonContextualCheckInputs(tx2, state, cache, false, SCRIPT_VERIFY_NONE, false, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
mtx2.vout.resize(1);
|
||||||
|
mtx2.vout[0].nValue = 500;
|
||||||
|
mtx2.vout[0].scriptPubKey = CScript() << OP_1;
|
||||||
|
|
||||||
|
{
|
||||||
|
CTransaction tx2(mtx2);
|
||||||
|
BOOST_CHECK(!NonContextualCheckInputs(tx2, state, cache, false, SCRIPT_VERIFY_NONE, false, NULL));
|
||||||
|
BOOST_CHECK(state.GetRejectReason() == "bad-txns-coinbase-spend-has-transparent-outputs");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|||||||
Reference in New Issue
Block a user