From 0765f44b5ba221032a6a3cb15271a4d9a389a2e6 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Thu, 18 Aug 2016 01:56:33 -0700 Subject: [PATCH] chaindb: ready for migration. --- lib/bcoin/chaindb.js | 15 ++---- migrate/chaindb0to1.js | 112 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 10 deletions(-) create mode 100644 migrate/chaindb0to1.js diff --git a/lib/bcoin/chaindb.js b/lib/bcoin/chaindb.js index 4dc74f74..4e9906e2 100644 --- a/lib/bcoin/chaindb.js +++ b/lib/bcoin/chaindb.js @@ -299,7 +299,7 @@ ChainDB.prototype._open = function open(callback) { utils.btc(self.state.value) ); - self.db.checkVersion('V', 0, callback); + self.db.checkVersion('V', 1, callback); } this.db.open(function(err) { @@ -1834,12 +1834,9 @@ ChainState.fromRaw = function fromRaw(data) { var state = new ChainState(); var p = new BufferReader(data); state.tip = p.readHash(); - // XXX Allow just a hash until I write a migration. - if (p.left() > 0) { - state.tx = p.readU53(); - state.coin = p.readU53(); - state.value = p.readU53(); - } + state.tx = p.readU53(); + state.coin = p.readU53(); + state.value = p.readU53(); return state; }; @@ -1863,9 +1860,7 @@ function pair(prefix, hash) { function ipair(prefix, num) { var key = new Buffer(5); key[0] = prefix; - // TODO: Change this to big - // endian for saner sorting. - key.writeUInt32LE(num, 1, true); + key.writeUInt32BE(num, 1, true); return key; } diff --git a/migrate/chaindb0to1.js b/migrate/chaindb0to1.js new file mode 100644 index 00000000..1ca09495 --- /dev/null +++ b/migrate/chaindb0to1.js @@ -0,0 +1,112 @@ +var bcoin = require('bcoin'); +var assert = require('assert'); +var file = process.argv[2]; + +assert(typeof file === 'string', 'Please pass in a database path.'); + +var db = bcoin.ldb({ + location: file, + db: 'leveldb', + compression: true, + cacheSize: 16 << 20, + writeBufferSize: 8 << 20, + createIfMissing: false, + bufferKeys: true +}); + +function makeKey(data) { + var height = data.readUInt32LE(1, true); + var key = new Buffer(5); + key[0] = 0x48; + key.writeUInt32BE(height, 1, true); + return key; +} + +function updateState(callback) { + var hash, batch, ver, p; + + console.log('Updating chain state.'); + + db.get('R', function(err, data) { + if (err) + return callback(err); + + if (!data || data.length < 32) + return callback(new Error('No chain state.')); + + hash = data.slice(0, 32); + + p = new bcoin.writer(); + p.writeHash(hash); + p.writeU64(0); + p.writeU64(0); + p.writeU64(0); + p = p.render(); + + batch = db.batch(); + + batch.put('R', p); + + ver = new Buffer(4); + ver.writeUInt32LE(1, 0, true); + batch.put('V', ver); + + batch.write(function(err) { + if (err) + return callback(err); + console.log('Updated chain state.'); + callback(); + }); + }); +} + +function updateEndian(callback) { + var lo = new Buffer('4800000000', 'hex'); + var hi = new Buffer('48ffffffff', 'hex'); + var batch = db.batch(); + var total = 0; + + console.log('Updating endianness.'); + console.log('Iterating...'); + + db.iterate({ + gte: lo, + lte: hi, + values: true, + parse: function(key, value) { + batch.del(key); + batch.put(makeKey(key), value); + total++; + } + }, function(err) { + if (err) + throw err; + + console.log('Migrating %d items.', total); + + batch.write(function(err) { + if (err) + throw err; + console.log('Migrated endianness.'); + callback(); + }); + }); +} + +db.open(function(err) { + if (err) + throw err; + + console.log('Opened %s.', file); + + updateState(function(err) { + if (err) + throw err; + updateEndian(function(err) { + if (err) + throw err; + console.log('Migration complete.'); + process.exit(0); + }); + }); +});