Merge pull request #12 from braydonf/block-optimize

Read block as a Node Buffer
This commit is contained in:
Chris Kleeschulte 2015-07-10 09:16:20 -04:00
commit e7160f0a09
2 changed files with 85 additions and 30 deletions

View File

@ -45,13 +45,51 @@ describe('Basic Functionality', function() {
}); });
}); });
describe('will get correct block data', function() { describe('get blocks by hash', function() {
blockData.forEach(function(data) { blockData.forEach(function(data) {
var block = bitcore.Block.fromString(data); var block = bitcore.Block.fromString(data);
it('block ' + block.hash, function(done) { it('block ' + block.hash, function(done) {
bitcoind.getBlock(block.hash, function(err, response) { bitcoind.getBlock(block.hash, function(err, response) {
assert(response === data, 'incorrect block data for ' + block.hash); assert(response.toString('hex') === data, 'incorrect block data for ' + block.hash);
done();
});
});
});
});
describe('get blocks by height', function() {
var knownHeights = [
[0, '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f'],
[1, '00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048'],
[100000,'000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506'],
[314159, '00000000000000001bb82a7f5973618cfd3185ba1ded04dd852a653f92a27c45']
];
knownHeights.forEach(function(data) {
it('block at height ' + data[0], function(done) {
bitcoind.getBlock(data[0], function(err, response) {
var block = bitcore.Block.fromBuffer(response);
block.hash.should.equal(data[1]);
done();
});
});
});
});
describe.skip('get the chain', function() {
var heights = [];
for (var i = 364599; i >= 0 ; i--) {
heights.push(i);
}
heights.forEach(function(height) {
it('block at height ' + height, function(done) {
bitcoind.getBlock(height, function(err, response) {
var block = bitcore.Block.fromBuffer(response);
console.log(block.hash);
done(); done();
}); });
}); });

View File

@ -189,6 +189,8 @@ struct async_block_data {
std::string err_msg; std::string err_msg;
std::string hash; std::string hash;
int64_t height; int64_t height;
char* buffer;
uint32_t size;
CBlock cblock; CBlock cblock;
CBlockIndex* cblock_index; CBlockIndex* cblock_index;
Eternal<Function> callback; Eternal<Function> callback;
@ -835,35 +837,52 @@ static void
async_get_block(uv_work_t *req) { async_get_block(uv_work_t *req) {
async_block_data* data = static_cast<async_block_data*>(req->data); async_block_data* data = static_cast<async_block_data*>(req->data);
if (data->height != -1) { CBlockIndex* pblockindex;
CBlockIndex* pblockindex = chainActive[data->height];
CBlock cblock;
if (ReadBlockFromDisk(cblock, pblockindex)) {
data->cblock = cblock;
data->cblock_index = pblockindex;
} else {
data->err_msg = std::string("Block not found.");
}
return;
}
std::string strHash = data->hash; std::string strHash = data->hash;
uint256 hash(strHash); uint256 hash(strHash);
if (mapBlockIndex.count(hash) == 0) { if (data->height != -1) {
data->err_msg = std::string("Block not found."); pblockindex = chainActive[data->height];
} else { } else {
if (mapBlockIndex.count(hash) == 0) {
CBlock block; data->err_msg = std::string("Block not found.");
CBlockIndex* pblockindex = mapBlockIndex[hash]; return;
if(!ReadBlockFromDisk(block, pblockindex)) {
data->err_msg = std::string("Can't read block from disk");
} else { } else {
data->cblock = block; pblockindex = mapBlockIndex[hash];
data->cblock_index = pblockindex;
} }
} }
const CDiskBlockPos& pos = pblockindex->GetBlockPos();
// We can read directly from the file, and pass that, we don't need to
// deserialize the entire block only for it to then be serialized
// and then deserialized again in JavaScript
// Open history file to read
CAutoFile filein(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION);
if (filein.IsNull()) {
data->err_msg = std::string("ReadBlockFromDisk: OpenBlockFile failed");
return;
}
// Get the actual file, seeked position and rewind a uint32_t
FILE* blockFile = filein.release();
long int filePos = ftell(blockFile);
fseek(blockFile, filePos - sizeof(uint32_t), SEEK_SET);
// Read the size of the block
uint32_t size = 0;
fread(&size, sizeof(uint32_t), 1, blockFile);
// Read block
char* buffer = (char *)malloc(sizeof(char) * size);
fread((void *)buffer, sizeof(char), size, blockFile);
fclose(blockFile);
data->buffer = buffer;
data->size = size;
data->cblock_index = pblockindex;
} }
static void static void
@ -883,19 +902,17 @@ async_get_block_after(uv_work_t *req) {
node::FatalException(try_catch); node::FatalException(try_catch);
} }
} else { } else {
const CBlock& cblock = data->cblock;
CBlockIndex* cblock_index = data->cblock_index; CBlockIndex* cblock_index = data->cblock_index;
CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION); Local<Value> rawNodeBuffer = node::Buffer::New(isolate, data->buffer, data->size);
ssBlock << cblock;
std::string strHex = HexStr(ssBlock.begin(), ssBlock.end());
Local<String> jsblock = NanNew<String>(strHex); delete data->buffer;
data->buffer = NULL;
const unsigned argc = 2; const unsigned argc = 2;
Local<Value> argv[argc] = { Local<Value> argv[argc] = {
Local<Value>::New(isolate, NanNull()), Local<Value>::New(isolate, NanNull()),
Local<Value>::New(isolate, jsblock) rawNodeBuffer
}; };
TryCatch try_catch; TryCatch try_catch;
cb->Call(isolate->GetCurrentContext()->Global(), argc, argv); cb->Call(isolate->GetCurrentContext()->Global(), argc, argv);