Skip to content

Commit e29c9c2

Browse files
rustyrussellniftynei
authored andcommitted
EXPERIMENTAL: handle receiving quiescence request.
Changelog-EXPERIMENTAL: Protocol: we support the quiescence protocol from lightning/bolts#869 Signed-off-by: Rusty Russell <[email protected]>
1 parent 40e2178 commit e29c9c2

File tree

1 file changed

+136
-3
lines changed

1 file changed

+136
-3
lines changed

channeld/channeld.c

Lines changed: 136 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,17 @@ struct peer {
159159
/* If master told us to send wrong_funding */
160160
struct bitcoin_outpoint *shutdown_wrong_funding;
161161

162+
#if EXPERIMENTAL_FEATURES
163+
/* Do we want quiescence? */
164+
bool stfu;
165+
/* Which side is considered the initiator? */
166+
enum side stfu_initiator;
167+
/* Has stfu been sent by each side? */
168+
bool stfu_sent[NUM_SIDES];
169+
/* Updates master asked, which we've deferred while quiescing */
170+
struct msg_queue *update_queue;
171+
#endif
172+
162173
/* Information used for reestablishment. */
163174
bool last_was_revoke;
164175
struct changed_htlc *last_sent_commit;
@@ -273,6 +284,99 @@ static struct amount_msat advertized_htlc_max(const struct channel *channel)
273284
return lower_bound_msat;
274285
}
275286

287+
#if EXPERIMENTAL_FEATURES
288+
static void maybe_send_stfu(struct peer *peer)
289+
{
290+
if (!peer->stfu)
291+
return;
292+
293+
if (!peer->stfu_sent[LOCAL] && !pending_updates(peer->channel, LOCAL)) {
294+
u8 *msg = towire_stfu(NULL, &peer->channel_id,
295+
peer->stfu_initiator == LOCAL);
296+
sync_crypto_write(peer->pps, take(msg));
297+
peer->stfu_sent[LOCAL] = true;
298+
}
299+
300+
/* FIXME: We're finished, do something! */
301+
if (peer->stfu_sent[LOCAL] && peer->stfu_sent[REMOTE])
302+
status_unusual("STFU complete: we are quiescent");
303+
}
304+
305+
static void handle_stfu(struct peer *peer, const u8 *stfu)
306+
{
307+
struct channel_id channel_id;
308+
u8 remote_initiated;
309+
310+
if (!fromwire_stfu(stfu, &channel_id, &remote_initiated))
311+
peer_failed_warn(peer->pps, &peer->channel_id,
312+
"Bad stfu %s", tal_hex(peer, stfu));
313+
314+
if (!channel_id_eq(&channel_id, &peer->channel_id)) {
315+
peer_failed_err(peer->pps, &channel_id,
316+
"Wrong stfu channel_id: expected %s, got %s",
317+
type_to_string(tmpctx, struct channel_id,
318+
&peer->channel_id),
319+
type_to_string(tmpctx, struct channel_id,
320+
&channel_id));
321+
}
322+
323+
/* Sanity check */
324+
if (pending_updates(peer->channel, REMOTE))
325+
peer_failed_warn(peer->pps, &peer->channel_id,
326+
"STFU but you still have updates pending?");
327+
328+
if (!peer->stfu) {
329+
peer->stfu = true;
330+
if (!remote_initiated)
331+
peer_failed_warn(peer->pps, &peer->channel_id,
332+
"Unsolicited STFU but you said"
333+
" you didn't initiate?");
334+
peer->stfu_initiator = REMOTE;
335+
} else {
336+
/* BOLT-quiescent #2:
337+
*
338+
* If both sides send `stfu` simultaneously, they will both
339+
* set `initiator` to `1`, in which case the "initiator" is
340+
* arbitrarily considered to be the channel funder (the sender
341+
* of `open_channel`).
342+
*/
343+
if (remote_initiated)
344+
peer->stfu_initiator = peer->channel->opener;
345+
}
346+
347+
/* BOLT-quiescent #2:
348+
* The receiver of `stfu`:
349+
* - if it has sent `stfu` then:
350+
* - MUST now consider the channel to be quiescent
351+
* - otherwise:
352+
* - SHOULD NOT send any more update messages.
353+
* - MUST reply with `stfu` once it can do so.
354+
*/
355+
peer->stfu_sent[REMOTE] = true;
356+
357+
maybe_send_stfu(peer);
358+
}
359+
360+
/* Returns true if we queued this for later handling (steals if true) */
361+
static bool handle_master_request_later(struct peer *peer, const u8 *msg)
362+
{
363+
if (peer->stfu) {
364+
msg_enqueue(peer->update_queue, take(msg));
365+
return true;
366+
}
367+
return false;
368+
}
369+
#else /* !EXPERIMENTAL_FEATURES */
370+
static bool handle_master_request_later(struct peer *peer, const u8 *msg)
371+
{
372+
return false;
373+
}
374+
375+
static void maybe_send_stfu(struct peer *peer)
376+
{
377+
}
378+
#endif
379+
276380
/* Create and send channel_update to gossipd (and maybe peer) */
277381
static void send_channel_update(struct peer *peer, int disable_flag)
278382
{
@@ -952,6 +1056,12 @@ static bool want_fee_update(const struct peer *peer, u32 *target)
9521056
if (peer->channel->opener != LOCAL)
9531057
return false;
9541058

1059+
#if EXPERIMENTAL_FEATURES
1060+
/* No fee update while quiescing! */
1061+
if (peer->stfu)
1062+
return false;
1063+
#endif
1064+
9551065
max = approx_max_feerate(peer->channel);
9561066
val = peer->desired_feerate;
9571067

@@ -1408,6 +1518,9 @@ static void handle_peer_commit_sig(struct peer *peer, const u8 *msg)
14081518
send_revocation(peer,
14091519
&commit_sig, htlc_sigs, changed_htlcs, txs[0]);
14101520

1521+
/* We may now be quiescent on our side. */
1522+
maybe_send_stfu(peer);
1523+
14111524
/* This might have synced the feerates: if so, we may want to
14121525
* update */
14131526
if (want_fee_update(peer, NULL))
@@ -1537,6 +1650,9 @@ static void handle_peer_revoke_and_ack(struct peer *peer, const u8 *msg)
15371650
type_to_string(tmpctx, struct pubkey,
15381651
&peer->old_remote_per_commit));
15391652

