Skip to content

Commit

Permalink
EXPERIMENTAL: dev-quiesce to initiate (and test) quiescence.
Browse files Browse the repository at this point in the history
Signed-off-by: Rusty Russell <[email protected]>
  • Loading branch information
rustyrussell authored and cdecker committed May 26, 2021
1 parent 49cefb0 commit a93c20a
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 4 deletions.
28 changes: 26 additions & 2 deletions channeld/channeld.c
Original file line number Diff line number Diff line change
Expand Up @@ -294,9 +294,11 @@ static void maybe_send_stfu(struct peer *peer)
peer->stfu_sent[LOCAL] = true;
}

/* FIXME: We're finished, do something! */
if (peer->stfu_sent[LOCAL] && peer->stfu_sent[REMOTE])
if (peer->stfu_sent[LOCAL] && peer->stfu_sent[REMOTE]) {
status_unusual("STFU complete: we are quiescent");
wire_sync_write(MASTER_FD,
towire_channeld_dev_quiesce_reply(tmpctx));
}
}

static void handle_stfu(struct peer *peer, const u8 *stfu)
Expand Down Expand Up @@ -3057,6 +3059,21 @@ static void channeld_send_custommsg(struct peer *peer, const u8 *msg)
master_badmsg(WIRE_CUSTOMMSG_OUT, msg);
sync_crypto_write(peer->pps, take(inner));
}

#if EXPERIMENTAL_FEATURES
static void handle_dev_quiesce(struct peer *peer, const u8 *msg)
{
if (!fromwire_channeld_dev_quiesce(msg))
master_badmsg(WIRE_CHANNELD_DEV_QUIESCE, msg);

/* Don't do this twice. */
if (peer->stfu)
status_failed(STATUS_FAIL_MASTER_IO, "dev_quiesce already");

peer->stfu = true;
maybe_send_stfu(peer);
}
#endif /* EXPERIMENTAL_FEATURES */
#endif /* DEVELOPER */

static void req_in(struct peer *peer, const u8 *msg)
Expand Down Expand Up @@ -3105,9 +3122,15 @@ static void req_in(struct peer *peer, const u8 *msg)
case WIRE_CHANNELD_DEV_MEMLEAK:
handle_dev_memleak(peer, msg);
return;
case WIRE_CHANNELD_DEV_QUIESCE:
#if EXPERIMENTAL_FEATURES
handle_dev_quiesce(peer, msg);
return;
#endif /* EXPERIMENTAL_FEATURES */
#else
case WIRE_CHANNELD_DEV_REENABLE_COMMIT:
case WIRE_CHANNELD_DEV_MEMLEAK:
case WIRE_CHANNELD_DEV_QUIESCE:
#endif /* DEVELOPER */
case WIRE_CHANNELD_INIT:
case WIRE_CHANNELD_OFFER_HTLC_REPLY:
Expand All @@ -3125,6 +3148,7 @@ static void req_in(struct peer *peer, const u8 *msg)
case WIRE_CHANNELD_FAIL_FALLEN_BEHIND:
case WIRE_CHANNELD_DEV_MEMLEAK_REPLY:
case WIRE_CHANNELD_SEND_ERROR_REPLY:
case WIRE_CHANNELD_DEV_QUIESCE_REPLY:
break;
}

Expand Down
4 changes: 4 additions & 0 deletions channeld/channeld_wire.csv
Original file line number Diff line number Diff line change
Expand Up @@ -217,3 +217,7 @@ msgdata,channeld_send_error,reason,wirestring,

# Tell master channeld has sent the error message.
msgtype,channeld_send_error_reply,1108

# Ask channeld to quiesce.
msgtype,channeld_dev_quiesce,1009
msgtype,channeld_dev_quiesce_reply,1109
45 changes: 44 additions & 1 deletion channeld/channeld_wiregen.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 13 additions & 1 deletion channeld/channeld_wiregen.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

52 changes: 52 additions & 0 deletions lightningd/channel_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -425,11 +425,13 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds)
case WIRE_CHANNELD_FEERATES:
case WIRE_CHANNELD_SPECIFIC_FEERATES:
case WIRE_CHANNELD_DEV_MEMLEAK:
case WIRE_CHANNELD_DEV_QUIESCE:
/* Replies go to requests. */
case WIRE_CHANNELD_OFFER_HTLC_REPLY:
case WIRE_CHANNELD_DEV_REENABLE_COMMIT_REPLY:
case WIRE_CHANNELD_DEV_MEMLEAK_REPLY:
case WIRE_CHANNELD_SEND_ERROR:
case WIRE_CHANNELD_DEV_QUIESCE_REPLY:
break;
}

Expand Down Expand Up @@ -937,4 +939,54 @@ static const struct json_command dev_feerate_command = {
"Set feerate for {id} to {feerate}"
};
AUTODATA(json_command, &dev_feerate_command);

#if EXPERIMENTAL_FEATURES
static void quiesce_reply(struct subd *channeld UNUSED,
const u8 *reply,
const int *fds UNUSED,
struct command *cmd)
{
struct json_stream *response;

response = json_stream_success(cmd);
was_pending(command_success(cmd, response));
}

static struct command_result *json_dev_quiesce(struct command *cmd,
const char *buffer,
const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params)
{
struct node_id *id;
struct peer *peer;
struct channel *channel;
const u8 *msg;

if (!param(cmd, buffer, params,
p_req("id", param_node_id, &id),
NULL))
return command_param_failed();

peer = peer_by_id(cmd->ld, id);
if (!peer)
return command_fail(cmd, LIGHTNINGD, "Peer not connected");

channel = peer_active_channel(peer);
if (!channel || !channel->owner || channel->state != CHANNELD_NORMAL)
return command_fail(cmd, LIGHTNINGD, "Peer bad state");

msg = towire_channeld_dev_quiesce(NULL);
subd_req(channel->owner, channel->owner, take(msg), -1, 0,
quiesce_reply, cmd);
return command_still_pending(cmd);
}

static const struct json_command dev_quiesce_command = {
"dev-quiesce",
"developer",
json_dev_quiesce,
"Initiate quiscence protocol with peer"
};
AUTODATA(json_command, &dev_quiesce_command);
#endif /* EXPERIMENTAL_FEATURES */
#endif /* DEVELOPER */
24 changes: 24 additions & 0 deletions tests/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -3494,3 +3494,27 @@ def test_htlc_failed_noclose(node_factory):

time.sleep(35)
assert l1.rpc.getpeer(l2.info['id'])['connected']


@unittest.skipIf(not EXPERIMENTAL_FEATURES, "quiescence is experimental")
@pytest.mark.developer("quiescence triggering is dev only")
def test_quiescence(node_factory, executor):
l1, l2 = node_factory.line_graph(2)

# Works fine.
l1.pay(l2, 1000)

assert l1.rpc.call('dev-quiesce', [l2.info['id']]) == {}

# Both should consider themselves quiescent.
l1.daemon.wait_for_log("STFU complete: we are quiescent")
l2.daemon.wait_for_log("STFU complete: we are quiescent")

# Should not be able to increase fees.
l1.rpc.call('dev-feerate', [l2.info['id'], 9999])

try:
l1.daemon.wait_for_log('peer_out WIRE_UPDATE_FEE', 5)
assert False
except TimeoutError:
pass

0 comments on commit a93c20a

Please sign in to comment.