This commit is contained in:
Christopher Jeffrey 2016-03-05 06:48:17 -08:00
parent 49bb2d44e4
commit 23285d282b
2 changed files with 86 additions and 73 deletions

View File

@ -384,6 +384,65 @@ Block.fromRaw = function fromRaw(data, enc, type) {
return new Block(Block._fromRaw(data, enc)); return new Block(Block._fromRaw(data, enc));
}; };
Block.prototype.toSmall = function toSmall() {
var block = this.abbr();
var buf = new Buffer(block.length + 4 + this.txs.length * 32);
var height = this.height;
var off = 0;
if (height === -1)
height = 0x7fffffff;
off += utils.copy(block, buf, off);
off += utils.writeU32(buf, height, off);
off += utils.writeIntv(buf, this.txs.length, off);
this.txs.forEach(function(tx) {
off += utils.copy(tx.hash(), buf, off);
});
return buf;
};
Block.fromSmall = function fromSmall(buf) {
var tx, txCount, i;
var off = 0;
var hashes = [];
var version = utils.read32(buf, 0);
var prevBlock = buf.slice(4, 36);
var merkleRoot = buf.slice(36, 68);
var ts = utils.readU32(buf, 68);
var bits = utils.readU32(buf, 72);
var nonce = utils.readU32(buf, 76);
var height = utils.readU32(buf, 80);
var txCount = utils.readIntv(buf, 84);
off = txCount.off;
txCount = txCount.r;
for (i = 0; i < txCount; i++) {
if (off + 32 > buf.length)
throw new Error('Bad TX count.');
hashes.push(utils.toHex(buf.slice(off, off + 32)));
off += 32;
}
if (height === 0x7fffffff)
height = -1;
return {
version: version,
prevBlock: utils.toHex(prevBlock),
merkleRoot: utils.toHex(merkleRoot),
ts: ts,
bits: bits,
nonce: nonce,
height: height,
totalTX: txCount,
hashes: hashes
};
};
/** /**
* Expose * Expose
*/ */

View File

