fillTransaction: allow destination output choice.

This commit is contained in:
Christopher Jeffrey 2014-09-29 16:46:26 -07:00
parent 58e40ce1ba
commit e65b7e8da3
2 changed files with 33 additions and 20 deletions

View File

@ -493,12 +493,12 @@ Transaction.prototype.verify = function() {
}; };
Transaction.prototype.sign = Transaction.prototype.sign =
Transaction.prototype.fill = function() { Transaction.prototype.fill = function(options) {
return Transaction.fill(this); return Transaction.fill(this, options);
}; };
Transaction.sign = Transaction.sign =
Transaction.fill = function(tx) { Transaction.fill = function(tx, options) {
var isTx = bitcoin.tx.isTx(tx) var isTx = bitcoin.tx.isTx(tx)
, newTx; , newTx;
@ -507,7 +507,7 @@ Transaction.fill = function(tx) {
} }
try { try {
newTx = bitcoindjs.fillTransaction(tx); newTx = bitcoindjs.fillTransaction(tx, options || {});
} catch (e) { } catch (e) {
return false; return false;
} }

View File

@ -1253,22 +1253,33 @@ NAN_METHOD(FillTransaction) {
CDataStream ssData(ParseHex(tx_hex), SER_NETWORK, PROTOCOL_VERSION); CDataStream ssData(ParseHex(tx_hex), SER_NETWORK, PROTOCOL_VERSION);
ssData >> tx; ssData >> tx;
// Get setCoins // Parse options
int64_t nValueTotal = 0; int d_output = 0;
CScript scriptPubKeyMain; if (args.Length() > 1 && args[1]->IsObject()) {
bool scriptPubKeySet = false; Local<Object> options = Local<Object>::Cast(args[1]);
for (unsigned int vo = 0; vo < tx.vout.size(); vo++) { // Destination output
const CTxOut& txout = tx.vout[vo]; if (options->Get(NanNew<String>("output"))->IsNumber()) {
int64_t nValue = txout.nValue; d_output = options->Get(NanNew<String>("output"))->IntegerValue();
const CScript& scriptPubKey = txout.scriptPubKey; if (d_output < 0 || d_output >= tx.vout.size()) {
if (!scriptPubKeySet) { return NanThrowError("Destination output does not exist");
scriptPubKeyMain = scriptPubKey; }
scriptPubKeySet = true;
} }
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) if (nValue <= 0)
return NanThrowError("Invalid amount"); return NanThrowError("Invalid amount");
if (nValue + nTransactionFee > pwalletMain->GetBalance()) if (nValue + nTransactionFee > pwalletMain->GetBalance())
@ -1294,19 +1305,20 @@ NAN_METHOD(FillTransaction) {
set<pair<const CWalletTx*,unsigned int> > setCoins; set<pair<const CWalletTx*,unsigned int> > setCoins;
int64_t nValueIn = 0; 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)) { if (!SelectCoins(*pwalletMain, nTotalValue, setCoins, nValueIn, coinControl)) {
return NanThrowError("Insufficient funds"); return NanThrowError("Insufficient funds");
} }
// Fill vin // Fill inputs if they aren't already filled
if (tx.vin.empty()) { if (tx.vin.empty()) {
BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins) { BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins) {
tx.vin.push_back(CTxIn(coin.first->GetHash(), coin.second)); tx.vin.push_back(CTxIn(coin.first->GetHash(), coin.second));
} }
} }
// Sign // Sign everything
int nIn = 0; int nIn = 0;
BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins) { BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins) {
if (!SignSignature(*pwalletMain, *coin.first, tx, nIn++)) { if (!SignSignature(*pwalletMain, *coin.first, tx, nIn++)) {
@ -1314,6 +1326,7 @@ NAN_METHOD(FillTransaction) {
} }
} }
// Turn our CTransaction into a javascript Transaction
Local<Object> entry = NanNew<Object>(); Local<Object> entry = NanNew<Object>();
ctx_to_jstx(tx, 0, entry); ctx_to_jstx(tx, 0, entry);