Skip to content

Commit df5f38d

Browse files
committed
spender: look for unsigned PSBT on awaiting channels on startup, and re-send.
This covers the other corner case, where we crash before actually signing and sending the PSBT. We can spot this because the channel is in AWAITING_LOCKIN and we have a PSBT, but it's not signed yet. Signed-off-by: Rusty Russell <[email protected]>
1 parent 606aad0 commit df5f38d

File tree

4 files changed

+91
-4
lines changed

4 files changed

+91
-4
lines changed

plugins/spender/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
static
1212
const char *spender_init(struct command *init_cmd, const char *b, const jsmntok_t *t)
1313
{
14-
openchannel_init(init_cmd->plugin, b, t);
14+
openchannel_init(init_cmd, b, t);
1515
/* whatever_init(p, b, t); */
1616
return NULL;
1717
}

plugins/spender/openchannel.c

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1034,10 +1034,95 @@ openchannel_init_dest(struct multifundchannel_destination *dest)
10341034
return send_outreq(req);
10351035
}
10361036

1037-
void openchannel_init(struct plugin *p, const char *b, const jsmntok_t *t)
1037+
static struct command_result *psbt_error(struct command *aux_cmd,
1038+
const char *methodname,
1039+
const char *buf,
1040+
const jsmntok_t *result,
1041+
struct channel_id *cid)
1042+
{
1043+
plugin_log(aux_cmd->plugin, LOG_UNUSUAL,
1044+
"Failed %s for waiting channel %s: %.*s",
1045+
methodname,
1046+
fmt_channel_id(tmpctx, cid),
1047+
json_tok_full_len(result),
1048+
json_tok_full(buf, result));
1049+
return aux_command_done(aux_cmd);
1050+
}
1051+
1052+
static struct command_result *sendpsbt_done(struct command *aux_cmd,
1053+
const char *methodname,
1054+
const char *buf,
1055+
const jsmntok_t *result,
1056+
struct channel_id *cid)
1057+
{
1058+
plugin_log(aux_cmd->plugin, LOG_INFORM,
1059+
"Signed and sent psbt for waiting channel %s",
1060+
fmt_channel_id(tmpctx, cid));
1061+
return aux_command_done(aux_cmd);
1062+
}
1063+
1064+
static struct command_result *signpsbt_done(struct command *aux_cmd,
1065+
const char *methodname,
1066+
const char *buf,
1067+
const jsmntok_t *result,
1068+
struct channel_id *cid)
1069+
{
1070+
const jsmntok_t *psbttok = json_get_member(buf, result, "signed_psbt");
1071+
struct wally_psbt *psbt = json_to_psbt(tmpctx, buf, psbttok);
1072+
struct out_req *req;
1073+
1074+
req = jsonrpc_request_start(aux_cmd, "sendpsbt",
1075+
sendpsbt_done, psbt_error,
1076+
cid);
1077+
json_add_psbt(req->js, "psbt", psbt);
1078+
return send_outreq(req);
1079+
}
1080+
1081+
/* If there are any channels with unsigned PSBTs in AWAITING_LOCKIN,
1082+
* sign them now (assume we crashed) */
1083+
static void list_awaiting_channels(struct command *init_cmd)
1084+
{
1085+
const char *buf;
1086+
size_t i;
1087+
const jsmntok_t *resp, *t, *channels;
1088+
1089+
resp = jsonrpc_request_sync(tmpctx, init_cmd,
1090+
"listpeerchannels",
1091+
NULL, &buf);
1092+
channels = json_get_member(buf, resp, "channels");
1093+
json_for_each_arr(i, t, channels) {
1094+
struct out_req *req;
1095+
const char *state;
1096+
struct channel_id cid;
1097+
struct command *aux_cmd;
1098+
struct wally_psbt *psbt;
1099+
1100+
if (json_scan(tmpctx, buf, t, "{state:%,channel_id:%,funding:{psbt:%}}",
1101+
JSON_SCAN_TAL(tmpctx, json_strdup, &state),
1102+
JSON_SCAN(json_tok_channel_id, &cid),
1103+
JSON_SCAN_TAL(tmpctx, json_to_psbt, &psbt)) != NULL)
1104+
continue;
1105+
1106+
if (!streq(state, "CHANNELD_AWAITING_LOCKIN")
1107+
&& !streq(state, "DUALOPEND_AWAITING_LOCKIN"))
1108+
continue;
1109+
1110+
/* Don't do this sync, as it can reasonably fail! */
1111+
aux_cmd = aux_command(init_cmd);
1112+
req = jsonrpc_request_start(aux_cmd, "signpsbt",
1113+
signpsbt_done, psbt_error,
1114+
tal_dup(aux_cmd, struct channel_id, &cid));
1115+
json_add_psbt(req->js, "psbt", psbt);
1116+
send_outreq(req);
1117+
}
1118+
}
1119+
1120+
void openchannel_init(struct command *init_cmd, const char *b, const jsmntok_t *t)
10381121
{
10391122
/* Initialize our list! */
10401123
list_head_init(&mfc_commands);
1124+
1125+
list_awaiting_channels(init_cmd);
10411126
}
10421127

10431128
const struct plugin_notification openchannel_notifs[] = {

plugins/spender/openchannel.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <ccan/tal/tal.h>
55

66
struct wally_psbt;
7+
struct command;
78

89
extern const struct plugin_notification openchannel_notifs[];
910
extern const size_t num_openchannel_notifs;
@@ -15,7 +16,7 @@ void register_mfc(struct multifundchannel_command *mfc);
1516
struct command_result *
1617
openchannel_init_dest(struct multifundchannel_destination *dest);
1718

18-
void openchannel_init(struct plugin *p, const char *b,
19+
void openchannel_init(struct command *init_cmd, const char *b,
1920
const jsmntok_t *t);
2021

2122
struct command_result *

tests/test_opening.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2849,7 +2849,6 @@ def censoring_sendrawtx(r):
28492849
bitcoind.generate_block(1, wait_for_mempool=txid)
28502850

28512851

2852-
@pytest.mark.xfail(strict=True)
28532852
@pytest.mark.openchannel('v1')
28542853
def test_sendpsbt_crash(bitcoind, node_factory):
28552854
"""Stop sendpsbt, check it eventually opens"""
@@ -2866,3 +2865,5 @@ def test_sendpsbt_crash(bitcoind, node_factory):
28662865
del l1.daemon.opts['plugin']
28672866
l1.start()
28682867
bitcoind.generate_block(1, wait_for_mempool=1)
2868+
2869+
assert l1.daemon.is_in_log('Signed and sent psbt for waiting channel')

0 commit comments

Comments
 (0)