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

Anthony Towns aj at erisian.com.au
Fri Nov 2 03:19:45 UTC 2018

On Fri, Nov 02, 2018 at 10:20:46AM +1030, Rusty Russell wrote:
>         There's been some discussion of what the lightning payment flow
> might look like in the future, and I thought I'd try to look forwards so
> we can avoid painting ourselves into a corner now.  I haven't spent time
> on concrete design and implementation to be sure this is correct,
> however.

I think I'd like to see v1.1 of the lightning spec include
experimental/optional support for using secp256k1 public/private keys
for payment hashes/preimages. That assumes using either 2-party ECDSA
magic or script magic until it's viable to do it via Schnorr scriptless
scripts, but that seems like it's not totally infeasible? I think the
components would need to be:

 - invoices: will the preimage for the hash be a secp256k1 private key
   or a sha256 preimage? (or payer's choice?)
 - channel announcements: do you support secp256k1 for hashes or just
 - node features: how do you support secp256k1? not at all (default),
   via 2p-ecdsa, via script magic, (eventually) via schnorr, ...?

I think this is (close to) a necessary precondition for payment
decorrelation, AMP, and third-party verifiable proof-of-payment.

> Desired Status
> --------------
> Ideally, you could create one invoice which could be paid arbitrary many
> times, by different individuals.  eg. "My donation invoice is on my web
> page", or "I've printed out the invoice for a widget and stuck it to the
> widget", or "Pay this invoice once a month please".
> Also, you should be able to prove you've paid, in a way I can't just
> copy the proof and claim I paid, too, even if I'm the merchant, and that
> you agreed to my terms, eg. "I'm paying for 500 widgets to be shipped to
> Rusty in Australia".

So, I think at a high level the logic here goes:

  1. Alice: "Buy a t-shirt from me for $5!"
  2. Bob: "Alice, I want to buy a t-shirt from you, here's $5"
  3. Alice: "Receipt: Bob bought a t-shirt from me"
  4. Bob: "Your Honour, here's my receipt from Alice for a t-shirt, please
     make her deliver on it!"

Going backwards; for the last step to be useful, the receipt has to be
a signature with the Alice's public key -- if it were anything short of
that, Alice will claim Bob could have just made up all the numbers. For a
Schnorr sig, that means (R,s) with the vendor choosing R and not revealing
R's preimage as that would reveal their private key.

If both vendor and customer know R, then to get the signature, you need
the private key holder to reveal s which is just revealing the secp256k1
private key corresponding to S, calculated as:

    S = R + H(P,R,"Bob bought a $5 t-shirt from me")*P

where P is Alice's public key. If R is calculated via the Schnorr BIP's
recommendation, then r = H(p, "Bob bought a $5 t-shirt from me") -- ie,
based on the private key and the message being signed.

Even if you calculate r differently, I don't think you can do this
without Bob and Alice interacting to get the nonce R prior to sending
the transaction, which seems effectively the same as having dynamic
invoice hashes, though.

Maybe querying for a nonce through the lightning network would make
sense though, which would allow the "invoice" to be static, and all the
dynamic things would be via lightning p2p? That step could perhaps be
combined with the 0 satoshi payment probes that Fabrice proposes in


but I think replying with a public nonce value would need a new message
type of some sort?

I think AMP is independent, other than also using secp256k1 preimages
rather than SHA256. I think AMP splits and joins are just:

 - if you're joining incoming payments, don't forward until you've
   got all the HTLCs, and ensure you can generate the secret for each
   incoming payment from the single outgoing payment

 - if you're splitting an incoming payment into many outgoing payments,
   ensure you can claim the incoming payment from *any* outgoing
   payments' secret

Which I think in practice just means knowing x_i for each input, and
y_j for each output other than the first, and verifying:

    I_i = O_1 + x_i*G
    O_j = O_1 + y_j*G

(this gives I_i = O_j + (x_i-y_j)*G and the corresponding secret being
i_i = o_j + x_i - y_j) allowing you to claim all incoming HTLCs given
the secret from any outgoing HTLC)


More information about the Lightning-dev mailing list