remove packet polling code.

This commit is contained in:
Christopher Jeffrey 2014-10-23 13:09:53 -07:00
parent 7977247b79
commit 090eb9ab42
2 changed files with 0 additions and 456 deletions

View File

@ -310,30 +310,6 @@ Bitcoin.prototype.start = function(options, callback) {
this._emitted = {};
// this.on('newListener', function(name) {
// if (name === 'version' || name === 'peer') {
// self._pollPeers();
// return;
// }
// if (name === 'addr') {
// self._pollAddresses();
// return;
// }
// if (name === 'block') {
// self._pollBlocks();
// return;
// }
// if (name === 'tx') {
// self._pollBlocks();
// self._pollMempool();
// return;
// }
// if (name === 'mptx') {
// self._pollMempool();
// return;
// }
// });
if (this.log_pipe !== -1) {
this.log('log pipe opened: %d', this.log_pipe);
this._pipe = new net.Socket(this.log_pipe);
@ -347,149 +323,6 @@ Bitcoin.prototype.start = function(options, callback) {
}
};
Bitcoin.prototype._pollBlocks = function() {
var self = this;
if (this._pollingBlocks) return;
this._pollingBlocks = true;
(function next() {
return bitcoindjs.pollBlocks(function(err, blocks) {
if (err) {
if (self.debug) {
console.log('poll error:');
console.log(err.message);
}
return setTimeout(next, self.pollInterval);
}
return utils.forEach(blocks, function(block, nextBlock) {
block = bitcoin.block(block);
// XXX Bad workaround
if (self._emitted[block.hash]) {
if (Object.keys(self._emitted[block.hash]).length > 10000) {
self._emitted = {};
}
return setImmediate(function() {
return nextBlock();
});
}
self._emitted[block.hash] = true;
self.emit('block', block);
if (!self._pollingTxs) {
return setImmediate(function() {
return nextBlock();
});
}
return utils.forEach(block.tx, function(tx, nextTx) {
tx = bitcoin.tx(tx);
self.emit('tx', tx);
return setImmediate(function() {
return nextTx();
});
}, function() {
return setImmediate(function() {
return nextBlock();
});
});
}, function() {
if (self.debug) {
console.log('emission finished');
}
return setTimeout(next, self.pollInterval);
});
});
})();
};
Bitcoin.prototype._pollMempool = function() {
var self = this;
if (this._pollingTxs) return;
this._pollingTxs = true;
(function next() {
return bitcoindjs.pollMempool(function(err, txs) {
if (err) return setTimeout(next, self.pollInterval);
return utils.forEach(txs, function(tx, nextTx) {
tx = bitcoin.tx(tx);
// XXX Bad workaround
if (self._emitted[tx.txid]) {
if (Object.keys(self._emitted[block.hash]).length > 10000) {
self._emitted = {};
}
return setImmediate(function() {
return nextTx();
});
}
self._emitted[tx.txid] = true;
self.emit('mptx', tx);
self.emit('tx', tx);
return setImmediate(function() {
return nextTx();
});
}, function() {
return setTimeout(next, self.pollInterval);
});
});
})();
};
// XXX Not perfect - will not catch all version packets.
Bitcoin.prototype._pollPeers = function() {
var self = this;
if (this._pollingPeers) return;
this._pollingPeers = true;
var lastPeers = bitcoindjs.getPeerInfo();
(function next() {
var peers = bitcoindjs.getPeerInfo();
peers = peers.filter(function(peer, i) {
return !lastPeers[i] || peer.addr !== lastPeers[i].addr;
});
peers.forEach(function(peer) {
self.emit('peer', peer);
self.emit('version', {
version: peer.version,
services: peer.services,
time: peer.conntime,
nonce: null,
useragent: peer.subver,
startheight: peer.startingheight,
relay: null // peer.fRelayTxes
});
});
lastPeers = peers;
return setTimeout(next, self.pollInterval);
})();
};
Bitcoin.prototype._pollAddresses = function() {
var self = this;
if (this._pollingAddresses) return;
this._pollingAddresses = true;
var lastAddrs = bitcoindjs.getAddresses();
(function next() {
var addrs = bitcoindjs.getAddresses();
addrs = addrs.filter(function(addr, i) {
return !lastAddrs[i] || addr.time !== lastAddrs[i].time;
});
addrs.forEach(function(addr) {
self.emit('addr', {
services: addr.services,
time: addr.time,
last: addr.last,
ip: addr.ip,
port: addr.port,
address: addr.address
});
});
lastAddrs = addrs;
return setTimeout(next, self.pollInterval);
})();
};
Bitcoin.prototype.getBlock = function(blockHash, callback) {
return bitcoindjs.getBlock(blockHash, function(err, block) {
if (err) return callback(err);

View File

@ -160,8 +160,6 @@ NAN_METHOD(IsStopped);
NAN_METHOD(StopBitcoind);
NAN_METHOD(GetBlock);
NAN_METHOD(GetTx);
NAN_METHOD(PollBlocks);
NAN_METHOD(PollMempool);
NAN_METHOD(BroadcastTx);
NAN_METHOD(VerifyBlock);
NAN_METHOD(VerifyTransaction);
@ -231,18 +229,6 @@ async_get_tx(uv_work_t *req);
static void
async_get_tx_after(uv_work_t *req);
static void
async_poll_blocks(uv_work_t *req);
static void
async_poll_blocks_after(uv_work_t *req);
static void
async_poll_mempool(uv_work_t *req);
static void
async_poll_mempool_after(uv_work_t *req);
static void
async_broadcast_tx(uv_work_t *req);
@ -300,7 +286,6 @@ init(Handle<Object>);
*/
static volatile bool shutdown_complete = false;
static int block_poll_top_height = -1;
static char *g_data_dir = NULL;
static bool g_rpc = false;
static bool g_testnet = false;
@ -360,39 +345,6 @@ struct async_tx_data {
Persistent<Function> callback;
};
/**
* poll_blocks_list
* A singly linked list containing any polled CBlocks and CBlockIndexes.
* Contained by async_poll_blocks_data struct.
*/
typedef struct _poll_blocks_list {
CBlock cblock;
CBlockIndex *cblock_index;
struct _poll_blocks_list *next;
} poll_blocks_list;
/**
* async_poll_blocks_data
*/
struct async_poll_blocks_data {
std::string err_msg;
poll_blocks_list *head;
Persistent<Array> result_array;
Persistent<Function> callback;
};
/**
* async_poll_mempool_data
*/
struct async_poll_mempool_data {
std::string err_msg;
Persistent<Array> result_array;
Persistent<Function> callback;
};
/**
* async_broadcast_tx_data
*/
@ -1010,245 +962,6 @@ async_get_tx_after(uv_work_t *req) {
delete req;
}
/**
* PollBlocks()
* bitcoind.pollBlocks(callback)
* Poll for new blocks on the chain. This is necessary since we have no way of
* hooking in to AcceptBlock(). Instead, we constant check for new blocks using
* a SetTimeout() within node.js.
* Creating a linked list of all blocks within the work function is necessary
* due to doing v8 things within the libuv thread pool will cause a segfault.
* Since this reads full blocks, obviously it will poll for transactions which
* have already been included in blocks as well.
*/
NAN_METHOD(PollBlocks) {
NanScope();
if (args.Length() < 1 || !args[0]->IsFunction()) {
return NanThrowError(
"Usage: bitcoindjs.pollBlocks(callback)");
}
Local<Function> callback = Local<Function>::Cast(args[0]);
async_poll_blocks_data *data = new async_poll_blocks_data();
data->err_msg = std::string("");
data->callback = Persistent<Function>::New(callback);
uv_work_t *req = new uv_work_t();
req->data = data;
int status = uv_queue_work(uv_default_loop(),
req, async_poll_blocks,
(uv_after_work_cb)async_poll_blocks_after);
assert(status == 0);
NanReturnValue(Undefined());
}
static void
async_poll_blocks(uv_work_t *req) {
async_poll_blocks_data* data = static_cast<async_poll_blocks_data*>(req->data);
int poll_saved_height = block_poll_top_height;
// Poll, wait until we actually have a blockchain download.
// Once we've noticed the height changed, assume we gained a few blocks.
while (chainActive.Tip()) {
int cur_height = chainActive.Height();
if (cur_height != block_poll_top_height) {
block_poll_top_height = cur_height;
break;
}
// Try again in 100ms
useconds_t usec = 100 * 1000;
usleep(usec);
}
// NOTE: Since we can't do v8 stuff on the uv thread pool, we need to create
// a linked list for all the blocks and free them up later.
poll_blocks_list *head = NULL;
poll_blocks_list *cur = NULL;
for (int i = poll_saved_height; i < block_poll_top_height; i++) {
if (i == -1) continue;
CBlockIndex *cblock_index = chainActive[i];
if (cblock_index != NULL) {
CBlock cblock;
if (ReadBlockFromDisk(cblock, cblock_index)) {
poll_blocks_list *next = new poll_blocks_list();
next->next = NULL;
if (cur == NULL) {
head = next;
cur = next;
} else {
cur->next = next;
cur = next;
}
cur->cblock = cblock;
cur->cblock_index = cblock_index;
}
}
}
data->head = head;
}
static void
async_poll_blocks_after(uv_work_t *req) {
NanScope();
async_poll_blocks_data* data = static_cast<async_poll_blocks_data*>(req->data);
if (!data->err_msg.empty()) {
Local<Value> err = Exception::Error(String::New(data->err_msg.c_str()));
const unsigned argc = 1;
Local<Value> argv[argc] = { err };
TryCatch try_catch;
data->callback->Call(Context::GetCurrent()->Global(), argc, argv);
if (try_catch.HasCaught()) {
node::FatalException(try_catch);
}
} else {
const unsigned argc = 2;
Local<Array> blocks = NanNew<Array>();
poll_blocks_list *cur = static_cast<poll_blocks_list*>(data->head);
poll_blocks_list *next;
int i = 0;
while (cur != NULL) {
CBlock cblock = cur->cblock;
CBlockIndex *cblock_index = cur->cblock_index;
Local<Object> jsblock = NanNew<Object>();
cblock_to_jsblock(cblock, cblock_index, jsblock);
blocks->Set(i, jsblock);
i++;
next = cur->next;
delete cur;
cur = next;
}
Local<Value> argv[argc] = {
Local<Value>::New(Null()),
Local<Value>::New(blocks)
};
TryCatch try_catch;
data->callback->Call(Context::GetCurrent()->Global(), argc, argv);
if (try_catch.HasCaught()) {
node::FatalException(try_catch);
}
}
data->callback.Dispose();
delete data;
delete req;
}
/**
* PollMempool()
* bitcoind.pollMempool(callback)
* This will poll for any transactions in the mempool. i.e. Transactions which
* have not been included in blocks yet. This is not technically necessary to
* be done asynchronously since there are no real blocking calls done here, but
* we will leave the async function here as a placeholder in case we're wrong.
*/
NAN_METHOD(PollMempool) {
NanScope();
if (args.Length() < 1 || !args[0]->IsFunction()) {
return NanThrowError(
"Usage: bitcoindjs.pollMempool(callback)");
}
Local<Function> callback = Local<Function>::Cast(args[0]);
async_poll_mempool_data *data = new async_poll_mempool_data();
data->err_msg = std::string("");
data->callback = Persistent<Function>::New(callback);
uv_work_t *req = new uv_work_t();
req->data = data;
int status = uv_queue_work(uv_default_loop(),
req, async_poll_mempool,
(uv_after_work_cb)async_poll_mempool_after);
assert(status == 0);
NanReturnValue(Undefined());
}
static void
async_poll_mempool(uv_work_t *req) {
// XXX Potentially do everything async, but would it matter? Everything is in
// memory. There aren't really any harsh blocking calls. Leave this here as a
// placeholder.
useconds_t usec = 5 * 1000;
usleep(usec);
}
static void
async_poll_mempool_after(uv_work_t *req) {
NanScope();
async_poll_mempool_data* data = static_cast<async_poll_mempool_data*>(req->data);
if (!data->err_msg.empty()) {
Local<Value> err = Exception::Error(String::New(data->err_msg.c_str()));
const unsigned argc = 1;
Local<Value> argv[argc] = { err };
TryCatch try_catch;
data->callback->Call(Context::GetCurrent()->Global(), argc, argv);
if (try_catch.HasCaught()) {
node::FatalException(try_catch);
}
} else {
int ti = 0;
Local<Array> txs = NanNew<Array>();
{
std::map<uint256, CTxMemPoolEntry>::const_iterator it = mempool.mapTx.begin();
for (; it != mempool.mapTx.end(); it++) {
const CTransaction& ctx = it->second.GetTx();
Local<Object> jstx = NanNew<Object>();
ctx_to_jstx(ctx, 0, jstx);
txs->Set(ti, jstx);
ti++;
}
}
{
std::map<COutPoint, CInPoint>::const_iterator it = mempool.mapNextTx.begin();
for (; it != mempool.mapNextTx.end(); it++) {
const CTransaction ctx = *it->second.ptx;
Local<Object> jstx = NanNew<Object>();
ctx_to_jstx(ctx, 0, jstx);
txs->Set(ti, jstx);
ti++;
}
}
const unsigned argc = 2;
Local<Value> argv[argc] = {
Local<Value>::New(Null()),
Local<Value>::New(txs)
};
TryCatch try_catch;
data->callback->Call(Context::GetCurrent()->Global(), argc, argv);
if (try_catch.HasCaught()) {
node::FatalException(try_catch);
}
}
data->callback.Dispose();
delete data;
delete req;
}
/**
* BroadcastTx()
* bitcoind.broadcastTx(tx, override_fees, own_only, callback)
@ -3964,8 +3677,6 @@ init(Handle<Object> target) {
NODE_SET_METHOD(target, "stopped", IsStopped);
NODE_SET_METHOD(target, "getBlock", GetBlock);
NODE_SET_METHOD(target, "getTx", GetTx);
NODE_SET_METHOD(target, "pollBlocks", PollBlocks);
NODE_SET_METHOD(target, "pollMempool", PollMempool);
NODE_SET_METHOD(target, "broadcastTx", BroadcastTx);
NODE_SET_METHOD(target, "verifyBlock", VerifyBlock);
NODE_SET_METHOD(target, "verifyTransaction", VerifyTransaction);