Upgrade the database from older formats. * * Currently implemented: from the per-tx utxo model (0.8..0.14.x) to per-txout. */
| 501 | * Currently implemented: from the per-tx utxo model (0.8..0.14.x) to per-txout. |
| 502 | */ |
| 503 | bool CCoinsViewDB::Upgrade() { |
| 504 | std::unique_ptr<CDBIterator> pcursor(m_db->NewIterator()); |
| 505 | pcursor->Seek(std::make_pair(DB_COINS, uint256())); |
| 506 | if (!pcursor->Valid()) { |
| 507 | return true; |
| 508 | } |
| 509 | |
| 510 | int64_t count = 0; |
| 511 | LogPrintf("Upgrading utxo-set database...\n"); |
| 512 | LogPrintf("[0%%]..."); /* Continued */ |
| 513 | uiInterface.ShowProgress(_("Upgrading UTXO database").translated, 0, true); |
| 514 | size_t batch_size = 1 << 24; |
| 515 | CDBBatch batch(*m_db); |
| 516 | int reportDone = 0; |
| 517 | std::pair<unsigned char, uint256> key; |
| 518 | std::pair<unsigned char, uint256> prev_key = {DB_COINS, uint256()}; |
| 519 | while (pcursor->Valid()) { |
| 520 | if (ShutdownRequested()) { |
| 521 | break; |
| 522 | } |
| 523 | if (pcursor->GetKey(key) && key.first == DB_COINS) { |
| 524 | if (count++ % 256 == 0) { |
| 525 | uint32_t high = 0x100 * *key.second.begin() + *(key.second.begin() + 1); |
| 526 | int percentageDone = (int)(high * 100.0 / 65536.0 + 0.5); |
| 527 | uiInterface.ShowProgress(_("Upgrading UTXO database").translated, percentageDone, true); |
| 528 | if (reportDone < percentageDone/10) { |
| 529 | // report max. every 10% step |
| 530 | LogPrintf("[%d%%]...", percentageDone); /* Continued */ |
| 531 | reportDone = percentageDone/10; |
| 532 | } |
| 533 | } |
| 534 | CCoins old_coins; |
| 535 | if (!pcursor->GetValue(old_coins)) { |
| 536 | return error("%s: cannot parse CCoins record", __func__); |
| 537 | } |
| 538 | COutPoint outpoint(key.second, 0); |
| 539 | for (size_t i = 0; i < old_coins.vout.size(); ++i) { |
| 540 | if (!old_coins.vout[i].IsNull() && !old_coins.vout[i].scriptPubKey.IsUnspendable()) { |
| 541 | Coin newcoin(std::move(old_coins.vout[i]), old_coins.nHeight, old_coins.fCoinBase); |
| 542 | outpoint.n = i; |
| 543 | CoinEntry entry(&outpoint); |
| 544 | batch.Write(entry, newcoin); |
| 545 | } |
| 546 | } |
| 547 | batch.Erase(key); |
| 548 | if (batch.SizeEstimate() > batch_size) { |
| 549 | m_db->WriteBatch(batch); |
| 550 | batch.Clear(); |
| 551 | m_db->CompactRange(prev_key, key); |
| 552 | prev_key = key; |
| 553 | } |
| 554 | pcursor->Next(); |
| 555 | } else { |
| 556 | break; |
| 557 | } |
| 558 | } |
| 559 | m_db->WriteBatch(batch); |
| 560 | m_db->CompactRange({DB_COINS, uint256()}, key); |
nothing calls this directly
no test coverage detected