This transaction selection algorithm orders the mempool based on feerate of a transaction including all unconfirmed ancestors. Since we don't remove transactions from the mempool as we select them for block inclusion, we need an alternate method of updating the feerate of a transaction with its not-yet-selected ancestors as we go. This is accomplished by walking the in-mempool descendants of selec
| 371 | // mapModifiedTxs with the next transaction in the mempool to decide what |
| 372 | // transaction package to work on next. |
| 373 | void BlockAssembler::addPackageTxs(int& nPackagesSelected, int& nDescendantsUpdated, std::chrono::seconds min_tx_age) |
| 374 | { |
| 375 | AssertLockHeld(m_mempool.cs); |
| 376 | |
| 377 | // mapModifiedTx will store sorted packages after they are modified |
| 378 | // because some of their txs are already in the block |
| 379 | indexed_modified_transaction_set mapModifiedTx; |
| 380 | // Keep track of entries that failed inclusion, to avoid duplicate work |
| 381 | CTxMemPool::setEntries failedTx; |
| 382 | |
| 383 | // Start by adding all descendants of previously added txs to mapModifiedTx |
| 384 | // and modifying them for their already included ancestors |
| 385 | UpdatePackagesForAdded(inBlock, mapModifiedTx); |
| 386 | |
| 387 | // ELEMENTS: we use confidential_score instead of ancestor_score |
| 388 | CTxMemPool::indexed_transaction_set::index<confidential_score>::type::iterator mi = m_mempool.mapTx.get<confidential_score>().begin(); |
| 389 | CTxMemPool::txiter iter; |
| 390 | |
| 391 | // Limit the number of attempts to add transactions to the block when it is |
| 392 | // close to full; this is just a simple heuristic to finish quickly if the |
| 393 | // mempool has a lot of entries. |
| 394 | const int64_t MAX_CONSECUTIVE_FAILURES = 1000; |
| 395 | constexpr int32_t BLOCK_FULL_ENOUGH_WEIGHT_DELTA = 4000; |
| 396 | int64_t nConsecutiveFailed = 0; |
| 397 | |
| 398 | while (mi != m_mempool.mapTx.get<confidential_score>().end() || !mapModifiedTx.empty()) { |
| 399 | // First try to find a new transaction in mapTx to evaluate. |
| 400 | if (mi != m_mempool.mapTx.get<confidential_score>().end() && |
| 401 | SkipMapTxEntry(m_mempool.mapTx.project<0>(mi), mapModifiedTx, failedTx)) { |
| 402 | ++mi; |
| 403 | continue; |
| 404 | } |
| 405 | |
| 406 | // Now that mi is not stale, determine which transaction to evaluate: |
| 407 | // the next entry from mapTx, or the best from mapModifiedTx? |
| 408 | bool fUsingModified = false; |
| 409 | |
| 410 | modconftxscoreiter modit = mapModifiedTx.get<confidential_score>().begin(); |
| 411 | if (mi == m_mempool.mapTx.get<confidential_score>().end()) { |
| 412 | // We're out of entries in mapTx; use the entry from mapModifiedTx |
| 413 | iter = modit->iter; |
| 414 | fUsingModified = true; |
| 415 | } else { |
| 416 | // Try to compare the mapTx entry to the mapModifiedTx entry |
| 417 | iter = m_mempool.mapTx.project<0>(mi); |
| 418 | if (modit != mapModifiedTx.get<confidential_score>().end() && |
| 419 | CompareTxMemPoolEntryByConfidentialFee()(*modit, CTxMemPoolModifiedEntry(iter))) { |
| 420 | // The best entry in mapModifiedTx has higher score |
| 421 | // than the one from mapTx. |
| 422 | // Switch which transaction (package) to consider |
| 423 | iter = modit->iter; |
| 424 | fUsingModified = true; |
| 425 | } else { |
| 426 | // Either no entry in mapModifiedTx, or it's worse than mapTx. |
| 427 | // Increment mi for the next loop iteration. |
| 428 | ++mi; |
| 429 | } |
| 430 | } |
nothing calls this directly
no test coverage detected