Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Add multiple options to fundrawtransaction #7518

Closed
wants to merge 3 commits into
from

Conversation

Projects
None yet
8 participants
Contributor

promag commented Feb 11, 2016

This PR allows to specify an address to receive the change of the fund. Currently fundrawtransaction accepts a boolean for the second parameter. With this change the second parameter can be either a boolean or a JSON object with the following optional keys: includeWatching, changeAddress and changePosition.

@promag promag and 1 other commented on an outdated diff Feb 11, 2016

src/wallet/rpcwallet.cpp
@@ -2468,7 +2468,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
+ HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
);
- RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL));
+ // RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL));
@promag

promag Feb 11, 2016

Contributor

Mixed feelings about how to do this since the second argument can be one of two types.

@luke-jr

luke-jr Feb 11, 2016

Member

IIRC you can just leave off the second type for RPCTypeCheck and it will skip it. Then do the check by hand.

@promag promag and 1 other commented on an outdated diff Feb 11, 2016

src/wallet/wallet.h
@@ -735,7 +735,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
* Insert additional inputs into the transaction by
* calling CreateTransaction();
*/
- bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosRet, std::string& strFailReason, bool includeWatching);
+ bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosRet, std::string& strFailReason, bool includeWatching, const CTxDestination& destChange);
@promag

promag Feb 11, 2016

Contributor

Don't know if the best place is at the end.

@luke-jr

luke-jr Feb 11, 2016

Member

As good a place as any. But you need to update the implementation too...

@promag

promag Feb 11, 2016

Contributor

Ops, missed that in git add -p.

@luke-jr

luke-jr Feb 13, 2016

Member

A default CNoDestination() here might be a good idea.

Member

luke-jr commented Feb 11, 2016

You need to update the help. I suggest replacing the Boolean with the Object entirely, and just supporting the boolean in code as a backward compatibility thing.

Contributor

promag commented Feb 11, 2016

@luke-jr done.

@luke-jr luke-jr and 1 other commented on an outdated diff Feb 11, 2016

src/wallet/rpcwallet.cpp
@@ -2468,7 +2472,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
+ HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
);
- RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL));
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VOBJ));
@luke-jr

luke-jr Feb 11, 2016

Member

The VOBJ check should be independent of RPCTypeCheck if you want to support boolean for backward compatibility.

@promag

promag Feb 11, 2016

Contributor

I see, so the help says it accepts a JSON object, but the implementation allows both?

@luke-jr luke-jr commented on an outdated diff Feb 11, 2016

src/wallet/wallet.cpp
@@ -377,7 +377,7 @@ bool CWallet::Verify(const string& walletFile, string& warningString, string& er
} catch (const boost::filesystem::filesystem_error&) {
// failure is ok (well, not really, but it's not worse than what we started with)
}
-
+
@luke-jr

luke-jr Feb 11, 2016

Member

Please don't change unrelated whitespace like this.

Contributor

promag commented Feb 11, 2016

@luke-jr ok, added a test for the changeAddress option.

@luke-jr luke-jr commented on an outdated diff Feb 13, 2016

src/wallet/rpcwallet.cpp
@@ -2478,15 +2482,31 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
if (origTx.vout.size() == 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "TX must have at least one output");
+ CBitcoinAddress changeAddress;
@luke-jr

luke-jr Feb 13, 2016

Member

This probably needs to be defaulting to CNoDestination()

Member

luke-jr commented Feb 13, 2016

Also, this conflicts with #7159 , so one of them will need to rebase. I think #7159 should adopt the options Object used here.

Contributor

promag commented Feb 13, 2016

@luke-jr agree #7159 should adopt options.

Contributor

promag commented Feb 13, 2016

@luke-jr done.

@laanwj laanwj added the Wallet label Feb 13, 2016

@promag promag changed the title from [RPC] Add changeAddress option to fundrawtransaction to [RPC] Add change options to fundrawtransaction Feb 13, 2016

Contributor

promag commented Feb 13, 2016

Added changePosition option to specify the desired vout index of change address.

@MarcoFalke MarcoFalke commented on the diff Feb 13, 2016

