Added bindings to be able to listen to tx leaving mempool.
This commit is contained in:
parent
275a0b57ea
commit
f0ec424161
|
@ -367,14 +367,27 @@ index f94771a..72ee00e 100644
|
|||
|
||||
|
||||
diff --git a/src/net.h b/src/net.h
|
||||
index 17502b9..e181d68 100644
|
||||
index 17502b9..c9ae1b2 100644
|
||||
--- a/src/net.h
|
||||
+++ b/src/net.h
|
||||
@@ -99,6 +99,7 @@ struct CNodeSignals
|
||||
@@ -99,6 +99,8 @@ struct CNodeSignals
|
||||
{
|
||||
boost::signals2::signal<int ()> GetHeight;
|
||||
boost::signals2::signal<bool (CNode*), CombinerAll> ProcessMessages;
|
||||
+ boost::signals2::signal<bool (const CTransaction&)> TxToMemPool;
|
||||
+ boost::signals2::signal<bool (const CTransaction&)> TxLeaveMemPool;
|
||||
boost::signals2::signal<bool (CNode*, bool), CombinerAll> SendMessages;
|
||||
boost::signals2::signal<void (NodeId, const CNode*)> InitializeNode;
|
||||
boost::signals2::signal<void (NodeId)> FinalizeNode;
|
||||
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
|
||||
index c3d1b60..03e265d 100644
|
||||
--- a/src/txmempool.cpp
|
||||
+++ b/src/txmempool.cpp
|
||||
@@ -133,6 +133,7 @@ void CTxMemPool::remove(const CTransaction &origTx, std::list<CTransaction>& rem
|
||||
if (!mapTx.count(hash))
|
||||
continue;
|
||||
const CTransaction& tx = mapTx[hash].GetTx();
|
||||
+ GetNodeSignals().TxLeaveMemPool(tx);
|
||||
if (fRecursive) {
|
||||
for (unsigned int i = 0; i < tx.vout.size(); i++) {
|
||||
std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(COutPoint(hash, i));
|
||||
|
|
|
@ -360,6 +360,30 @@ describe('Daemon Binding Functionality', function() {
|
|||
});
|
||||
});
|
||||
|
||||
describe('transactions leaving the mempool', function() {
|
||||
it('receive event when transaction leaves', function(done) {
|
||||
|
||||
// add transaction to build a new block
|
||||
var tx = bitcore.Transaction();
|
||||
tx.from(utxos[4]);
|
||||
tx.change(privateKey.toAddress());
|
||||
tx.to(destKey.toAddress(), utxos[4].amount * 1e8 - 1000);
|
||||
tx.sign(bitcore.PrivateKey.fromWIF(utxos[4].privateKeyWIF));
|
||||
bitcoind.sendTransaction(tx.serialize());
|
||||
|
||||
bitcoind.once('txleave', function(txInfo) {
|
||||
txInfo.hash.should.equal(tx.hash);
|
||||
done();
|
||||
});
|
||||
|
||||
client.generate(1, function(err, response) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('mempool functionality', function() {
|
||||
|
||||
var fromAddress = 'mszYqVnqKoQx4jcTdJXxwKAissE3Jbrrc1';
|
||||
|
|
|
@ -110,12 +110,19 @@ Bitcoin.prototype._registerEventHandlers = function() {
|
|||
// Set the height and emit a new tip
|
||||
bindings.onTipUpdate(self._onTipUpdate.bind(this));
|
||||
|
||||
// Register callback function to handle incoming transactions
|
||||
// Register callback function to handle transactions entering the mempool
|
||||
bindings.startTxMon(function(txs) {
|
||||
for(var i = 0; i < txs.length; i++) {
|
||||
self.emit('tx', txs[i]);
|
||||
}
|
||||
});
|
||||
|
||||
// Register callback function to handle transactions leaving the mempool
|
||||
bindings.startTxMonLeave(function(txs) {
|
||||
for(var i = 0; i < txs.length; i++) {
|
||||
self.emit('txleave', txs[i]);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Bitcoin.prototype._onReady = function(result, callback) {
|
||||
|
|
|
@ -39,6 +39,9 @@ extern int64_t nTimeBestReceived;
|
|||
static void
|
||||
tx_notifier(uv_async_t *handle);
|
||||
|
||||
static void
|
||||
txleave_notifier(uv_async_t *handle);
|
||||
|
||||
static void
|
||||
async_tip_update(uv_work_t *req);
|
||||
|
||||
|
@ -90,6 +93,9 @@ async_get_tx_and_info_after(uv_work_t *req);
|
|||
static bool
|
||||
queueTx(const CTransaction&);
|
||||
|
||||
static bool
|
||||
queueTxLeave(const CTransaction&);
|
||||
|
||||
extern "C" void
|
||||
init(Handle<Object>);
|
||||
|
||||
|
@ -98,9 +104,13 @@ init(Handle<Object>);
|
|||
* Used only by bitcoind functions.
|
||||
*/
|
||||
static std::vector<CTransaction> txQueue;
|
||||
static std::vector<CTransaction> txQueueLeave;
|
||||
static uv_async_t txmon_async;
|
||||
static uv_async_t txmonleave_async;
|
||||
static Eternal<Function> txmon_callback;
|
||||
static Eternal<Function> txmonleave_callback;
|
||||
static bool txmon_callback_available;
|
||||
static bool txmonleave_callback_available;
|
||||
|
||||
static volatile bool shutdown_complete = false;
|
||||
static char *g_data_dir = NULL;
|
||||
|
@ -259,6 +269,21 @@ NAN_METHOD(StartTxMon) {
|
|||
info.GetReturnValue().Set(Null());
|
||||
};
|
||||
|
||||
NAN_METHOD(StartTxMonLeave) {
|
||||
Isolate* isolate = info.GetIsolate();
|
||||
Local<Function> callback = Local<Function>::Cast(info[0]);
|
||||
Eternal<Function> cb(isolate, callback);
|
||||
txmonleave_callback = cb;
|
||||
txmonleave_callback_available = true;
|
||||
|
||||
CNodeSignals& nodeSignals = GetNodeSignals();
|
||||
nodeSignals.TxLeaveMemPool.connect(&queueTxLeave);
|
||||
|
||||
uv_async_init(uv_default_loop(), &txmonleave_async, txleave_notifier);
|
||||
|
||||
info.GetReturnValue().Set(Null());
|
||||
};
|
||||
|
||||
static void
|
||||
tx_notifier(uv_async_t *handle) {
|
||||
Isolate* isolate = Isolate::GetCurrent();
|
||||
|
@ -307,6 +332,53 @@ queueTx(const CTransaction& tx) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
txleave_notifier(uv_async_t *handle) {
|
||||
Isolate* isolate = Isolate::GetCurrent();
|
||||
HandleScope scope(isolate);
|
||||
|
||||
Local<Array> results = Array::New(isolate);
|
||||
int arrayIndex = 0;
|
||||
|
||||
LOCK(cs_main);
|
||||
BOOST_FOREACH(const CTransaction& tx, txQueueLeave) {
|
||||
|
||||
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ssTx << tx;
|
||||
std::string stx = ssTx.str();
|
||||
Nan::MaybeLocal<v8::Object> txBuffer = Nan::CopyBuffer((char *)stx.c_str(), stx.size());
|
||||
|
||||
uint256 hash = tx.GetHash();
|
||||
|
||||
Local<Object> obj = New<Object>();
|
||||
|
||||
Nan::Set(obj, New("buffer").ToLocalChecked(), txBuffer.ToLocalChecked());
|
||||
Nan::Set(obj, New("hash").ToLocalChecked(), New(hash.GetHex()).ToLocalChecked());
|
||||
|
||||
results->Set(arrayIndex, obj);
|
||||
arrayIndex++;
|
||||
}
|
||||
|
||||
const unsigned argc = 1;
|
||||
Local<Value> argv[argc] = {
|
||||
Local<Value>::New(isolate, results)
|
||||
};
|
||||
|
||||
Local<Function> cb = txmonleave_callback.Get(isolate);
|
||||
|
||||
cb->Call(isolate->GetCurrentContext()->Global(), argc, argv);
|
||||
|
||||
txQueueLeave.clear();
|
||||
|
||||
}
|
||||
static bool
|
||||
queueTxLeave(const CTransaction& tx) {
|
||||
LOCK(cs_main);
|
||||
txQueueLeave.push_back(tx);
|
||||
uv_async_send(&txmonleave_async);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Functions
|
||||
*/
|
||||
|
@ -1527,6 +1599,7 @@ NAN_MODULE_INIT(init) {
|
|||
Nan::Set(target, New("sendTransaction").ToLocalChecked(), GetFunction(New<FunctionTemplate>(SendTransaction)).ToLocalChecked());
|
||||
Nan::Set(target, New("estimateFee").ToLocalChecked(), GetFunction(New<FunctionTemplate>(EstimateFee)).ToLocalChecked());
|
||||
Nan::Set(target, New("startTxMon").ToLocalChecked(), GetFunction(New<FunctionTemplate>(StartTxMon)).ToLocalChecked());
|
||||
Nan::Set(target, New("startTxMonLeave").ToLocalChecked(), GetFunction(New<FunctionTemplate>(StartTxMonLeave)).ToLocalChecked());
|
||||
Nan::Set(target, New("syncPercentage").ToLocalChecked(), GetFunction(New<FunctionTemplate>(SyncPercentage)).ToLocalChecked());
|
||||
Nan::Set(target, New("isSynced").ToLocalChecked(), GetFunction(New<FunctionTemplate>(IsSynced)).ToLocalChecked());
|
||||
Nan::Set(target, New("getBestBlockHash").ToLocalChecked(), GetFunction(New<FunctionTemplate>(GetBestBlockHash)).ToLocalChecked());
|
||||
|
|
|
@ -144,7 +144,8 @@ describe('Bitcoin Service', function() {
|
|||
name.should.equal('bitcoind.node');
|
||||
return {
|
||||
onTipUpdate: sinon.stub(),
|
||||
startTxMon: sinon.stub().callsArgWith(0, [transaction])
|
||||
startTxMon: sinon.stub().callsArgWith(0, [transaction]),
|
||||
startTxMonLeave: sinon.stub().callsArgWith(0, [transaction])
|
||||
};
|
||||
}
|
||||
});
|
||||
|
@ -175,7 +176,8 @@ describe('Bitcoin Service', function() {
|
|||
callback(height++);
|
||||
});
|
||||
},
|
||||
startTxMon: sinon.stub()
|
||||
startTxMon: sinon.stub(),
|
||||
startTxMonLeave: sinon.stub()
|
||||
};
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue