I’ve had this one in drafts for, checks notes, more than 3 years! And I thought it made sense to just push it out. Make sure it is known to the world, no matter if people want to use it or not.
So this is a document that uses the concepts of HD wallets. Masterkeys and derivations. It explains various neat things you can do with them and a standard numbering for those new ideas as I imagined or even use them today.
Please have fun, and maybe we can extend this with other known derivation path innovations people use today?
I recently made a pull request for Electron-Cash (pending review) using the keys at m/44'/145'/0'/2/0 and m/44'/145'/0'/2/1 for RPA, but apparently it’s already used according to your CHIP and I will update my branch to something else.
Initially I used the keys below the path m/44'/145'/0'/8 because that was one higher than …/7 which is promoted by the WizardConnect documentation for DeFi: Wallet integration - Riften
This shows that a registry of known paths that the community can gather around is needed and this CHIP could be the start of it.
I also am imminently publishing an RPA library for TypeScript and was planning to use m/44'/145'/0'/2/0 and m/44'/145'/0'/2/1 for RPA.
However, upon reading Tom’s CHIP draft, I do not think this usage is incompatible with Tom’s usage of this path for “wallet identification.”
If the intent is beyond identification of the wallet itself, such as some user account scheme, I would personally use m/44'/145'/N', where each path N is a single account, with the existing 0' path simply being a “default account.”
My thoughts were that 0 is the wallet itself in a way that you use it for store/restore. You’d use it to find the comments on all your old transactions.
It doesn’t specifically seems a problem as RPA itself doesn’t really announce the pubkey or its address AFAIK. But it does beg the question how many RPA’s you want to publish. Why not an infinite amount?
And you can cleanly mix it with logins for websites. All on the same derivation. Just don’t reuse addresses
The zero is a bit special since you JUST have a seed at the time you derive that one. No backup is restored yet. You get the backup from that zero’th key. Hence the reservation.
After you restore the wallet with that zeroth, your metadata can indicate which index was used for what.
My suggestion is to just start with 1 on your library. Probably allowing the user to select any N in m/44'/145'/0'/2/N where N is larger than 0.
This mirrors the CHIP. So, sounds good.
After the BASE (2 levels) we add a 3rd level we call the extension . The extension defines multiple actual physical wallets being used from the same seed and the same base.
The paycode itself, that the user publishes openly, does contain 2 pubkeys.
Theoretically a user could create an infinite number of RPAs.
I propose:
RPA #1: m/44'/145'/0'/X/0 and m/44'/145'/0'/X/1
RPA #2: m/44'/145'/0'/X/2 and m/44'/145'/0'/X/3
RPA #3: m/44'/145'/0'/X/4 and m/44'/145'/0'/X/5
And so on.
I think X=2 should be avoided if there is any known usage. I used X=8 in my pull request for Electron-Cash, but I can certainly change it to something else. What do you think @kzKallisti ?
In practice I think most users will only publish 1 RPA/wallet and I think most wallets will only allow that for the foreseeable future, but flexibility is needed.
I was suggesting m/44'/145'/0'/2/1 and m/44'/145'/0'/2/2 in your setup, with 3+4 maybe for the next.
The idea is to avoid hard coding them and just like with the main and the change chains, you just keep increasing the number as the user requests a new ‘thing’. Where the 2 chain is labeled as “ownership” that works for logins as well as for RPA in my own humble opinion.
So if you have a website that you reserve an index for, you skip that one. Giving the next two after that for your next RPA. All inside of the BASE/EXTENSION/2/* list of addresses.
I agree with this. We can have “infinite RPAs” for a single “account” (as defined earlier in this thread) simply by deriving more keys from the /2 path.
From a UX perspective, this would likely represent individual logins for the same “identity” - e.g. if my /0 “default account” is named “Kallisti”, then I can have a separate RPA for each service I log into under the “Kallisti” account. If I want a new account/alias, I will derive from the previously-unused /1 path, which can derive its own RPAs under /1/2/0+1, /1/2/2+3, etc.
@tom - I want to make sure I understand your concern correctly. The main problem is if the RPA pubkey is exposed, right? And if I understand your backup system, technically we would consider the 0th key to be “exposed” as it was written to backup, right?
Does it make sense to instead use the hardened m'/44'/145'/0' path to identify an entire wallet (including all of its derived accounts/identities)?
I don’t necessarily oppose simply moving RPA up by 1 index. It’s just quirky
Semantically, though, I feel like /2 makes the most sense. Would be nice to be able to have it, but it’s not worth extensively bikeshedding over either.
The backup can be publicly stored on a server, under the address resulting from the zero.
As such, the publishing of the address for the same wallet, for instance for RPA, binds it to an encrypted backup file. I don’t specifically forsee that being a huge deal, but there is no reason to take any risk when addresses are practically free.
Maybe the word ‘identify’ is not clear. As the technical wallet already uses the path you pasted. It appends things like the change chain etc.
This is not the identity I was referring to.
The wallet identity is one bitcoin address that can be used to refer to the wallet. As opposed to referring to reddit.com (as in, a login key) or another public key that is the login for this site, bccr com.
The choice of 2/0 (appended to that pasted path of yours) is simply to pick an address that is unused by any payments or other things. So thigns stay private and nobody will be able to find that comment-backup file and tie it to you.
It is a simple avoidance of reusing an address.
I mean, my point of view is to not see it as “moving it up one index”. The point I’m trying to support is that the /2/* chain is for a lot of keys. And you want to avoid reusing of keys.
So it becomes needed to reserve keys in your wallet. If you implement the feature to do logins on websites then you reserve keys for that. And if the user just happens to create an RPA at a later date, it just uses the first free one.
So no different than main or change addresses where you avoid reuse.
And I agree, please use /2/*
It falls in the concept of the CHIP, I have no problem with it.
Just the basic request to consider the /2/0 key pre-reserved. If you don’t, then I won’t lose any sleep over it. Some users may complain and if you want to do backups in your wallet at a later time you’ll be forced to do is incompatible with mine, which is why I’m writing here.
If I am reading this correctly this would mean that it would be hard to move a seed between wallets with different functionality. Wallet A (that supports “identity” but not RPA) could use m'/44'/145'/0'/2/0 as a login to a specific website. If a user enters the seed into Wallet B (that supports RPA but not “identity”) a paycode would expose the pubkeys m'/44'/145'/0'/2/0 and m'/44'/145'/0'/2/1 and anyone with knowledge of the identity and paycode would be able to link the two to the same user.
Therefor RPA should not be derived on a path that is known to be used for anything else so any RPA capable wallet could recover funds from the known path.
@kzKallisti So “up 1 index” and use m'/44'/145'/0'/3/x for RPA seems appropriate.
To tie it al into a nice ribbon; the /2/0 key is used to do the comments-backup I mentioned? This can naturally also be used to backup your other details, like which identity matches which key. So restoring from seed also restores all this info from a (cloud based) backup.
Why keep RPA under 44' at all? Even in this thread it’s slid from /2 to /3, and identity/backup and logins also sit on /2. Giving RPA its own purpose like m'/47'/145'/0' or m'/X'/145' reserves it by namespace instead of a child index everyone has to remember to keep clear, so it stays isolated whatever else gets added under 44' later. 47' is already the reusable-payment slot and 145' keeps it BCH. I might be missing why 44' is the better home though.
RPA is not the same as BIP-47 so using 47 would not be ideal.
The reason it makes sense is that the RPA keys at m/44'/145'/0'/3/[0,1] “belongs” to the wallet m/44'/145'/0'.
If a new wallet for the same seed would be needed it would naturally be m/44'/145'/1' and it’s RPA keys would be below the same path: m/44'/145'/1'/3/[0,1]
It’s a logical grouping of what belongs to a specific wallet and you can recover all the RPA funds given one xpriv.
You can treat 47' just as the nearest existing label, not me proposing BIP47. The idea is a dedicated purpose m'/X'/145', so “RPA isn’t BIP47” isn’t the issue you can choose any arbitrary number its just that BIP47 is famous for payment code and the implementation is BCH native.
On grouping though, “recover everything from one xpriv” is the same property as “link everything from one xpub.” With RPA at m'/44'/145'/0'/3/[0,1], anyone you hand the account xpub to (watch-only, a backup service, a third party) can derive /3/0 and /3/1 to rebuild your paycode and /2/x for what Tom mentioned about login/identity, and tie them to one wallet. That’s the linkage again, just at xpub level instead of a reused address.
A separate purpose puts RPA in a tree the 44' account xpub can’t reach, so handing out that xpub doesn’t rebuild your paycode. You lose single-account-xpriv recovery for it, but the seed still recovers everything either way.
So it’s a real tradeoff, not a clear win for 44': grouping is convenient if you only ever restore from seed, but it’s the same key that ties RPA to your logins the moment an account xpub leaves the wallet. Wallet implementation can follow both 47' and 44'and with clear labeling for the end user just like the picture shown below
Why would you handle a third party a xpub for an entire account and not expect that party to link everything that belongs to it? At that point it would make more sense if paycodes and identities was revealed then not. You are giving away almost all privacy (Fused coins? Nope! All fusing history is there…)
To me it seems more consistent to have a use-case: “I have one seed, here is xpriv for wallet 0, 1 and 2 with its own identity and paycode”
Electron Cash has for years been handling RPA as its own wallet and the response has been clear that a paycode should be “linked” to a normal wallet.
What is it you are showing with the picture?
A minor side note: if you are only given a xpub where you can derive the scan and spend pubkeys you will not be able to find the transactions that corresponds to it, the private keys are needed for that.
The picture is from an experimental implementation @0pen and I did in 00wallet, a BIP352 silent payments variant for BCH, where two separate m'/X'/145' branches are derived from the same seed and tracked by the wallet. 44' for normal BCH and 352' for stealth. It was experimental, but it worked.
To add to that, Cauldron is using the /7 path for LP pools. If you give anyone the full account xpub the third party will also be fully aware of any pools that belongs to the wallet account and those pools will also be recoverable from account xpriv.
From an UI perspective: if you from your wallet create pools, paycodes and use identity services it should be expected that those resources is coupled with the account. Hence it would make sense that if you provide a “watch-only” key for the account to a service all the resources would be “watchable” by that service.
There will always be need for watch-only wallet this is why the user should have an easy solution to do that in isolation. Therefore user can have two different accounts for RPA one for watch only wallet and one for normal RPA payments. This is one of worries i was always thinking about and one of the reasons i thought harden gate for the derivation was needed.
I do not fully understand what you are proposing. Why should there be 2 accounts for RPA? How would you distinguish between them in a wallet UI?
What is the need exactly for a watch only wallet? I don’t know where an account level xpub is shared to an untrusted third party and it should be heavily discouraged. The CHIP in OP proposes sharing of xpubs on specific subpaths (not for the whole account) and the WizardConnect protocol is strict about which xpubs are shared (never for the whole account).
Watch-only here is special for RPA. Detecting incoming payments needs the private scan key, not an xpub. So a watch-only RPA wallet means handing over a scan key that can see every payment to that paycode but can’t spend like a merchant terminal, a second device, or an accounting view that should detect incoming RPA but never spend it. For RPA an xpub detects nothing, so the watch case necessarily means sharing a private scan key, not a pubkey.
And because that scan key covers everything it can derive, the best way i can think of to delegate it is to keep the RPA you expose in its own account, separate from your private RPA. The shared key is then scoped to that account and reaches nothing else. In the UI that’s just two accounts like 0’ and 1’, one labeled receive/watch, the other normal.