qa/rpc-tests/fundrawtransaction.py
@@ -575,7 +601,7 @@ def run_test(self):
outputs = {self.nodes[2].getnewaddress() : watchonly_amount / 2}
rawtx = self.nodes[3].createrawtransaction(inputs, outputs)
- result = self.nodes[3].fundrawtransaction(rawtx, True)
+ result = self.nodes[3].fundrawtransaction(rawtx, {'includeWatching': True })
@MarcoFalke

MarcoFalke Feb 13, 2016

Member

Can you leave one of them and mention that this is testing backward compatibility?

@promag

promag Feb 13, 2016

Contributor

👍

@promag

promag Mar 24, 2016

Contributor

See below.

@promag promag commented on the diff Feb 13, 2016

qa/rpc-tests/fundrawtransaction.py
@@ -591,6 +617,7 @@ def run_test(self):
outputs = {self.nodes[2].getnewaddress() : watchonly_amount}
rawtx = self.nodes[3].createrawtransaction(inputs, outputs)
+ # Backward compatibility test (2nd param is includeWatching)
result = self.nodes[3].fundrawtransaction(rawtx, True)

@promag promag commented on the diff Feb 13, 2016

src/wallet/wallet.h
@@ -735,7 +735,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
* Insert additional inputs into the transaction by
* calling CreateTransaction();
*/
- bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosRet, std::string& strFailReason, bool includeWatching);
@promag

promag Feb 13, 2016

Contributor

I feel we should have a better argument order. Suggestion:

bool FundTransaction(CMutableTransaction& tx, const CTxDestination& changeDestination, int& changePosition, bool includeWatching, CAmount& nFeeRet, std::string& strFailReason);
@luke-jr

luke-jr Feb 13, 2016

Member

It doesn't really matter as long as existing code either fails to compile or behaves the same. Note that to put destChange earlier, you would need to make it a required option.

@jonasschnelli

jonasschnelli Feb 19, 2016

Member

I guess we should rename nChangePosRet to nChangePosInOut and add a comment in the header that -1 as a input value will result in setting a random position.

@promag promag referenced this pull request Feb 19, 2016

Merged

Add importmulti RPC call #7551

@jonasschnelli jonasschnelli commented on an outdated diff Feb 19, 2016

src/wallet/rpcwallet.cpp
@@ -2468,7 +2473,31 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
+ HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
);
- RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL));
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR));
+
+ CTxDestination changeAddress = CNoDestination();
+ int changePosition = -1;
+ bool includeWatching = false;
+
+ if (params.size() > 1) {
+ if (params[1].type() == UniValue::VBOOL) {
@jonasschnelli

jonasschnelli Feb 19, 2016

Member

If we go for the backward compatibility way: I guess then this code part should be commented as "backward compatibility bool only fallback".

@jonasschnelli jonasschnelli commented on an outdated diff Feb 19, 2016

src/wallet/wallet.cpp
@@ -2134,14 +2136,17 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
// add the dust to the fee.
if (newTxOut.IsDust(::minRelayTxFee))
{
+ nChangePos = -1;
@jonasschnelli

jonasschnelli Feb 19, 2016

Member

nit: indent.

@jonasschnelli jonasschnelli commented on an outdated diff Feb 19, 2016

src/wallet/wallet.cpp
nFeeRet += nChange;
reservekey.ReturnKey();
}
else
{
- // Insert change txn at random position:
- nChangePosRet = GetRandInt(txNew.vout.size()+1);
- vector<CTxOut>::iterator position = txNew.vout.begin()+nChangePosRet;
+ if (nChangePos == -1) {
+ // Insert change txn at random position:
@jonasschnelli

jonasschnelli Feb 19, 2016

Member

nit: indent (2 instead 4), maybe run the clang format script.

@jonasschnelli jonasschnelli and 1 other commented on an outdated diff Feb 19, 2016

src/wallet/rpcwallet.cpp
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR));
+
+ CTxDestination changeAddress = CNoDestination();
+ int changePosition = -1;
+ bool includeWatching = false;
+
+ if (params.size() > 1) {
+ if (params[1].type() == UniValue::VBOOL) {
+ includeWatching = params[1].get_bool();
+ }
+ else {
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VOBJ));
+
+ UniValue options = params[1];
+
+ if (options.exists("changeAddress"))
@jonasschnelli

jonasschnelli Feb 19, 2016

Member

nit: Not sure if we should make this check case insensitive. Very likely, some users will try it with "changeaddress".

@luke-jr

luke-jr Feb 19, 2016

Member

I think we already have precedent for case-sensitive options?

@jonasschnelli jonasschnelli commented on the diff Feb 19, 2016

src/wallet/rpcwallet.cpp
- RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL));
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR));
+
+ CTxDestination changeAddress = CNoDestination();
+ int changePosition = -1;
+ bool includeWatching = false;
+
+ if (params.size() > 1) {
+ if (params[1].type() == UniValue::VBOOL) {
+ includeWatching = params[1].get_bool();
+ }
+ else {
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VOBJ));
+
+ UniValue options = params[1];
+
@jonasschnelli