1653+
/* We may now be quiescent on our side. */
1654+
maybe_send_stfu(peer);
1655+
15401656
start_commit_timer(peer);
15411657
}
15421658

@@ -1931,6 +2047,11 @@ static void peer_in(struct peer *peer, const u8 *msg)
19312047
handle_peer_shutdown(peer, msg);
19322048
return;
19332049

2050+
#if EXPERIMENTAL_FEATURES
2051+
case WIRE_STFU:
2052+
handle_stfu(peer, msg);
2053+
return;
2054+
#endif
19342055
case WIRE_INIT:
19352056
case WIRE_OPEN_CHANNEL:
19362057
case WIRE_ACCEPT_CHANNEL:
@@ -1949,9 +2070,6 @@ static void peer_in(struct peer *peer, const u8 *msg)
19492070
return;
19502071
case WIRE_INIT_RBF:
19512072
case WIRE_ACK_RBF:
1952-
#if EXPERIMENTAL_FEATURES
1953-
case WIRE_STFU:
1954-
#endif
19552073
break;
19562074

19572075
case WIRE_CHANNEL_REESTABLISH:
@@ -2972,18 +3090,28 @@ static void req_in(struct peer *peer, const u8 *msg)
29723090
handle_funding_depth(peer, msg);
29733091
return;
29743092
case WIRE_CHANNELD_OFFER_HTLC:
3093+
if (handle_master_request_later(peer, msg))
3094+
return;
29753095
handle_offer_htlc(peer, msg);
29763096
return;
29773097
case WIRE_CHANNELD_FEERATES:
3098+
if (handle_master_request_later(peer, msg))
3099+
return;
29783100
handle_feerates(peer, msg);
29793101
return;
29803102
case WIRE_CHANNELD_FULFILL_HTLC:
3103+
if (handle_master_request_later(peer, msg))
3104+
return;
29813105
handle_preimage(peer, msg);
29823106
return;
29833107
case WIRE_CHANNELD_FAIL_HTLC:
3108+
if (handle_master_request_later(peer, msg))
3109+
return;
29843110
handle_fail(peer, msg);
29853111
return;
29863112
case WIRE_CHANNELD_SPECIFIC_FEERATES:
3113+
if (handle_master_request_later(peer, msg))
3114+
return;
29873115
handle_specific_feerates(peer, msg);
29883116
return;
29893117
case WIRE_CHANNELD_SEND_SHUTDOWN:
@@ -3266,6 +3394,11 @@ int main(int argc, char *argv[])
32663394
/* We actually received it in the previous daemon, but near enough */
32673395
peer->last_recv = time_now();
32683396
peer->last_empty_commitment = 0;
3397+
#if EXPERIMENTAL_FEATURES
3398+
peer->stfu = false;
3399+
peer->stfu_sent[LOCAL] = peer->stfu_sent[REMOTE] = false;
3400+
peer->update_queue = msg_queue_new(peer);
3401+
#endif
32693402

32703403
/* We send these to HSM to get real signatures; don't have valgrind
32713404
* complain. */

0 commit comments

Comments
 (0)