Skip to content

Conversation

Sjors
Copy link
Member

@Sjors Sjors commented Jul 12, 2019

When the user doesn't specificy inputs, it makes sense to automatically select them. But when the user does specify inputs, walletcreatefundedpsbt now fails if the amount is insufficient, unless addInputs is set to true.

Similarly for fundrawtransaction if the original transaction already specified inputs, we only add more if addInputs is set to true.

This protects against fat finger mistakes in the amount or fee rate (see also #16257). The behavior is also more similar to GUI coin selection.

@Sjors Sjors force-pushed the 2019/07/walletcreatefundedpsbt_addinputs branch from a74855c to e87e089 Compare July 12, 2019 11:41
@Sjors Sjors force-pushed the 2019/07/walletcreatefundedpsbt_addinputs branch from e87e089 to 4bf5d6a Compare July 12, 2019 12:30
@DrahtBot
Copy link
Contributor

DrahtBot commented Jul 12, 2019

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, this pull request conflicts with the following ones:

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@Sjors Sjors mentioned this pull request Jul 12, 2019
3 tasks
@instagibbs
Copy link
Member

concept ACK

Copy link
Contributor

@promag promag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concept ACK.

@Sjors
Copy link
Member Author

Sjors commented Jul 29, 2019

Instead of bool default_add_inputs into FundTransaction I'm now passing a CCoinControl object. Also addressed nits.

@Sjors Sjors force-pushed the 2019/07/walletcreatefundedpsbt_addinputs branch from 4bf5d6a to d8e51a2 Compare July 29, 2019 08:15
@achow101
Copy link
Member

This effects fundrawtransaction too, so documentation should be updated to indicate that.

@Sjors
Copy link
Member Author

Sjors commented Aug 1, 2019

@achow101 I didn't change this behavior in fundrawtransaction.

@achow101
Copy link
Member

achow101 commented Aug 1, 2019

@achow101 I didn't change this behavior in fundrawtransaction.

Yes, but FundTransaction is used by both fundrawtransaction and walletcreatefundedpsbt. The add_inputs option is now something that both can have, but is not documented for fundrawtransaction. Furthermore, both of these do pretty much the same thing, just return different formats. So I think their behavior with this option should be the same.

@Sjors Sjors force-pushed the 2019/07/walletcreatefundedpsbt_addinputs branch from d8e51a2 to 6769883 Compare August 2, 2019 09:51
@Sjors Sjors changed the title [rpc] don't automatically append inputs in walletcreatefundedpsbt [rpc] don't automatically append inputs in walletcreatefundedpsbt & fundrawtransaction Aug 2, 2019
@Sjors
Copy link
Member Author

Sjors commented Aug 2, 2019

I changed fundrawtransaction to have the same behavior.

@Sjors Sjors force-pushed the 2019/07/walletcreatefundedpsbt_addinputs branch from 6769883 to f82a770 Compare August 2, 2019 15:50
@@ -3107,6 +3111,7 @@ static UniValue fundrawtransaction(const JSONRPCRequest& request)
{"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex string of the raw transaction"},
{"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}",
{
{"add_inputs", RPCArg::Type::BOOL, /* default */ "false", "For a transaction with existing inputs, automatically include more if they are not enough."},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is backward-incompatible, and it makes no sense for this RPC which does exactly only that? Confused.

Copy link
Member Author

@Sjors Sjors Aug 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See @achow101's comment above: #16377 (comment)

I tend to agree that walletcreatefundedpspbt is different from fundrawtransaction in this aspect, because walletcreatefundedpspbt also sets the destination.

Would like to hear some more opinions, otherwise I'll drop the last commit (where this is added). Or I can change the default for fundrawtransaction but keep the option, in case it's useful.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think both walletcreatefundedpsbt and fundrawtransaction are both most commonly used with no inputs. As I understand it, with add_inputs defaulting to false, this behavior doesn't change. Even so, the option is useful in fundrawtransaction as sometimes you just want it to set the change output and fee for a transaction after you've already selected the inputs.

@Fonta1n3
Copy link

Fonta1n3 commented Aug 21, 2019

I have built an app on top of bitcoin-cli and definitely would prefer no inputs to be added at all by default when using walletcreatefundedpsbt and fundrawtransaction if a user specifies their own inputs. If a user is specifying inputs then it would be better to force them to recreate a transaction with the necessary inputs rather than automatically adding additional inputs the user has not specified.

It makes fee optimization a lot easier in this scenario where a user wants to specify inputs as one can not take advantage of the conf_target argument or other Bitcoin Core fee optimization arguments when building custom transactions with createpsbt and createrawtransaction.

@Sjors
Copy link
Member Author

Sjors commented Aug 21, 2019

@FontaineDenton does your application use walletcreatefundedpsbt or fundrawtransaction? And can you elaborate on fee optimization?

@Fonta1n3
Copy link

@FontaineDenton does your application use walletcreatefundedpsbt or fundrawtransaction? And can you elaborate on fee optimization?

I just updated my original comment so it hopefully makes more sense.

@Sjors Sjors force-pushed the 2019/07/walletcreatefundedpsbt_addinputs branch from f82a770 to 21af29a Compare October 30, 2019 19:34
@Sjors Sjors changed the title [rpc] don't automatically append inputs in walletcreatefundedpsbt & fundrawtransaction [rpc] don't automatically append inputs in walletcreatefundedpsbt Feb 20, 2020
@Sjors Sjors force-pushed the 2019/07/walletcreatefundedpsbt_addinputs branch from 21af29a to 914009d Compare February 20, 2020 15:18
@@ -3030,6 +3030,10 @@ void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& f
},
true, true);

if (options.exists("add_inputs") ) {
coinControl.m_add_inputs = options["add_inputs"].get_bool();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense to allow add_inputs = false when no input is manually selected?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'll just fail with insufficient funds. I don't think it's necessary to special-case that.

@Sjors
Copy link
Member Author

Sjors commented Mar 11, 2020

Rebased, slightly tweaked one test and added a new one.

@Sjors Sjors force-pushed the 2019/07/walletcreatefundedpsbt_addinputs branch from 5fc79ef to 9d0ef2a Compare March 11, 2020 20:27
Copy link
Contributor

@promag promag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, just some small suggestions.

The `walletcreatefundedpsbt` RPC call will now fail with
`Insufficient funds` when inputs are manually selected but are not enough to cover
the outputs and fee. Additional inputs can automatically be added through the
new `add_inputs` option.
Copy link
Contributor

@promag promag Mar 11, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also add something like

The `fundrawtransaction` RPC now supports `add_inputs` option that when `false` prevents adding more inputs if necessary and consequently the RPC fails.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

FundTransaction(pwallet, tx, fee, change_position, request.params[1]);
CCoinControl coin_control;
// Automatically select (additional) coins. Can be overriden by options.add_inputs.
coin_control.m_add_inputs = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already the default value in coin_control so maybe remove this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it adds clarity that this (default) value matters for this caller.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

e5327f9

nit

// By default new inputs are added automatically. Can be overriden by options.add_inputs.
CHECK_NONFATAL(coin_control.m_add_inputs);

"Implements the Creator and Updater roles.\n",
{
{"inputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The inputs",
{"inputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The inputs. Leave empty to add inputs automatically.",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, maybe add See add_inputs option.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Sjors added 2 commits March 12, 2020 13:07
When the user doesn't specificy inputs, it makes sense to automatically select them. But when the user does specify inputs, we now fail if the amount is insufficient, unless addInputs is set to true.
@Sjors Sjors force-pushed the 2019/07/walletcreatefundedpsbt_addinputs branch from 9d0ef2a to e5327f9 Compare March 12, 2020 12:07
@sipa
Copy link
Member

sipa commented Mar 25, 2020

With add_inputs set to false, how does walletcreatefundedpsbt differ from createpsbt? If there is no difference, it seems the default should always be true.

@Sjors
Copy link
Member Author

Sjors commented Mar 26, 2020

@sipa the difference is when when you don't specify inputs. walletcreatefundedpsbt will pick inputs from your wallet, createpsbt won't.

If you do specificy inputs, then by default (as of this PR) neither command will add them. But they're still different, because createpsbt doesn't have wallet context to fill out redeem/witness scripts.

I didn't even realise createpsbt existed up to now :-)

@achow101
Copy link
Member

ACK e5327f9

@Sjors Sjors requested a review from promag June 12, 2020 09:07
Copy link
Contributor

@promag promag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review ACK but left some comments. This looks great and gives more control to the caller.

The RPC bumpfee also adds inputs (or reduces change output) so maybe we could add this option there too in a follow-up.

FundTransaction(pwallet, tx, fee, change_position, request.params[1]);
CCoinControl coin_control;
// Automatically select (additional) coins. Can be overriden by options.add_inputs.
coin_control.m_add_inputs = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

e5327f9

nit

// By default new inputs are added automatically. Can be overriden by options.add_inputs.
CHECK_NONFATAL(coin_control.m_add_inputs);

@@ -3148,8 +3148,8 @@ static UniValue fundrawtransaction(const JSONRPCRequest& request)
}

RPCHelpMan{"fundrawtransaction",
"\nAdd inputs to a transaction until it has enough in value to meet its out value.\n"
"This will not modify existing inputs, and will add at most one change output to the outputs.\n"
"\nIf the transaction has no inputs, they will be automatically selected to meet its out value.\n"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

e5327f9

Previous text was fine?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the previous text suggests that it always adds inputs. I reworded that to make it clear we only do automatic coin selection if there is no manual coin selection.

@@ -10,6 +10,7 @@ void CCoinControl::SetNull()
{
destChange = CNoDestination();
m_change_type.reset();
m_add_inputs = true;
Copy link
Contributor

@promag promag Jun 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haven't tested and looks like nobody asked, but can't we use fAllowOtherInputs instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That won't work. I think fAllowOtherInputs was designed with RBF in mind. It permits adding coins, as long as all the currently selected coins are included. But this PR tries to prevent adding coins.

@@ -3016,13 +3016,12 @@ static UniValue listunspent(const JSONRPCRequest& request)
return results;
}

void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& fee_out, int& change_position, UniValue options)
void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& fee_out, int& change_position, UniValue options, CCoinControl& coinControl)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

79804fe

nit, unrelated, could receive options by reference.

@Sjors
Copy link
Member Author

Sjors commented Jun 12, 2020

I'll leave the CHECK_NONFATAL in case I need to rebase or change something.

@@ -2149,6 +2149,11 @@ void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector<
}

for (unsigned int i = 0; i < wtx.tx->vout.size(); i++) {
// Only consider selected coins if add_inputs is false
if (coinControl && !coinControl->m_add_inputs && !coinControl->IsSelected(COutPoint(entry.first, i))) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ultra nit, cache IsSelected() by adding above:

const bool is_selected = coinControl && coinControl->IsSelected(COutPoint(entry.first, i));

then use this in L2160 below.

Copy link
Contributor

@meshcollider meshcollider left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK e5327f9

@meshcollider meshcollider merged commit 6bb5f6d into bitcoin:master Jun 21, 2020
@Sjors Sjors deleted the 2019/07/walletcreatefundedpsbt_addinputs branch June 21, 2020 15:04
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Jul 7, 2020
…tcreatefundedpsbt

e5327f9 [rpc] fundrawtransaction: add_inputs option to control automatic input adding (Sjors Provoost)
79804fe [rpc] walletcreatefundedpsbt: don't automatically append inputs (Sjors Provoost)

Pull request description:

  When the user doesn't specificy inputs, it makes sense to automatically select them. But when the user does specify inputs, `walletcreatefundedpsbt` now fails if the amount is insufficient, unless `addInputs` is set to `true`.

  Similarly for `fundrawtransaction` if the original transaction already specified inputs, we only add more if `addInputs` is set to `true`.

  This protects against fat finger mistakes in the amount or fee rate (see also bitcoin#16257). The behavior is also more similar to GUI coin selection.

ACKs for top commit:
  achow101:
    ACK e5327f9
  meshcollider:
    utACK e5327f9

Tree-SHA512: d8653b820914396c7c25b0d0a2b7e92de214aa023bc1aa085feb37d3b20fab361ebea90416a7db989f19bdc37e26cf0adfbcb712c80985c87afa67a9bd44fecb
@Fonta1n3
Copy link

Fonta1n3 commented Sep 7, 2020

Which version of Bitcoin Core will this get released on?

@sipa
Copy link
Member

sipa commented Sep 7, 2020

Current master branch will become 0.21.

meshcollider added a commit that referenced this pull request Sep 15, 2020
92326d8 [rpc] add send method (Sjors Provoost)
2c2a144 [rpc] add snake case aliases for transaction methods (Sjors Provoost)
1bc8d0f [rpc] walletcreatefundedpsbt: allow inputs to be null (Sjors Provoost)

Pull request description:

  `walletcreatefundedpsbt` has some interesting features that `sendtoaddress` and `sendmany` don't have:
  * manual coin selection
  * outputting a PSBT (it was controversial to add this, see #18201)
  * create a transaction without adding to wallet (which leads to broadcasting, unless `-walletbroadcast=0`)

  At the same time `walletcreatefundedpsbt` can't broadcast a transaction, which is inconvenient for simple use cases.

  This PR introduces a new `send` RPC method which creates a PSBT, signs it if possible and adds it to the wallet by default. If it can't sign all inputs, it outputs a PSBT. If `add_to_wallet` is set to `false` it will return the transaction in both PSBT and hex format.

  Because it uses a PSBT internally, it will much easier to add hardware wallet support to this method (see #16546).

  For `bitcoin-cli` users, it tries to keep the simplest use case easy to use:

  ```sh
  bitcoin-cli -regtest send '{"ADDRESS": 0.1}' 1 sat/b
  ```

  This paves the way for deprecating `sendtoaddress` and `sendmany` though there's no rush. The only missing feature compared to these older methods is adding labels to a destination address.

  Depends on:
  - [x] #16377 (`[rpc] don't automatically append inputs in walletcreatefundedpsbt`)
  - [x] #11413 (`[wallet] [rpc] sendtoaddress/sendmany: Add explicit feerate option`)
  - [x] #18244 (`[rpc] have lockUnspents also lock manually selected coins`)

ACKs for top commit:
  meshcollider:
    Light re-utACK 92326d8
  achow101:
    ACK 92326d8 Reviewed code and test, ran tests.
  kallewoof:
    utACK 92326d8

Tree-SHA512: 7552ef1b193d4c06e381c44932fdb0d54f64383e4c7d6b988f49d059c7d4bba45ce6aa7813e03df86360ad9dad6f3010eb76ee7da480551742d5fd98c2251c0f
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Sep 15, 2020
92326d8 [rpc] add send method (Sjors Provoost)
2c2a144 [rpc] add snake case aliases for transaction methods (Sjors Provoost)
1bc8d0f [rpc] walletcreatefundedpsbt: allow inputs to be null (Sjors Provoost)

Pull request description:

  `walletcreatefundedpsbt` has some interesting features that `sendtoaddress` and `sendmany` don't have:
  * manual coin selection
  * outputting a PSBT (it was controversial to add this, see bitcoin#18201)
  * create a transaction without adding to wallet (which leads to broadcasting, unless `-walletbroadcast=0`)

  At the same time `walletcreatefundedpsbt` can't broadcast a transaction, which is inconvenient for simple use cases.

  This PR introduces a new `send` RPC method which creates a PSBT, signs it if possible and adds it to the wallet by default. If it can't sign all inputs, it outputs a PSBT. If `add_to_wallet` is set to `false` it will return the transaction in both PSBT and hex format.

  Because it uses a PSBT internally, it will much easier to add hardware wallet support to this method (see bitcoin#16546).

  For `bitcoin-cli` users, it tries to keep the simplest use case easy to use:

  ```sh
  bitcoin-cli -regtest send '{"ADDRESS": 0.1}' 1 sat/b
  ```

  This paves the way for deprecating `sendtoaddress` and `sendmany` though there's no rush. The only missing feature compared to these older methods is adding labels to a destination address.

  Depends on:
  - [x] bitcoin#16377 (`[rpc] don't automatically append inputs in walletcreatefundedpsbt`)
  - [x] bitcoin#11413 (`[wallet] [rpc] sendtoaddress/sendmany: Add explicit feerate option`)
  - [x] bitcoin#18244 (`[rpc] have lockUnspents also lock manually selected coins`)

ACKs for top commit:
  meshcollider:
    Light re-utACK 92326d8
  achow101:
    ACK 92326d8 Reviewed code and test, ran tests.
  kallewoof:
    utACK 92326d8

Tree-SHA512: 7552ef1b193d4c06e381c44932fdb0d54f64383e4c7d6b988f49d059c7d4bba45ce6aa7813e03df86360ad9dad6f3010eb76ee7da480551742d5fd98c2251c0f
Fabcien pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Dec 11, 2020
… append inputs

Summary:
When the user doesn't specificy inputs, it makes sense to automatically select them. But when the user does specify inputs, we now fail if the amount is insufficient, unless addInputs is set to true.

---

Backport of Core [[bitcoin/bitcoin#16377 | PR16377]] [1/2]

Test Plan:
  ninja all check check-functional

Reviewers: #bitcoin_abc, PiRK

Reviewed By: #bitcoin_abc, PiRK

Differential Revision: https://reviews.bitcoinabc.org/D8659
Fabcien pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Dec 11, 2020
…ntrol automatic input adding

Summary:
---

Backport of Core [[bitcoin/bitcoin#16377 | PR16377]]

Depends on D8659

Note: replaced a couple unused `i` for-loop variables in functional tests that the linter complained about with `_`'s

Test Plan:
  ninja all check check-functional

Reviewers: #bitcoin_abc, PiRK

Reviewed By: #bitcoin_abc, PiRK

Differential Revision: https://reviews.bitcoinabc.org/D8660
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Feb 15, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.