jonasschnelli Feb 19, 2016

Member

Maybe add a RPCTypeCheckObj() to ensure that changePosition, etc. are the correct types? Otherwise you get a plain JSON value is not a boolean as expected (etc.)?

@promag

promag Mar 5, 2016

Contributor

👍

@promag

promag Mar 24, 2016

Contributor

See below.

Member

jonasschnelli commented Feb 19, 2016

utACK.
Nice work!

I'm not sure if we should add the backward compatibility fallback (includeWatchonly = true). Because it could also lead to problems in future. If so, we should also mention in in the RPC help (something like a plain True results in includeWatchonly=true).

IMO a API break would be acceptable.

@promag promag changed the title from [RPC] Add change options to fundrawtransaction to Add change options to fundrawtransaction Feb 25, 2016

luke-jr added a commit to bitcoinknots/bitcoin that referenced this pull request Feb 25, 2016

Add change options to fundrawtransaction
Github-Pull: #7518
Rebased-From: 49cea7936dc44b5f3c3373c4190cb260996ef56b

nunofgs commented Mar 2, 2016

@promag: it would be useful to add an option "lockUnspents: true" to ensure that chosen unspents are effectively locked before sending the transaction.

Contributor

promag commented Mar 2, 2016

@nunofgs yes, that idea was also in #7498.

@promag promag changed the title from Add change options to fundrawtransaction to Add multiple options to fundrawtransaction Mar 5, 2016

Contributor

promag commented Mar 5, 2016

@nunofgs lockUnspents option added. Missing test for the moment.

Contributor

promag commented Mar 5, 2016

Visited all comments and rebased. Please review.

Contributor

promag commented Mar 5, 2016

What about adding unlockUnspents option to sendrawtransaction?

@promag I think that should be part of the standard process - as soon as the transaction is sent to the network, the unspents should be unlocked and considered spent.

Member

jonasschnelli commented Mar 7, 2016

@ruimarinho: you probably mean "locking". I think locking of the unspents should happen somewhere between sign and send. I'm fine with an option in fundrawtransaction, but IMO we should not make it the default.

Contributor

promag commented Mar 7, 2016

@sipa @laanwj do you think it's acceptable to specify a fixed fee and bypass the minimal fee calculation through iteration in CWallet::CreateTransaction?

Contributor

promag commented Mar 7, 2016

@jonasschnelli sure, default for locking is false. The use case is to prevent consecutive fundrawtransactions calls selecting the same unspents.

@jonasschnelli if I call lockUnspent(false, [unspents]) manually, those unspents will remain unlocked until bitcoind is restarted or lockUnspent(true, [unspents]) is called. I did not see a code path where these unspents are cleaned up - removed from the "locked" list but still unavailable for future spending.

Member

jonasschnelli commented Mar 7, 2016

@ruimarinho: Yes. There is no such thing as a auto-release because the intention is the keep these unspents locked.

But if you lock the unspents in fundrawtransaction by default, you need to unlock them in case you don't sign or send them (or in cases of an error).
But I agree, there are use-cases where you want to directly lock the unspent in the fundrawtransaction call (concurrency).

Contributor

promag commented Mar 7, 2016

@jonasschnelli the same applies if someone locks some unspents with lockunspent and don't use it.

Member

jonasschnelli commented Mar 7, 2016

@promag: yes. Agree. The default value is debatable.

Contributor

promag commented Mar 24, 2016

