Skip to content

Commit

Permalink
mfc: use consolidated error reporting, reduce reliance on json-str
Browse files Browse the repository at this point in the history
Previously this ported errors around as JSON. A nicer thing to do is to
deconstruct/reconstruct it; this also allows us to create our own errors
from within the multifundchannel family.
  • Loading branch information
niftynei authored and rustyrussell committed Mar 15, 2021
1 parent ef1e36e commit 2586641
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 150 deletions.
145 changes: 68 additions & 77 deletions plugins/spender/multifundchannel.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,47 @@ size_t dest_count(const struct multifundchannel_command *mfc,
return count;
}

void fail_destination(struct multifundchannel_destination *dest,
char *error TAKES)
static void fail_destination(struct multifundchannel_destination *dest)
{
dest->fail_state = dest->state;
dest->state = MULTIFUNDCHANNEL_FAILED;
if (taken(error))
dest->error = tal_steal(dest->mfc, error);
}

void fail_destination_tok(struct multifundchannel_destination *dest,
const char *buf,
const jsmntok_t *error)
{
const char *err;
const jsmntok_t *data_tok;

err = json_scan(tmpctx, buf, error, "{code:%,message:%}",
JSON_SCAN(json_to_int, &dest->error_code),
JSON_SCAN_TAL(dest->mfc,
json_strdup,
&dest->error_message));
if (err)
plugin_err(dest->mfc->cmd->plugin,
"`fundchannel_complete` failure failed to parse %s",
err);

data_tok = json_get_member(buf, error, "data");
if (data_tok)
dest->error_data = json_strdup(dest->mfc, buf, data_tok);
else
dest->error = tal_strdup(dest->mfc, error);
dest->error_data = NULL;

fail_destination(dest);
}

void fail_destination_msg(struct multifundchannel_destination *dest,
errcode_t error_code,
const char *err_str TAKES)
{
dest->error_code = error_code;
dest->error_message = tal_strdup(dest->mfc, err_str);
dest->error_data = NULL;

fail_destination(dest);
}

/* Return true if this destination failed, false otherwise. */
Expand Down Expand Up @@ -474,7 +506,14 @@ multifundchannel_finished(struct multifundchannel_command *mfc)
json_object_start(out, NULL);
json_add_node_id(out, "id", &mfc->removeds[i].id);
json_add_string(out, "method", mfc->removeds[i].method);
json_add_jsonstr(out, "error", mfc->removeds[i].error);
json_object_start(out, "error"); /* Start error object */
json_add_s32(out, "code", mfc->removeds[i].error_code);
json_add_string(out, "message",
mfc->removeds[i].error_message);
if (mfc->removeds[i].error_data)
json_add_jsonstr(out, "data",
mfc->removeds[i].error_data);
json_object_end(out); /* End error object */
json_object_end(out);
}
json_array_end(out);
Expand Down Expand Up @@ -670,7 +709,7 @@ after_fundchannel_complete(struct multifundchannel_command *mfc)

/* One of them failed, oh no. */
return redo_multifundchannel(mfc, "fundchannel_complete",
dest->error);
dest->error_message);
}

if (dest_count(mfc, OPEN_CHANNEL) > 0)
Expand Down Expand Up @@ -725,7 +764,6 @@ fundchannel_complete_err(struct command *cmd,
struct multifundchannel_destination *dest)
{
struct multifundchannel_command *mfc = dest->mfc;
const jsmntok_t *code_tok;

plugin_log(mfc->cmd->plugin, LOG_DBG,
"mfc %"PRIu64", dest %u: "
Expand All @@ -734,22 +772,7 @@ fundchannel_complete_err(struct command *cmd,
node_id_to_hexstr(tmpctx, &dest->id),
json_tok_full_len(error), json_tok_full(buf, error));

code_tok = json_get_member(buf, error, "code");
if (!code_tok)
plugin_err(cmd->plugin,
"`fundchannel_complete` failure "
"did not have `code`? "
"%.*s",
json_tok_full_len(error),
json_tok_full(buf, error));
if (!json_to_errcode(buf, code_tok, &dest->code))
plugin_err(cmd->plugin,
"`fundchannel_complete` has unparseable `code`? "
"%.*s",
json_tok_full_len(error),
json_tok_full(buf, error));

fail_destination(dest, take(json_strdup(NULL, buf, error)));
fail_destination_tok(dest, buf, error);
return fundchannel_complete_done(dest);
}

Expand Down Expand Up @@ -970,7 +993,7 @@ after_channel_start(struct multifundchannel_command *mfc)
is_v2(dest) ?
"openchannel_init" :
"fundchannel_start",
dest->error);
dest->error_message);
}