@ -161,23 +161,11 @@ BlockDB.prototype.parseOffset = function parseOffset(data) {
BlockDB.prototype.saveBlock = function saveBlock(block, callback) { BlockDB.prototype.saveBlock = function saveBlock(block, callback) {
var self = this; var self = this;
this.data.saveAsync(block._raw, function(err, data) { var batch = self.index.batch();
var batch, blockOffset;
if (err) batch.put('b/b/' + block.hash('hex'), block.toSmall());
return callback(err);
batch = self.index.batch(); self.connectBlock(block, callback, batch);
block._fileOffset = data.offset;
assert(block._size === data.size);
blockOffset = self.createOffset(block._size, block._fileOffset, block.height);
batch.put('b/b/' + block.hash('hex'), blockOffset);
self.connectBlock(block, callback, batch, blockOffset);
});
}; };
BlockDB.prototype.removeBlock = function removeBlock(hash, callback) { BlockDB.prototype.removeBlock = function removeBlock(hash, callback) {
@ -229,23 +217,14 @@ BlockDB.prototype.connectBlock = function connectBlock(block, callback, batch, b
if (!batch) if (!batch)
batch = self.index.batch(); batch = self.index.batch();
if (!blockOffset) batch.put('b/h/' + block.height, block.hash());
blockOffset = self.createOffset(block._size, block._fileOffset, block.height);
batch.put('b/h/' + block.height, blockOffset);
block.txs.forEach(function(tx, i) { block.txs.forEach(function(tx, i) {
var hash = tx.hash('hex'); var hash = tx.hash('hex');
var uniq = {}; var uniq = {};
var txOffset; var txOffset;
txOffset = self.createOffset( batch.put('t/t/' + hash, tx.toExtended());
tx._size,
block._fileOffset + tx._offset,
block.height
);
batch.put('t/t/' + hash, txOffset);
tx.inputs.forEach(function(input) { tx.inputs.forEach(function(input) {
var type = input.getType(); var type = input.getType();
@ -268,7 +247,7 @@ BlockDB.prototype.connectBlock = function connectBlock(block, callback, batch, b
} }
if (uaddr) if (uaddr)
batch.put('t/a/' + uaddr + '/' + hash, txOffset); batch.put('t/a/' + uaddr + '/' + hash, new Buffer([]));
if (address) { if (address) {
batch.del( batch.del(
@ -300,19 +279,13 @@ BlockDB.prototype.connectBlock = function connectBlock(block, callback, batch, b
uaddr = null; uaddr = null;
} }
coinOffset = self.createOffset(
output._size,
block._fileOffset + tx._offset + output._offset,
block.height
);
if (uaddr) if (uaddr)
batch.put('t/a/' + uaddr + '/' + hash, txOffset); batch.put('t/a/' + uaddr + '/' + hash, new Buffer([]));
if (address) if (address)
batch.put('u/a/' + address + '/' + hash + '/' + i, coinOffset); batch.put('u/a/' + address + '/' + hash + '/' + i, new Buffer([]));
batch.put('u/t/' + hash + '/' + i, coinOffset); batch.put('u/t/' + hash + '/' + i, bcoin.coin(tx, i).toRaw());
}); });
}); });
@ -516,7 +489,6 @@ BlockDB.prototype.fillTX = function fillTX(tx, callback) {
if (tx) { if (tx) {
input.output = bcoin.coin(tx, input.prevout.index); input.output = bcoin.coin(tx, input.prevout.index);
input.output._fileOffset = tx._fileOffset + input.output._offset;
} }
next(); next();
@ -633,6 +605,7 @@ BlockDB.prototype.getCoin = function getCoin(hash, index, callback) {
return callback(err); return callback(err);
} }
return callback(null, bcoin.coin.fromRaw(record));
record = self.parseOffset(record); record = self.parseOffset(record);
self.data.getAsync(record.size, record.offset, function(err, data) { self.data.getAsync(record.size, record.offset, function(err, data) {
@ -790,6 +763,7 @@ BlockDB.prototype.getTX = function getTX(hash, callback) {
return callback(err); return callback(err);
} }
return callback(null, bcoin.tx.fromExtended(record));
record = self.parseOffset(record); record = self.parseOffset(record);
self.data.getAsync(record.size, record.offset, function(err, data) { self.data.getAsync(record.size, record.offset, function(err, data) {
@ -931,47 +905,27 @@ BlockDB.prototype.getBlock = function getBlock(hash, callback) {
return callback(err); return callback(err);
} }
record = self.parseOffset(record); var block = bcoin.block.fromSmall(record);
block.txs = [];
self.data.getAsync(record.size, record.offset, function(err, data) { utils.forEach(block.hashes, function(hash, next, i) {
var block; self.getTX(hash, function(err, tx) {
if (err)
return next(err);
if (!tx)
return next(new Error('TX not found.'));
block.txs[i] = tx;
next();
})
}, function(err) {
if (err) if (err)
return callback(err); return callback(err);
if (data) { delete block.hashes;
try { block = new bcoin.block(block);
block = bcoin.protocol.parser.parseBlock(data);
block = new bcoin.block(block);
} catch (e) {
return callback(e);
}
block._fileOffset = record.offset;
block.height = record.height;
block.txs.forEach(function(tx) {
tx.height = block.height;
});
if (self.options.paranoid) {
if (typeof hash === 'number') {
self._getEntry(hash, function(err, entry) {
if (err)
return callback(err);
if (!entry)
return callback(null, block);
if (block.hash('hex') !== entry.hash)
return callback(new Error('BlockDB is corrupt. All is lost.'));
return callback(null, block);
});
return;
}
if (block.hash('hex') !== hash)
return callback(new Error('BlockDB is corrupt. All is lost.'));
}
}
return callback(null, block); return callback(null, block);
}); });
}); });