@laanwj @sipa bump.

Contributor

promag commented Mar 24, 2016

Rebased.

@MarcoFalke MarcoFalke and 1 other commented on an outdated diff Mar 25, 2016

src/wallet/wallet.cpp
// Add new txins (keeping original txin scriptSig/order)
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
{
if (!coinControl.IsSelected(txin.prevout))
tx.vin.push_back(txin);
+ }
@MarcoFalke

MarcoFalke Mar 25, 2016

Member

Where does this scope start?

@promag

promag Mar 25, 2016

Contributor

It doesn't :)

@MarcoFalke

MarcoFalke Mar 29, 2016

Member

Mind to fix it?

Member

jonasschnelli commented Mar 29, 2016

I really think this is useful!
@promag can you look at the travis issues, maybe rebase it? I promise to test it afterwards. :)

Contributor

promag commented Mar 29, 2016

@MarcoFalke fixed
@jonasschnelli rebased and renamed nChangePosRet to nChangePosInOut. I wonder if other *Ret should be renamed to *Out?

@jonasschnelli jonasschnelli commented on an outdated diff Mar 29, 2016

src/wallet/wallet.cpp
@@ -1908,7 +1908,7 @@ bool CWallet::SelectCoins(const vector<COutput>& vAvailableCoins, const CAmount&
return res;
}
-bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nChangePosRet, std::string& strFailReason, bool includeWatching)
+bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, const CTxDestination& destChange)
@jonasschnelli

jonasschnelli Mar 29, 2016

Member

missing bool lockUnspents, argument.

Member

jonasschnelli commented Mar 29, 2016

I think this PR should be in 0.13 (once finalized)!
Tested a bit after fixing the compile error (see above).

Some issues:

1)
I called

fundrawtransaction 01000000000100e1f505000000001976a914f592d5ff0f4cad760d23601e32714639c244d27588ac00000000 '{"changeAddress":"mfrczJz4p5ziD4CiVTip3R7jjXJAjDKBmf", "includeWatching":true, "changePos":0}'
I used changePos but the valid argument would be changePosition. An error in a such case would be nice.

2)
Also, I used a invalid change address...
fundrawtransaction 01000000000100e1f505000000001976a914f592d5ff0f4cad760d23601e32714639c244d27588ac00000000 '{"changeAddress":"dontforget.to.call@your.mother", "includeWatching":true, "changePosition":0}'
... which was accepted (no error or warning) but not used. It used one from the wallets pool (which could be dangerous in a watchOnly-fund-environment.

  • detect invalid options and reject command with an error
  • detect invalid change addresses and reject if so

Happy to test again.

Contributor

promag commented Mar 29, 2016

@jonasschnelli Thanks, I'll add tests to cover those cases. BTW, travis is not picking this PR?

Contributor

promag commented Mar 30, 2016

Please review.

@jonasschnelli FYI

  • detect invalid options and reject command with an error: 7ba5713
  • detect invalid change addresses and reject if so

@jonasschnelli, since you're more involved in this PR, what do you think of @promag's suggestion above?

do you think it's acceptable to specify a fixed fee and bypass the minimal fee calculation through iteration in CWallet::CreateTransaction?

Contributor

promag commented Mar 30, 2016

@ruimarinho maybe a separate PR on top of this because that is a change on CWallet::CreateTransaction.

Member

jonasschnelli commented Mar 30, 2016

@ruimarinho: Yes. A common problems of Bitcoin Core pulls is the "expanding scope". Keep it simple, add other features later in a different PR.

I think we need to distinct FRT and keep it – relatively simple. If we add options to set the fee, the only thing thats left is the coin selection then? not? Maybe someone could just grab the unspents over listunspents and do his own coin selection and create a final transaction with createrawtransaction.

And if you know the changeoutputs address, you could rewrite the transaction after FRT (on your side of the application) and change its fee.

@promag: thanks. Will re-test soon.

Contributor

promag commented Mar 30, 2016

And if you know the changeoutputs address, you could rewrite the transaction after FRT (on your side of the application) and change its fee.

@jonasschnelli this is not entirely correct because there may be a better subset of unspents to better satisfy the output value + fixed fee. But since the fee is very low this may be a good tradeoff.

Edit:

Also there this special case when no change is created, so the application has to create one to adjust the difference.

2nd edit::

And the worst case is when the total input value of the selected unspents isn't enough to cover the fixed fee. So I would say that having the option to specify the fixed fee is the way to go.

Contributor

promag commented Mar 30, 2016

the only thing thats left is the coin selection then

@jonasschnelli actually this is accomplished with createrawtransaction.

Member

jonasschnelli commented Mar 30, 2016

[...] And the worst case is when the total input value of the selected unspents isn't enough to cover the fixed fee. So I would say that having the option to specify the fixed fee is the way to go.

Yes. This is a point.

the only thing thats left is the coin selection then

actually this is accomplished with createrawtransaction.

createrawtransaction does not use coinselection IMO. FRT does.

@jonasschnelli jonasschnelli commented on an outdated diff Mar 30, 2016

src/wallet/wallet.cpp
tx.vin.push_back(txin);
+
+ if (lockUnspents)
+ LockCoin(txin.prevout);
@jonasschnelli

jonasschnelli Mar 30, 2016

Member

You need to hold cs_wallet for this operation.
I think between L1944 and L1945 you should add a LOCK2(cs_main, cs_wallet);

Member

jonasschnelli commented Mar 30, 2016

The type check works and I think it's great.
Missing LockCoin lock needs to be fixed.

Contributor

promag commented Mar 30, 2016

@jonasschnelli Thanks! Fixed and rebased.

I was not suggesting otherwise regarding merging this PR and only then creating a new one to add the fixed fee feature :) like @promag mentioned on the edited comments, I believe there is still space for such feature as at least two scenarios are not covered by standard calls.

