binary keys.
This commit is contained in:
parent
0abf791bb7
commit
fd7a42a240
@ -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();
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user