Currently, it's not possible for the sender of a Spark transaction to recover certain transaction information unless it caches coin nonces locally. This information includes recipient addresses and memos. It's possible to include this in a way that would ensure senders can obtain these details when restoring a wallet, and would also simplify payment proofs significantly.
One approach would be to encrypt coin nonces and recipient addresses (without the encrypted diversifier) using a key derived from coin public data and the sender's full view key.
For full view key component s_2 and coin serial commitment, S, we can define the disclosure key k_disc = KDF(s_2, S) for a key derivation function KDF. Given a stream cipher keyed with k_disc, the sender encrypts the tuple (k, Q_1, Q_2). Here k is the coin nonce and Q_1, Q_2 are two of the components of the recipient address.
When the user wishes to restore a wallet or otherwise scan using the full view key, it uses the full view key already to derive incoming coin linking tags, which are used to determine when the coin is later spent. On such detection of a spend, the user would derive k_disc and use it to decrypt the tuple. It then uses k and Q_1 to derive the recipient AEAD key k_aead and decrypt the recipient data, which includes the coin memo m, the value v, and the component d of the recipient address.
When the user wishes to produce a payment proof, it follows the approach in the Spark preprint. However, it no longer sends the tuple (k, d, Q_1, Q_2) with the proof; instead, it sends k_disc. Since this key is derived from the user's full view key uniquely using a KDF, this does not leak information about other coins. The verifier uses the key to decrypt (k, Q_1, Q_2), and then continues with proof verification as usual.
Encryption of this additional data can use a fixed (zero) initialization vector and does not require an authentication tag, so encryption using a stream cipher means each coin requires an additional 96 bytes of data included. While the sender could provide a payment proof verifier with a different key than k_disc and obtain different (k, Q_1, Q_2), payment proof security guarantees still apply and cannot be used to fool the verifier.
Currently, it's not possible for the sender of a Spark transaction to recover certain transaction information unless it caches coin nonces locally. This information includes recipient addresses and memos. It's possible to include this in a way that would ensure senders can obtain these details when restoring a wallet, and would also simplify payment proofs significantly.
One approach would be to encrypt coin nonces and recipient addresses (without the encrypted diversifier) using a key derived from coin public data and the sender's full view key.
For full view key component
s_2and coin serial commitment,S, we can define the disclosure keyk_disc = KDF(s_2, S)for a key derivation functionKDF. Given a stream cipher keyed withk_disc, the sender encrypts the tuple(k, Q_1, Q_2). Herekis the coin nonce andQ_1, Q_2are two of the components of the recipient address.When the user wishes to restore a wallet or otherwise scan using the full view key, it uses the full view key already to derive incoming coin linking tags, which are used to determine when the coin is later spent. On such detection of a spend, the user would derive
k_discand use it to decrypt the tuple. It then useskandQ_1to derive the recipient AEAD keyk_aeadand decrypt the recipient data, which includes the coin memom, the valuev, and the componentdof the recipient address.When the user wishes to produce a payment proof, it follows the approach in the Spark preprint. However, it no longer sends the tuple
(k, d, Q_1, Q_2)with the proof; instead, it sendsk_disc. Since this key is derived from the user's full view key uniquely using a KDF, this does not leak information about other coins. The verifier uses the key to decrypt(k, Q_1, Q_2), and then continues with proof verification as usual.Encryption of this additional data can use a fixed (zero) initialization vector and does not require an authentication tag, so encryption using a stream cipher means each coin requires an additional 96 bytes of data included. While the sender could provide a payment proof verifier with a different key than
k_discand obtain different(k, Q_1, Q_2), payment proof security guarantees still apply and cannot be used to fool the verifier.