Support generating and validating payment proofs for sender-initiated (i.e. non-invoice) transactions.
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.
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.
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
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
sender_signature can be generated for
(amount || kernel_commitment || sender_address) using the private key of the
Sender will then create and store the following info, which can be considered the complete
Sizes of each corresponding field
sender_address will occuppy 32 bytes under assumption of being stored as ed25519 public keys.
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:
- Ensure the
kernel_commitmentis confirmed on-chain.
- Verify that the
receiver_addressbelongs to the payee.
- Verify that the
- Verify that the
As part of the first step of the tx-building process, the sender/payer generates the
sender_address using their keychain.
receiver_address and keychain path of the
sender_address must be stored locally, along with the
receiver_address will then be added to the
payment_proof structure of the slate.
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.
slate_id, the sender can retrieve the original
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.
payment_info details have been validated, the sender can generate and store the
Generating Proofs above), and then finalize the transaction as normal.
- 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.
- 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.
- Can this be adapted to work for invoices?
- Payment proofs could potentially be added to invoice payments in the future, but at the cost of an additional round of communication.