From e65b7e8da314dd1eb0ded792d0e62efea805ba3e Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Mon, 29 Sep 2014 16:46:26 -0700 Subject: [PATCH] fillTransaction: allow destination output choice. --- lib/bitcoind.js | 8 ++++---- src/bitcoindjs.cc | 45 +++++++++++++++++++++++++++++---------------- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/lib/bitcoind.js b/lib/bitcoind.js index 6f111441..ca13ceef 100644 --- a/lib/bitcoind.js +++ b/lib/bitcoind.js @@ -493,12 +493,12 @@ Transaction.prototype.verify = function() { }; Transaction.prototype.sign = -Transaction.prototype.fill = function() { - return Transaction.fill(this); +Transaction.prototype.fill = function(options) { + return Transaction.fill(this, options); }; Transaction.sign = -Transaction.fill = function(tx) { +Transaction.fill = function(tx, options) { var isTx = bitcoin.tx.isTx(tx) , newTx; @@ -507,7 +507,7 @@ Transaction.fill = function(tx) { } try { - newTx = bitcoindjs.fillTransaction(tx); + newTx = bitcoindjs.fillTransaction(tx, options || {}); } catch (e) { return false; } diff --git a/src/bitcoindjs.cc b/src/bitcoindjs.cc index 8a6049e2..ed763ba1 100644 --- a/src/bitcoindjs.cc +++ b/src/bitcoindjs.cc @@ -1253,22 +1253,33 @@ NAN_METHOD(FillTransaction) { CDataStream ssData(ParseHex(tx_hex), SER_NETWORK, PROTOCOL_VERSION); ssData >> tx; - // Get setCoins - int64_t nValueTotal = 0; - CScript scriptPubKeyMain; - bool scriptPubKeySet = false; - for (unsigned int vo = 0; vo < tx.vout.size(); vo++) { - const CTxOut& txout = tx.vout[vo]; - int64_t nValue = txout.nValue; - const CScript& scriptPubKey = txout.scriptPubKey; - if (!scriptPubKeySet) { - scriptPubKeyMain = scriptPubKey; - scriptPubKeySet = true; + // Parse options + int d_output = 0; + if (args.Length() > 1 && args[1]->IsObject()) { + Local options = Local::Cast(args[1]); + // Destination output + if (options->Get(NanNew("output"))->IsNumber()) { + d_output = options->Get(NanNew("output"))->IntegerValue(); + if (d_output < 0 || d_output >= tx.vout.size()) { + return NanThrowError("Destination output does not exist"); + } } - nValueTotal += nValue; } - int64_t nValue = nValueTotal; + // Get total value of outputs + // Get the scriptPubKey of the first output (presumably our destination) + int64_t nValue = 0; + CScript scriptPubKeyMain; + for (unsigned int vo = 0; vo < tx.vout.size(); vo++) { + const CTxOut& txout = tx.vout[vo]; + int64_t value = txout.nValue; + const CScript& scriptPubKey = txout.scriptPubKey; + if (vo == d_output) { + scriptPubKeyMain = scriptPubKey; + } + nValue += value; + } + if (nValue <= 0) return NanThrowError("Invalid amount"); if (nValue + nTransactionFee > pwalletMain->GetBalance()) @@ -1294,19 +1305,20 @@ NAN_METHOD(FillTransaction) { set > setCoins; int64_t nValueIn = 0; - //if (!pwalletMain->SelectCoins(nTotalValue, setCoins, nValueIn, coinControl)) { + // XXX CWallet::SelectCoins() needs to be made public! + // if (!pwalletMain->SelectCoins(nTotalValue, setCoins, nValueIn, coinControl)) { if (!SelectCoins(*pwalletMain, nTotalValue, setCoins, nValueIn, coinControl)) { return NanThrowError("Insufficient funds"); } - // Fill vin + // Fill inputs if they aren't already filled if (tx.vin.empty()) { BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins) { tx.vin.push_back(CTxIn(coin.first->GetHash(), coin.second)); } } - // Sign + // Sign everything int nIn = 0; BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins) { if (!SignSignature(*pwalletMain, *coin.first, tx, nIn++)) { @@ -1314,6 +1326,7 @@ NAN_METHOD(FillTransaction) { } } + // Turn our CTransaction into a javascript Transaction Local entry = NanNew(); ctx_to_jstx(tx, 0, entry);