BIP: ???? Title: Change forwarding Author: Yuval Kogman <nothingmuch@woobling.org> Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-???? Status: Draft Type: Informational Created: 2018-11-05 License: CC0-1.0 GNU-All-Permissive
This document proposes a method for configuring BIP32 capable wallets in order to improve UTXO handling for non privacy/fungibility oriented wallets, by forwarding change outputs to a privacy preserving wallet.
- Forwarding wallet - any BIP32 capable wallet for day to day usage, for instance a hot wallet or special purpose application with embedded wallet (e.g. bisq, open bazaar, protip.is), extended with the functionality described in this document.
- Fungibility wallet - any BIP32 capable wallet with privacy and fungibility features, in particular mixing (e.g. join market, wasabi)
Different BIP32 capable wallets have been designed with various use cases in mind. Many of these (especially mobile wallets) lack good controls over the outputs being spent, and fewer still are focused on maintaining good privacy and fungibility. This creates the potential for inadvertently linking otherwise unrelated transactions when change outputs are used as inputs to subsequent transactions.
By adding the ability to forward all change outputs from such wallets directly to a branch of the BIP44 account hierarchy of a specializing mixing wallet, accidental linking due to human error or naive coin selection can be prevented. If UTXOs of the forwarding wallet can be assumed to be fungible, transaction independence can be maintained without special coin selection functionality since each subset of outputs can only be used by the wallet exactly once, and none of the resulting outputs are directly usable by the forwarding wallet. Those change outputs can subsequently be mixed and then redistributed to the forwarding wallet(s), preserving the validity of fungibility assumptions.
BIP32 describes the "Unsecure money receiver" role, which derives addresses using the public extended key for a specific chain. The forwarding wallet will function as an unsecure money receiver for the fungibility wallet.
BIP44 recommends separate non-hardened derivation for receiving (external) and change (internal) address chains, created as children hardened account paths. Separate hardened accounts should therefore be created, one for each forwarding wallet, with the external non-hardened chain, denoted m below, being exported using the following serialization format.
In order to ensure that the fungibility wallet can recognize spendable outputs generated by the forwarding wallet, both wallets must agree on the script derivation for a given public key in the address chain.
The BIP32 serialization format can therefore be ammended by the fungibility wallet with additional information using one of the following options:
- SHA256( scriptPubKeym / 0 ) - allows arbitrary scripts/addresses, open for extension, multisig possible. Electrum protocol uses SHA256 but HMAC_SHA512(scriptPubKeym / 0, xpub) could also be used. Simplest to implement for forwarding wallets (go/no-go during setup based on existing address derivation).
- SLIP32/SLIP132 or Electrum style version bytes - electrum also mentions but doesn't specify standard multsig version bytes, compact, only supports fixed script/address formats
- miniscript
- BIP124 templates - encoding/serialization format is still TODO, would allow arbitrary scripts, could in principle be parameterized over multiple xpubs to derive multisig scripts, relatively complex
- BIP178 version bytes - fixed script formats, compact, no standard multisig, intended for WIF keys (mainly included for completeness)
In the forwarding wallet, an additional configuration option should be provided which overrides the standard change internal address chain.
The configuration value must only be accepted if the forwarding wallet is capable of deriving a matching script as specified by the fungibility wallet.
(note: This section makes the assumption that SHA256(scriptPubKey) is the preferred option for the serialization format which is still TBD. However, this is not clearly the case, primarily because version bytes approach is already prevalent, and the hashes are significantly less compact. On the other hand SLIP-0032 style extended public keys can lead to non fail-safe behaviour if the two wallets differ in their interpretation of the version bytes, and the derivation sub-path is only specified by convention. BIP124 templates are still not fully specified, and would require forwarding wallets to construct scripts differently, instead of just verifying that the fungibility wallet recognizes scripts of a form they already implement)
This proposal aims to improve interoperability of less coupled wallet implementations, specifically in a way that ensures that forwarding wallet transactions utilize separate master seeds in their inputs and outputs, under the assumption that the master seed used for the outputs is managed by specialized fungibility wallet.
Public extended keys are already in common use, though their main application has been to protect key material, and this typically assumes a high degree of coupling between the implementation of the watching wallet and the signing wallet, and that address chains derive from a single master seed.
Furthermore, since improving fungibility through interoperability is the main goal, the changes required in order to add forwarding capabilities to existing wallets should be minimal and leave little room for implementation error (no ambiguity with respect either the derivation path or the script being used).
Any non-fungible coins sent to the forwarding wallet are in no way protected by this setup, so the fungibility wallet must first be used correctly to ensure fungibility.
Secondly, subset sum analysis could still be performed on the change outputs used as inputs into mixing transactions, potentially linking pre-mix transactions. This concern can be alleviated by mixing in larger batches but is otherwise beyond the scope of this document.
This proposal is designed to minimize the required changes to forwarding wallets.
When creating change outputs, the only required change should be the switch to an address chain based on a public key instead of the wallet's regular account hierachy. If change forwarding is not configured, the same code path can still be used to derive change addresses from the forwarding wallet's account hierarchy using public child key derivation.
Most of the complexity of any changes is expected to be in the configuration and balance UIs.
Since change outputs become unspendable, forwarding wallets should convey to the user that after a payment is made the usable balance may decrease by more than the payment amount. Forwarding wallets can still display balances from the unspendable address chain (e.g. as "locked" balances) similar to watching wallets.
The fungibility wallet should allow exporting of different forms of public extended keys, but only for its supported script/address types, to avoid loss of funds. If multiple options are available the user can manually select which type to use, or leave that choice up to the forwarding wallet.
The fungibility wallet should keep track of exported keys and use separate hardened account derivation paths for different forwarding wallets, to avoid address reuse when different forwarding wallets are used concurrently. To ensure account discovery when recovering from seed using another wallet in accordance with BIP44 recommendations, the receiving wallet should only export new accounts if the previous account index has a transaction history, and may create a transaction that utilizes the first address in the chain before exporting.
We can consider two example scenarios, though technically one is just a special case of the other:
- Wallet has one large UTXO
- Wallet has multiple UTXOs of uniform or varying size
When a wallet has a single large UTXO and a payment is made, a transaction with a single change output will typically be created, effectively returning to the starting condition.
The resulting transaction graph might look something like the following, where edges terminating in x
denote fungible outputs, o
denotes likely tainted outputs, and ...
denotes outputs controlled by other parties:
x--initial output--> TX_1--+--change--> TX_2--+--change--> TX_3--+--change---o | | | +--payment--... +--payment--... +--payment--...
With more fragmented UTXOs the situation might look more like:
x--+ | x--+--> TX_1--+--change---o | | x--+ +--payment--... x--+ x--+ | | x--+--> TX_2--+--change--+--> TX_3--+--change---o | | +--payment--... +--payment--...
In addition to coin selection features, BIP69 and BIP126 can be used to make inputs less distinguishable payment vs. change outputs, but we assume the forwarding wallets do not necessarily make such considerations.
By interspersing payment transactions with mixing transactions, the resulting transaction graph is harder to analyze, even if the forwarding wallet makes no considerations when constructing inputs, since the property that all spendable UTXOs are unlinkable is preserved by the mixing wallet.
Note that in the following diagrams mixing stages may represent multiple transactions. Additionally, change outputs of all transactions are only spendable by the mixing wallet, and at the end of the following sequence the forwarding wallet balance is 0, i.e. fungible outputs (x
) are only spendable by the forwarding wallet, and tainted outputs (o
) are only spendable by the mixing wallet:
: | : : ...--3rd party--+ : | | | | ...--3rd party--+ +--3rd party--... | +--3rd party--... | | | | x--> TX_1--+--change--+--> MIX_1--+--> TX_2--+--change--+--> MIX_2--+--> TX_3--+--change---o | | | +--payment--... +--payment--... +--payment--...
Similarly with higher UTXO fragmentation:
: : | | x--+ ...--3rd party--+ +--3rd party--... | | | x--+--> TX_1--+--change--+--> MIX_1--+--mixed------x | | x--+ +--payment--... : : | | x--+ ...--3rd party--+ +--3rd party--... | | | x--+--> TX_2--+--change--+--> MIX_2--+--mixed------x | +--payment--... x--+ | x--+--> TX_3--+--change---o | +--payment--...
This section will be added pending final decision on the preferrable serialization format(s).
Please don't apologize, this is very valuable input!
I will attempt to clarify these points
This is correct, though I think not at the level of a single transaction - the forwarding wallet should still be utilzing outputs with
scriptPubKey
s of the same form as it would if not configured to forward change, the only difference in constructing transactions should be the BIP32 parent key being used to generate the address, which should be indistinguishable to anyone not in possession of the derivation keys.However, outputs can be identified as change outputs in that they would likely be redeemed differently, i.e. the fungibility wallet would presumably use them as inputs into a mix. I'm not sure if this is what you meant? Either this is a serious concern that must be acknowledged in this BIP, even if it is not directly addressed.
This is indeed a critical question, and in its current form this proposal does makes the unqualified assumption the fungibility wallet functions optimally. At the very least I must qualify these assumptions better, but of course that would do little to actually help the state of bitcoin fungibility directly ;-)
As far as I know Joinmarket is somewhat more useful in this regard when using the tumbler script, as it attempts to achieve de-correlation of amounts as well sa of merged inputs by having multiple mixing stages.
(ab)using Joinmarket's terminology by analogy, forwarding wallets implementing this proposal configured with one of the mixing depths of the joinmarket wallet as the change chain, and assuming funds sent to the forwarding wallet are the outputs of SpendJMTxs, would allow all transactions made by the forwarding wallet to function as SourceJMTxs with respect to their change, as an alternative to using the sendpayment script (and with reduced benefits over the patient sendpayments mode). BTW, it should be noted that this entire proposal is basically just JM's concept of different mixing depths having different BIP32 branches .
FWIW, I have a related proposal for ZeroLink for to handling unequal input denominations based on fairly conservative assumptions, however I haven't yet finished writing it up. I believe that would hopefully improve its usefulness for handling change outputs of arbitrary sizes, while only trading off throughput (i.e. time to finish a mixing round, which is still arguably reduction in the anonymity set size for a given wallclock time interval, but not in terms of discrete time as measured by number of mixes).
These give me a lot to think about... Some very preliminary thoughts:
While I certainly don't, the approach I was going for attempting to find a path of least resistance for substituting the (lack of) protection afforded by wallets whose functionality is focused on other features (ease of use, niche platforms, special purpose applications) for the arguably better protection afforded by mixing wallets.
I would think so, but I don't see a simple way to achieve that on a technical level (apart from the fact that this proposal requires fungibility wallets to be able to export BIP32 keys, which is more generally useful for receiving payments into them).
This question also seems important for BIP79, which I see as a sort of "transpose" of this proposal, but for the receiving side (incidentally, I think the two proposals can complement each other for payment processing, i.e. receiving payments via BIP79 into a forwarding wallet, but in this case more for security reasons - forwarding in order to limit the amount of funds spendable by the payment processing service hot wallet)
If I understand what you mean by this, then I believe that yes, i.e. like patient sendingpayments in joinmarket, or the GroupSend proposal for Wasabi, which is similar to the broken bc.i coinjoin, but which can still increase privacy if it only spends anonymized inputs. If I'm not mistaken Bisq can already be used in this way (it can fund transactions from its internal wallet or using an address with an external wallet), and this would be preferable to this change forwarding approach, but I can't think of other examples.
However, the barriers to achieving this seem very high in terms of design and implementation complexity, so the intent behind this proposal is to offer an incremental improvement in this direction.
I believe that we can't, not in general, and that the risks are high, but this is part of the implicit design goals of fungibility wallets, so I have made that assumption in the proposal, and that also must be qualified.
Thank you for taking the time to review! I will do my best to iterate on it, this criticism is all on point. Regretfully I don't think I can answer these questions, but at the very least I can make it clearer that these questions are relevant to the proposal.
I don't think conceding defeat is a clear requirement, but rather that it depends on the form of the forwarding wallet's transactions, the fungibility wallet's handling of received funds, and the behaviour of the counterparty. For example, as a hypothetical, if Alice buys coffee from Bob, and both parties use Joinmarket afterwords, I believe that would actually reduce the effectiveness of the change output heuristic, but still allow Alice to buy the coffee, fully on chain as satoshi intended, without needing to use the sendpayment script at the point of sale.
This is definitely a concern for wallets like Bisq which use a recognizable transaction format (though if I'm not mistaken, it's been a while since I read the code, it also uses a consistent output ordering so perhaps it's not a good example since no heuristic would be necessary there...)