@ruimarinho ruimarinho commented on the diff Mar 31, 2016

src/wallet/rpcwallet.cpp
@@ -2451,8 +2451,14 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
"in the wallet using importaddress or addmultisigaddress (to calculate fees).\n"
"Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n"
"\nArguments:\n"
- "1. \"hexstring\" (string, required) The hex string of the raw transaction\n"
- "2. includeWatching (boolean, optional, default false) Also select inputs which are watch only\n"
+ "1. \"hexstring\" (string, required) The hex string of the raw transaction\n"
+ "2. options (object, optional)\n"
+ " {\n"
+ " \"changeAddress\" (string, optional, default pool address) The bitcoin address to receive the change\n"
+ " \"changePosition\" (numeric, optional, default random) The index of the change output\n"
+ " \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n"
@ruimarinho

ruimarinho Mar 31, 2016

Bikeshedding but have you considered includeWatchOnly to follow a consistent nomenclature?

@promag

promag Mar 31, 2016

Contributor

The underlying flag is allowWatchOnly. includeWatching is the old parameter name. Happy to rename if others agree.

@jonasschnelli

jonasschnelli Mar 31, 2016

Member

IMO we should keep includeWatching.

@jonasschnelli jonasschnelli commented on the diff Mar 31, 2016

src/wallet/rpcwallet.cpp
@@ -2451,8 +2451,14 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
"in the wallet using importaddress or addmultisigaddress (to calculate fees).\n"
"Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n"
"\nArguments:\n"
- "1. \"hexstring\" (string, required) The hex string of the raw transaction\n"
- "2. includeWatching (boolean, optional, default false) Also select inputs which are watch only\n"
+ "1. \"hexstring\" (string, required) The hex string of the raw transaction\n"
+ "2. options (object, optional)\n"
@jonasschnelli

jonasschnelli Mar 31, 2016

Member

nit: here we should mention something like : "for backward compatibility: passing in a true instead of an object will result in {"includeWatching":true}"

@jonasschnelli jonasschnelli commented on the diff Mar 31, 2016

src/wallet/wallet.cpp
return false;
- if (nChangePosRet != -1)
- tx.vout.insert(tx.vout.begin() + nChangePosRet, wtx.vout[nChangePosRet]);
+ if (nChangePosInOut != -1)
+ tx.vout.insert(tx.vout.begin() + nChangePosInOut, wtx.vout[nChangePosInOut]);
@jonasschnelli

jonasschnelli Mar 31, 2016

Member

Here we need another check.
What if nChangePosInOut = 10 but tx.vout.size()==2?
We need a out-of-range exception in a such case.

