Support for "exact send" with manual coin selection #354

pull pasky wants to merge 3 commits into bitcoin:master from pasky:master changing 4 files +211 −37
  1. pasky commented at 2:11 AM on June 27, 2011: none

    These commits introduce CWallet::CreateExactTransaction() function that works like CWallet::CreateTransaction(), but takes explicit list of prev_out transactions for sourcing the new transaction and fixed value of transaction fee.

    Furthermore, new RPC call 'sendexact' is introduced; it works like 'sendmany', but takes explicit list of transactions to use as coin sources, and explicit value of transaction fee.

    All outputs of the listed transactions that the account can claim are used to source coins; the output of the new transaction must be exactly the same amount, the user is responsible for dealing with any change. The user is also responsible for setting the transaction fee to such a value that other nodes will relay the transaction.

    The point is to provide a low-level interface for making transactions without all the auto-guessing implicitly done by the client. My primary motivation is that I am a control freak and I want to have precise control over the addresses used as "sources" of my transactions.

    There are other applications too - even if more specific interfaces might be more suited to them, this interface makes them possible at all as the lowest common denominator. E.g. people who wish to be sure no transaction fees will be paid for their transaction can use this interface. Or people wishing to try out different coin selection algorithms (or when coin selection makes sense at the moment of transaction setup, e.g. in case of anonymizers).

    Q: Why use explicit transactions instead of addresses? A: In reality, you do not quite transfer money "from" an address. Address is just a token that proves you are authorized to claim a particular amount of bitcoins listed as one of outputs of some transaction. Specific use-cases might be simplified, but you would still be in hands of a fixed coin selection algorithm. You can use (somewhat laborously) listtransactions or external service to discover transactions that send money to a given address.

    Q: Why use account instead of explicit addresses? A: First, it is more consistent with the other "send" interfaces and the wallet organization. Second, I believe account is the right abstraction - as mentioned, address is just a token for claiming some bitcoins, but different kind of claim proofs might be used (e.g. the now-deprecated "send to IP address", or it could be possible to also specify password-protected coins). In the future, you could associate further methods of authentication with accounts, but addresses are limited. If you require a specific set of addresses to be used, you can set up an ad-hoc account.

    Q: What does that bit about "change" mean? A: If transaction input claims some output of a previous transaction, it must claim all the coins in the output. If you need to transfer smaller amount than that, you must specify what to do with the remaining amount (change). The built-in coin selection algorithm either sends them to a new address (for better anonymity) or returns them to the source address. Here, you are responsible for manually specifying the destiny of your remaining amount.

    Q: Can I be finally sure I pay only the TX fee I specify? A: Yes, the TX fee you specify is final. However, please note that if the new transaction is large (i.e. has many inputs and outputs) or transfers too small amount and you do not offer any TX fee, it may not be accepted by any other nodes. Note that this is more serious than not being included in a block - you could just wait longer for a benevolent miner. In these circumstances, your transaction is not likely to even reach a mining node because the P2P network will not relay it.

    (If you like the feature, you can send donations to 19VF444umGxX76DZwPuWVMHpv7i84DHM1D.)

  2. CWalletTx::GetAmounts(): Move address divination to CTxOut::GetAddress() ddc16956b1
  3. RPC sendmany(): Move address-amount list parsing to AddressAmountList() c591baf418
  4. Support for "exact send" with manual coin selection
    This patch introduces CWallet::CreateExactTransaction() function that
    works like CWallet::CreateTransaction(), but takes explicit list of
    prev_out transactions for sourcing the new transaction and fixed value
    of transaction fee.
    
    Furthermore, new RPC call 'sendexact' is introduced; it works like
    'sendmany', but takes explicit list of transactions to use as coin
    sources, and explicit value of transaction fee.
    
    All outputs of the listed transactions that the account can claim are
    used to source coins; the output of the new transaction must be exactly
    the same amount, the user is responsible for dealing with any change.
    The user is also responsible for setting the transaction fee to such
    a value that other nodes will relay the transaction.
    
    The point is to provide a low-level interface for making transactions
    without all the auto-guessing implicitly done by the client. My primary
    motivation is that I am a control freak and I want to have precise
    control over the addresses used as "sources" of my transactions.
    
    There are other applications too - even if more specific interfaces
    might be more suited to them, this interface makes them possible at all
    as the lowest common denominator. E.g. people who wish to be sure no
    transaction fees will be paid for their transaction can use this
    interface. Or people wishing to try out different coin selection
    algorithms (or when coin selection makes sense at the moment of
    transaction setup, e.g. in case of anonymizers).
    
    Q: Why use explicit transactions instead of addresses?
    A: In reality, you do not quite transfer money "from" an address.
    Address is just a token that proves you are authorized to claim
    a particular amount of bitcoins listed as one of outputs of some
    transaction. Specific use-cases might be simplified, but you would
    still be in hands of a fixed coin selection algorithm.  You can use
    (somewhat laborously) listtransactions or external service to discover
    transactions that send money to a given address.
    
    Q: Why use account instead of explicit addresses?
    A: First, it is more consistent with the other "send" interfaces
    and the wallet organization. Second, I believe account is the right
    abstraction - as mentioned, address is just a token for claiming some
    bitcoins, but different kind of claim proofs might be used (e.g. the
    now-deprecated "send to IP address", or it could be possible to also
    specify password-protected coins). In the future, you could associate
    further methods of authentication with accounts, but addresses are
    limited. If you require a specific set of addresses to be used, you can
    set up an ad-hoc account.
    
    Q: What does that bit about "change" mean?
    A: If transaction input claims some output of a previous transaction,
    it must claim all the coins in the output. If you need to transfer
    smaller amount than that, you must specify what to do with the
    remaining amount (change). The built-in coin selection algorithm
    either sends them to a new address (for better anonymity) or returns
    them to the source address. Here, you are responsible for manually
    specifying the destiny of your remaining amount.
    
    Q: Can I be finally sure I pay only the TX fee I specify?
    A: Yes, the TX fee you specify is final. However, please note that
    if the new transaction is large (i.e. has many inputs and outputs)
    or transfers too small amount and you do not offer any TX fee, it
    may not be accepted by any other nodes. Note that this is more
    serious than not being included in a block - you could just wait
    longer for a benevolent miner. In these circumstances, your
    transaction is not likely to even *reach* a mining node because
    the P2P network will not relay it.
    34fd79f9ca
  5. gavinandresen commented at 1:44 PM on June 27, 2011: contributor

    This feels like the wrong level of abstraction to me.

    If you want this level of control, then an even lower-level interface seems like the way to go-- something like "here's a transaction, please sign it and broadcast it if it is valid (return txid if it is a valid transaction, error if not)".

    I also don't like all the duplicated code in CreateTransaction/CreateExactTransaction, it may make bug fixing any problems in send or supporting new transaction types like 3-party escrows harder.

    Finally, what is the TxIn syntax? Just txid? What happens if you point this at a send-to-self or a receive-many where you own more than one TxOut of a previous transaction?

  6. pasky commented at 3:45 PM on June 27, 2011: none

    Thanks for the feedback! I'm not sure about your suggestion of providing a raw transaction. I aim at something that is suitable for automated use, but at the same time users can still realistically use manually. It is not clear what exactly do you mean by "here's a transaction" - would you like something like, say:

    { "in": [ { "prev_out": { "hash": "...", "n": "..." } } ], "out": [ { "value": ..., "address": "..." } ] }
    

    There is a couple of questions here:

    • Identify prev_outs by specific n's instead of account-based autoselection (answer to your last question: all txouts claimable by the given account are selected). Maybe this really is the best way to go, but then gettransaction and listtransactions output needs to include an 'n' field too.
    • Switch syntax from two-object form to tx-like form. I don't see the benefit, IMO it just leads to a more baroque syntax.

    I'm all for switching to explicit n-form for inputs, but how to integrate this with the account system then? Currently, each transaction has single strFromAccount. Should the user still specify the account and the input amount just gets subtracted from that account's balance and it's the user's responsibility to sort out the account balance?

    I agree that the duplicated code is bad. I was a bit shy to do large changes in CreateTransaction(), but I will refactor this part of code and I agree it will make the code better. I just want to agree on the final way to select inputs first.

  7. pasky commented at 7:14 PM on June 27, 2011: none

    By the way, thinking things through more, now I think that sendtxfee/paytxfee should not be imposed on these transactions (our goal is still creating transaction only based on pubkeys stored in our wallet, but no extra client automagic), but creating unrelayable transactions still should not be allowed. Does that make sense? In line with that, AIUI I should check against nMinFee but not nPayFee?

  8. gavinandresen commented at 9:43 PM on June 27, 2011: contributor

    When I say "here's a transaction, please sign it (if you need to) and send it" I'm imagining you hand it the serialized hex version of a transaction (with all-zeros placeholders for the ECDSA signatures). Really extremely low-level.

    My thinking is that a very-low-level routine like that might be the path to all sorts of interesting functionality, including things like escrow transactions where some of the transaction signing is done outside the p2p network.

    But I haven't thought about this terribly hard, and, frankly, the high priorities right now are NOT new features like this but scalability and security.

  9. pasky commented at 10:50 PM on June 27, 2011: none

    Ok, I agree that such a command would open other interesting possibilities, but that is already something completely different from what I have in mind. You would not be able to use the wallet at all anymore and I am just personally not interested in figuring out how to externally fetch a key from wallet while bitcoind is running and re-implementing all the cryptography and script execution. I want to still make use of all these bitcoind facilities, just specify precise coin flow.

    I will do the modifications I outlined before and re-submit, you guys will see if you have time to review and merge the patch before you get your high priorities done. If not, I will be a bit sad but try to maintain my changes up-to-date against current code until they are merged.

  10. gavinandresen commented at 3:58 PM on October 5, 2011: contributor

    Closing; specifying precise coin flow just isn't a high priority. Also, new RPC commands should be discussed on the mailing list or forum.

  11. gavinandresen closed this on Oct 5, 2011

  12. sipa referenced this in commit f41ed612dd on Aug 27, 2016
  13. sipa referenced this in commit 2f342da4b9 on Nov 30, 2016
  14. sipa referenced this in commit 634ad51703 on Dec 2, 2016
  15. ptschip referenced this in commit 69c316832d on Apr 9, 2017
  16. classesjack referenced this in commit 7b4d775cef on Jan 2, 2018
  17. lateminer referenced this in commit c6634ef065 on Feb 19, 2019
  18. sipa referenced this in commit cc05fa919a on Mar 30, 2019
  19. sipa referenced this in commit 54245985fb on Mar 31, 2019
  20. LongShao007 referenced this in commit 3d9a3d2063 on Jul 15, 2019
  21. fjahr referenced this in commit 1086fda4c1 on Jul 24, 2019
  22. kallewoof referenced this in commit 2d465aa9cd on Oct 4, 2019
  23. lateminer referenced this in commit e903130ef7 on Oct 16, 2019
  24. 0xartem referenced this in commit c4e6041496 on Feb 29, 2020
  25. 0xartem referenced this in commit 45935322ed on Feb 29, 2020
  26. cryptapus referenced this in commit 9d333c1082 on May 3, 2021
  27. cryptapus referenced this in commit 67d1ae5f3b on May 3, 2021
  28. rajarshimaitra referenced this in commit b49f8fcb3f on Aug 5, 2021
  29. DrahtBot locked this on Sep 8, 2021
Contributors
Labels

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-05-02 12:16 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me