> ## Documentation Index
> Fetch the complete documentation index at: https://docs.metalntwx.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Keys and Addresses

> How shielded keys control spending, generate payment addresses, and enable delegated viewing and proving

The recipient virtual asset service provider (VASP) needs to read payment
details. A delegated viewer may also need visibility into notes and their
spends. Neither activity requires spending authority. MIP410's key hierarchy
gives different parties the capabilities needed for their roles. These
capabilities derive from one wallet seed and can be delegated through different
keys.

The same hierarchy also connects payment addresses to viewing and spending
keys. One incoming viewing key can generate many diversified addresses and
recognize payments sent to them, while spending the received notes still
requires authorization from the corresponding spending key. Recipients can
therefore use fresh addresses to reduce linkability without managing a separate
set of keys for every address.

## Key hierarchy

The spending key authorizes note spends and derives the keys used for
viewing and proving. The derivations are one-way. Possessing a derived key
does not reveal the spending key.

| Key | Capability |
| - | - |
| Spending key (`zsk`) | Authorizes note spends and derives the other keys |
| Spend-verification key (`ak`) | Used during proof construction to verify signatures produced with the spending key |
| Nullifier key (`nk`) | Derives nullifiers and input lock IDs for known notes |
| Incoming viewing key (`ivk`) | Generates diversified addresses and decrypts incoming payment memos |
| Outgoing viewing key (`ovk`) | Derived separately from the incoming viewing key |

## Computing the keys

The wallet derives its shielded keys from a 32-byte seed using Poseidon2 and
Grumpkin curve multiplication. In the formulas below, `H` means Poseidon2,
`G` is Grumpkin's fixed generator, and `*` denotes scalar multiplication when
applied to a curve point. Each `DOMAIN_*` is a fixed domain-separation tag.

```text theme={null}
seed_lo = big_endian_integer(seed[0:16])
seed_hi = big_endian_integer(seed[16:32])

zsk = H(DOMAIN_ZSK, seed_lo, seed_hi)
ak  = zsk * G
nk  = H(zsk, DOMAIN_NK)
ivk = H(ak.x, ak.y, nk, DOMAIN_VIEW)
ovk = H(DOMAIN_OVK, zsk)
```

The seed halves are named by their position in the byte array. Each half is
read as a big-endian integer. The order of the hash inputs is part of the
construction. For example, `DOMAIN_NK` follows `zsk`, while `DOMAIN_OVK`
precedes it.

The derivations let a proving service compute `ivk` from `ak` and `nk`
without receiving `zsk`. Recovering `zsk` from `ak` requires solving a discrete
logarithm on Grumpkin. Recovering the inputs to `ivk` requires breaking the
hash's preimage resistance. These cryptographic assumptions support the
separation between spending, proving, and viewing capabilities.

## Diversified addresses

A diversified address is the pair `(d, pk_d)`, where `d` selects a base
point and `pk_d` is the address point derived from `ivk`. Both parts are
public. The base point on Grumpkin is derived as follows.

```text theme={null}
x   = H(DOMAIN_GD, d)
y   = smaller canonical square root of (x^3 - 17)
g_d = (x, y)

pk_d = ivk * g_d
diversified_address = (d, pk_d)
```

For some values of `d`, `x^3 - 17` has no square root in the field. Address
generation samples another diversifier until it finds a valid base point.
Choosing the smaller root makes the derivation deterministic. Address
generation also excludes the identity point. This is MIP410's specific construction.
A generic hash-to-curve function would not necessarily produce the same point.

One incoming viewing key can generate and recognize many diversified
addresses. For any valid diversifier `d`, it can reproduce `pk_d`. Changing
`d` changes the base point and resulting address without changing the viewing
key or spending authority.

Reusing an address gives observers an explicit connection between payments.
Fresh diversified addresses conceal their common incoming viewing key from
observers of the addresses alone. Information from payment requests or
transactions may still reveal a connection.

## How an address is tied to spending authority

