[Lightning-dev] BOLT11 In the World of Scriptless Scripts

Rusty Russell rusty at rustcorp.com.au
Sun Nov 4 03:00:48 UTC 2018

Anthony Towns <aj at erisian.com.au> writes:
>> >  - channel announcements: do you support secp256k1 for hashes or just
>> >    sha256?
>> Worse, it becomes "I support secp256k1 with ECDSA" then a new "I support
>> secp256k1 with Schnorr".  You need a continuous path of channels with
>> the same feature.
> I don't think that's correct: whether it's 2p-ecdsa, Schnorr or script
> magic only matters for the two nodes directly involved in the channel
> (who need to be able to understand the commitment transactions they're
> signing, and extract the private key from the on-chain tx if the channel
> gets unilaterally closed). For everyone else, they just need to know that
> they can put in a public key based HTLC, and get back the corresponding
> private key when the HTLC goes through.

I'm not sure.  Jonas Nick proposed a scheme, which very much assumes
Schnorr AFAICT:

Jonas Nick wrote:
> How I thought it would work is that the invoice would contain a
> Schnorr nonce R. Then the payer would construct s*G = R +
> H(payee_pubkey,R,"I've bought 5 shirts shipped to Germany")*G. Then
> the payer builds the scriptless script payment path such that when the
> payee claims, the payer learns s and thus has a complete
> signature. However, that doesn’t work with recurrent payments because
> the payee can use the nonce only once.

I would probably enhance this to include a nonce, which allows for AMP
(you have to xor the AMP payments to get the nonce):

R + H(payee_pubkey,R,"I've bought 5 shirts shipped to Germany",NONCE)*G

> I think it makes sense to think of proof-of-payment in terms of a
> verification algorithm (that a third party court could use), that takes:
>   m - the invoice details, eg
>       "aj paid $11 for stickers to be delivered to Australia"
>   P - the pubkey of the vendor
>   sig - some signature
> With the current SHA256 preimages, you can make sig=(R,s,pre)
> where the sig is valid if:
>   s*G = R + H(P,R,m+SHA256(pre))*P
> If you share R,s,SHA256(pre) beforehand, the payer can tell they'll have
> a valid signature if they pay to SHA256(pre). That's a 96B signature,
> and it requires "pre" be different for each sale, and needs pre-payment
> interactivity to agree on m and communicate R,s back to the payer.

For current-style invoices (no payer-supplied data), the payee knows
'm', so no interactivity needed, which is nice.

In the payer-supplied data case, I think 'm' should include a signature
for a key only the payer knows: this lets them prove *they* made the

How does this interact with AMP, however?

> With seckp256k1 preimages, it's easy to reduce that to sig=(R,s),
> and needing to communicate an R to the payer initially, who can then
> calculate S and send "m" along with the payment.

OK, I buy that.

> Maybe it makes sense to disambiguate the term "invoice" -- when you don't
> know who you might be giving the goods/service to, call it an "offer",
> which can be a write-once/accept-by-anyone deal that you just leave on
> a webpage or your email signature; but an "invoice" should be specific
> to each individual payment, with a "receipt" provided once an invoice
> is paid.

"offer" is a good name, since I landed on the same one while thinking
about this too :)

For an "offer" you would need a (lightning-network-carried) req/resp to
get the per-payment invoice.  An offer could use a 128-bit 'p': smaller
would do, but this is too large to brute-force iterate through (hey, I
wonder if they sell other stuff?).

> Rereading through the AMP threads, Christian's post makes a lot of sense
> to me:
> https://lists.linuxfoundation.org/pipermail/lightning-dev/2018-February/001023.html
> I'm not really seeing the benefits in complicated AMP schemes without
> decorrelation...

In practice it should increase reliability of payments through capacity
bottlenecks.  But don't underestimate the benefits of PoP: we're so used
to intermediates we take it for granted, but once the middleman is
removed the ability to prove the invoice/payment cycles is vital for

> It seems to me like there are three levels that could be implemented:
>  - laolu/conner: ("low AMP" ?)
>     works with sha256
>     some privacy improvement
>     loses proof-of-payment
>     can't claim unless all payments arrive


>  - just send multiple payments with the same hash:
>     works with sha256
>     privacy not improved much (some intermediary nodes no longer know
>       full invoice value)
>     can claim partial payments as soon as they arrive
>     accepting any partial payment provides proof-of-payment

Interestingly, if vendor takes part payment, rest can be stolen by
intermediaries.  This puts pressure on vendor to treat them atomically.
I haven't thought about this before, but it has desirable attributes.
(If the contract is "you will only release preimage once you've got the
payment", all this requires is a single bit to say "I know this is
partial, more are coming, please wait").

>  - secp256k1: ("high AMP" ?)
>     needs secp256k1 preimages
>     works fine with decorrelation improving privacy at every step
>     can set it up so can only claim once all partial payments arrive
>     accepting partial payment provides proof-of-payment

Yes.  Though I'm not sure exactly how this works with your scheme

> In theory, both "just send multiple payments" and "secp256k1" could have
> splitting and joining at any hop, if we could encode the instructions
> on how to do that in the onion message; joining is probably easy, but
> splitting seems like it might be hard?

I don't think so.  If you can join two payments, it wasn't private?  For
splitting, in the specific case of having two channels between the same
nodes, you might be able to do something, but that's a pretty narrow
case.  And as TCP discovered, you're better off failing back to sender
than trying to add fragmentation to the protocol.

Note: if we need an interaction message for BOLT11 features we want in
future[1], then it has the advantage that it decouples the bolt11
features from changing preimages to secp256k1.  That makes this question
*critical* for the Summit next week.


[1] If we're not careful we're going to implement HORNET so we can pass
arbitrary messages around, which means we want to start charging for
them to prevent spam, which means we reopen the pre-payment debate, and
need reliable error messages...

More information about the Lightning-dev mailing list