Skip to content

Payment Proofs

Summary

Support generating and validating payment proofs for sender-initiated (i.e. non-invoice) transactions.

Motivation

Bitcoin and other cryptocurrencies with transparent protocol-level addressing and immutable, unprunable blockchains can prove sender, receiver, and amounts of payments simply by pointing to the transaction in the blockchain. Grin's privacy and scalability means users no longer have this ability. This prevents some merchants from accepting Grin due to the high possibility of payment disputes that are unresolvable in the same way they are for transparent coins.

This RFC changes the transaction building process where payers can require payees to create a "proof" they've received a payment before the payer finalizes and broadcasts the transaction.

Community-level explanation

From an end-user perspective, payers can require payees to prove receipt of funds as part of the transacting process. Payers can then use these "proofs" to resolve payment disputes and prove they sent funds to the correct payee.

Reference-level explanation

Slate changes

A new (optional) structure (payment_info) will be added to transaction slates, along with a version increase. The payment_info structure will contain:

  • sender_address - An ed25519 public key generated by the sender.
  • receiver_address - An ed25519 public key for the receiver, typically the public key of the user's v3 onion address.
  • receiver_signature - A signature of the sender_address, received amount, and kernel commitment that validates against the receiver_address.

Generating proofs

Receipt confirmations (receiver_signature) will be generated by the payee by providing an ED25519 signature of: (amount || kernel_commitment || sender_address), using the private key of the receiver_address.

The sender_signature can be generated for (amount || kernel_commitment || sender_address) using the private key of the sender_address.

Sender will then create and store the following info, which can be considered the complete payment_proof:

  • receiver_address
  • receiver_signature
  • amount
  • kernel_commitment
  • sender_address
  • sender_signature

Sizes of each corresponding field

Field Size
amount 8 bytes
excess 33 bytes
recipient_address 32 bytes
recipient_sig 64 bytes
sender_address 32 bytes
sender_sig 64 bytes

The fields recipient_address and sender_address will occuppy 32 bytes under assumption of being stored as ed25519 public keys.

Verifying Proofs

This payment_proof can be provided by the sender at any time to convince a payee that a payment was made to them. The proof can be verified as follows:

  1. Ensure the kernel_commitment is confirmed on-chain.
  2. Verify that the receiver_address belongs to the payee.
  3. Verify that the receiver_signature is valid.
  4. Verify that the sender_signature is valid.

Wallet actions

init-send

As part of the first step of the tx-building process, the sender/payer generates the sender_address using their keychain.

The receiver_address and keychain path of the sender_address must be stored locally, along with the slate_id.

The sender_address and receiver_address will then be added to the payment_proof structure of the slate.

receive

If the payment_proof structure exists on the slate, it is mandatory that the receiver_signature is generated and added to the slate as part of the receive tx-building step.

finalize

Using the slate_id, the sender can retrieve the original sender_address and receiver_address that were included in the slate, and verify that those fields remain unchanged. The sender must then validate the receiver_signature. If any of the original payment_proof slate fields were modified, or if the receiver_signature is invalid, the transaction must be rejected by the sender.

Once the payment_info details have been validated, the sender can generate and store the payment_proof (See Generating Proofs above), and then finalize the transaction as normal.

Drawbacks

  • Increases the size of tx slates.
  • Possibility of privacy leakage through address reuse.

Rationale and alternatives

  • This design works well with TOR tx building, yet is generic enough to work with all known transacting mechanisms.

Prior art

  • Wallet713 implements payment proofs for grinbox transactions, which our design adapts and builds on to work more seemlessly with onion addresses and with transaction building methods that don't inherently rely on addresses.

Unresolved questions

  • Can this be adapted to work for invoices?

Future possibilities

  • Payment proofs could potentially be added to invoice payments in the future, but at the cost of an additional round of communication.

References