aboutsummaryrefslogtreecommitdiff
path: root/src/node
diff options
context:
space:
mode:
authorglozow <gloriajzhao@gmail.com>2023-07-14 11:28:00 +0100
committerglozow <gloriajzhao@gmail.com>2023-11-03 10:17:41 +0000
commitf4b1b24a3bcd0199a6d2e828ad46033e1368336e (patch)
tree793da6dcda5affff7652b6865bb1aab9d5ca0290 /src/node
parent004075963f12f17c3c399d81e3b48d6a8151aebd (diff)
downloadbitcoin-f4b1b24a3bcd0199a6d2e828ad46033e1368336e.tar.xz
[MiniMiner] track inclusion order and add Linearize() function
Sometimes we are just interested in the order in which transactions would be included in a block (we want to "linearize" the transactions). Track and store this information. This doesn't change any of the bump fee calculations.
Diffstat (limited to 'src/node')
-rw-r--r--src/node/mini_miner.cpp16
-rw-r--r--src/node/mini_miner.h19
2 files changed, 33 insertions, 2 deletions
diff --git a/src/node/mini_miner.cpp b/src/node/mini_miner.cpp
index ea702ab734..3d24a3f58e 100644
--- a/src/node/mini_miner.cpp
+++ b/src/node/mini_miner.cpp
@@ -170,6 +170,7 @@ MiniMiner::MiniMiner(const std::vector<MiniMinerMempoolEntry>& manual_entries,
Assume(m_to_be_replaced.empty());
Assume(m_requested_outpoints_by_txid.empty());
Assume(m_bump_fees.empty());
+ Assume(m_inclusion_order.empty());
SanityCheck();
}
@@ -255,6 +256,7 @@ void MiniMiner::SanityCheck() const
void MiniMiner::BuildMockTemplate(std::optional<CFeeRate> target_feerate)
{
const auto num_txns{m_entries_by_txid.size()};
+ uint32_t sequence_num{0};
while (!m_entries_by_txid.empty()) {
// Sort again, since transaction removal may change some m_entries' ancestor feerates.
std::sort(m_entries.begin(), m_entries.end(), AncestorFeerateComparator());
@@ -290,18 +292,32 @@ void MiniMiner::BuildMockTemplate(std::optional<CFeeRate> target_feerate)
to_process.erase(iter);
}
}
+ // Track the order in which transactions were selected.
+ for (const auto& ancestor : ancestors) {
+ m_inclusion_order.emplace(Txid::FromUint256(ancestor->first), sequence_num);
+ }
DeleteAncestorPackage(ancestors);
SanityCheck();
+ ++sequence_num;
}
if (!target_feerate.has_value()) {
Assume(m_in_block.size() == num_txns);
} else {
Assume(m_in_block.empty() || m_total_fees >= target_feerate->GetFee(m_total_vsize));
}
+ Assume(m_in_block.empty() || sequence_num > 0);
+ Assume(m_in_block.size() == m_inclusion_order.size());
// Do not try to continue building the block template with a different feerate.
m_ready_to_calculate = false;
}
+
+std::map<Txid, uint32_t> MiniMiner::Linearize()
+{
+ BuildMockTemplate(std::nullopt);
+ return m_inclusion_order;
+}
+
std::map<COutPoint, CAmount> MiniMiner::CalculateBumpFees(const CFeeRate& target_feerate)
{
if (!m_ready_to_calculate) return {};
diff --git a/src/node/mini_miner.h b/src/node/mini_miner.h
index e0051f3364..8f86709ae4 100644
--- a/src/node/mini_miner.h
+++ b/src/node/mini_miner.h
@@ -67,8 +67,14 @@ struct IteratorComparator
}
};
-/** A minimal version of BlockAssembler. Allows us to run the mining algorithm on a subset of
- * mempool transactions, ignoring consensus rules, to calculate mining scores. */
+/** A minimal version of BlockAssembler, using the same ancestor set scoring algorithm. Allows us to
+ * run this algorithm on a limited set of transactions (e.g. subset of mempool or transactions that
+ * are not yet in mempool) instead of the entire mempool, ignoring consensus rules.
+ * Callers may use this to:
+ * - Calculate the "bump fee" needed to spend an unconfirmed UTXO at a given feerate
+ * - "Linearize" a list of transactions to see the order in which they would be selected for
+ * inclusion in a block
+ */
class MiniMiner
{
// When true, a caller may use CalculateBumpFees(). Becomes false if we failed to retrieve
@@ -84,6 +90,10 @@ class MiniMiner
// the same tx will have the same bumpfee. Excludes non-mempool transactions.
std::map<uint256, std::vector<COutPoint>> m_requested_outpoints_by_txid;
+ // Txid to a number representing the order in which this transaction was included (smaller
+ // number = included earlier). Transactions included in an ancestor set together have the same
+ // sequence number.
+ std::map<Txid, uint32_t> m_inclusion_order;
// What we're trying to calculate. Outpoint to the fee needed to bring the transaction to the target feerate.
std::map<COutPoint, CAmount> m_bump_fees;
@@ -151,6 +161,11 @@ public:
* if it cannot be calculated. */
std::optional<CAmount> CalculateTotalBumpFees(const CFeeRate& target_feerate);
+ /** Construct a new block template with all of the transactions and calculate the order in which
+ * they are selected. Returns the sequence number (lower = selected earlier) with which each
+ * transaction was selected, indexed by txid, or an empty map if it cannot be calculated.
+ */
+ std::map<Txid, uint32_t> Linearize();
};
} // namespace node