Receiving and change addresses
This is an article about or from the perspective of wallet development, as most of mine are.
I use the term addresses, simply because that is the current way they are displayed. But when an address is used, what happens is that a new key is allocated and transformed into it’s address representation.
We are currently stuck with the approach that a user gives someone an address to pay to, but within the next year as simpler and safer alternatives become commonly supported, I expect users will find this feels like an unsafe and arcane experience. Even worse for those that try and stick with it, is that very likely services will want to deprecate the ability to give them addresses as soon as possible. Instead a user will pay to a contact, or to a Paymail address, and how they are paying and what might serve in place of an address is something they can remain oblivious to.
As a wallet developer, I find myself at the point where I wonder what purpose separating receiving and change addresses serves, and why we do it. Do I need to preserve this behaviour going forward?
The origin of receiving and change addresses
The biggest benefit I can discern for the separation of receiving and change addresses, is that the wallet can be sure that it won’t send change to receiving addresses it has not yet received coins on. Ones that the payee has given out, and the payer who was given them has not sent coins to yet.
ElectrumSV only uses the knowledge that an address it has encountered, is a change address, for one of two actions. It displays different colour in it’s transaction dialog for both receiving and change addresses. Otherwise, through the code base if the index and type of address is looked up, it is used to recreate the derivation path of the given address.
BIP32 touches on the subject briefly, saying:
In the example of a webshop, the webserver does not need access to all public keys of the merchant’s wallet; only to those addresses which are used to receive customer’s payments, and not for example the change addresses that are generated when the merchant spends money.
My best guess is that it is a prescription taken from BIP32 which all wallets who adopted it followed:
Each account is composed of two keypair chains: an internal and an external one. The external keychain is used to generate new public addresses, while the internal keychain is used for all other operations (change addresses, generation addresses, …, anything that doesn’t need to be communicated). Clients that do not support separate keychains for these should use the external one for everything.
Reconsidering BIP32 in context
I’ve written about the fallacy that with a master private key (or a mnemonic/seed words from which one can be obtained) and BIP32 derivation paths, we were told that we could recover our wallets without any additional information. How in reality, it falls apart when we start doing more than simple payments.
Let’s think for a moment.. BIP32 was written by a Bitcoin Core developer. One of the same set of people that crippled Bitcoin in order to promote off-chain solutions. They intentionally locked it down with limits and other concepts like “standard transactions”, so that all users could do were simple payments.
Let us return to the abstract of BIP32 where this Bitcoin Core developer wrote:
The specification is intended to set a standard for deterministic wallets that can be interchanged between different clients.
An ungenerous interpretation might look at BIP32 and in hindsight assert that it is a prescription that forces wallets to implement a lowest common denominator of wallet functionality, and not stray from that. One rendered from the mind of a Bitcoin Developer who has participated in one of the most public cases of removing the potential of a software project in history.
However, that is perhaps reading too much into BIP32. It is more likely that the author had no real idea of where it was heading, and just did his best to flesh out a standard way of describing key enumeration. Until Bitcoin SV, it is questionable if wallets thought to step outside of the limits that seed-based wallet recovery force on both wallet software, and the uses that users can make of them.
Where we are now is that the approach of using BIP32 derivation paths is a tried and tested tool. Modern wallet developers seeing the limits removed from the protocol, can ignore the claustrophobic past expectation of BIP32 inter-wallet compatibility from themselves and also build new and exciting solutions. For a start, I see myself using BIP32 to produce keys and addresses, and beyond that bringing in WP42 as we build the foundations that also let us use that safely. I expect each tool will have uses it is best suited to.
So, what of receiving and change addresses? I suspect they are a historical anachronism that there is no reason to retain.
For a wallet that has gone beyond simple payments, it already needs metadata and a recovery and backup mechanism that works. We can no longer rely on the fantasy that seed words will magically do this for us. If we have metadata already, then what is more metadata. As keys are generated and used, we will be associating contextual information with them, including their derivation link to the master key they come from. This already suffices to support all the current uses that ElectrumSV makes of the knowledge an address is a change address. And we can extend it as needed.
ElectrumSV in the future should be able to switch all key generation to what was designated the “receiving address” sequence. And if at some point the key is to be deprecated, it can switch out that master key for another one. Turn a single key account to a multi-signature account, if you want.
I’ll end this here. Do you have anything to add on the subject of receiving and change addresses? Please feel free to discuss it in the comments below, or on either of Unwriter’s slack or Metanet.icu slack.