blockchain / thunder

Off-Chain Bitcoin payments using smart contracts
https://blockchain.com/thunder
GNU Affero General Public License v3.0
561 stars 175 forks source link

Designing addresses in thunder #30

Open matsjj opened 8 years ago

matsjj commented 8 years ago

Addresses in LN

So far thunder nodes have been quite altruistic when relaying payments. That is, they would not dare to take a payment, even though they perfectly could. I am talking about the fact that nodes can claim any payment if they know the preimage of the secret hash of the payment (known as R-value). R is the only thing that makes lightning technology works, it's the only incentive to relay a payment. Once a payment has been redeemed, the secret preimage of R has been revealed to all hops of the route. Making another payment with the very same R means that any of the nodes can now just take the payment instead of relaying it.

In 0.1 of thunder, nodes always relayed a payment, which was very convenient for trying around with the wallet. Addresses are still just hex-representations of R-value+Pubkey, and sharing a new one for each payment is not very handy. With 0.2, nodes will look up if they know the R-value already, and claim every payment they possibly can. This will reinforce a very important aspect of LN technology - DON'T REUSE R-VALUES.

As a matter of fact, users love reusable addresses though. And there are some use cases, where there is no alternative either (my favourite example is the Ukraine protestor holding up a QR image). So what are our options?

P2LPKR (Pay-to-Lightning-Public-Key-with-R)

Just to reiterate what is going on behind the scenes right now. The address contains

- 20B hash - 33B compressed public key The sender then uses the public key to compute a route to the receiver and starts the payment with the given R value. This type of address is NOT reusable, as the sender uses the same R value all the time. In fact, the wallet software should prevent making another payment with the same R value as soon as one payment has been sent. There are also privacy and routing issues with both, P2LPKR and P2LPK (see below). ## P2LPK (Pay-to-Lightning-Public-Key) Okay, so this is probably the simplest solution. The receiver just publishes the public key of his node on the network, and the sender can use routing to find a suitable path of hops. The address only contains - 33B compressed public key It would also be possible to truncate the key in any way, as long as the sender can find the corresponding public key in its database (e.g. only use the first 20B, as its sufficiently unique). The sender then calculates an R-value of his choice and uses DH to calculate a shared secret between an ephemeral key of his and the public key of the receiver. He encrypts the preimage of R with that shared secret and sends the ephemeral public key and the encrypted preimage together with the payment. One way of doing that would be to include it in the _heart_ of the onion object (which is just a blob that could be used to send any message). That kind of address would be reasonable short and it could be reused without any restrictions. However, there are problems when it comes to privacy. The sender would still know who the final receiver of the payment is, which might not be desirable. It also does not solve our routing problem, as the sender needs to know the complete network topology including all wallets to be able to route the payment. A last problem with this kind of address is that there is no way to proof a payment. With P2LPKR one can construct a cryptographic contract, saying 'if you can produce the preimage of the following R-value , it means you paid me $50'. This is inherently impossible with P2LPK, as the sender chose the R-value. The only thing the sender can prove after making the payment, is that someone claimed a payment using an R value. But there is no way to prove that it is the owner of the public key who did it. (He might have routed the payment through his own node, which he shared the preimage with?) ## P2LRPR (Pay-to-Lightning-Rendezvous-Point-with-R) To solve the privacy and routing issues described above, it is also possible that the receiver sends the last N hops of a route towards him in encrypted form to the sender. The sender then only knows some intermediate node of the payment, he will construct an onion object directed towards this node and then put the encrypted route he got from the receiver into it. Basic example: A <-> B <-> C <-> D <-> E E wants to receive a payment from A, but he does not want to reveal his identity (that is, his public key). He figures that if A only knows that E is in the neighbourhood of C, that serves him sufficient privacy. So he creates the route C -> D -> E and the corresponding onion object C-nodekey || C-ephemeralkey || C-encrypted ( D-nodekey || D-ephemeralkey || D-encrypted ( E-nodekey )) which is constructed in a way that only allows each hop to see the direct next hop (so C knows that it should relay to D, and D knows that it should relay to E, but C does NOT know that D should relay to E). He then sends this blob of data to A, who can include it into his onion object B-nodekey || B-ephemeralkey || B-encrypted ( ) For this type of payment, the receiver still sends the R-value that he expects for the payment. The address then contains - 20B hash - 86B*N blob 86B is the minimum we can achieve per hop of the onion object if we do not include any additional data. (33B ephemeral-key used for DH, 33B public key of next hop, 20B HMAC, even though we could technically scrap a few B off of the public key using some determinist way and let each node look the correct node up in their database) This payment type solves the privacy and routing issue, as the sender only needs to know the route towards some 24/7 online node, and not towards some guys LN-wallet, that might only be online once a week. It is still only usable once, as it got the R value hardcoded into it. ## P2LRP (Pay-to-Lightning-Rendezvous-Point) Because the receiver dictates the core of the onion object, we cannot use that anymore to save the preimage of the R-value. (We would corrupt the onion object by just changing bytes somewhere at the end, as the HMAC would not match up anymore) An alternative is to send the encrypted R-value along the onion object in a separate data structure that each node has to relay. There are some possibilities about how to send it, with various complexity. For example the address could just be - ephemeral public key - RP-routing-blob The sender will create a new ephemeral key for each payment, create a shared secret and use it to derive a preimage and ultimately the R-value. He then just sends his ephemeral key along the payment, such that the receiver can go through the same process and calculate the preimage. The problem with that is that a payment is now identifiable as one payment by both, the R-value of the payment AND the ephemeral key. ## Remarks about payment amount We need some way of safely transporting information about the amount from either receiver->sender or sender->receiver. The receiver needs to know how big of a payment to expect. Otherwise, any node in the route can just take whatever amount he wants, as long as the receiver reveals R in the end. But when the receiver knows exactly how big the payment should be, he can refuse to reveal R, letting the payment refund. That is why thunder addresses currently contain the expected amount. In a further step, we will put the amount each node can expect to receive and each node should relay into the onion object. The receiver of the payment can be sure that the onion object has not been tinkered with, and it allows for tamper-proof transportation from sender of the payment to the receiver. ## Address encoding Another hot topic is how to encode the blobs of data we need to send from the receiver to the sender. Depending on the type of payment chosen, we either end up with 20B (truncating a public key) or with >300B for a 4-hop P2LRP address. A common complaint about B58 is that its very difficult to audio transcribe. However, I think that RP-addresses will be the dominant address type soon, and with >100B in their most basic form they are already very difficult to transcribe manually. Unless others have a good reason to abandon B58 encoding, we should stick with it for LN.
Gorislim13 commented 6 years ago

Help me fix it