diff options
author | Pieter Wuille <pieter.wuille@gmail.com> | 2017-04-25 11:29:46 -0700 |
---|---|---|
committer | Pieter Wuille <pieter.wuille@gmail.com> | 2017-06-01 13:15:24 -0700 |
commit | 8b25d2c0ce64d7f8577a0c2e601e505c9f1140bf (patch) | |
tree | f0e2511a6e0aebf0012c209f54574b649651d3b2 /src | |
parent | b2af357f39c7d17ab6ddb2938531155bf90126ec (diff) |
Upgrade from per-tx database to per-txout
Diffstat (limited to 'src')
-rw-r--r-- | src/coins.h | 1 | ||||
-rw-r--r-- | src/init.cpp | 6 | ||||
-rw-r--r-- | src/txdb.cpp | 45 | ||||
-rw-r--r-- | src/txdb.h | 2 |
4 files changed, 54 insertions, 0 deletions
diff --git a/src/coins.h b/src/coins.h index 7f4dffc7ec..5ffb810aab 100644 --- a/src/coins.h +++ b/src/coins.h @@ -82,6 +82,7 @@ public: } }; +//! Legacy class to deserialize pre-pertxout database entries without reindex. class CCoins { public: diff --git a/src/init.cpp b/src/init.cpp index 4420b6f658..8ce3847955 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1455,6 +1455,12 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) //If we're reindexing in prune mode, wipe away unusable block files and all undo data files if (fPruneMode) CleanupBlockRevFiles(); + } else { + // If necessary, upgrade from older database format. + if (!pcoinsdbview->Upgrade()) { + strLoadError = _("Error upgrading chainstate database"); + break; + } } if (!LoadBlockIndex(chainparams)) { diff --git a/src/txdb.cpp b/src/txdb.cpp index 19c9002506..f4a6fad85b 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -252,3 +252,48 @@ bool CBlockTreeDB::LoadBlockIndexGuts(std::function<CBlockIndex*(const uint256&) return true; } + +/** Upgrade the database from older formats. + * + * Currently implemented: from the per-tx utxo model (0.8..0.14.x) to per-txout. + */ +bool CCoinsViewDB::Upgrade() { + std::unique_ptr<CDBIterator> pcursor(db.NewIterator()); + pcursor->Seek(std::make_pair(DB_COINS, uint256())); + if (!pcursor->Valid()) { + return true; + } + + LogPrintf("Upgrading database...\n"); + size_t batch_size = 1 << 24; + CDBBatch batch(db); + while (pcursor->Valid()) { + boost::this_thread::interruption_point(); + std::pair<unsigned char, uint256> key; + if (pcursor->GetKey(key) && key.first == DB_COINS) { + CCoins old_coins; + if (!pcursor->GetValue(old_coins)) { + return error("%s: cannot parse CCoins record", __func__); + } + COutPoint outpoint(key.second, 0); + for (size_t i = 0; i < old_coins.vout.size(); ++i) { + if (!old_coins.vout[i].IsNull() && !old_coins.vout[i].scriptPubKey.IsUnspendable()) { + Coin newcoin(std::move(old_coins.vout[i]), old_coins.nHeight, old_coins.fCoinBase); + outpoint.n = i; + CoinEntry entry(&outpoint); + batch.Write(entry, newcoin); + } + } + batch.Erase(key); + if (batch.SizeEstimate() > batch_size) { + db.WriteBatch(batch); + batch.Clear(); + } + pcursor->Next(); + } else { + break; + } + } + db.WriteBatch(batch); + return true; +} diff --git a/src/txdb.h b/src/txdb.h index 189094737e..51dc355bba 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -77,6 +77,8 @@ public: bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override; CCoinsViewCursor *Cursor() const override; + //! Attempt to update from an older database format. Returns whether an error occurred. + bool Upgrade(); size_t EstimateSize() const override; }; |