Payment Proofs
- Title: payment-proofs
- Authors: David Burkett
- Start date: Nov 05 2019
- RFC PR: mimblewimble/grin-rfcs#31
- Tracking issue: mimblewimble/grin-wallet#230
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 thereceiver_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
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:
- Ensure the
kernel_commitment
is confirmed on-chain. - Verify that the
receiver_address
belongs to the payee. - Verify that the
receiver_signature
is valid. - 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.