How to do Payment proofs following the original proposal (not the “reverse” one, which has easier payment proofs):
Due to the fact that it is the receiver that finally broadcasts the transaction, the traditional payment proof cannot be performed in this proposal. Here is a proposed solition:
Set up:
- Grin users have a base secp256k1 public key that is used when they receive transactions, call it
B. Call the associate private keyb - Grin’s senders of transactions generate an ephemeral secp256k1 key when they send a transaction: call it
S, and letsbe the associated private key.Sis to be sent by the sender in the slatepack for the receiver to gain knowledge of it to finalize the transaction.
Protocol:
Let’s call c the Diffie-Hellman secret, which can be computed by the sender and the receiver only:
c = Hash(s.B) = Hash(b.S).
Now, the receiver’s partial nonce R_b could be derived by the following formula:
R_b = c.G + B. That would work well for building the transaction, but we will modify this a bit in order to enable payment proofs.
Let’s define x = Hash(c||B||tx_amount||timestamp). And we actually define R_b by the following formula instead:
R_b = x.G + B.
Only the receiver knows the private key of R_b since only him knows the private key of B.
Define by R_a being the sender’s partial nonce, and by R being the total nonce: R = R_a + R_b.
R is going to be onchain data. The receiver, in David’s scheme, cannot trick everyone and use a different partial nonce since the sender has committed to R when creating his partial signature already.
How can the sender prove payment?
He can do that by doing the three following things:
- Prove knowledge of the secret key to
R_a - Show that
R - R_a = x.G + B - Provide the preimage to
x(and toc).
The sender has successfully proven that he sent tx_amount coins at time t = timestamp to the owner of the public key B.