As described in USDC Transfers Temporarily Affected by Noble Chain Upgrade , a recent Noble upgrade broke USDC withdrawals for ultimately pretty silly reasons: a change to a Bech32 library unintentionally added a new length limit, breaking compatibility with Penumbra addresses.
The correct fix for that issue is for a bugfix to be deployed to the Noble chain. However, this may take time (as of now, there is no concrete timeline for deployment of a fix). And, this isn’t the first compatibility issue that’s arisen with Penumbra addresses, and it may not be the last.
Rather than waiting for a third party fix, it may be better to perform “proactive interoperability”, and define a maximally compatible address format: truncated addresses. These addresses would be 32-byte Bech32 addresses, like this:
ptrunc16t45lct6x4w6an6hvv7zp9p49qx0teg78qyukcgfk76ch87leggq0wlmdc
Truncated addresses have compatibility both with external systems and with Penumbra. A truncated address can be directly decoded to an ordinary Penumbra address. The address above decodes to
penumbra169wv6gf7r2fp0p0z6dsdlr7ntjetp2v2s4q77l434vw2qsdg3lqzlpyy6krgueygk0z3m2c77galpszc6q053nd4tjyu03d6hawlw4992ahdasgazqy54k39g2ezu536etjzkr
so that the truncation is really just an encoding difference, and no changes are needed to any other part of Penumbra.
Unfortunately, truncated addresses achieve this compatibility at a cost:
- There is only one truncated address per Penumbra wallet
- That address points at a random, fixed sub-account
- Reusing a truncated address creates linkability (e.g., using it for IBC deposits or withdrawals causes all deposits and withdrawals to be linked, as there is only one truncated address per wallet)
These make the UX much, much worse than normal Penumbra addresses in hard-to-explain ways, so the use of truncated addresses should always be discouraged. However, it may be useful to add the capability anyways as a kind of compatibility escape hatch: a user might prefer to at least be able to do withdrawals or deposits in the event of a current or future compatibility issue, rather than having stuck funds.
How Truncated Addresses Work
A Penumbra address has three components:
- The diversifier,
d
; - The transmission key,
pk_d
; - The clue key,
ck_d
;
The controller of the address creates the diversifier (random bytes) by choosing a 16-byte address index, which encodes structured information about the address metadata. By convention, the address index is LE32(account index) || 12-byte randomizer
. The address index is then symmetrically encrypted with the wallet’s viewing key. The output of that encryption is used as the diversifier. The diversifier is used to derive the transmission key, which a counterparty uses to encrypt messages to the user. The clue key allows fuzzy message detection, for future scaling, but this is not used in the client stack at this time. This design has two really useful properties:
- The wallet’s viewing key can scan messages encrypted to all possible transmission keys simultaneously (i.e., one scanning pass can detect messages sent to any address)
- The viewing key can “decode” the encrypted metadata in the diversifier, so it can statelessly determine which account the address corresponds to.
These components are 16 + 32 + 32 = 80
bytes, and are jumbled as part of the encoding (so it’s always safe to do the common user behavior of checking only the first N characters).
Truncated addresses truncate the address data to only 32 bytes, by:
- Requiring the diversifier is
[0; 16]
and skipping its encoding (it is filled in with zero bytes on the decoding side); - Encoding only the transmission key;
- Discarding the clue key, and filling it in with a dummy value (the identity element) on decoding.
Pros
- Truncated addresses are as compatible with Cosmos or other systems as possible: 32 bytes of Bech32 encoded data
- Because truncated addresses can be decoded to an ordinary address, the extra address format does not need to “propagate” through the rest of the client stack, and would require no changes to the core cryptography or protocol.
- Penumbra could add truncated addresses without waiting for any other chain, and leave them as an ugly hack that allows compatibility workarounds for future issues.
Cons
- There is only one truncated address per wallet, which breaks privacy when making IBC transfers.
- Currently, IBC transfers can use unique addresses for each transfer automatically, so users never have to think about address reuse. Truncated addresses would force users to think about this issue, and they would probably get it wrong.
- The truncated address points at a random account, which is weird and unexpected.
- Truncated addresses are not compatible with FMD
- This is probably not a big deal, since FMD is not currently used, and the model Penumbra is evolving towards with Spend Backreferences would mean that FMD could be used to detect any one transaction made by a user
- Adding a third address format, even if only marginally used, adds to the already substantial conceptual UX burden
In spite of those downsides, I still think this could be worthwhile to implement, if only as an escape hatch. The right solution to compatibility issues with other chains is to have full support for normal Penumbra addresses. But in the meantime, having an ugly hack that allows users to transact is probably preferable, and having it available for the future seems desirable.
Proof of Concept
A PoC implementation can be found at [WIP]: Truncated address formats by hdevalence · Pull Request #4950 · penumbra-zone/penumbra · GitHub