| 36 | static const uint64_t MEMPOOL_DUMP_VERSION = 1; |
| 37 | |
| 38 | bool LoadMempool(CTxMemPool &pool, const fs::path &load_path, |
| 39 | Chainstate &active_chainstate, |
| 40 | FopenFn mockable_fopen_function) { |
| 41 | if (load_path.empty()) { |
| 42 | return false; |
| 43 | } |
| 44 | |
| 45 | AutoFile file{mockable_fopen_function(load_path, "rb")}; |
| 46 | if (file.IsNull()) { |
| 47 | LogPrintf( |
| 48 | "Failed to open mempool file from disk. Continuing anyway.\n"); |
| 49 | return false; |
| 50 | } |
| 51 | |
| 52 | int64_t count = 0; |
| 53 | int64_t expired = 0; |
| 54 | int64_t failed = 0; |
| 55 | int64_t already_there = 0; |
| 56 | int64_t unbroadcast = 0; |
| 57 | auto now = NodeClock::now(); |
| 58 | |
| 59 | try { |
| 60 | uint64_t version; |
| 61 | file >> version; |
| 62 | if (version != MEMPOOL_DUMP_VERSION) { |
| 63 | return false; |
| 64 | } |
| 65 | |
| 66 | uint64_t num; |
| 67 | file >> num; |
| 68 | while (num) { |
| 69 | --num; |
| 70 | CTransactionRef tx; |
| 71 | int64_t nTime; |
| 72 | int64_t nFeeDelta; |
| 73 | file >> tx; |
| 74 | file >> nTime; |
| 75 | file >> nFeeDelta; |
| 76 | |
| 77 | Amount amountdelta = nFeeDelta * SATOSHI; |
| 78 | if (amountdelta != Amount::zero()) { |
| 79 | pool.PrioritiseTransaction(tx->GetId(), amountdelta); |
| 80 | } |
| 81 | if (nTime > |
| 82 | TicksSinceEpoch<std::chrono::seconds>(now - pool.m_expiry)) { |
| 83 | LOCK(cs_main); |
| 84 | const auto &accepted = |
| 85 | AcceptToMemoryPool(active_chainstate, tx, nTime, |
| 86 | /*bypass_limits=*/false, |
| 87 | /*test_accept=*/false); |
| 88 | if (accepted.m_result_type == |
| 89 | MempoolAcceptResult::ResultType::VALID) { |
| 90 | ++count; |
| 91 | } else { |
| 92 | // mempool may contain the transaction already, e.g. from |
| 93 | // wallet(s) having loaded it while we were processing |
| 94 | // mempool transactions; consider these as valid, instead of |
| 95 | // failed, but mark them as 'already there' |
no test coverage detected