mirror of
https://github.com/aljazceru/lightning.git
synced 2026-01-11 10:04:28 +01:00
funder: cleanup datastore on state-change/channel failure
Let's not leave old state hanging around! Note that this fires for pretty much every/any channel (even if we're not the opener).
This commit is contained in:
committed by
Christian Decker
parent
efd096dc96
commit
e00857827f
@@ -128,6 +128,31 @@ command_hook_cont_psbt(struct command *cmd, struct wally_psbt *psbt)
|
||||
return command_finished(cmd, response);
|
||||
}
|
||||
|
||||
static struct command_result *
|
||||
datastore_del_fail(struct command *cmd,
|
||||
const char *buf,
|
||||
const jsmntok_t *error,
|
||||
void *data UNUSED)
|
||||
{
|
||||
/* Eh, ok fine */
|
||||
return notification_handled(cmd);
|
||||
}
|
||||
|
||||
static struct command_result *
|
||||
datastore_del_success(struct command *cmd,
|
||||
const char *buf,
|
||||
const jsmntok_t *result,
|
||||
void *data UNUSED)
|
||||
{
|
||||
/* Cool we deleted some stuff */
|
||||
plugin_log(cmd->plugin, LOG_DBG,
|
||||
"`datastore` del succeeded: %*.s",
|
||||
json_tok_full_len(result),
|
||||
json_tok_full(buf, result));
|
||||
|
||||
return notification_handled(cmd);
|
||||
}
|
||||
|
||||
static struct command_result *
|
||||
datastore_add_fail(struct command *cmd,
|
||||
const char *buf,
|
||||
@@ -1047,6 +1072,64 @@ static struct command_result *json_disconnect(struct command *cmd,
|
||||
return notification_handled(cmd);
|
||||
}
|
||||
|
||||
static struct command_result *
|
||||
delete_channel_from_datastore(struct command *cmd,
|
||||
struct channel_id *cid)
|
||||
{
|
||||
const struct out_req *req;
|
||||
|
||||
/* Fetch out previous utxos from the datastore.
|
||||
* If we were clever, we'd have some way of tracking
|
||||
* channels that we actually might have data for
|
||||
* but this is much easier */
|
||||
req = jsonrpc_request_start(cmd->plugin, cmd,
|
||||
"deldatastore",
|
||||
&datastore_del_success,
|
||||
&datastore_del_fail,
|
||||
NULL);
|
||||
json_add_string(req->js, "key",
|
||||
tal_fmt(cmd, "funder/%s",
|
||||
type_to_string(cmd, struct channel_id, cid)));
|
||||
return send_outreq(cmd->plugin, req);
|
||||
}
|
||||
|
||||
static struct command_result *json_channel_state_changed(struct command *cmd,
|
||||
const char *buf,
|
||||
const jsmntok_t *params)
|
||||
{
|
||||
struct channel_id cid;
|
||||
const char *err, *old_state, *new_state;
|
||||
|
||||
err = json_scan(tmpctx, buf, params,
|
||||
"{channel_state_changed:"
|
||||
"{channel_id:%"
|
||||
",old_state:%"
|
||||
",new_state:%}}",
|
||||
JSON_SCAN(json_to_channel_id, &cid),
|
||||
JSON_SCAN_TAL(cmd, json_strdup, &old_state),
|
||||
JSON_SCAN_TAL(cmd, json_strdup, &new_state));
|
||||
|
||||
if (err)
|
||||
plugin_err(cmd->plugin,
|
||||
"`channel_state_changed` notification payload did"
|
||||
" not scan %s: %.*s",
|
||||
err, json_tok_full_len(params),
|
||||
json_tok_full(buf, params));
|
||||
|
||||
/* Moving out of "awaiting lockin",
|
||||
* means we clean up the datastore */
|
||||
/* FIXME: splicing state? */
|
||||
if (!streq(old_state, "DUALOPEND_AWAITING_LOCKIN")
|
||||
&& !streq(old_state, "CHANNELD_AWAITING_LOCKIN"))
|
||||
return notification_handled(cmd);
|
||||
|
||||
plugin_log(cmd->plugin, LOG_DBG,
|
||||
"Cleaning up datastore for channel_id %s",
|
||||
type_to_string(tmpctx, struct channel_id, &cid));
|
||||
|
||||
return delete_channel_from_datastore(cmd, &cid);
|
||||
}
|
||||
|
||||
static struct command_result *json_channel_open_failed(struct command *cmd,
|
||||
const char *buf,
|
||||
const jsmntok_t *params)
|
||||
@@ -1074,7 +1157,8 @@ static struct command_result *json_channel_open_failed(struct command *cmd,
|
||||
if (open)
|
||||
unreserve_psbt(open);
|
||||
|
||||
return notification_handled(cmd);
|
||||
/* Also clean up datastore for this channel */
|
||||
return delete_channel_from_datastore(cmd, &cid);
|
||||
}
|
||||
|
||||
static void json_add_policy(struct json_stream *stream,
|
||||
@@ -1427,6 +1511,10 @@ const struct plugin_notification notifs[] = {
|
||||
"disconnect",
|
||||
json_disconnect,
|
||||
},
|
||||
{
|
||||
"channel_state_changed",
|
||||
json_channel_state_changed,
|
||||
},
|
||||
};
|
||||
|
||||
static char *option_channel_base(const char *arg, struct funder_policy *policy)
|
||||
|
||||
@@ -398,14 +398,23 @@ def test_v2_rbf_liquidity_ad(node_factory, bitcoind, chainparams):
|
||||
funding_feerate=next_feerate)
|
||||
update = l1.rpc.openchannel_update(chan_id, bump['psbt'])
|
||||
assert update['commitments_secured']
|
||||
|
||||
# Sign our inputs, and continue
|
||||
signed_psbt = l1.rpc.signpsbt(update['psbt'])['signed_psbt']
|
||||
l1.rpc.openchannel_signed(chan_id, signed_psbt)
|
||||
|
||||
# There's data in the datastore now (l2 only)
|
||||
assert l1.rpc.listdatastore() == {'datastore': []}
|
||||
only_one(l2.rpc.listdatastore("funder/{}".format(chan_id))['datastore'])
|
||||
|
||||
# what happens when the channel opens?
|
||||
bitcoind.generate_block(6)
|
||||
l1.daemon.wait_for_log('to CHANNELD_NORMAL')
|
||||
|
||||
# Datastore should be cleaned up!
|
||||
assert l1.rpc.listdatastore() == {'datastore': []}
|
||||
assert l2.rpc.listdatastore() == {'datastore': []}
|
||||
|
||||
# This should be the accepter's amount
|
||||
fundings = only_one(only_one(l1.rpc.listpeers()['peers'])['channels'])['funding']
|
||||
# The lease is still there!
|
||||
|
||||
Reference in New Issue
Block a user