Skip to content

Commit c734081

Browse files
committed
txgraph: Introduce TxGraph::GetWorstMainChunk (feature)
It returns the last chunk that would be suggested for mining by BlockBuilder objects. This is intended for eviction.
1 parent 394dbe2 commit c734081

File tree

3 files changed

+62
-0
lines changed

3 files changed

+62
-0
lines changed

src/test/fuzz/txgraph.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,32 @@ FUZZ_TARGET(txgraph)
748748
}
749749
builder_data.done = new_done;
750750
break;
751+
} else if (!main_sim.IsOversized() && command-- == 0) {
752+
// GetWorstMainChunk.
753+
auto [worst_chunk, worst_chunk_feerate] = real->GetWorstMainChunk();
754+
// Just do some sanity checks here. Consistency with GetBlockBuilder is checked
755+
// below.
756+
if (main_sim.GetTransactionCount() == 0) {
757+
assert(worst_chunk.empty());
758+
assert(worst_chunk_feerate.IsEmpty());
759+
} else {
760+
assert(!worst_chunk.empty());
761+
SimTxGraph::SetType done;
762+
FeePerWeight sum;
763+
for (TxGraph::Ref* ref : worst_chunk) {
764+
// Each transaction in the chunk must exist in the main graph.
765+
auto simpos = main_sim.Find(ref);
766+
assert(simpos != SimTxGraph::MISSING);
767+
sum += main_sim.graph.FeeRate(simpos);
768+
// Make sure the chunk contains no duplicate transactions.
769+
assert(!done[simpos]);
770+
done.Set(simpos);
771+
// All elements are preceded by all their descendants.
772+
assert(main_sim.graph.Descendants(simpos).IsSubsetOf(done));
773+
}
774+
assert(sum == worst_chunk_feerate);
775+
}
776+
break;
751777
}
752778
}
753779
}
@@ -806,6 +832,8 @@ FUZZ_TARGET(txgraph)
806832
// if nothing is skipped.
807833
auto builder = real->GetBlockBuilder();
808834
std::vector<SimTxGraph::Pos> vec_builder;
835+
std::vector<TxGraph::Ref*> last_chunk;
836+
FeePerWeight last_chunk_feerate;
809837
while (auto chunk = builder->GetCurrentChunk()) {
810838
FeePerWeight sum;
811839
for (TxGraph::Ref* ref : chunk->first) {
@@ -820,10 +848,18 @@ FUZZ_TARGET(txgraph)
820848
vec_builder.push_back(simpos);
821849
}
822850
assert(sum == chunk->second);
851+
last_chunk = std::move(chunk->first);
852+
last_chunk_feerate = chunk->second;
823853
builder->Include();
824854
}
825855
assert(vec_builder == vec1);
826856

857+
// The last chunk returned by the BlockBuilder must match GetWorstMainChunk, in reverse.
858+
std::reverse(last_chunk.begin(), last_chunk.end());
859+
auto [worst_chunk, worst_chunk_feerate] = real->GetWorstMainChunk();
860+
assert(last_chunk == worst_chunk);
861+
assert(last_chunk_feerate == worst_chunk_feerate);
862+
827863
// Check that the implied ordering gives rise to a combined diagram that matches the
828864
// diagram constructed from the individual cluster linearization chunkings.
829865
auto main_real_diagram = get_diagram_fn(/*main_only=*/true);

src/txgraph.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@ class TxGraphImpl final : public TxGraph
545545
std::pair<std::vector<FeeFrac>, std::vector<FeeFrac>> GetMainStagingDiagrams() noexcept final;
546546

547547
std::unique_ptr<BlockBuilder> GetBlockBuilder() noexcept final;
548+
std::pair<std::vector<Ref*>, FeePerWeight> GetWorstMainChunk() noexcept final;
548549

549550
void SanityCheck() const final;
550551
};
@@ -2379,6 +2380,26 @@ std::unique_ptr<TxGraph::BlockBuilder> TxGraphImpl::GetBlockBuilder() noexcept
23792380
return std::make_unique<BlockBuilderImpl>(*this);
23802381
}
23812382

2383+
std::pair<std::vector<TxGraph::Ref*>, FeePerWeight> TxGraphImpl::GetWorstMainChunk() noexcept
2384+
{
2385+
std::pair<std::vector<Ref*>, FeePerWeight> ret;
2386+
// Make sure all clusters in main are up to date, and acceptable.
2387+
MakeAllAcceptable(0);
2388+
Assume(m_main_clusterset.m_deps_to_add.empty());
2389+
// If the graph is not empty, populate ret.
2390+
if (!m_main_chunkindex.empty()) {
2391+
const auto& chunk_data = *m_main_chunkindex.rbegin();
2392+
const auto& chunk_end_entry = m_entries[chunk_data.m_graph_index];
2393+
Cluster* cluster = chunk_end_entry.m_locator[0].cluster;
2394+
ret.first.resize(chunk_data.m_chunk_count);
2395+
auto start_pos = chunk_end_entry.m_main_lin_index + 1 - chunk_data.m_chunk_count;
2396+
cluster->GetClusterRefs(*this, ret.first, start_pos);
2397+
std::reverse(ret.first.begin(), ret.first.end());
2398+
ret.second = chunk_end_entry.m_main_chunk_feerate;
2399+
}
2400+
return ret;
2401+
}
2402+
23822403
} // namespace
23832404

23842405
TxGraph::Ref::~Ref()

src/txgraph.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@ class TxGraph
192192
* oversized. While the returned object exists, no mutators on the main graph are allowed.
193193
* The BlockBuilder object must not outlive the TxGraph it was created with. */
194194
virtual std::unique_ptr<BlockBuilder> GetBlockBuilder() noexcept = 0;
195+
/** Get the last chunk in the main graph, i.e., the last chunk that would be returned by a
196+
* BlockBuilder created now, together with its feerate. The chunk is returned in
197+
* reverse-topological order, so every element is preceded by all its descendants. The main
198+
* graph must not be oversized. If the graph is empty, {{}, FeePerWeight{}} is returned. */
199+
virtual std::pair<std::vector<Ref*>, FeePerWeight> GetWorstMainChunk() noexcept = 0;
195200

196201
/** Perform an internal consistency check on this object. */
197202
virtual void SanityCheck() const = 0;

0 commit comments

Comments
 (0)