Skip to content

Commit

Permalink
[BlockAssembler]: return selected packages feerate and vsize
Browse files Browse the repository at this point in the history
- The commit also test that block assembler now returns selected package
  vsize's and fee rates.

Co-authored-by: ismaelsadeeq <ask4ismailsadiq@gmail.com>
  • Loading branch information
willcl-ark and ismaelsadeeq committed Aug 12, 2024
1 parent 20ccb30 commit 8a830f1
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 4 deletions.
3 changes: 3 additions & 0 deletions src/node/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
Ticks<MillisecondsDouble>(time_2 - time_1),
Ticks<MillisecondsDouble>(time_2 - time_start));

pblocktemplate->vFeeratePerSize = std::move(feerate_per_size);

return std::move(pblocktemplate);
}

Expand Down Expand Up @@ -417,6 +419,7 @@ void BlockAssembler::addPackageTxs(const CTxMemPool& mempool, int& nPackagesSele
}

++nPackagesSelected;
feerate_per_size.emplace_back(CFeeRate{packageFees, static_cast<uint32_t>(packageSize)}, static_cast<uint32_t>(packageSize));

// Update transactions that depend on each of these
nDescendantsUpdated += UpdatePackagesForAdded(mempool, ancestors, mapModifiedTx);
Expand Down
4 changes: 4 additions & 0 deletions src/node/miner.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
#define BITCOIN_NODE_MINER_H

#include <node/types.h>
#include <policy/feerate.h>
#include <policy/policy.h>
#include <primitives/block.h>
#include <txmempool.h>

#include <memory>
#include <optional>
#include <stdint.h>
#include <tuple>

#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/indexed_by.hpp>
Expand All @@ -39,6 +41,7 @@ struct CBlockTemplate
std::vector<CAmount> vTxFees;
std::vector<int64_t> vTxSigOpsCost;
std::vector<unsigned char> vchCoinbaseCommitment;
std::vector<std::tuple<CFeeRate, uint32_t>> vFeeratePerSize;
};

// Container for tracking updates to ancestor feerate as we include (parent)
Expand Down Expand Up @@ -144,6 +147,7 @@ class BlockAssembler
uint64_t nBlockSigOpsCost;
CAmount nFees;
std::unordered_set<Txid, SaltedTxidHasher> inBlock;
std::vector<std::tuple<CFeeRate, uint32_t>> feerate_per_size;

// Chain context for the block
int nHeight;
Expand Down
31 changes: 27 additions & 4 deletions src/test/miner_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <consensus/merkle.h>
#include <consensus/tx_verify.h>
#include <node/miner.h>
#include <policy/feerate.h>
#include <policy/policy.h>
#include <test/util/random.h>
#include <test/util/txmempool.h>
Expand All @@ -24,6 +25,9 @@
#include <test/util/setup_common.h>

#include <memory>
#include <optional>
#include <tuple>
#include <vector>

#include <boost/test/unit_test.hpp>

Expand Down Expand Up @@ -54,6 +58,7 @@ struct MinerTestingSetup : public TestingSetup {
return *m_node.mempool;
}
BlockAssembler AssemblerForTest(CTxMemPool& tx_mempool);

};
} // namespace miner_tests

Expand Down Expand Up @@ -122,26 +127,44 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const
tx.vout[0].nValue = 5000000000LL - 1000;
// This tx has a low fee: 1000 satoshis
Txid hashParentTx = tx.GetHash(); // save this txid for later use
tx_mempool.addUnchecked(entry.Fee(1000).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
const auto lowFeeTx{entry.Fee(1000).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx)};
tx_mempool.addUnchecked(lowFeeTx);

// This tx has a medium fee: 10000 satoshis
tx.vin[0].prevout.hash = txFirst[1]->GetHash();
tx.vout[0].nValue = 5000000000LL - 10000;
Txid hashMediumFeeTx = tx.GetHash();
tx_mempool.addUnchecked(entry.Fee(10000).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
const auto mediumFeeTx{entry.Fee(10000).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx)};
tx_mempool.addUnchecked(mediumFeeTx);

// This tx has a high fee, but depends on the first transaction
tx.vin[0].prevout.hash = hashParentTx;
tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 50k satoshi fee
Txid hashHighFeeTx = tx.GetHash();
tx_mempool.addUnchecked(entry.Fee(50000).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx));
const auto highFeeChildTx{entry.Fee(50000).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx)};
tx_mempool.addUnchecked(highFeeChildTx);

std::unique_ptr<CBlockTemplate> pblocktemplate = AssemblerForTest(tx_mempool).CreateNewBlock(scriptPubKey);
auto assembler{AssemblerForTest(tx_mempool)};
auto pblocktemplate{assembler.CreateNewBlock(scriptPubKey)};
const auto blockFeeAndVsizes{pblocktemplate->vFeeratePerSize};
BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 4U);
BOOST_CHECK(pblocktemplate->block.vtx[1]->GetHash() == hashParentTx);
BOOST_CHECK(pblocktemplate->block.vtx[2]->GetHash() == hashHighFeeTx);
BOOST_CHECK(pblocktemplate->block.vtx[3]->GetHash() == hashMediumFeeTx);

BOOST_CHECK(blockFeeAndVsizes.size() == 2);
// lowFeeTx and highFeeChildTx are added to the block as a package.
const auto packageFee{lowFeeTx.GetFee() + highFeeChildTx.GetFee()};
const auto packageSize{static_cast<uint32_t>(lowFeeTx.GetTxSize() + highFeeChildTx.GetTxSize())};
CFeeRate packageFeeRate{packageFee, packageSize};
BOOST_CHECK(std::get<0>(blockFeeAndVsizes[0]) == packageFeeRate);
BOOST_CHECK(std::get<1>(blockFeeAndVsizes[0]) == packageSize);

const auto mediumFeeTxSize{static_cast<uint32_t>(mediumFeeTx.GetTxSize())};
CFeeRate mediumFeeRate{mediumFeeTx.GetFee(), mediumFeeTxSize};
BOOST_CHECK(std::get<0>(blockFeeAndVsizes[1]) == mediumFeeRate);
BOOST_CHECK(std::get<1>(blockFeeAndVsizes[1]) == mediumFeeTxSize);

// Test that a package below the block min tx fee doesn't get included
tx.vin[0].prevout.hash = hashHighFeeTx;
tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 0 fee
Expand Down

0 comments on commit 8a830f1

Please sign in to comment.