From rusty at rustcorp.com.au Sat Apr 30 10:11:34 2016 From: rusty at rustcorp.com.au (Rusty Russell) Date: Sat, 30 Apr 2016 19:41:34 +0930 Subject: [Lightning-dev] Clearing process in BOLT #2 In-Reply-To: References: Message-ID: <87wpnf5ru1.fsf@rustcorp.com.au> Pierre writes: > Hello, > > I see a few issues with the clearing process as currently described in BOLT #2. > > There seem to be a contradiction between: > ?4.1 "A node MUST respond with update_fail_htlc to any HTLC received > after it sent close_clearing." > and: > ?3.3 "There are three reasons for removing an HTLC: it has timed > out, it has failed to route, or the R preimage is supplied.") > ?3.3 "A node MUST check that id corresponds to an HTLC in its > current commitment transaction." Hi! Hmm, 4.1 should say: "A node must fail to route any HTLC received after it sent close_clearing". Basically, once you announce you're shutting down the channel, you don't accept any more routes. You could still receive them, because the other node might not have received your "close_clearing" yet. > In ?4.1, the node must decline/remove the still-uncommitted HTLC, > which is explicitely forbidden by ?3.3. That was not the intent of 4.1; all responses are delayed until receipt of `update_commit`. > AFAICT, in this version of the > procotol an HTLC can only be accepted, then committed, then removed. > There is no way to decline an HTLC, the receiver must always accept it > except when the sender doesn't have the money or there are two many > pending HTLC, in which case the connection should be failed (?3.2, > although it is actually not clear for the too-many-htlc case). It's the same with a node sending you an HTLC with too short a timeout or insufficient fee. There's no harm in you signing the *offer*; you're just not going to redeem it. Too-many-htlcs is a protocol violation, OTOH, and fail immediately. > We could decide to just fail the connection instead of declining the > htlc, but there is another issue: if the sender of a "close_clearing" > message subsequently receives an update_add_htlc, there is no way to > tell if the other party had received the close_clearing prior to > sending the htlc since update_add_htlc message doesn't have an 'ack' > field. Yes, this is why we don't have a "that HTLC will fail" message. We *could* add one, but it would be advisory only, and require the originator to send a "HTLC_UNADD" (?) message. Since failure should be an unusual case, I considered that a premature optimization. > There is potentially the same issue with the signature process: when > node A sends an update_commit message to B, it is expecting an > update_revocation rather sooner than later. But what if B just ignores > the update_commit message and keeps sending new htlcs ? There is no > way for A to be sure that B indeed received the update_commit, for the > same reason as above. The intent was that B can't get more than one step ahead. But I didn't say that explicitly. Patch below. B could ignore update_commit. But to make progess, at some point it has to send update_commit to A. Then A sends update_revocation. Now, B can keep sending more htlcs to A, but it *can't* send another update_commit, because you're not allowed to send it without receiving the previous update_revocation. So it has to ack it at that point. (My implementation never sends htlcs while waiting for an update_revocation, but it is explicitly legal, to allow more optimal pipelining). Here's the diff, I hope it clarifies. Thanks! Rusty. diff --git a/bolts/02-wire-protocol.md b/bolts/02-wire-protocol.md index e48aa1a..637bec1 100644 --- a/bolts/02-wire-protocol.md +++ b/bolts/02-wire-protocol.md @@ -484,6 +484,11 @@ staged changes, it generates the other node's commitment transaction with those A node MUST NOT send an `update_commit` message which does not include any updates. Note that a node MAY send an `update_commit` message which only alters the fee, and MAY send an `update_commit` message which doesn't change the commitment transaction other than the new revocation hash (due to dust, identical HTLC replacement, or insignificant or multiple fee changes). +A node MUST acknowledge the previous `update_revocation` (if any) in +the `update_commit` message. A node SHOULD fail the connection if it +receives an `update_commit` which does not acknowledge its previously +sent `update_revocation`. + A node MUST NOT send out a message with an `ack` field lower than any previous `ack` field. @@ -647,7 +652,7 @@ Either node (or both) can send a `close_clearing` message to initiate closing: A node MUST NOT send a `update_add_htlc` after a `close_clearing`, and must not send more than one `close_clearing`. A node SHOULD send a `close_clearing` (if it has not already) after receiving `close_clearing`. -A node MUST respond with `update_fail_htlc` to any HTLC received after it sent `close_clearing`. +A node MUST fail to route any HTLC added received after it sent `close_clearing`. ### 4.1.1. close_clearing message format