librustzcash
librustzcash copied to clipboard
Decide where in the key tree ZIP 320 ephemeral addresses should go
We have a few options that we need to decide between:
- Take "unused" addresses within the existing chain of change addresses for an account (scope
1at theis_changelevel of the path, where in BIP 44 it is treated as a boolean).- This risks that the "ephemeral" addresses become linked to the rest of the transparent part of the wallet, if the wallet seed phrase is used in a wallet that behaves like a regular Bitcoin-style wallet and links change outputs together. Linkability can occur in two ways:
- If the recipient TEX address sends funds back to the ephemeral address, and the transparent wallet then treats it as change.
- If the second transaction in a TEX payment doesn't get mined, the transparent wallet treats the output as change, and then the "ephemeral" address gets reused with the same TEX recipient in a subsequent transaction.
- This risks that the "ephemeral" addresses become linked to the rest of the transparent part of the wallet, if the wallet seed phrase is used in a wallet that behaves like a regular Bitcoin-style wallet and links change outputs together. Linkability can occur in two ways:
- Use the scope
2at theis_changelevel (effectively turning that level into an enum within Zcash). - Use the scope
ZCASH_DOMAIN_SEPARATOR | 0at theis_changelevel (same as above, but providing domain separation from any accidental collisions against other specifications that may themselves have said "just use2"). - Use a different key tree derived from the wallet seed phrase but not derived from the account's transparent IVK.
- This would mean that the IVK / FVK doesn't see everything in the wallet, which is less desirable.
- Derive a path in the key tree deterministically from the recipient TEX address (i.e. have a 1:1 mapping between TEX addresses and the "ephemeral" addresses we connect to them).
- The other approaches can be recovered by the usual BIP 44 dead reckoning (count from zero until you reach the gap limit). This one would require storing additional metadata in memo fields within the transaction.
With the middle three options, it is possible to determine solely from the transaction graph structure which outputs went to TEX addresses: if an ephemeral address is observed, then for any transaction spending from that address, its transparent outputs are TEX addresses.
With the first option, this isn't possible because there is no way to distinguish between a change address and an ephemeral address. You'd need to store the recipient address map in a memo field.
With the last option, ephemeral addresses aren't detectable directly, and instead you need to rely on metadata conveyed in e.g. memo fields for detection.
#1257 currently implements the second option:
Use the scope
2at theis_changelevel (effectively turning that level into an enum within Zcash).
In a pairing, @nuttycom and I looked through every BIP that mentions the word "change" to find BIP 32 derivation paths. All of them that were not BIP 44 generally changed the "purpose" level (so it would not precisely collide with us), and those that had a "change" level only defined 0 and 1 a la BIP 44 (so they would not collide semantically with us). We also looked over https://walletsrecovery.org/ (mentioned in BIP 88) and didn't see any non-{0-1} change levels there either (although that website almost exclusively only shows hardened derivation levels, presumably because non-hardened derivation can be churned through more easily as it doesn't involve private derivation that might require a hardware wallet).
We decided that the additional domain separation that the ZCASH_DOMAIN_SEPARATOR | 0 scope would provide is unnecessary, and we will use scope 2 (i.e. keep what #1257 currently implements). ZIP 32 will be updated to document this (as an extension to BIP 44, which we otherwise incorporate by reference in e.g. ZIP 316), so that people looking for "how does HD derivation work in the Zcash ecosystem" will find it in ZIP 32.
We've made the decision. I've filed updating the ZIP as https://github.com/zcash/zips/issues/877.