| 1070 | } |
| 1071 | |
| 1072 | void GenericClusterImpl::Updated(TxGraphImpl& graph, int level, bool rename) noexcept |
| 1073 | { |
| 1074 | // Update all the Locators for this Cluster's Entry objects. |
| 1075 | for (DepGraphIndex idx : m_linearization) { |
| 1076 | auto& entry = graph.m_entries[m_mapping[idx]]; |
| 1077 | // Discard any potential ChunkData prior to modifying the Cluster (as that could |
| 1078 | // invalidate its ordering). |
| 1079 | if (level == 0 && !rename) graph.ClearChunkData(entry); |
| 1080 | entry.m_locator[level].SetPresent(this, idx); |
| 1081 | } |
| 1082 | // If this is for the main graph (level = 0), and the Cluster's quality is ACCEPTABLE or |
| 1083 | // OPTIMAL, compute its chunking and store its information in the Entry's m_main_lin_index |
| 1084 | // and m_main_chunk_feerate. These fields are only accessed after making the entire graph |
| 1085 | // ACCEPTABLE, so it is pointless to compute these if we haven't reached that quality level |
| 1086 | // yet. |
| 1087 | // When rename=true, this is always performed for level 0, to make sure the values inside the |
| 1088 | // entries remain consistent with the chunk index (otherwise unrelated chunk index operations |
| 1089 | // could cause the index to become corrupted, by inserting elements in the wrong place). |
| 1090 | if (level == 0 && (rename || IsAcceptable())) { |
| 1091 | auto chunking = ChunkLinearizationInfo(m_depgraph, m_linearization); |
| 1092 | LinearizationIndex lin_idx{0}; |
| 1093 | /** The sum of all chunk feerate FeeFracs with the same feerate as the current chunk, |
| 1094 | * up to and including the current chunk. */ |
| 1095 | FeeFrac equal_feerate_chunk_feerate; |
| 1096 | // Iterate over the chunks. |
| 1097 | for (unsigned chunk_idx = 0; chunk_idx < chunking.size(); ++chunk_idx) { |
| 1098 | auto& chunk = chunking[chunk_idx]; |
| 1099 | auto chunk_count = chunk.transactions.Count(); |
| 1100 | Assume(chunk_count > 0); |
| 1101 | // Update equal_feerate_chunk_feerate to include this chunk, starting over when the |
| 1102 | // feerate changed. |
| 1103 | if (ByRatio{chunk.feerate} < ByRatio{equal_feerate_chunk_feerate}) { |
| 1104 | equal_feerate_chunk_feerate = chunk.feerate; |
| 1105 | } else { |
| 1106 | // Note that this is adding fees to fees, and sizes to sizes, so the overall |
| 1107 | // ratio remains the same; it's just accounting for the size of the added chunk. |
| 1108 | equal_feerate_chunk_feerate += chunk.feerate; |
| 1109 | } |
| 1110 | // Determine the m_fallback_order maximum transaction in the chunk. |
| 1111 | auto it = chunk.transactions.begin(); |
| 1112 | GraphIndex max_element = m_mapping[*it]; |
| 1113 | ++it; |
| 1114 | while (it != chunk.transactions.end()) { |
| 1115 | GraphIndex this_element = m_mapping[*it]; |
| 1116 | if (graph.m_fallback_order(*graph.m_entries[this_element].m_ref, *graph.m_entries[max_element].m_ref) > 0) { |
| 1117 | max_element = this_element; |
| 1118 | } |
| 1119 | ++it; |
| 1120 | } |
| 1121 | // Iterate over the transactions in the linearization, which must match those in chunk. |
| 1122 | while (true) { |
| 1123 | DepGraphIndex idx = m_linearization[lin_idx]; |
| 1124 | GraphIndex graph_idx = m_mapping[idx]; |
| 1125 | auto& entry = graph.m_entries[graph_idx]; |
| 1126 | entry.m_main_lin_index = lin_idx++; |
| 1127 | entry.m_main_chunk_feerate = FeePerWeight::FromFeeFrac(chunk.feerate); |
| 1128 | entry.m_main_equal_feerate_chunk_prefix_size = equal_feerate_chunk_feerate.size; |
| 1129 | entry.m_main_max_chunk_fallback = max_element; |
no test coverage detected