use tiny to cache addresses and start where we left off.
This commit is contained in:
parent
144cb40195
commit
774f08c91f
|
@ -417,36 +417,78 @@ Bitcoin.prototype.getMiningInfo = function() {
|
|||
return bitcoindjs.getMiningInfo();
|
||||
};
|
||||
|
||||
Bitcoin._addrCache = {};
|
||||
Bitcoin._collectAddrGarbage = null;
|
||||
Bitcoin.prototype.getAddrTransactions = function(addr, callback) {
|
||||
if (!Bitcoin._collectAddrGarbage) {
|
||||
Bitcoin._collectAddrGarbage = setInterval(function() {
|
||||
Bitcoin._addrCache = {};
|
||||
}, 20 * 60 * 1000);
|
||||
Bitcoin._collectAddrGarbage.unref();
|
||||
}
|
||||
var cached = Bitcoin._addrCache[addr];
|
||||
if (cached && Date.now() <= (cached.time + 10 * 60 * 1000)) {
|
||||
setImmediate(function() {
|
||||
return callback(null, cached.addr);
|
||||
if (!bitcoin.db) {
|
||||
var tiny = require('tiny').json;
|
||||
bitcoin.db = tiny({
|
||||
file: process.env.HOME + '/.bitcoindjs.addr.db',
|
||||
saveIndex: false,
|
||||
initialCache: false
|
||||
});
|
||||
return;
|
||||
}
|
||||
return bitcoindjs.getAddrTransactions(addr, function(err, addr) {
|
||||
if (err) return callback(err);
|
||||
addr = bitcoin.addr(addr);
|
||||
if (addr.tx[0] && !addr.tx[0].vout[0]) {
|
||||
return callback(null, bitcoin.addr({
|
||||
address: addr.address,
|
||||
tx: []
|
||||
}));
|
||||
return bitcoin.db.get(addr, function(err, records) {
|
||||
var found = !err && records && records.length;
|
||||
var last = found && records[records.length - 1];
|
||||
var limit = 15 * 60 * 1000;
|
||||
if (!found || last.timestamp + limit < Date.now()) {
|
||||
var options = {
|
||||
address: addr,
|
||||
blockindex: (records || []).reduce(function(out, record) {
|
||||
return record.blockindex > out
|
||||
? record.blockindex
|
||||
: out;
|
||||
}, -1)
|
||||
};
|
||||
return bitcoindjs.getAddrTransactions(options, function(err, addr) {
|
||||
if (err) return callback(err);
|
||||
addr = bitcoin.addr(addr);
|
||||
if (addr.tx[0] && !addr.tx[0].vout[0]) {
|
||||
return bitcoin.db.set(addr, [{
|
||||
txid: null,
|
||||
blockhash: null,
|
||||
blockindex: null,
|
||||
timestamp: Date.now()
|
||||
}], function() {
|
||||
return callback(null, bitcoin.addr({
|
||||
address: addr.address,
|
||||
tx: []
|
||||
}));
|
||||
});
|
||||
}
|
||||
var set = [];
|
||||
if (records && records.length) {
|
||||
set = records;
|
||||
}
|
||||
addr.tx.forEach(function(tx) {
|
||||
set.push({
|
||||
txid: tx.txid,
|
||||
blockhash: tx.blockhash,
|
||||
blockindex: tx.blockindex,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
});
|
||||
return bitcoin.db.set(addr, set, function() {
|
||||
return callback(null, addr);
|
||||
});
|
||||
});
|
||||
}
|
||||
Bitcoin._addrCache[addr.address] = {
|
||||
addr: addr,
|
||||
time: Date.now()
|
||||
};
|
||||
return callback(null, addr);
|
||||
var txs = [];
|
||||
return utils.forEach(records, function(record, next) {
|
||||
var block = record.block;
|
||||
var txid = record.txid;
|
||||
var index = record.blockindex;
|
||||
if (txid == null) return next();
|
||||
return bitcoin.getTransaction(txid, block, function(err, tx) {
|
||||
if (err) return next();
|
||||
txs.push(tx);
|
||||
return next();
|
||||
});
|
||||
}, function() {
|
||||
return callback(null, bitcoin.addr({
|
||||
address: addr,
|
||||
tx: txs
|
||||
}));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -455,6 +497,10 @@ Bitcoin.prototype.getBestBlock = function(callback) {
|
|||
return bitcoindjs.getBlock(hash, callback);
|
||||
};
|
||||
|
||||
Bitcoin.prototype.getChainHeight = function() {
|
||||
return bitcoindjs.getChainHeight();
|
||||
};
|
||||
|
||||
Bitcoin.prototype.log =
|
||||
Bitcoin.prototype.info = function() {
|
||||
if (this.options.silent) return;
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
],
|
||||
"dependencies": {
|
||||
"nan": "1.3.0",
|
||||
"mkdirp": "0.5.0"
|
||||
"mkdirp": "0.5.0",
|
||||
"tiny": "0.0.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "~1.16.2",
|
||||
|
|
|
@ -212,6 +212,7 @@ NAN_METHOD(GetGenerate);
|
|||
NAN_METHOD(GetMiningInfo);
|
||||
NAN_METHOD(GetAddrTransactions);
|
||||
NAN_METHOD(GetBestBlock);
|
||||
NAN_METHOD(GetChainHeight);
|
||||
|
||||
NAN_METHOD(GetBlockHex);
|
||||
NAN_METHOD(GetTxHex);
|
||||
|
@ -473,6 +474,7 @@ struct async_addrtx_data {
|
|||
std::string err_msg;
|
||||
std::string addr;
|
||||
ctx_list *ctxs;
|
||||
int64_t blockindex;
|
||||
Persistent<Function> callback;
|
||||
};
|
||||
|
||||
|
@ -1966,24 +1968,46 @@ NAN_METHOD(GetAddrTransactions) {
|
|||
NanScope();
|
||||
|
||||
if (args.Length() < 2
|
||||
|| !args[0]->IsString()
|
||||
|| (!args[0]->IsString() && !args[0]->IsObject())
|
||||
|| !args[1]->IsFunction()) {
|
||||
return NanThrowError(
|
||||
"Usage: bitcoindjs.getAddrTransactions(addr, callback)");
|
||||
}
|
||||
|
||||
String::Utf8Value addr_(args[0]->ToString());
|
||||
std::string addr = "";
|
||||
int64_t blockindex = -1;
|
||||
|
||||
if (args[0]->IsString()) {
|
||||
String::Utf8Value addr_(args[0]->ToString());
|
||||
addr = std::string(*addr_);
|
||||
} else if (args[0]->IsObject()) {
|
||||
Local<Object> options = Local<Object>::Cast(args[0]);
|
||||
if (options->Get(NanNew<String>("address"))->IsString()) {
|
||||
String::Utf8Value s_(options->Get(NanNew<String>("address"))->ToString());
|
||||
addr = std::string(*s_);
|
||||
}
|
||||
if (options->Get(NanNew<String>("addr"))->IsString()) {
|
||||
String::Utf8Value s_(options->Get(NanNew<String>("addr"))->ToString());
|
||||
addr = std::string(*s_);
|
||||
}
|
||||
if (options->Get(NanNew<String>("index"))->IsString()) {
|
||||
blockindex = options->Get(NanNew<String>("index"))->IntegerValue();
|
||||
}
|
||||
if (options->Get(NanNew<String>("blockindex"))->IsString()) {
|
||||
blockindex = options->Get(NanNew<String>("blockindex"))->IntegerValue();
|
||||
}
|
||||
}
|
||||
|
||||
Local<Function> callback = Local<Function>::Cast(args[1]);
|
||||
|
||||
Persistent<Function> cb;
|
||||
cb = Persistent<Function>::New(callback);
|
||||
|
||||
std::string addr = std::string(*addr_);
|
||||
|
||||
async_addrtx_data *data = new async_addrtx_data();
|
||||
data->err_msg = std::string("");
|
||||
data->addr = addr;
|
||||
data->ctxs = NULL;
|
||||
data->blockindex = blockindex;
|
||||
data->callback = Persistent<Function>::New(callback);
|
||||
|
||||
uv_work_t *req = new uv_work_t();
|
||||
|
@ -2002,6 +2026,11 @@ static void
|
|||
async_get_addrtx(uv_work_t *req) {
|
||||
async_addrtx_data* data = static_cast<async_addrtx_data*>(req->data);
|
||||
|
||||
if (data->addr.empty()) {
|
||||
data->err_msg = std::string("Invalid address.");
|
||||
return;
|
||||
}
|
||||
|
||||
CBitcoinAddress address = CBitcoinAddress(data->addr);
|
||||
if (!address.IsValid()) {
|
||||
data->err_msg = std::string("Invalid address.");
|
||||
|
@ -2011,10 +2040,16 @@ async_get_addrtx(uv_work_t *req) {
|
|||
#if !USE_LDB_ADDR
|
||||
CScript expected = GetScriptForDestination(address.Get());
|
||||
|
||||
// int64_t i = 0;
|
||||
int64_t i = 0;
|
||||
|
||||
// Check the last 20,000 blocks
|
||||
int64_t i = chainActive.Height() - 20000;
|
||||
if (i < 0) i = 0;
|
||||
// int64_t i = chainActive.Height() - 20000;
|
||||
// if (i < 0) i = 0;
|
||||
|
||||
if (data->blockindex != -1) {
|
||||
i = data->blockindex;
|
||||
}
|
||||
|
||||
int64_t height = chainActive.Height();
|
||||
|
||||
for (; i <= height; i++) {
|
||||
|
@ -2152,6 +2187,23 @@ NAN_METHOD(GetBestBlock) {
|
|||
NanReturnValue(NanNew<String>(hash.GetHex()));
|
||||
}
|
||||
|
||||
/**
|
||||
* GetChainHeight()
|
||||
* bitcoindjs.getChainHeight()
|
||||
* Get miscellaneous information
|
||||
*/
|
||||
|
||||
NAN_METHOD(GetChainHeight) {
|
||||
NanScope();
|
||||
|
||||
if (args.Length() > 0) {
|
||||
return NanThrowError(
|
||||
"Usage: bitcoindjs.getChainHeight()");
|
||||
}
|
||||
|
||||
NanReturnValue(NanNew<Number>((int)chainActive.Height())->ToInt32());
|
||||
}
|
||||
|
||||
/**
|
||||
* GetBlockHex()
|
||||
* bitcoindjs.getBlockHex(callback)
|
||||
|
@ -6179,6 +6231,7 @@ init(Handle<Object> target) {
|
|||
NODE_SET_METHOD(target, "getMiningInfo", GetMiningInfo);
|
||||
NODE_SET_METHOD(target, "getAddrTransactions", GetAddrTransactions);
|
||||
NODE_SET_METHOD(target, "getBestBlock", GetBestBlock);
|
||||
NODE_SET_METHOD(target, "getChainHeight", GetChainHeight);
|
||||
NODE_SET_METHOD(target, "getBlockHex", GetBlockHex);
|
||||
NODE_SET_METHOD(target, "getTxHex", GetTxHex);
|
||||
NODE_SET_METHOD(target, "blockFromHex", BlockFromHex);
|
||||
|
|
Loading…
Reference in New Issue