mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
EXPERIMENTAL: dev-quiesce to initiate (and test) quiescence.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
e29c9c2fc0
commit
03cfe0b468
@ -297,9 +297,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)
|
||||
@ -3079,6 +3081,22 @@ 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;
|
||||
peer->stfu_initiator = LOCAL;
|
||||
maybe_send_stfu(peer);
|
||||
}
|
||||
#endif /* EXPERIMENTAL_FEATURES */
|
||||
#endif /* DEVELOPER */
|
||||
|
||||
static void req_in(struct peer *peer, const u8 *msg)
|
||||
@ -3127,9 +3145,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:
|
||||
@ -3147,6 +3171,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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Can't render this file because it has a wrong number of fields in line 12.
|
45
channeld/channeld_wiregen.c
generated
45
channeld/channeld_wiregen.c
generated
@ -46,6 +46,8 @@ const char *channeld_wire_name(int e)
|
||||
case WIRE_CHANNELD_GOT_ANNOUNCEMENT: return "WIRE_CHANNELD_GOT_ANNOUNCEMENT";
|
||||
case WIRE_CHANNELD_SEND_ERROR: return "WIRE_CHANNELD_SEND_ERROR";
|
||||
case WIRE_CHANNELD_SEND_ERROR_REPLY: return "WIRE_CHANNELD_SEND_ERROR_REPLY";
|
||||
case WIRE_CHANNELD_DEV_QUIESCE: return "WIRE_CHANNELD_DEV_QUIESCE";
|
||||
case WIRE_CHANNELD_DEV_QUIESCE_REPLY: return "WIRE_CHANNELD_DEV_QUIESCE_REPLY";
|
||||
}
|
||||
|
||||
snprintf(invalidbuf, sizeof(invalidbuf), "INVALID %i", e);
|
||||
@ -81,6 +83,8 @@ bool channeld_wire_is_defined(u16 type)
|
||||
case WIRE_CHANNELD_GOT_ANNOUNCEMENT:;
|
||||
case WIRE_CHANNELD_SEND_ERROR:;
|
||||
case WIRE_CHANNELD_SEND_ERROR_REPLY:;
|
||||
case WIRE_CHANNELD_DEV_QUIESCE:;
|
||||
case WIRE_CHANNELD_DEV_QUIESCE_REPLY:;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -1070,4 +1074,43 @@ bool fromwire_channeld_send_error_reply(const void *p)
|
||||
return false;
|
||||
return cursor != NULL;
|
||||
}
|
||||
// SHA256STAMP:60143693b0c3611c8ecdf7f3549ef9f4c280e359cac0cd1f4df38cdca2dad3cb
|
||||
|
||||
/* WIRE: CHANNELD_DEV_QUIESCE */
|
||||
/* Ask channeld to quiesce. */
|
||||
u8 *towire_channeld_dev_quiesce(const tal_t *ctx)
|
||||
{
|
||||
u8 *p = tal_arr(ctx, u8, 0);
|
||||
|
||||
towire_u16(&p, WIRE_CHANNELD_DEV_QUIESCE);
|
||||
|
||||
return memcheck(p, tal_count(p));
|
||||
}
|
||||
bool fromwire_channeld_dev_quiesce(const void *p)
|
||||
{
|
||||
const u8 *cursor = p;
|
||||
size_t plen = tal_count(p);
|
||||
|
||||
if (fromwire_u16(&cursor, &plen) != WIRE_CHANNELD_DEV_QUIESCE)
|
||||
return false;
|
||||
return cursor != NULL;
|
||||
}
|
||||
|
||||
/* WIRE: CHANNELD_DEV_QUIESCE_REPLY */
|
||||
u8 *towire_channeld_dev_quiesce_reply(const tal_t *ctx)
|
||||
{
|
||||
u8 *p = tal_arr(ctx, u8, 0);
|
||||
|
||||
towire_u16(&p, WIRE_CHANNELD_DEV_QUIESCE_REPLY);
|
||||
|
||||
return memcheck(p, tal_count(p));
|
||||
}
|
||||
bool fromwire_channeld_dev_quiesce_reply(const void *p)
|
||||
{
|
||||
const u8 *cursor = p;
|
||||
size_t plen = tal_count(p);
|
||||
|
||||
if (fromwire_u16(&cursor, &plen) != WIRE_CHANNELD_DEV_QUIESCE_REPLY)
|
||||
return false;
|
||||
return cursor != NULL;
|
||||
}
|
||||
// SHA256STAMP:720f9917311384d373593dc1550619ddf461bdabde8b312ed6dc632cb7860c34
|
||||
|
14
channeld/channeld_wiregen.h
generated
14
channeld/channeld_wiregen.h
generated
@ -70,6 +70,9 @@ enum channeld_wire {
|
||||
WIRE_CHANNELD_SEND_ERROR = 1008,
|
||||
/* Tell master channeld has sent the error message. */
|
||||
WIRE_CHANNELD_SEND_ERROR_REPLY = 1108,
|
||||
/* Ask channeld to quiesce. */
|
||||
WIRE_CHANNELD_DEV_QUIESCE = 1009,
|
||||
WIRE_CHANNELD_DEV_QUIESCE_REPLY = 1109,
|
||||
};
|
||||
|
||||
const char *channeld_wire_name(int e);
|
||||
@ -211,6 +214,15 @@ bool fromwire_channeld_send_error(const tal_t *ctx, const void *p, wirestring **
|
||||
u8 *towire_channeld_send_error_reply(const tal_t *ctx);
|
||||
bool fromwire_channeld_send_error_reply(const void *p);
|
||||
|
||||
/* WIRE: CHANNELD_DEV_QUIESCE */
|
||||
/* Ask channeld to quiesce. */
|
||||
u8 *towire_channeld_dev_quiesce(const tal_t *ctx);
|
||||
bool fromwire_channeld_dev_quiesce(const void *p);
|
||||
|
||||
/* WIRE: CHANNELD_DEV_QUIESCE_REPLY */
|
||||
u8 *towire_channeld_dev_quiesce_reply(const tal_t *ctx);
|
||||
bool fromwire_channeld_dev_quiesce_reply(const void *p);
|
||||
|
||||
|
||||
#endif /* LIGHTNING_CHANNELD_CHANNELD_WIREGEN_H */
|
||||
// SHA256STAMP:60143693b0c3611c8ecdf7f3549ef9f4c280e359cac0cd1f4df38cdca2dad3cb
|
||||
// SHA256STAMP:720f9917311384d373593dc1550619ddf461bdabde8b312ed6dc632cb7860c34
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
@ -3470,6 +3470,30 @@ def test_openchannel_init_alternate(node_factory, executor):
|
||||
fut.result(10)
|
||||
|
||||
|
||||
@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
|
||||
|
||||
|
||||
def test_htlc_failed_noclose(node_factory):
|
||||
"""Test a bug where the htlc timeout would kick in even if the HTLC failed"""
|
||||
l1, l2 = node_factory.line_graph(2)
|
||||
|
Loading…
Reference in New Issue
Block a user