Changeset View
Changeset View
Standalone View
Standalone View
src/test/miner_tests.cpp
// Copyright (c) 2011-2016 The Bitcoin Core developers | // Copyright (c) 2011-2016 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include "miner.h" | #include "miner.h" | ||||
#include "chainparams.h" | #include "chainparams.h" | ||||
#include "coins.h" | #include "coins.h" | ||||
#include "config.h" | #include "config.h" | ||||
#include "consensus/consensus.h" | #include "consensus/consensus.h" | ||||
#include "consensus/merkle.h" | #include "consensus/merkle.h" | ||||
#include "consensus/validation.h" | #include "consensus/validation.h" | ||||
#include "policy/policy.h" | #include "policy/policy.h" | ||||
#include "pubkey.h" | #include "pubkey.h" | ||||
▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | |||||
// Note that this test assumes blockprioritypercentage is 0. | // Note that this test assumes blockprioritypercentage is 0. | ||||
void TestPackageSelection(const CChainParams &chainparams, CScript scriptPubKey, | void TestPackageSelection(const CChainParams &chainparams, CScript scriptPubKey, | ||||
std::vector<CTransactionRef> &txFirst) { | std::vector<CTransactionRef> &txFirst) { | ||||
// Test the ancestor feerate transaction selection. | // Test the ancestor feerate transaction selection. | ||||
TestMemPoolEntryHelper entry; | TestMemPoolEntryHelper entry; | ||||
GlobalConfig config; | GlobalConfig config; | ||||
// test 0 fee transaction is included in a block with | |||||
// default configuration. | |||||
blockMinFeeRate = CFeeRate(Amount(0)); | |||||
// Test that a medium fee transaction will be selected after a higher fee | |||||
// rate package with a low fee rate parent. | |||||
CMutableTransaction tx; | |||||
tx.vin.resize(1); | |||||
tx.vin[0].scriptSig = CScript() << OP_1; | |||||
tx.vin[0].prevout.hash = txFirst[0]->GetId(); | |||||
tx.vin[0].prevout.n = 0; | |||||
tx.vout.resize(1); | |||||
tx.vout[0].nValue = Amount(5000000000LL); | |||||
// This tx has a low fee: 1000 satoshis. | |||||
// Save this txid for later use. | |||||
uint256 zeroFeeTx = tx.GetId(); | |||||
mempool.addUnchecked( | |||||
zeroFeeTx, | |||||
entry.Fee(Amount(0)).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); | |||||
std::unique_ptr<CBlockTemplate> pblocktemplate = | |||||
BlockAssembler(config, chainparams).CreateNewBlock(scriptPubKey); | |||||
BOOST_CHECK(pblocktemplate->block.vtx[1]->GetId() == zeroFeeTx); | |||||
// these 3 tests assume blockprioritypercentage is 0. | // these 3 tests assume blockprioritypercentage is 0. | ||||
config.SetBlockPriorityPercentage(0); | config.SetBlockPriorityPercentage(0); | ||||
// the following tests assume that minimum fee rate is 1000 satoshi per kB. | |||||
BlockAssembler ba(config, chainparams); | |||||
ba.SetBlockMinTxFee(Amount(1000)); | |||||
blockMinFeeRate = CFeeRate(Amount(1000)); | |||||
// Test that a medium fee transaction will be selected after a higher fee | // Test that a medium fee transaction will be selected after a higher fee | ||||
// rate package with a low fee rate parent. | // rate package with a low fee rate parent. | ||||
CMutableTransaction tx; | |||||
tx.vin.resize(1); | tx.vin.resize(1); | ||||
tx.vin[0].scriptSig = CScript() << OP_1; | tx.vin[0].scriptSig = CScript() << OP_1; | ||||
tx.vin[0].prevout.hash = txFirst[0]->GetId(); | tx.vin[0].prevout.hash = txFirst[0]->GetId(); | ||||
tx.vin[0].prevout.n = 0; | tx.vin[0].prevout.n = 0; | ||||
tx.vout.resize(1); | tx.vout.resize(1); | ||||
tx.vout[0].nValue = Amount(5000000000LL - 1000); | tx.vout[0].nValue = Amount(5000000000LL - 1000); | ||||
// This tx has a low fee: 1000 satoshis. | // This tx has a low fee: 1000 satoshis. | ||||
// Save this txid for later use. | // Save this txid for later use. | ||||
Show All 17 Lines | void TestPackageSelection(const CChainParams &chainparams, CScript scriptPubKey, | ||||
// 50k satoshi fee. | // 50k satoshi fee. | ||||
tx.vout[0].nValue = Amount(5000000000LL - 1000 - 50000); | tx.vout[0].nValue = Amount(5000000000LL - 1000 - 50000); | ||||
uint256 hashHighFeeTx = tx.GetId(); | uint256 hashHighFeeTx = tx.GetId(); | ||||
mempool.addUnchecked(hashHighFeeTx, entry.Fee(Amount(50000)) | mempool.addUnchecked(hashHighFeeTx, entry.Fee(Amount(50000)) | ||||
.Time(GetTime()) | .Time(GetTime()) | ||||
.SpendsCoinbase(false) | .SpendsCoinbase(false) | ||||
.FromTx(tx)); | .FromTx(tx)); | ||||
std::unique_ptr<CBlockTemplate> pblocktemplate = | pblocktemplate = ba.CreateNewBlock(scriptPubKey); | ||||
BlockAssembler(config, chainparams).CreateNewBlock(scriptPubKey); | |||||
BOOST_CHECK(pblocktemplate->block.vtx[1]->GetId() == hashParentTx); | BOOST_CHECK(pblocktemplate->block.vtx[1]->GetId() == hashParentTx); | ||||
BOOST_CHECK(pblocktemplate->block.vtx[2]->GetId() == hashHighFeeTx); | BOOST_CHECK(pblocktemplate->block.vtx[2]->GetId() == hashHighFeeTx); | ||||
BOOST_CHECK(pblocktemplate->block.vtx[3]->GetId() == hashMediumFeeTx); | BOOST_CHECK(pblocktemplate->block.vtx[3]->GetId() == hashMediumFeeTx); | ||||
// Test that a package below the block min tx fee doesn't get included | // Test that a package below the block min tx fee doesn't get included | ||||
tx.vin[0].prevout.hash = hashHighFeeTx; | tx.vin[0].prevout.hash = hashHighFeeTx; | ||||
// 0 fee. | // 0 fee. | ||||
tx.vout[0].nValue = Amount(5000000000LL - 1000 - 50000); | tx.vout[0].nValue = Amount(5000000000LL - 1000 - 50000); | ||||
uint256 hashFreeTx = tx.GetId(); | uint256 hashFreeTx = tx.GetId(); | ||||
mempool.addUnchecked(hashFreeTx, entry.Fee(Amount(0)).FromTx(tx)); | mempool.addUnchecked(hashFreeTx, entry.Fee(Amount(0)).FromTx(tx)); | ||||
size_t freeTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); | size_t freeTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); | ||||
// Calculate a fee on child transaction that will put the package just | // Calculate a fee on child transaction that will put the package just | ||||
// below the block min tx fee (assuming 1 child tx of the same size). | // below the block min tx fee (assuming 1 child tx of the same size). | ||||
Amount feeToUse = blockMinFeeRate.GetFee(2 * freeTxSize) - Amount(1); | Amount feeToUse = blockMinFeeRate.GetFee(2 * freeTxSize) - Amount(1); | ||||
tx.vin[0].prevout.hash = hashFreeTx; | tx.vin[0].prevout.hash = hashFreeTx; | ||||
tx.vout[0].nValue = Amount(5000000000LL - 1000 - 50000) - feeToUse; | tx.vout[0].nValue = Amount(5000000000LL - 1000 - 50000) - feeToUse; | ||||
uint256 hashLowFeeTx = tx.GetId(); | uint256 hashLowFeeTx = tx.GetId(); | ||||
mempool.addUnchecked(hashLowFeeTx, entry.Fee(feeToUse).FromTx(tx)); | mempool.addUnchecked(hashLowFeeTx, entry.Fee(feeToUse).FromTx(tx)); | ||||
pblocktemplate = | pblocktemplate = ba.CreateNewBlock(scriptPubKey); | ||||
BlockAssembler(config, chainparams).CreateNewBlock(scriptPubKey); | |||||
// Verify that the free tx and the low fee tx didn't get selected. | // Verify that the free tx and the low fee tx didn't get selected. | ||||
for (size_t i = 0; i < pblocktemplate->block.vtx.size(); ++i) { | for (size_t i = 0; i < pblocktemplate->block.vtx.size(); ++i) { | ||||
BOOST_CHECK(pblocktemplate->block.vtx[i]->GetId() != hashFreeTx); | BOOST_CHECK(pblocktemplate->block.vtx[i]->GetId() != hashFreeTx); | ||||
BOOST_CHECK(pblocktemplate->block.vtx[i]->GetId() != hashLowFeeTx); | BOOST_CHECK(pblocktemplate->block.vtx[i]->GetId() != hashLowFeeTx); | ||||
} | } | ||||
// Test that packages above the min relay fee do get included, even if one | // Test that packages above the min relay fee do get included, even if one | ||||
// of the transactions is below the min relay fee. Remove the low fee | // of the transactions is below the min relay fee. Remove the low fee | ||||
// transaction and replace with a higher fee transaction | // transaction and replace with a higher fee transaction | ||||
mempool.removeRecursive(tx); | mempool.removeRecursive(tx); | ||||
// Now we should be just over the min relay fee. | // Now we should be just over the min relay fee. | ||||
tx.vout[0].nValue -= Amount(2); | tx.vout[0].nValue -= Amount(2); | ||||
hashLowFeeTx = tx.GetId(); | hashLowFeeTx = tx.GetId(); | ||||
mempool.addUnchecked(hashLowFeeTx, | mempool.addUnchecked(hashLowFeeTx, | ||||
entry.Fee(feeToUse + Amount(2)).FromTx(tx)); | entry.Fee(feeToUse + Amount(2)).FromTx(tx)); | ||||
pblocktemplate = | pblocktemplate = ba.CreateNewBlock(scriptPubKey); | ||||
BlockAssembler(config, chainparams).CreateNewBlock(scriptPubKey); | |||||
BOOST_CHECK(pblocktemplate->block.vtx[4]->GetId() == hashFreeTx); | BOOST_CHECK(pblocktemplate->block.vtx[4]->GetId() == hashFreeTx); | ||||
BOOST_CHECK(pblocktemplate->block.vtx[5]->GetId() == hashLowFeeTx); | BOOST_CHECK(pblocktemplate->block.vtx[5]->GetId() == hashLowFeeTx); | ||||
// Test that transaction selection properly updates ancestor fee | // Test that transaction selection properly updates ancestor fee | ||||
// calculations as ancestor transactions get included in a block. Add a | // calculations as ancestor transactions get included in a block. Add a | ||||
// 0-fee transaction that has 2 outputs. | // 0-fee transaction that has 2 outputs. | ||||
tx.vin[0].prevout.hash = txFirst[2]->GetId(); | tx.vin[0].prevout.hash = txFirst[2]->GetId(); | ||||
tx.vout.resize(2); | tx.vout.resize(2); | ||||
tx.vout[0].nValue = Amount(5000000000LL - 100000000); | tx.vout[0].nValue = Amount(5000000000LL - 100000000); | ||||
// 1BCC output. | // 1BCC output. | ||||
tx.vout[1].nValue = Amount(100000000); | tx.vout[1].nValue = Amount(100000000); | ||||
uint256 hashFreeTx2 = tx.GetId(); | uint256 hashFreeTx2 = tx.GetId(); | ||||
mempool.addUnchecked(hashFreeTx2, | mempool.addUnchecked(hashFreeTx2, | ||||
entry.Fee(Amount(0)).SpendsCoinbase(true).FromTx(tx)); | entry.Fee(Amount(0)).SpendsCoinbase(true).FromTx(tx)); | ||||
// This tx can't be mined by itself. | // This tx can't be mined by itself. | ||||
tx.vin[0].prevout.hash = hashFreeTx2; | tx.vin[0].prevout.hash = hashFreeTx2; | ||||
tx.vout.resize(1); | tx.vout.resize(1); | ||||
feeToUse = blockMinFeeRate.GetFee(freeTxSize); | feeToUse = blockMinFeeRate.GetFee(freeTxSize); | ||||
tx.vout[0].nValue = Amount(5000000000LL) - Amount(100000000) - feeToUse; | tx.vout[0].nValue = Amount(5000000000LL) - Amount(100000000) - feeToUse; | ||||
uint256 hashLowFeeTx2 = tx.GetId(); | uint256 hashLowFeeTx2 = tx.GetId(); | ||||
mempool.addUnchecked(hashLowFeeTx2, | mempool.addUnchecked(hashLowFeeTx2, | ||||
entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx)); | entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx)); | ||||
pblocktemplate = | pblocktemplate = ba.CreateNewBlock(scriptPubKey); | ||||
BlockAssembler(config, chainparams).CreateNewBlock(scriptPubKey); | |||||
// Verify that this tx isn't selected. | // Verify that this tx isn't selected. | ||||
for (size_t i = 0; i < pblocktemplate->block.vtx.size(); ++i) { | for (size_t i = 0; i < pblocktemplate->block.vtx.size(); ++i) { | ||||
BOOST_CHECK(pblocktemplate->block.vtx[i]->GetId() != hashFreeTx2); | BOOST_CHECK(pblocktemplate->block.vtx[i]->GetId() != hashFreeTx2); | ||||
BOOST_CHECK(pblocktemplate->block.vtx[i]->GetId() != hashLowFeeTx2); | BOOST_CHECK(pblocktemplate->block.vtx[i]->GetId() != hashLowFeeTx2); | ||||
} | } | ||||
// This tx will be mineable, and should cause hashLowFeeTx2 to be selected | // This tx will be mineable, and should cause hashLowFeeTx2 to be selected | ||||
// as well. | // as well. | ||||
tx.vin[0].prevout.n = 1; | tx.vin[0].prevout.n = 1; | ||||
// 10k satoshi fee. | // 10k satoshi fee. | ||||
tx.vout[0].nValue = Amount(100000000 - 10000); | tx.vout[0].nValue = Amount(100000000 - 10000); | ||||
mempool.addUnchecked(tx.GetId(), entry.Fee(Amount(10000)).FromTx(tx)); | mempool.addUnchecked(tx.GetId(), entry.Fee(Amount(10000)).FromTx(tx)); | ||||
pblocktemplate = | pblocktemplate = ba.CreateNewBlock(scriptPubKey); | ||||
BlockAssembler(config, chainparams).CreateNewBlock(scriptPubKey); | |||||
BOOST_CHECK(pblocktemplate->block.vtx[8]->GetId() == hashLowFeeTx2); | BOOST_CHECK(pblocktemplate->block.vtx[8]->GetId() == hashLowFeeTx2); | ||||
} | } | ||||
void TestCoinbaseMessageEB(uint64_t eb, std::string cbmsg) { | void TestCoinbaseMessageEB(uint64_t eb, std::string cbmsg) { | ||||
GlobalConfig config; | GlobalConfig config; | ||||
config.SetMaxBlockSize(eb); | config.SetMaxBlockSize(eb); | ||||
const CChainParams &chainparams = config.GetChainParams(); | const CChainParams &chainparams = config.GetChainParams(); | ||||
▲ Show 20 Lines • Show All 567 Lines • Show Last 20 Lines |