Skip to content

Commit 8b25d2c

Browse files
committed
Upgrade from per-tx database to per-txout
1 parent b2af357 commit 8b25d2c

File tree

4 files changed

+54
-0
lines changed

4 files changed

+54
-0
lines changed

src/coins.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ class Coin
8282
}
8383
};
8484

85+
//! Legacy class to deserialize pre-pertxout database entries without reindex.
8586
class CCoins
8687
{
8788
public:

src/init.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1455,6 +1455,12 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
14551455
//If we're reindexing in prune mode, wipe away unusable block files and all undo data files
14561456
if (fPruneMode)
14571457
CleanupBlockRevFiles();
1458+
} else {
1459+
// If necessary, upgrade from older database format.
1460+
if (!pcoinsdbview->Upgrade()) {
1461+
strLoadError = _("Error upgrading chainstate database");
1462+
break;
1463+
}
14581464
}
14591465

14601466
if (!LoadBlockIndex(chainparams)) {

src/txdb.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,3 +252,48 @@ bool CBlockTreeDB::LoadBlockIndexGuts(std::function<CBlockIndex*(const uint256&)
252252

253253
return true;
254254
}
255+
256+
/** Upgrade the database from older formats.
257+
*
258+
* Currently implemented: from the per-tx utxo model (0.8..0.14.x) to per-txout.
259+
*/
260+
bool CCoinsViewDB::Upgrade() {
261+
std::unique_ptr<CDBIterator> pcursor(db.NewIterator());
262+
pcursor->Seek(std::make_pair(DB_COINS, uint256()));
263+
if (!pcursor->Valid()) {
264+
return true;
265+
}
266+
267+
LogPrintf("Upgrading database...\n");
268+
size_t batch_size = 1 << 24;
269+
CDBBatch batch(db);
270+
while (pcursor->Valid()) {
271+
boost::this_thread::interruption_point();
272+
std::pair<unsigned char, uint256> key;
273+
if (pcursor->GetKey(key) && key.first == DB_COINS) {
274+
CCoins old_coins;
275+
if (!pcursor->GetValue(old_coins)) {
276+
return error("%s: cannot parse CCoins record", __func__);
277+
}
278+
COutPoint outpoint(key.second, 0);
279+
for (size_t i = 0; i < old_coins.vout.size(); ++i) {
280+
if (!old_coins.vout[i].IsNull() && !old_coins.vout[i].scriptPubKey.IsUnspendable()) {
281+
Coin newcoin(std::move(old_coins.vout[i]), old_coins.nHeight, old_coins.fCoinBase);
282+
outpoint.n = i;
283+
CoinEntry entry(&outpoint);
284+
batch.Write(entry, newcoin);
285+
}
286+
}
287+
batch.Erase(key);
288+
if (batch.SizeEstimate() > batch_size) {
289+
db.WriteBatch(batch);
290+
batch.Clear();
291+
}
292+
pcursor->Next();
293+
} else {
294+
break;
295+
}
296+
}
297+
db.WriteBatch(batch);
298+
return true;
299+
}

src/txdb.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ class CCoinsViewDB : public CCoinsView
7777
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override;
7878
CCoinsViewCursor *Cursor() const override;
7979

80+
//! Attempt to update from an older database format. Returns whether an error occurred.
81+
bool Upgrade();
8082
size_t EstimateSize() const override;
8183
};
8284

0 commit comments

Comments
 (0)