Addresses and Detection Keys

Rather than having a single address for each spending authority, Penumbra allows the creation of many different publicly unlinkable diversified addresses. An incoming viewing key can scan transactions to every diversified address simultaneously, so there is no per-address scanning cost. In addition, Penumbra attaches a detection key to each address, allowing a user to outsource probabilistic transaction detection to a relatively untrusted third-party scanning service.


Addresses are parameterized by diversifiers, 11-byte tags used to derive up to distinct addresses for each spending authority. The diversifier is included in the address, so it should be uniformly random. To ensure this, diversifiers are indexed by a diversifier index ; the -th diversifier is the encryption of using AES-FF1 with the diversifier key .1

Each diversifier is used to generate a diversified basepoint as where performs hash-to-group for decaf377 as follows: first, apply BLAKE2b-512 with personalization b"Penumbra_Divrsfy" to the input, then, interpret the 64-byte output as an integer in little-endian byte order and reduce it modulo , and finally, use the resulting element as input to the decaf377 CDH map-to-group method.

Detection Keys

Each address has an associated detection key, allowing the creator of the address to delegate a probabilistic detection capability to a third-party scanning service.

The detection key consists of one component,

  • , the detection key (component)2,

derived as follows. Define prf_expand(label, key, input) as BLAKE2b-512 with personalization label, key key, and input input. Define from_le_bytes(bytes) as the function that interprets its input bytes as an integer in little-endian order, and to_le_bytes as the function that encodes an integer to little-endian bytes. Then

dtk_d = from_le_bytes(prf_expand(b"PenumbraExpndFMD", to_le_bytes(ivk), d))


Each payment address has three components:

  • the diversifier ;
  • the transmission key , a decaf377 element;
  • the clue key , a decaf377 element.

The diversifier is derived from a diversifier index as described above. The diversifier with index is the default diversifier, and corresponds to the default payment address.

The transmission key is derived as , where is the diversified basepoint.

The clue key is is derived as , where is the conventional decaf377 basepoint.

Address Encodings

The raw binary encoding of a payment address is the 75-byte string d || pk_d || ck_d. We pad this string to 80 bytes, then apply the F4Jumble algorithm to this padded string. This mitigates attacks where an attacker replaces a valid address with one derived from an attacker controlled key that encodes to an address with a subset of characters that collide with the target valid address. For example, an attacker may try to generate an address with the first characters matching the target address. See ZIP316 for more on this scenario as well as F4Jumble, which is a 4-round Feistel construction.

This jumbled string is then encoded with Bech32m with the following human-readable prefixes:

  • penumbra for mainnet, and
  • penumbra_tnXYZ_ for testnets, where XYZ is the current testnet number padded to three decimal places.

This convention is not enforced by the protocol; client software could in principle construct diversifiers in another way, although deviating from this mechanism risks compromising privacy.


As in the previous section, we use the modifier “component” to distinguish between the internal key component and the external, opaque key.