mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 09:54:16 +01:00
mfc: use consolidated error reporting, reduce reliance on json-str
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.
This commit is contained in:
parent
ef1e36efe5
commit
2586641678
@ -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. */
|
||||
@ -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);
|
||||
@ -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)
|
||||
@ -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: "
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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. */
|
||||
@ -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.
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
@ -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.",
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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)) {
|
||||
@ -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 {
|
||||
@ -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);
|
||||
@ -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;
|
||||
|
@ -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. */
|
||||
@ -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;
|
||||
@ -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,
|
||||
|
@ -344,11 +344,12 @@ openchannel_finished(struct multifundchannel_command *mfc)
|
||||
mfc->id, dest->index);
|
||||
|
||||
out = jsonrpc_stream_fail_data(mfc->cmd,
|
||||
dest->code,
|
||||
dest->error);
|
||||
dest->error_code,
|
||||
dest->error_message);
|
||||
json_add_node_id(out, "id", &dest->id);
|
||||
json_add_string(out, "method", "openchannel_signed");
|
||||
json_add_jsonstr(out, "error", dest->error);
|
||||
if (dest->error_data)
|
||||
json_add_jsonstr(out, "data", dest->error_data);
|
||||
json_object_end(out);
|
||||
|
||||
return mfc_finished(mfc, out);
|
||||
@ -415,23 +416,8 @@ openchannel_signed_err(struct command *cmd,
|
||||
struct multifundchannel_destination *dest)
|
||||
{
|
||||
struct multifundchannel_command *mfc = dest->mfc;
|
||||
const jsmntok_t *code_tok;
|
||||
|
||||
code_tok = json_get_member(buf, error, "code");
|
||||
if (!code_tok)
|
||||
plugin_err(cmd->plugin,
|
||||
"`openchannel_signed` 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,
|
||||
"`openchannel_signed` 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 after_openchannel_signed(mfc);
|
||||
}
|
||||
|
||||
@ -755,23 +741,7 @@ openchannel_update_err(struct command *cmd,
|
||||
const jsmntok_t *error,
|
||||
struct multifundchannel_destination *dest)
|
||||
{
|
||||
const jsmntok_t *code_tok;
|
||||
|
||||
code_tok = json_get_member(buf, error, "code");
|
||||
if (!code_tok)
|
||||
plugin_err(cmd->plugin,
|
||||
"`openchannel_update` failure missing "
|
||||
"`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,
|
||||
"`openchannel_update` returned 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 openchannel_update_returned(dest);
|
||||
}
|
||||
|
||||
@ -818,7 +788,7 @@ perform_openchannel_update(struct multifundchannel_command *mfc)
|
||||
if (dest->state == MULTIFUNDCHANNEL_FAILED)
|
||||
return redo_multifundchannel(mfc,
|
||||
"openchannel_update",
|
||||
dest->error);
|
||||
dest->error_message);
|
||||
|
||||
if (dest->state == MULTIFUNDCHANNEL_SECURED ||
|
||||
dest->state == MULTIFUNDCHANNEL_SIGNED) {
|
||||
@ -846,11 +816,12 @@ perform_openchannel_update(struct multifundchannel_command *mfc)
|
||||
if (!update_parent_psbt(mfc, dest, dest->psbt,
|
||||
dest->updated_psbt,
|
||||
&mfc->psbt)) {
|
||||
fail_destination(dest, "\"Unable to update parent "
|
||||
"with node's PSBT\"");
|
||||
fail_destination_msg(dest, FUNDING_PSBT_INVALID,
|
||||
"Unable to update parent "
|
||||
"with node's PSBT");
|
||||
return redo_multifundchannel(mfc,
|
||||
"openchannel_init_parent",
|
||||
dest->error);
|
||||
dest->error_message);
|
||||
}
|
||||
/* Get everything sorted correctly */
|
||||
psbt_sort_by_serial_id(mfc->psbt);
|
||||
@ -871,11 +842,12 @@ perform_openchannel_update(struct multifundchannel_command *mfc)
|
||||
continue;
|
||||
|
||||
if (!update_node_psbt(mfc, mfc->psbt, &dest->psbt)) {
|
||||
fail_destination(dest, "\"Unable to node PSBT"
|
||||
" with parent PSBT\"");
|
||||
fail_destination_msg(dest, FUNDING_PSBT_INVALID,
|
||||
"Unable to update peer's PSBT"
|
||||
" with parent PSBT");
|
||||
return redo_multifundchannel(mfc,
|
||||
"openchannel_init_node",
|
||||
dest->error);
|
||||
dest->error_message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -957,9 +929,9 @@ openchannel_init_ok(struct command *cmd,
|
||||
/* Port any updates onto 'parent' PSBT */
|
||||
if (!update_parent_psbt(dest->mfc, dest, dest->psbt,
|
||||
dest->updated_psbt, &mfc->psbt)) {
|
||||
fail_destination(dest,
|
||||
take(tal_fmt(NULL, "\"Unable to update parent"
|
||||
" with node's PSBT\"")));
|
||||
fail_destination_msg(dest, FUNDING_PSBT_INVALID,
|
||||
"Unable to update parent"
|
||||
" with node's PSBT");
|
||||
}
|
||||
|
||||
/* Clone updated-psbt to psbt, so original changeset
|
||||
@ -977,23 +949,7 @@ openchannel_init_err(struct command *cmd,
|
||||
const jsmntok_t *error,
|
||||
struct multifundchannel_destination *dest)
|
||||
{
|
||||
const jsmntok_t *code_tok;
|
||||
|
||||
code_tok = json_get_member(buf, error, "code");
|
||||
if (!code_tok)
|
||||
plugin_err(cmd->plugin,
|
||||
"`openchannel_init` 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,
|
||||
"`openchannel_init` 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 openchannel_init_done(dest);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user