From cjp at ultimatestunts.nl Tue Jun 13 19:28:03 2017 From: cjp at ultimatestunts.nl (CJP) Date: Tue, 13 Jun 2017 21:28:03 +0200 Subject: [Lightning-dev] Composing a transaction of many small transactions Message-ID: <1497382083.2344.55.camel@ultimatestunts.nl> Hi, ======= Problem ======= One major vulnerability of the Lightning network is that, if someone wants to perform a DoS attack on the network, that possible for the attacker by sending many large transactions to himself, over a long route, and letting them time out (never reveal the payment pre-image). Nobody (including the attacker) gains or loses any funds, but a lot of funds get locked up, and the total cost of lost opportunity to innocent nodes is a lot higher than that of the attacker. In Milan, we came to a solution for this DoS mode, where nodes require either a fast commit or roll-back within a short amount of time (say 30 seconds), or a proof that another channel was closed. This increases the cost for the attacker with the cost of closing a channel. I've always disliked this approach a bit, since a "proof that another channel was closed" can only be accepted by other nodes in the route if all those nodes can understand such proof; this means that if a route hops over channels on different block chains (e.g. alt coins or side chains), or different channel designs, some nodes have to understand all these varieties. This limits freedom of node pairs to join the network with new / unusual channels in a useful way. So far, I had accepted this, as the DoS-protection really seemed necessary. ================ Another approach ================ Last week, Michiel de Jong (CC'ed) presented Interledger at a local cryptocurrency meet-up here in Delft. Since Interledger's core feature is the routing between different 'ledgers' (including block chains, but also banks), using HTLCs on different hops in the same way as Lightning, I asked him how they were planning to avoid this DoS mode. His answer was basically that transactions were being sent in really small parts at a time, so that, at any given point in time, only a small amount would be locked. If it turns out to be locked for a long time, that would not be a problem since it's only a small amount. I suggested that, if you do transactions this way, you might as well just add the locked amount to the channel transaction fee, and thereby avoid the complexity of the HTLC. ============= Will it work? ============= Initially, my concern with splitting a tx into many small parts was that it creates the possibility that only a part of the funds gets transferred. I now think that, in most cases, that will not be an issue, since usually a certain amount of trust is already required between the endpoints of a transaction, e.g. when you pay for physical goods, you have to trust they will be delivered. Based on the same trust, the endpoints of the transaction can cooperate to resolve the situation, e.g. with an attempt to refund through Lightning, or by paying through a new channel. But: does this really resolve the DoS attack mode? I suppose that, after locking funds in one small transaction, an attacker can easily lock funds in another small transaction, and so on; in the end locking up the same amount of funds for the same amount of time as in the original attack. Once you detect that one small transaction doesn't unlock, you have to somehow stop all subsequent transactions from the attacker. If, on a channel-level, you just say "I'll no longer accept any new transactions as long as one transaction keeps being locked", I think you'll end up worse: it will allow an attacker to disable entire channels (potentially very high-capacity channels) with very small attack funds, for all users, for the same lock time. So, to prevent this, you have to distinguish the attacker from regular users; this is difficult in a network where the identity of source and destination are protected , e.g. by Sphinx routing. **Maybe this is where Lightning and Interledger are different? I don't know enough about Interledger.** ========== Solutions? ========== Maybe this can be resolved by requiring nodes to "unwrap the onion" in case of a transaction that stays locked for too long? This would be mostly useful towards the payee, since the payee side is responsible for either showing the hash pre-image, or voluntarily canceling the transaction. This could identify the "closest non-cooperating node" in the route, but it wouldn't prevent the next locked transaction, since you can't see in advance where an onion-routed transaction is going. The next thing you could say is "the last cooperating node in the route (a direct neighbor of the closest non-cooperating node) is no longer allowed to forward payments through the non-cooperating node". Instead, he has to immediately roll back any transaction that is aimed in that direction. If the otherwise cooperative node fails this rule, you mark it as non-cooperative; the next time, the second-last cooperating node is no longer allowed to forward payments through that node. This may continue a couple of times, until a truly cooperative node follows all the rules, and attacker transactions are canceled in a fast an efficient manner by that node. This might work if there is only a single route on the network (line-shaped network), but I'm afraid an attacker can significantly delay being blocked, by creating a part of the network under his own control, which has at least one "cooperating" node as gateway, followed by large numbers of non-cooperating nodes, which are continuously being replaced once old ones are being flagged as non-cooperating. Also, it could force Lightning nodes to keep very large lists of which nodes have to block which of their neighbors. Do you have any thoughts on this? CJP PS. I couldn't find anything related to this in the Lightning RFC: https://github.com/lightningnetwork/lightning-rfc