fast
This commit is contained in:
parent
49bb2d44e4
commit
23285d282b
@ -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
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -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);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user