fcoin/migrate/walletdb3to4.js
2018-03-29 21:56:48 -07:00

147 lines
3.0 KiB
JavaScript

'use strict';
const assert = require('assert');
const bcoin = require('../');
const encoding = require('bufio/lib/encoding');
const WalletDB = require('../lib/wallet/walletdb');
const BufferReader = require('bufio/lib/reader');
const TX = require('../lib/primitives/tx');
const Coin = require('../lib/primitives/coin');
let file = process.argv[2];
let batch;
assert(typeof file === 'string', 'Please pass in a database path.');
file = file.replace(/\.ldb\/?$/, '');
const db = bcoin.ldb({
location: file,
db: 'leveldb',
compression: true,
cacheSize: 32 << 20,
createIfMissing: false,
bufferKeys: true
});
async function updateVersion() {
const bak = `${process.env.HOME}/walletdb-bak-${Date.now()}.ldb`;
console.log('Checking version.');
const data = await db.get('V');
assert(data, 'No version.');
let ver = data.readUInt32LE(0, true);
if (ver !== 3)
throw Error(`DB is version ${ver}.`);
console.log('Backing up DB to: %s.', bak);
await db.backup(bak);
ver = Buffer.allocUnsafe(4);
ver.writeUInt32LE(4, 0, true);
batch.put('V', ver);
}
async function updateTXDB() {
let txs = {};
const keys = await db.keys({
gte: Buffer.from([0x00]),
lte: Buffer.from([0xff])
});
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
if (key[0] === 0x74 && key[5] === 0x74) {
let tx = await db.get(key);
tx = fromExtended(tx);
const hash = tx.hash('hex');
txs[hash] = tx;
}
if (key[0] === 0x74)
batch.del(key);
}
txs = getValues(txs);
await batch.write();
await db.close();
const walletdb = new WalletDB({
location: file,
db: 'leveldb',
resolution: true,
verify: false,
network: process.argv[3]
});
await walletdb.open();
for (let i = 0; i < txs.length; i++) {
const tx = txs[i];
await walletdb.addTX(tx);
}
await walletdb.close();
}
function fromExtended(data, saveCoins) {
const tx = new TX();
const p = BufferReader(data);
tx.fromRaw(p);
tx.height = p.readU32();
tx.block = p.readHash('hex');
tx.index = p.readU32();
tx.time = p.readU32();
tx.mtime = p.readU32();
if (tx.block === encoding.NULL_HASH)
tx.block = null;
if (tx.height === 0x7fffffff)
tx.height = -1;
if (tx.index === 0x7fffffff)
tx.index = -1;
if (saveCoins) {
const coinCount = p.readVarint();
for (let i = 0; i < coinCount; i++) {
let coin = p.readVarBytes();
if (coin.length === 0)
continue;
coin = Coin.fromRaw(coin);
coin.hash = tx.inputs[i].prevout.hash;
coin.index = tx.inputs[i].prevout.index;
tx.inputs[i].coin = coin;
}
}
return tx;
}
function getValues(map) {
const items = [];
for (const key of Object.keys(map))
items.push(map[key]);
return items;
}
(async () => {
await db.open();
batch = db.batch();
console.log('Opened %s.', file);
await updateVersion();
await updateTXDB();
})().then(() => {
console.log('Migration complete.');
process.exit(0);
});