/* Next step. */
Expand Down Expand Up @@ -1052,31 +1075,13 @@ fundchannel_start_err(struct command *cmd,
const jsmntok_t *error,
struct multifundchannel_destination *dest)
{
struct multifundchannel_command *mfc = dest->mfc;
const jsmntok_t *code_tok;

plugin_log(mfc->cmd->plugin, LOG_DBG,
plugin_log(dest->mfc->cmd->plugin, LOG_DBG,
"mfc %"PRIu64", dest %u: "
"failed! fundchannel_start %s: %.*s.",
mfc->id, dest->index,
dest->mfc->id, dest->index,
node_id_to_hexstr(tmpctx, &dest->id),
json_tok_full_len(error),
json_tok_full(buf, error));

code_tok = json_get_member(buf, error, "code");
if (!code_tok)
plugin_err(cmd->plugin,
"`fundchannel_start` failure did not have `code`? "
"%.*s",
json_tok_full_len(error),
json_tok_full(buf, error));
if (!json_to_errcode(buf, code_tok, &dest->code))
plugin_err(cmd->plugin,
"`fundchannel_start` has unparseable `code`? "
"%.*s",
json_tok_full_len(code_tok),
json_tok_full(buf, code_tok));

/*
You might be wondering why we do not just use
mfc_forward_error here.
Expand All @@ -1089,7 +1094,7 @@ fundchannel_start_err(struct command *cmd,
completed, we can then fail.
*/

fail_destination(dest, take(json_strdup(NULL, buf, error)));
fail_destination_tok(dest, buf, error);
return fundchannel_start_done(dest);
}

Expand Down Expand Up @@ -1491,7 +1496,8 @@ after_multiconnect(struct multifundchannel_command *mfc)
continue;

/* One of them failed, oh no. */
return redo_multifundchannel(mfc, "connect", dest->error);
return redo_multifundchannel(mfc, "connect",
dest->error_message);
}

