# Exploring Payment Proofs for invoice flow

**URL:** <https://forum.grin.mw/t/exploring-payment-proofs-for-invoice-flow/7873>\
**Category:** Development and Technical Discussion\
**Created:** [October 1, 2020, 12:57pm UTC](https://forum.grin.mw/t/exploring-payment-proofs-for-invoice-flow/7873 "2020-10-01T12:57:59Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![tromp](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.grin.mw/tromp/32/22_2.png) [@tromp](https://forum.grin.mw/u/tromp)\
**Post date:** [October 1, 2020, 12:57pm UTC](https://forum.grin.mw/t/exploring-payment-proofs-for-invoice-flow/7873/1 "2020-10-01T12:57:59Z")

</div>

The payment proofs RFC at

> <https://github.com/mimblewimble/grin-rfcs/blob/22d3835de1ec816de765c29ea4c3b5559d86a1b6/text/0000-payment-proofs.md>

states payment proofs for invoices as an Unresolved question.  
In the invoice transaction building flow we have

1. receiver sends her public nonce and excess
2. sender sends back his public nonce and excess, and other stuff including a partial kernel signature
3. receiver computes their partial kernel signature and finalizes

The payment proof is a signed statement that the receiver accepts the on-chain confirmation of a specific kernel as proof of payment of a specific amount by a specific sender.

The receiver doesn’t know the kernel yet in step 1, as the kernel excess depends on the sender excess sent in step 2. So for the sender to withhold payment until they have a payment proof would require two extra rounds, if we want the receiver to finalize (for which there are good reasons):

1. receiver sends her public nonce and excess
2. sender sends back his public nonce and excess
3. receiver sends payment proof
4. sender sends other stuff including a a partial kernel signature
5. receiver computes their partial kernel signature and finalizes

This is obviously undesirable. So the question is if we can come up with a payment proof that can be sent in round 1, depending only on the receiver nonce R\_r and excess X\_r.

Recall that in step 3, the receiver produces a partial signature (s\_r, R\_r) that satisfies

s\_r \* G = R\_r + e \* X\_r

where e is the hash challenge H((R | X | …) .

What if the receiver accepts, as proof of payment of a specific amount by a specific sender, any pair (s\_r, i) where i is the index of an on-chain kernel whose hash challenge e satisfies the above equation?

No one should be able to present this information unless the receiver made her partial signature, and the resulting transaction hit the chain.

---

<div class="post-metadata">

**Author:** ![david](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.grin.mw/david/32/660_2.png) [@david](https://forum.grin.mw/u/david)\
**Post date:** [October 1, 2020, 1:16pm UTC](https://forum.grin.mw/t/exploring-payment-proofs-for-invoice-flow/7873/2 "2020-10-01T13:16:28Z")

</div>

Don’t we already have a potential solution here: [https://github.com/DavidBurkett/grin-rfcs/blob/eliminate\_finalize/text/0000-eliminate-finalize.md#building-the-proof](https://github.com/DavidBurkett/grin-rfcs/blob/eliminate_finalize/text/0000-eliminate-finalize.md#building-the-proof)

At a technical level, the RFC is roughly just a switch to invoices with the addition of payment proofs and some UX tweaks to reduce the number of steps (this is a loaded word, so don’t read too much into it).

As far as I know, the scheme (developed by kurt, which I simplified when including in the RFC) hasn’t been shown to be insecure. The only thing that was found to be insecure was the separate idea, discussed in the comments, which involved modifying the actual signature scheme.

---

<div class="post-metadata">

**Author:** ![tromp](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.grin.mw/tromp/32/22_2.png) [@tromp](https://forum.grin.mw/u/tromp)\
**Post date:** [October 1, 2020, 1:50pm UTC](https://forum.grin.mw/t/exploring-payment-proofs-for-invoice-flow/7873/3 "2020-10-01T13:50:43Z")

</div>

It’s quite similar to your proposal, but much closer to the existing payment proofs, as the payment info is signed by the ed25519 key.

I find yours harder to reason about, since it puts the payment info into a proof\_nonce that gets added to the existing sender and receiver nonce.

For instance, when you say

1. Show that `sender.public_nonce + receiver.public_nonce + (proof_nonce * G)` = `total_nonce * G` (ie. the `k*G` in the kernel signature)
2. Provide the preimage to `proof_nonce` ( `sender.public_nonce | receiver.address | tx.amount` )

it appears that the pair of sender.nonce and proof\_nonce is malleable until one notices the proof\_nonce depending on the sender nonce.

---

<div class="post-metadata">

**Author:** ![Kurt](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.grin.mw/kurt/32/3361_2.png) [@Kurt](https://forum.grin.mw/u/Kurt)\
**Post date:** [October 1, 2020, 2:14pm UTC](https://forum.grin.mw/t/exploring-payment-proofs-for-invoice-flow/7873/4 "2020-10-01T14:14:46Z")

</div>

I don’t care anymore about \> 2-step txs, and i would hope leaders of the coin and technical people here do too (some like David, made a lot of efforts for this, including the great idea for 2 steps). It is just the expression of striving for the better for the user, rather than accepting a text-book and useless status quo.

---

<div class="post-metadata">

**Author:** ![oryhp](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.grin.mw/oryhp/32/2923_2.png) [@oryhp](https://forum.grin.mw/u/oryhp)\
**Post date:** [October 4, 2020, 6:57pm UTC](https://forum.grin.mw/t/exploring-payment-proofs-for-invoice-flow/7873/5 "2020-10-04T18:57:46Z")

</div>

> [@tromp](#):
>
> So the question is if we can come up with a payment proof that can be sent in round 1, depending only on the receiver nonce R\_r and excess X\_r.

I think the main idea behind the payment proofs described in this document could be used. The idea is that `Kr` has a structure such that it commits to a few things, including the `amount` and the `receiver_pub_key`.

> <https://gist.github.com/pkariz/9da5c3decffba0661a11f49c645b966e>

---

<div class="post-metadata">

**Author:** ![vegycslol](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.grin.mw/vegycslol/32/3340_2.png) [@vegycslol](https://forum.grin.mw/u/vegycslol)\
**Post date:** [October 4, 2020, 10:26pm UTC](https://forum.grin.mw/t/exploring-payment-proofs-for-invoice-flow/7873/6 "2020-10-04T22:26:27Z")

</div>

I like the simplicity of your invoice solution, seems pretty easy to reason about:

1. only the sender can know sr since only he knows ss
2. only the sender can know Rr since only he knows Rs
3. only the sender can know Xr since only he knows Xs

Ofc the receiver also knows the above stuff.

My solution is a bit more complicated and therefore harder to reason about. It has a nice property though in that both the receiver and the sender can prove it in the same way + the payment proof when the other party finalizes the transaction is symmetric. I haven’t thought much about your solution but it feels like yours is also symmetric (or even better, the same), so when the sender finalizes it he can provide (sr, i) + signed message. Is that correct? I know we have payment proofs for that flow but am just wondering if that holds.

Another question: why do you use i and not R or K to reference the kernel?

---

<div class="post-metadata">

**Author:** ![tromp](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.grin.mw/tromp/32/22_2.png) [@tromp](https://forum.grin.mw/u/tromp)\
**Post date:** [October 5, 2020, 8:35am UTC](https://forum.grin.mw/t/exploring-payment-proofs-for-invoice-flow/7873/7 "2020-10-05T08:35:24Z")

</div>

> [@vegycslol](#):
>
> I haven’t thought much about your solution but it feels like yours is also symmetric (or even better, the same)

When sender initiates, then the receiver can send the exact same payment proof (that they send in round 1 of invoice flow) in round 2 instead. That is, an ed25519 signature on payment info, receiver public nonce and excess, to be witnessed by a pair (sr,i).

> [@vegycslol](#):
>
> Another question: why do you use i and not R or K to reference the kernel?

Because specifying K takes more bytes and the first thing a verifier would do is lookup K in the kernel MMR to find its index and check that it has sufficient confirmations. So we might as well provide the index directly.
