binary keys.

This commit is contained in:
Christopher Jeffrey 2016-05-26 19:14:05 -07:00
parent 0abf791bb7
commit fd7a42a240
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD

View File

@ -33,6 +33,80 @@ var BufferReader = require('./reader');
var Framer = bcoin.protocol.framer;
var Parser = bcoin.protocol.parser;
var layout = {
R: function R() {
var p = new BufferWriter();
p.writeString('R', 'ascii');
return p.render();
},
e: function e(hash) {
var p = new BufferWriter();
p.writeString('e', 'ascii');
p.writeHash(hash);
return p.render();
},
h: function h(hash) {
var p = new BufferWriter();
p.writeString('h', 'ascii');
p.writeHash(hash);
return p.render();
},
H: function H(height) {
var p = new BufferWriter();
p.writeString('H', 'ascii');
p.writeU32(height);
return p.render();
},
n: function n(hash) {
var p = new BufferWriter();
p.writeString('n', 'ascii');
p.writeHash(hash);
return p.render();
},
b: function b(hash) {
var p = new BufferWriter();
p.writeString('b', 'ascii');
p.writeHash(hash);
return p.render();
},
t: function t(hash) {
var p = new BufferWriter();
p.writeString('t', 'ascii');
p.writeHash(hash);
return p.render();
},
c: function c(hash) {
var p = new BufferWriter();
p.writeString('c', 'ascii');
p.writeHash(hash);
return p.render();
},
u: function u(hash) {
var p = new BufferWriter();
p.writeString('u', 'ascii');
p.writeHash(hash);
return p.render();
},
T: function T(address, hash) {
var p = new BufferWriter();
p.writeString('T', 'ascii');
p.writeString(address, 'hex');
p.writeString('\0', 'binary');
p.writeHash(hash);
return p.render();
},
C: function C(address, hash, index) {
var p = new BufferWriter();
p.writeString('C', 'ascii');
p.writeString(address, 'hex');
p.writeString('\0', 'binary');
p.writeHash(hash);
p.writeString('\0', 'binary');
p.writeU32(index);
return p.render();
}
};
/**
* The database backend for the {@link Chain} object.
* @exports ChainDB
@ -138,7 +212,7 @@ ChainDB.prototype._init = function _init() {
self.emit('open');
}
self.db.has('h/' + self.network.genesis.hash, function(err, exists) {
self.db.has(layout.h(self.network.genesis.hash), function(err, exists) {
if (err)
return self.emit('error', err);
@ -258,7 +332,7 @@ ChainDB.prototype.getHeight = function getHeight(hash, callback) {
return callback(null, this.cacheHash.get(hash).height);
}
this.db.fetch('h/' + hash, function(data) {
this.db.fetch(layout.h(hash), function(data) {
assert(data.length === 4, 'Database corruption.');
return data.readUInt32LE(0, true);
}, function(err, height) {
@ -295,7 +369,7 @@ ChainDB.prototype.getHash = function getHash(height, callback) {
return callback(null, this.cacheHeight.get(height).hash);
}
this.db.fetch('H/' + pad32(height), function(data) {
this.db.fetch(layout.H(height), function(data) {
assert(data.length === 32, 'Database corruption.');
return data.toString('hex');
}, callback);
@ -380,7 +454,7 @@ ChainDB.prototype.getEntry = function getEntry(hash, callback) {
if (self.cacheHash.has(hash))
return callback(null, self.cacheHash.get(hash));
return self.db.fetch('e/' + hash, function(data) {
return self.db.fetch(layout.e(hash), function(data) {
return bcoin.chainentry.fromRaw(self.chain, data);
}, callback);
});
@ -437,8 +511,8 @@ ChainDB.prototype.save = function save(entry, block, view, connect, callback) {
height = new Buffer(4);
height.writeUInt32LE(height, 0, true);
batch.put('h/' + entry.hash, height);
batch.put('e/' + entry.hash, entry.toRaw());
batch.put(layout.h(entry.hash), height);
batch.put(layout.e(entry.hash), entry.toRaw());
this.cacheHash.set(entry.hash, entry);
@ -452,9 +526,9 @@ ChainDB.prototype.save = function save(entry, block, view, connect, callback) {
this.cacheHeight.set(entry.height, entry);
batch.put('n/' + entry.prevBlock, hash);
batch.put('H/' + pad32(entry.height), hash);
batch.put('R', hash);
batch.put(layout.n(entry.prevBlock), hash);
batch.put(layout.H(entry.height), hash);
batch.put(layout.R(), hash);
this.emit('add entry', entry);
@ -472,7 +546,7 @@ ChainDB.prototype.save = function save(entry, block, view, connect, callback) {
ChainDB.prototype.getTip = function getTip(callback) {
var self = this;
return this.db.fetch('R', function(data) {
return this.db.fetch(layout.R(), function(data) {
assert(data.length === 32, 'Database corruption.');
return data.toString('hex');
}, function(err, hash) {
@ -496,9 +570,9 @@ ChainDB.prototype.connect = function connect(entry, block, view, callback) {
var batch = this.db.batch();
var hash = new Buffer(entry.hash, 'hex');
batch.put('n/' + entry.prevBlock, hash);
batch.put('H/' + pad32(entry.height), hash);
batch.put('R', hash);
batch.put(layout.n(entry.prevBlock), hash);
batch.put(layout.H(entry.height), hash);
batch.put(layout.R(), hash);
this.cacheHash.set(entry.hash, entry);
this.cacheHeight.set(entry.height, entry);
@ -529,9 +603,9 @@ ChainDB.prototype.disconnect = function disconnect(block, callback) {
batch = this.db.batch();
batch.del('n/' + entry.prevBlock);
batch.del('H/' + pad32(entry.height));
batch.put('R', new Buffer(entry.prevBlock, 'hex'));
batch.del(layout.n(entry.prevBlock));
batch.del(layout.H(entry.height));
batch.put(layout.R(), new Buffer(entry.prevBlock, 'hex'));
this.cacheHeight.remove(entry.height);
@ -564,7 +638,7 @@ ChainDB.prototype.disconnect = function disconnect(block, callback) {
*/
ChainDB.prototype.getNextHash = function getNextHash(hash, callback) {
return this.db.fetch('n/' + hash, function(data) {
return this.db.fetch(layout.n(hash), function(data) {
assert(data.length === 32, 'Database corruption.');
return data.toString('hex');
}, callback);
@ -641,14 +715,14 @@ ChainDB.prototype.reset = function reset(block, callback) {
batch = self.db.batch();
if (tip.hash === entry.hash) {
batch.put('R', new Buffer(tip.hash, 'hex'));
batch.put(layout.R(), new Buffer(tip.hash, 'hex'));
return batch.write(callback);
}
batch.del('H/' + pad32(tip.height));
batch.del('h/' + tip.hash);
batch.del('e/' + tip.hash);
batch.del('n/' + tip.prevBlock);
batch.del(layout.H(tip.height));
batch.del(layout.h(tip.hash));
batch.del(layout.e(tip.hash));
batch.del(layout.n(tip.prevBlock));
self.emit('remove entry', tip);
@ -699,7 +773,7 @@ ChainDB.prototype.saveBlock = function saveBlock(block, view, batch, connect, ca
if (this.options.spv)
return utils.nextTick(callback);
batch.put('b/' + block.hash('hex'), block.render());
batch.put(layout.b(block.hash()), block.render());
if (!connect)
return utils.nextTick(callback);
@ -725,7 +799,7 @@ ChainDB.prototype.removeBlock = function removeBlock(hash, batch, callback) {
if (!block)
return callback();
batch.del('b/' + block.hash('hex'));
batch.del(layout.b(block.hash()));
if (self.options.spv)
return callback(null, block);
@ -760,12 +834,12 @@ ChainDB.prototype.connectBlock = function connectBlock(block, view, batch, callb
hash = tx.hash('hex');
if (this.options.indexTX) {
batch.put('t/' + hash, tx.toExtended());
batch.put(layout.t(hash), tx.toExtended());
if (this.options.indexAddress) {
addresses = tx.getHashes();
for (j = 0; j < addresses.length; j++) {
address = addresses[j];
batch.put('T/' + address + '/' + hash, DUMMY);
batch.put(layout.T(address, hash), DUMMY);
}
}
}
@ -782,7 +856,7 @@ ChainDB.prototype.connectBlock = function connectBlock(block, view, batch, callb
if (this.options.indexAddress) {
address = input.getHash();
if (address)
batch.del('C/' + address + '/' + key);
batch.del(layout.C(address, input.prevout.hash, input.prevout.index));
}
Framer.coin(input.coin, false, undo);
@ -797,7 +871,7 @@ ChainDB.prototype.connectBlock = function connectBlock(block, view, batch, callb
if (this.options.indexAddress) {
address = output.getHash();
if (address)
batch.put('C/' + address + '/' + key, DUMMY);
batch.put(layout.C(address, hash, j), DUMMY);
}
}
}
@ -807,17 +881,17 @@ ChainDB.prototype.connectBlock = function connectBlock(block, view, batch, callb
for (i = 0; i < view.length; i++) {
coins = view[i];
if (coins.count() === 0) {
batch.del('c/' + coins.hash);
batch.del(layout.c(coins.hash));
this.coinCache.remove(coins.hash);
} else {
raw = coins.toRaw();
batch.put('c/' + coins.hash, raw);
batch.put(layout.c(coins.hash), raw);
this.coinCache.set(coins.hash, raw);
}
}
if (undo.written > 0)
batch.put('u/' + block.hash('hex'), undo.render());
batch.put(layout.u(block.hash()), undo.render());
this.emit('add block', block);
@ -851,12 +925,12 @@ ChainDB.prototype.disconnectBlock = function disconnectBlock(block, batch, callb
hash = tx.hash('hex');
if (self.options.indexTX) {
batch.del('t/' + hash);
batch.del(layout.t(hash));
if (self.options.indexAddress) {
addresses = tx.getHashes();
for (j = 0; j < addresses.length; j++) {
address = addresses[j];
batch.del('T/' + address + '/' + hash);
batch.del(layout.T(address, hash));
}
}
}
@ -873,7 +947,7 @@ ChainDB.prototype.disconnectBlock = function disconnectBlock(block, batch, callb
if (self.options.indexAddress) {
address = input.getHash();
if (address)
batch.put('C/' + address + '/' + key, DUMMY);
batch.put(layout.C(address, input.prevout.hash, input.prevout.index), DUMMY);
}
}
@ -889,7 +963,7 @@ ChainDB.prototype.disconnectBlock = function disconnectBlock(block, batch, callb
if (self.options.indexAddress) {
address = output.getHash();
if (address)
batch.del('C/' + address + '/' + key);
batch.del(layout.C(address, hash, j));
}
view.spend(hash, j);
@ -901,16 +975,16 @@ ChainDB.prototype.disconnectBlock = function disconnectBlock(block, batch, callb
for (i = 0; i < view.length; i++) {
coins = view[i];
if (coins.count() === 0) {
batch.del('c/' + coins.hash);
batch.del(layout.c(coins.hash));
self.coinCache.remove(coins.hash);
} else {
raw = coins.toRaw();
batch.put('c/' + coins.hash, raw);
batch.put(layout.c(coins.hash), raw);
self.coinCache.set(coins.hash, raw);
}
}
batch.del('u/' + block.hash('hex'));
batch.del(layout.u(block.hash()));
self.emit('remove block', block);
@ -1036,7 +1110,7 @@ ChainDB.prototype.getCoins = function getCoins(hash, callback) {
return callback(null, coins);
}
this.db.fetch('c/' + hash, function(data) {
this.db.fetch(layout.c(hash), function(data) {
self.coinCache.set(hash, data);
return bcoin.coins.fromRaw(data, hash);
}, callback);
@ -1054,7 +1128,7 @@ ChainDB.prototype.getTX = function getTX(hash, callback) {
if (!this.options.indexTX)
return utils.nextTick(callback);
this.db.fetch('t/' + hash, function(data) {
this.db.fetch(layout.t(hash), function(data) {
return bcoin.tx.fromExtended(data);
}, function(err, tx) {
if (err)
@ -1076,7 +1150,7 @@ ChainDB.prototype.hasTX = function hasTX(hash, callback) {
if (!this.options.indexTX)
return utils.asyncify(callback)(null, false);
return this.db.has('t/' + hash, callback);
return this.db.has(layout.t(hash), callback);
};
/**
@ -1266,7 +1340,7 @@ ChainDB.prototype.getCoinView = function getCoinView(block, callback) {
*/
ChainDB.prototype.getUndoCoins = function getUndoCoins(hash, callback) {
return this.db.fetch('u/' + hash, function(data) {
return this.db.fetch(layout.u(hash), function(data) {
var p = new BufferReader(data);
var coins = [];
var coin;
@ -1337,7 +1411,7 @@ ChainDB.prototype.getBlock = function getBlock(hash, callback) {
if (!hash)
return callback();
self.db.fetch('b/' + hash, function(data) {
self.db.fetch(layout.b(hash), function(data) {
var block = bcoin.block.fromRaw(data);
block.setHeight(height);
return block;
@ -1411,8 +1485,8 @@ ChainDB.prototype._pruneBlock = function _pruneBlock(block, batch, callback) {
return callback();
batch.del(key);
batch.del('b/' + hash);
batch.del('u/' + hash);
batch.del(layout.b(hash));
batch.del(layout.u(hash));
return callback();
});