The sender and unshield circuits connect a note's address to the key that
authorized its spend. The prover supplies `ak`, `nk`, the note opening, its
Merkle path, and a spending authorization as private inputs. The circuit
derives `ivk` from those keys and reconstructs the address stored in the note.
The following pseudocode shows these checks for each input note.

```text theme={null}
ivk = H(ak.x, ak.y, nk, DOMAIN_VIEW)
g_d = derive_base_point(note.d)

assert ivk * g_d == note.pk_d
assert merkle_root(commit(note), path) == public_commitment_root
assert schnorr_verify(ak, authorization_digest, signature)
```

Reconstructing the address establishes which key material controls the note.
A spending authorization provides permission for this particular spend.
The circuit verifies a Schnorr signature against the same `ak` used to
derive the note's address. It recomputes the authorization digest from the
transaction's bound parameters, including the chain ID and pool contract
address. Initiation binds the proposed payment, payment nonce, and deadline.
Unshielding binds the public token, amount, destination, and input and output
identifiers.

```text theme={null}
# A signature consists of the point R and scalar s.
e = H(DOMAIN_SCHNORR_CHALLENGE, R.x, R.y, ak.x, ak.y, digest)

# Verification equation:
s * G == R + e * ak
```

Producing that authorization requires the corresponding spending key
`zsk`, while verifying it requires only `ak`. The signer forms the response
as `s = signing_nonce + e * zsk` modulo Grumpkin's group order, with
`R = signing_nonce * G`. The circuit receives the signature, not `zsk`. The software
signer derives its signing nonce using a separate secret
`rsk = H(zsk, DOMAIN_RSK)`. This is part of the signer's secret key material.
Exposing it can also compromise the spending key.

Knowing `ivk` lets someone reconstruct addresses and decrypt payment memos.
It does not let them forge the spending authorization checked by the
circuit. A proving service with `ak` and `nk` can build the proof, but still
needs a signature produced with the spending key. The circuit checks the address and
signature relationships without recomputing the wallet's secret derivations
from `zsk`.

## Payment addresses

A payment request pairs the recipient's diversified address with the VASP
responsible for resolving the payment. It also carries that VASP's registry
index, a request expiry, and asset-specific thresholds indicating when the VASP
expects a Travel Rule record. The recipient VASP signs these fields with its
registered messaging key. The recipient shares the signed request with the
sender offchain.

Before preparing the payment, the sender checks that the request's VASP
identifier matches the admitted institution at the named registry index,
verifies its signature with that institution's messaging public key, and checks
the expiry. These checks run offchain and establish that the VASP issued the
request for this address.

Initiation binds the chosen recipient VASP to the payment. At resolution, the
policy-wrapper proof requires that VASP's signature and registered policy.
The recipient proof separately checks that the incoming viewing key derives
the address receiving the note. Customer identity and the VASP's relationship
with that customer are managed offchain.

## Delegating capabilities

Sharing the incoming viewing key lets a scanner find and read incoming
payment memos without authorizing spends. The scanner also needs access to the
encrypted memos. The key lets it recognize and decrypt memos
addressed to any diversified address generated from that key.

A scanner can recognize incoming notes but cannot identify their spends from
`ivk` alone. A viewing capability adds the nullifier key to identify spends
of known notes. It uses `ivk` and `nk` together with the corresponding note
data and leaf indices. A wallet can delegate this capability for regulatory
viewing, but the pool does not automatically grant it to the MIP410 authority
or enforce its delivery. It grants no authority to spend notes or redirect value.

Travel Rule records and institutional identifiers travel in a separate
encrypted payload addressed to the recipient VASP's messaging key. Delegating
`ivk` does not grant access to that payload.

Preparing a proof requires the spend-verification key as well. A proving
service uses the spend-verification key and nullifier key to build sender and
unshield proofs. Together, those keys also derive the incoming viewing key
and identify spends of known notes. Each spend still requires authorization from
the spending key. The service cannot substitute a different payment for the one
authorized.

A fresh diversified address does not restrict an existing viewing-key
holder's access. The same incoming viewing key recognizes payments across
all its addresses. Addresses derived from independent incoming viewing keys
have separate viewing scopes.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.