return perform_fundpsbt(mfc);
Expand Down Expand Up @@ -1555,7 +1561,6 @@ connect_err(struct command *cmd,
struct multifundchannel_destination *dest)
{
struct multifundchannel_command *mfc = dest->mfc;
const jsmntok_t *code_tok;

plugin_log(mfc->cmd->plugin, LOG_DBG,
"mfc %"PRIu64", dest %u: failed! connect %s: %.*s.",
Expand All @@ -1564,21 +1569,7 @@ connect_err(struct command *cmd,
json_tok_full_len(error),
json_tok_full(buf, error));

code_tok = json_get_member(buf, error, "code");
if (!code_tok)
plugin_err(cmd->plugin,
"`connect` failure did not have `code`? "
"%.*s",
json_tok_full_len(error),
json_tok_full(buf, error));
if (!json_to_errcode(buf, code_tok, &dest->code))
plugin_err(cmd->plugin,
"`connect` has unparseable `code`? "
"%.*s",
json_tok_full_len(code_tok),
json_tok_full(buf, code_tok));

fail_destination(dest, take(json_strdup(NULL, buf, error)));
fail_destination_tok(dest, buf, error);
return connect_done(dest);
}

Expand Down Expand Up @@ -1687,12 +1678,12 @@ post_cleanup_redo_multifundchannel(struct multifundchannel_redo *redo)
/* We have to fail any v2 that has commitments already */
if (is_v2(dest) && has_commitments_secured(dest)
&& !dest_failed(dest)) {
fail_destination(dest, take(tal_fmt(NULL, "%s",
"\"Attempting retry,"
" yet this peer already has"
" exchanged commitments and is"
" using the v2 open protocol."
" Must spend input to reset.\"")));
fail_destination_msg(dest, FUNDING_STATE_INVALID,
"Attempting retry,"
" yet this peer already has"
" exchanged commitments and is"
" using the v2 open protocol."
" Must spend input to reset.");
}

if (dest_failed(dest)) {
Expand All @@ -1706,8 +1697,9 @@ post_cleanup_redo_multifundchannel(struct multifundchannel_redo *redo)

removed.id = dest->id;
removed.method = failing_method;
removed.error = dest->error;
removed.code = dest->code;
removed.error_message = dest->error_message;
removed.error_code = dest->error_code;
removed.error_data = dest->error_data;
/* Add to removeds. */
tal_arr_expand(&mfc->removeds, removed);
} else {
Expand Down Expand Up @@ -1741,13 +1733,13 @@ post_cleanup_redo_multifundchannel(struct multifundchannel_redo *redo)
i = tal_count(mfc->removeds) - 1;

out = jsonrpc_stream_fail_data(mfc->cmd,
mfc->removeds[i].code,
tal_fmt(tmpctx,
"'%s' failed",
failing_method));
mfc->removeds[i].error_code,
mfc->removeds[i].error_message);
json_add_node_id(out, "id", &mfc->removeds[i].id);
json_add_string(out, "method", failing_method);
json_add_jsonstr(out, "error", mfc->removeds[i].error);
if (mfc->removeds[i].error_data)
json_add_jsonstr(out, "data",
mfc->removeds[i].error_data);

/* Close 'data'. */
json_object_end(out);
Expand Down Expand Up @@ -1862,7 +1854,6 @@ param_destinations_array(struct command *cmd, const char *name,
dest->amount = dest->all ? AMOUNT_SAT(0) : *amount;
dest->announce = *announce;
dest->push_msat = *push_msat;
dest->error = NULL;
dest->psbt = NULL;
dest->updated_psbt = NULL;
dest->protocol = FUND_CHANNEL;
Expand Down
26 changes: 16 additions & 10 deletions plugins/spender/multifundchannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,10 @@ struct multifundchannel_removed {
connect, fundchannel_start, fundchannel_complete.
*/
const char *method;
/* The error that caused this destination to be removed, in JSON. */
const char *error;
errcode_t code;
const char *error_message;
errcode_t error_code;
/* Optional JSON object containing extra data */
const char *error_data;
};

/* the object for a single destination. */
Expand Down Expand Up @@ -124,9 +125,10 @@ struct multifundchannel_destination {
/* the actual channel_id. */
struct channel_id channel_id;

/* any error messages. */
const char *error;
errcode_t code;
const char *error_message;
errcode_t error_code;
/* Optional JSON object containing extra data */
const char *error_data;

/* what channel protocol this destination is using */
enum channel_protocol protocol;
Expand Down Expand Up @@ -240,10 +242,14 @@ mfc_forward_error(struct command *cmd,
const char *buf, const jsmntok_t *error,
struct multifundchannel_command *);

/* When a destination fails, we record the furthest state
* reached, and the error message for the failure */
void fail_destination(struct multifundchannel_destination *dest,
char *error TAKES);
/* When a destination fails, record the furthest state reached, and the
* error message for the failure */
void fail_destination_tok(struct multifundchannel_destination *dest,
const char *buf,
const jsmntok_t *error);
void fail_destination_msg(struct multifundchannel_destination *dest,
int error_code,
const char *err_str TAKES);

/* dest_count - Returns count of destinations using given protocol version */
size_t dest_count(const struct multifundchannel_command *mfc,
Expand Down
Loading

0 comments on commit 2586641

Please sign in to comment.