mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-20 15:19:07 +01:00
Merge bitcoin/bitcoin#24236: Remove utxo db upgrade code
fa9112aac0Remove utxo db upgrade code (MarcoFalke) Pull request description: It is not possible to upgrade Bitcoin Core pre-segwit (pre-0.13.1) to a recent version without a full IBD from scratch after commit19a56d1519(released in version 22.0). Any Bitcoin Core version with the new database format after commit1088b02f0c(released in version 0.15), can upgrade to any version that is supported as of today. This leaves the versions 0.13.1-0.14.x. Even though those versions are unsupported, some users with an existing datadir may want to upgrade to a recent version. However, it seems reasonable to simply ask them to `-reindex` to run a full IBD from scratch. This allows us to remove the utxo db upgrade code. ACKs for top commit: Sjors: re-ACKfa9112aac0laanwj: Code review ACKfa9112aac0Tree-SHA512: 4243bb35df9ac4892f9fad30fe486d338745952bcff4160bcb0937c772d57b13b800647da14695e21e3655e85ee0d95fa3dc7789ee309d59ad84f422297fecb8
This commit is contained in:
136
src/txdb.cpp
136
src/txdb.cpp
@@ -6,7 +6,6 @@
|
||||
#include <txdb.h>
|
||||
|
||||
#include <chain.h>
|
||||
#include <node/ui_interface.h>
|
||||
#include <pow.h>
|
||||
#include <random.h>
|
||||
#include <shutdown.h>
|
||||
@@ -18,7 +17,6 @@
|
||||
#include <stdint.h>
|
||||
|
||||
static constexpr uint8_t DB_COIN{'C'};
|
||||
static constexpr uint8_t DB_COINS{'c'};
|
||||
static constexpr uint8_t DB_BLOCK_FILES{'f'};
|
||||
static constexpr uint8_t DB_BLOCK_INDEX{'b'};
|
||||
|
||||
@@ -29,6 +27,7 @@ static constexpr uint8_t DB_REINDEX_FLAG{'R'};
|
||||
static constexpr uint8_t DB_LAST_BLOCK{'l'};
|
||||
|
||||
// Keys used in previous version that might still be found in the DB:
|
||||
static constexpr uint8_t DB_COINS{'c'};
|
||||
static constexpr uint8_t DB_TXINDEX_BLOCK{'T'};
|
||||
// uint8_t DB_TXINDEX{'t'}
|
||||
|
||||
@@ -50,6 +49,15 @@ std::optional<bilingual_str> CheckLegacyTxindex(CBlockTreeDB& block_tree_db)
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool CCoinsViewDB::NeedsUpgrade()
|
||||
{
|
||||
std::unique_ptr<CDBIterator> cursor{m_db->NewIterator()};
|
||||
// DB_COINS was deprecated in v0.15.0, commit
|
||||
// 1088b02f0ccd7358d2b7076bb9e122d59d502d02
|
||||
cursor->Seek(std::make_pair(DB_COINS, uint256{}));
|
||||
return cursor->Valid();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct CoinEntry {
|
||||
@@ -60,7 +68,7 @@ struct CoinEntry {
|
||||
SERIALIZE_METHODS(CoinEntry, obj) { READWRITE(obj.key, obj.outpoint->hash, VARINT(obj.outpoint->n)); }
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace
|
||||
|
||||
CCoinsViewDB::CCoinsViewDB(fs::path ldb_path, size_t nCacheSize, bool fMemory, bool fWipe) :
|
||||
m_db(std::make_unique<CDBWrapper>(ldb_path, nCacheSize, fMemory, fWipe, true)),
|
||||
@@ -337,125 +345,3 @@ bool CBlockTreeDB::LoadBlockIndexGuts(const Consensus::Params& consensusParams,
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
//! Legacy class to deserialize pre-pertxout database entries without reindex.
|
||||
class CCoins
|
||||
{
|
||||
public:
|
||||
//! whether transaction is a coinbase
|
||||
bool fCoinBase;
|
||||
|
||||
//! unspent transaction outputs; spent outputs are .IsNull(); spent outputs at the end of the array are dropped
|
||||
std::vector<CTxOut> vout;
|
||||
|
||||
//! at which height this transaction was included in the active block chain
|
||||
int nHeight;
|
||||
|
||||
//! empty constructor
|
||||
CCoins() : fCoinBase(false), vout(0), nHeight(0) { }
|
||||
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream &s) {
|
||||
unsigned int nCode = 0;
|
||||
// version
|
||||
unsigned int nVersionDummy;
|
||||
::Unserialize(s, VARINT(nVersionDummy));
|
||||
// header code
|
||||
::Unserialize(s, VARINT(nCode));
|
||||
fCoinBase = nCode & 1;
|
||||
std::vector<bool> vAvail(2, false);
|
||||
vAvail[0] = (nCode & 2) != 0;
|
||||
vAvail[1] = (nCode & 4) != 0;
|
||||
unsigned int nMaskCode = (nCode / 8) + ((nCode & 6) != 0 ? 0 : 1);
|
||||
// spentness bitmask
|
||||
while (nMaskCode > 0) {
|
||||
unsigned char chAvail = 0;
|
||||
::Unserialize(s, chAvail);
|
||||
for (unsigned int p = 0; p < 8; p++) {
|
||||
bool f = (chAvail & (1 << p)) != 0;
|
||||
vAvail.push_back(f);
|
||||
}
|
||||
if (chAvail != 0)
|
||||
nMaskCode--;
|
||||
}
|
||||
// txouts themself
|
||||
vout.assign(vAvail.size(), CTxOut());
|
||||
for (unsigned int i = 0; i < vAvail.size(); i++) {
|
||||
if (vAvail[i])
|
||||
::Unserialize(s, Using<TxOutCompression>(vout[i]));
|
||||
}
|
||||
// coinbase height
|
||||
::Unserialize(s, VARINT_MODE(nHeight, VarIntMode::NONNEGATIVE_SIGNED));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/** 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(m_db->NewIterator());
|
||||
pcursor->Seek(std::make_pair(DB_COINS, uint256()));
|
||||
if (!pcursor->Valid()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int64_t count = 0;
|
||||
LogPrintf("Upgrading utxo-set database...\n");
|
||||
LogPrintf("[0%%]..."); /* Continued */
|
||||
uiInterface.ShowProgress(_("Upgrading UTXO database").translated, 0, true);
|
||||
size_t batch_size = 1 << 24;
|
||||
CDBBatch batch(*m_db);
|
||||
int reportDone = 0;
|
||||
std::pair<unsigned char, uint256> key;
|
||||
std::pair<unsigned char, uint256> prev_key = {DB_COINS, uint256()};
|
||||
while (pcursor->Valid()) {
|
||||
if (ShutdownRequested()) {
|
||||
break;
|
||||
}
|
||||
if (pcursor->GetKey(key) && key.first == DB_COINS) {
|
||||
if (count++ % 256 == 0) {
|
||||
uint32_t high = 0x100 * *key.second.begin() + *(key.second.begin() + 1);
|
||||
int percentageDone = (int)(high * 100.0 / 65536.0 + 0.5);
|
||||
uiInterface.ShowProgress(_("Upgrading UTXO database").translated, percentageDone, true);
|
||||
if (reportDone < percentageDone/10) {
|
||||
// report max. every 10% step
|
||||
LogPrintf("[%d%%]...", percentageDone); /* Continued */
|
||||
reportDone = percentageDone/10;
|
||||
}
|
||||
}
|
||||
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) {
|
||||
m_db->WriteBatch(batch);
|
||||
batch.Clear();
|
||||
m_db->CompactRange(prev_key, key);
|
||||
prev_key = key;
|
||||
}
|
||||
pcursor->Next();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_db->WriteBatch(batch);
|
||||
m_db->CompactRange({DB_COINS, uint256()}, key);
|
||||
uiInterface.ShowProgress("", 100, false);
|
||||
LogPrintf("[%s].\n", ShutdownRequested() ? "CANCELLED" : "DONE");
|
||||
return !ShutdownRequested();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user