@promag

promag Apr 2, 2016

Contributor

Check is in rpcwallet.cpp.

@jonasschnelli

jonasschnelli Apr 5, 2016

Member

@promag: The check should should really be here (maybe an additional check). If someone uses CWallet::FundTransaction() with a nChangePosInOut >= wtx.vout.size(), the app crashes/throws an exceptions. Future changes might easy get trapped by this.

The problematic part is wtx.vout[nChangePosInOut]. There should be a check somewhere in CWallet::FundTransaction() that leads to a return false if a overflow has detected.

Member

jonasschnelli commented Mar 31, 2016

Allmost done. Last iteration:

  • needs out-of-range detection of changePosition.
  • needs simple documentation of backward compatibility (true instead of an parameter object)
Contributor

promag commented Apr 2, 2016

@jonasschnelli updated and rebased. not sure where is the best place to put the new help message.

Member

jonasschnelli commented Apr 6, 2016

ping @promag: Would be nice if you could take the change output order check into CreateTransaction(): https://github.com/bitcoin/bitcoin/pull/7518/files#r58496250
I'm convince that this is the last issue before this is ready for merging.

Please also fix the commit order. The head commit is from March 5, but the HEAD~2 is March 30.

commit 4b0360f4160e059b61a21a95a6106d0eed927bd9
Author: João Barbosa <joao@uphold.com>
Date:   Sat Mar 5 09:45:57 2016 +0000

commit c2a3ff1a08df8619f7af77ebe6c3b7661e858bc1
Author: João Barbosa <joao@uphold.com>
Date:   Wed Mar 30 02:04:22 2016 +0100

commit 699720b3baa9e0d3dab679b1da91ab45808aa85e
Author: João Barbosa <joao@uphold.com>
Date:   Wed Mar 30 00:59:29 2016 +0100

@promag promag commented on the diff Apr 6, 2016

src/wallet/wallet.cpp
nFeeRet += nChange;
reservekey.ReturnKey();
}
else
{
- // Insert change txn at random position:
- nChangePosRet = GetRandInt(txNew.vout.size()+1);
- vector<CTxOut>::iterator position = txNew.vout.begin()+nChangePosRet;
+ if (nChangePosInOut == -1)
+ {
+ // Insert change txn at random position:
+ nChangePosInOut = GetRandInt(txNew.vout.size()+1);
+ }
+ else if (nChangePosInOut > txNew.vout.size())
@promag

promag Apr 6, 2016

Contributor

@jonasschnelli I think the best place to check if index is out of range is here.

Member

jonasschnelli commented Apr 13, 2016

Tested ACK 18be394.

This is very useful.
It allows to fully decouple the private keys from the node/wallet.

Member

btcdrak commented Apr 14, 2016

utACK 18be394

laanwj added a commit that referenced this pull request Apr 15, 2016

Merge #7518: Add multiple options to fundrawtransaction
f2d0944 Add lockUnspents option to fundrawtransaction (João Barbosa)
af4fe7f Add change options to fundrawtransaction (João Barbosa)
41e835d Add strict flag to RPCTypeCheckObj (João Barbosa)
Owner

laanwj commented Apr 15, 2016

Merged this as be14ca5, with a trivial rebase (only overlap in test framework) to master

@laanwj laanwj closed this Apr 15, 2016

luke-jr added a commit to bitcoinknots/bitcoin that referenced this pull request Jun 28, 2016

codablock added a commit to codablock/dash that referenced this pull request Sep 16, 2017

Merge #7518: Add multiple options to fundrawtransaction
f2d0944 Add lockUnspents option to fundrawtransaction (João Barbosa)
af4fe7f Add change options to fundrawtransaction (João Barbosa)
41e835d Add strict flag to RPCTypeCheckObj (João Barbosa)

codablock added a commit to codablock/dash that referenced this pull request Sep 19, 2017

Merge #7518: Add multiple options to fundrawtransaction
f2d0944 Add lockUnspents option to fundrawtransaction (João Barbosa)
af4fe7f Add change options to fundrawtransaction (João Barbosa)
41e835d Add strict flag to RPCTypeCheckObj (João Barbosa)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment