From 801679df75015cffd4fa4b21be828b6fd8f2368d Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Wed, 15 Jul 2015 17:45:36 -0400 Subject: [PATCH 1/3] Add isSpent call --- integration/index.js | 20 ++++++++++++++++- integration/livenet-spents.json | 18 ++++++++++++++++ lib/bitcoind.js | 4 ++++ src/bitcoindjs.cc | 38 +++++++++++++++++++++++++++++++++ src/bitcoindjs.h | 1 + 5 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 integration/livenet-spents.json diff --git a/integration/index.js b/integration/index.js index 5ffedeb3..3e2b12f2 100644 --- a/integration/index.js +++ b/integration/index.js @@ -14,6 +14,8 @@ var sinon = require('sinon'); var txData = require('./livenet-tx-data.json'); var blockData = require('./livenet-block-data.json'); var testTxData = require('./livenet-tx-data.json'); +var spentData = require('./livenet-spents.json').spent; +var unspentData = require('./livenet-spents.json').unspent; var testBlockData = require('./testnet-block-data.json'); describe('Basic Functionality', function() { @@ -59,9 +61,25 @@ describe('Basic Functionality', function() { }); }); }); + + describe.only('determine if outpoint is unspent/spent', function() { + spentData.forEach(function(data) { + it('for txid ' + data.txid + ' and output ' + data.outputIndex, function() { + var spent = bitcoind.isSpent(data.txid, data.outputIndex, true); + spent.should.equal(true); + }); + }); + + unspentData.forEach(function(data) { + it('for txid ' + data.txid + ' and output ' + data.outputIndex, function() { + var spent = bitcoind.isSapent(data.txid, data.outputIndex, true); + spent.should.equal(false); + }); + }); + }); describe('get blocks by hash', function() { - + blockData.forEach(function(data) { var block = bitcore.Block.fromString(data); it('block ' + block.hash, function(done) { diff --git a/integration/livenet-spents.json b/integration/livenet-spents.json new file mode 100644 index 00000000..d8b84e52 --- /dev/null +++ b/integration/livenet-spents.json @@ -0,0 +1,18 @@ +{ + "unspent": [ + { + "txid": "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098", + "outputIndex": 0 + } + ], + "spent": [ + { + "txid": "0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9", + "outputIndex": 0 + }, + { + "txid": "fff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4", + "outputIndex": 1 + } + ] +} diff --git a/lib/bitcoind.js b/lib/bitcoind.js index 045f4039..e9b6095a 100644 --- a/lib/bitcoind.js +++ b/lib/bitcoind.js @@ -323,6 +323,10 @@ Bitcoin.prototype.getBlockHeight = function(height, callback) { }); }; +Bitcoin.prototype.isSpent = function(txid, outputIndex, queryMempool) { + return bitcoindjs.isSpent(txid, outputIndex, queryMempool); +}; + Bitcoin.prototype.getTransaction = Bitcoin.prototype.getTx = function(txid, blockhash, callback) { if (bitcoin.stopping) return []; diff --git a/src/bitcoindjs.cc b/src/bitcoindjs.cc index 38e81bd9..cbf6870f 100644 --- a/src/bitcoindjs.cc +++ b/src/bitcoindjs.cc @@ -930,6 +930,43 @@ async_get_tx_after(uv_work_t *req) { delete req; } +/** + * IsSpent() + * bitcoindjs.isSpent() + * Determine if an outpoint is spent + */ +NAN_METHOD(IsSpent) { + NanScope(); + + if (args.Length() > 3) { + return NanThrowError( + "Usage: bitcoindjs.isSpent(txid, outputIndex, queryMempool)"); + } + + // XXX: include the mempool in the coins viewcache + + String::Utf8Value arg(args[0]->ToString()); + std::string argStr = std::string(*arg); + const uint256 txid = uint256S(argStr); + int outputIndex = args[1]->IntegerValue(); + bool queryMempool = args[2]->BooleanValue(); + + CCoinsViewCache &view = *pcoinsTip; + + if (view.HaveCoins(txid)) { + const CCoins* coins = view.AccessCoins(txid); + if (!coins || !coins->IsAvailable(outputIndex)) { + NanReturnValue(NanNew(false)); + return; + } + } else { + NanReturnValue(NanNew(false)); + return; + } + + NanReturnValue(NanNew(true)); +}; + /** * GetInfo() * bitcoindjs.getInfo() @@ -997,6 +1034,7 @@ init(Handle target) { NODE_SET_METHOD(target, "getBlock", GetBlock); NODE_SET_METHOD(target, "getTransaction", GetTransaction); NODE_SET_METHOD(target, "getInfo", GetInfo); + NODE_SET_METHOD(target, "isSpent", IsSpent); } diff --git a/src/bitcoindjs.h b/src/bitcoindjs.h index 571e0c39..3a965149 100644 --- a/src/bitcoindjs.h +++ b/src/bitcoindjs.h @@ -27,3 +27,4 @@ NAN_METHOD(StopBitcoind); NAN_METHOD(GetBlock); NAN_METHOD(GetTransaction); NAN_METHOD(GetInfo); +NAN_METHOD(IsSpent); From 1c615ac7c00063a9c0510126421fb241dbf26a73 Mon Sep 17 00:00:00 2001 From: Chris Kleeschulte Date: Wed, 15 Jul 2015 18:52:36 -0400 Subject: [PATCH 2/3] Added extern mempool and fixed method name. --- integration/index.js | 6 +++--- src/bitcoindjs.cc | 13 +++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/integration/index.js b/integration/index.js index 3e2b12f2..14da0300 100644 --- a/integration/index.js +++ b/integration/index.js @@ -64,15 +64,15 @@ describe('Basic Functionality', function() { describe.only('determine if outpoint is unspent/spent', function() { spentData.forEach(function(data) { - it('for txid ' + data.txid + ' and output ' + data.outputIndex, function() { + it('for spent txid ' + data.txid + ' and output ' + data.outputIndex, function() { var spent = bitcoind.isSpent(data.txid, data.outputIndex, true); spent.should.equal(true); }); }); unspentData.forEach(function(data) { - it('for txid ' + data.txid + ' and output ' + data.outputIndex, function() { - var spent = bitcoind.isSapent(data.txid, data.outputIndex, true); + it('for unspent txid ' + data.txid + ' and output ' + data.outputIndex, function() { + var spent = bitcoind.isSpent(data.txid, data.outputIndex, true); spent.should.equal(false); }); }); diff --git a/src/bitcoindjs.cc b/src/bitcoindjs.cc index cbf6870f..b77bdb78 100644 --- a/src/bitcoindjs.cc +++ b/src/bitcoindjs.cc @@ -22,6 +22,7 @@ using namespace v8; extern void WaitForShutdown(boost::thread_group* threadGroup); static termios orig_termios; +extern CTxMemPool mempool; /** * Node.js Internal Function Templates @@ -951,19 +952,19 @@ NAN_METHOD(IsSpent) { int outputIndex = args[1]->IntegerValue(); bool queryMempool = args[2]->BooleanValue(); - CCoinsViewCache &view = *pcoinsTip; + CCoinsView dummy; + CCoinsViewCache view(&dummy); + + CCoinsViewMemPool viewMemPool(pcoinsTip, mempool); + view.SetBackend(viewMemPool); if (view.HaveCoins(txid)) { const CCoins* coins = view.AccessCoins(txid); - if (!coins || !coins->IsAvailable(outputIndex)) { + if (coins && coins->IsAvailable(outputIndex)) { NanReturnValue(NanNew(false)); return; } - } else { - NanReturnValue(NanNew(false)); - return; } - NanReturnValue(NanNew(true)); }; From dcaa6203e96f6bf13ec59887a2077ed14d475327 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Wed, 15 Jul 2015 19:38:19 -0400 Subject: [PATCH 3/3] Add additional livenet tests and remove used param. --- integration/index.js | 2 +- integration/livenet-spents.json | 8 ++++++++ lib/bitcoind.js | 4 ++-- src/bitcoindjs.cc | 7 ++----- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/integration/index.js b/integration/index.js index 14da0300..c48bbd6f 100644 --- a/integration/index.js +++ b/integration/index.js @@ -62,7 +62,7 @@ describe('Basic Functionality', function() { }); }); - describe.only('determine if outpoint is unspent/spent', function() { + describe('determine if outpoint is unspent/spent', function() { spentData.forEach(function(data) { it('for spent txid ' + data.txid + ' and output ' + data.outputIndex, function() { var spent = bitcoind.isSpent(data.txid, data.outputIndex, true); diff --git a/integration/livenet-spents.json b/integration/livenet-spents.json index d8b84e52..8c1eed28 100644 --- a/integration/livenet-spents.json +++ b/integration/livenet-spents.json @@ -3,6 +3,14 @@ { "txid": "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098", "outputIndex": 0 + }, + { + "txid": "64b2da257d93ab44d19ef9b374788d82b6885bc3fb3c17704f42f09b1096e982", + "outputIndex": 0 + }, + { + "txid": "226bbc4b1f851857f37aa96e9eb702946fc128b055e4decc684740005f5044cf", + "outputIndex": 0 } ], "spent": [ diff --git a/lib/bitcoind.js b/lib/bitcoind.js index e9b6095a..bb022a84 100644 --- a/lib/bitcoind.js +++ b/lib/bitcoind.js @@ -323,8 +323,8 @@ Bitcoin.prototype.getBlockHeight = function(height, callback) { }); }; -Bitcoin.prototype.isSpent = function(txid, outputIndex, queryMempool) { - return bitcoindjs.isSpent(txid, outputIndex, queryMempool); +Bitcoin.prototype.isSpent = function(txid, outputIndex) { + return bitcoindjs.isSpent(txid, outputIndex); }; Bitcoin.prototype.getTransaction = diff --git a/src/bitcoindjs.cc b/src/bitcoindjs.cc index b77bdb78..61dc487a 100644 --- a/src/bitcoindjs.cc +++ b/src/bitcoindjs.cc @@ -939,18 +939,15 @@ async_get_tx_after(uv_work_t *req) { NAN_METHOD(IsSpent) { NanScope(); - if (args.Length() > 3) { + if (args.Length() > 2) { return NanThrowError( - "Usage: bitcoindjs.isSpent(txid, outputIndex, queryMempool)"); + "Usage: bitcoindjs.isSpent(txid, outputIndex)"); } - // XXX: include the mempool in the coins viewcache - String::Utf8Value arg(args[0]->ToString()); std::string argStr = std::string(*arg); const uint256 txid = uint256S(argStr); int outputIndex = args[1]->IntegerValue(); - bool queryMempool = args[2]->BooleanValue(); CCoinsView dummy; CCoinsViewCache view(&dummy);