Skip to content

Commit

Permalink
openchannel: make openchannel hook chainable
Browse files Browse the repository at this point in the history
  • Loading branch information
m-schmoock committed Aug 20, 2020
1 parent af4eec7 commit 11b6257
Showing 1 changed file with 81 additions and 59 deletions.
140 changes: 81 additions & 59 deletions lightningd/opening_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,8 @@ struct openchannel_hook_payload {
u16 max_accepted_htlcs;
u8 channel_flags;
u8 *shutdown_scriptpubkey;
const u8 *our_upfront_shutdown_script;
char *errmsg;
};

static void
Expand Down Expand Up @@ -799,13 +801,80 @@ static void openchannel_payload_remove_openingd(struct subd *openingd,
payload->openingd = NULL;
}

static void openchannel_hook_cb(struct openchannel_hook_payload *payload STEALS,
const char *buffer,
const jsmntok_t *toks)
static bool
openchannel_hook_deserialize(struct openchannel_hook_payload *payload,
const char *buffer,
const jsmntok_t *toks)
{
struct subd *openingd = payload->openingd;
const u8 *our_upfront_shutdown_script;
const char *errmsg = NULL;

if (!toks || !buffer)
return true;

const jsmntok_t *t = json_get_member(buffer, toks, "result");
if (!t)
fatal("Plugin returned an invalid response to the"
" openchannel hook: %.*s",
toks[0].end - toks[0].start,
buffer + toks[0].start);

if (json_tok_streq(buffer, t, "reject")) {
payload->errmsg = "";
t = json_get_member(buffer, toks, "error_message");
if (t)
payload->errmsg = json_strdup(tmpctx, buffer, t);
log_debug(openingd->ld->log,
"openchannel_hook rejetcs and says '%s'",
payload->errmsg);
} else if (!json_tok_streq(buffer, t, "continue"))
fatal("Plugin returned an invalid result for the "
"openchannel hook: %.*s",
t->end - t->start, buffer + t->start);

if (payload->errmsg) {
t = json_get_member(buffer, toks, "close_to");
if (t)
fatal("Plugin rejected openchannel but also set a close_to");
/* don't call further plugins if a channel is to be rejected */
return false;
}

/* Check for a 'close_to' address passed back */
t = json_get_member(buffer, toks, "close_to");
if (t) {
/* First plugin can set close_to. Log others. */
if (payload->our_upfront_shutdown_script) {
log_unusual(openingd->ld->log,
"openchannel_hook close_to address was"
" already set by other plugin. Ignoring!");
return true;
}
switch (json_to_address_scriptpubkey(tmpctx, chainparams,
buffer, t,
&payload->our_upfront_shutdown_script)) {
case ADDRESS_PARSE_UNRECOGNIZED:
fatal("Plugin returned an invalid response to"
" the openchannel.close_to hook: %.*s",
t->end - t->start, buffer + t->start);
case ADDRESS_PARSE_WRONG_NETWORK:
fatal("Plugin returned invalid response to the"
" openchannel.close_to hook: address %s is"
" not on network %s",
tal_hex(NULL, payload->our_upfront_shutdown_script),
chainparams->network_name);
case ADDRESS_PARSE_SUCCESS:
break;
}
}
return true;
}

static void
openchannel_hook_final(struct openchannel_hook_payload *payload STEALS)
{
struct subd *openingd = payload->openingd;
const u8 *our_upfront_shutdown_script = payload->our_upfront_shutdown_script;
const char *errmsg = payload->errmsg;

/* We want to free this, whatever happens. */
tal_steal(tmpctx, payload);
Expand All @@ -816,65 +885,16 @@ static void openchannel_hook_cb(struct openchannel_hook_payload *payload STEALS,

tal_del_destructor2(openingd, openchannel_payload_remove_openingd, payload);

/* If we had a hook, check what it says */
if (buffer) {
const jsmntok_t *t = json_get_member(buffer, toks, "result");
if (!t)
fatal("Plugin returned an invalid response to the"
" openchannel hook: %.*s",
toks[0].end - toks[0].start,
buffer + toks[0].start);

if (json_tok_streq(buffer, t, "reject")) {
t = json_get_member(buffer, toks, "error_message");
if (t)
errmsg = json_strdup(tmpctx, buffer, t);
else
errmsg = "";
log_debug(openingd->ld->log,
"openchannel_hook_cb says '%s'",
errmsg);
our_upfront_shutdown_script = NULL;
} else if (!json_tok_streq(buffer, t, "continue"))
fatal("Plugin returned an invalid result for the "
"openchannel hook: %.*s",
t->end - t->start, buffer + t->start);

/* Check for a 'close_to' address passed back */
if (!errmsg) {
t = json_get_member(buffer, toks, "close_to");
if (t) {
switch (json_to_address_scriptpubkey(tmpctx, chainparams,
buffer, t,
&our_upfront_shutdown_script)) {
case ADDRESS_PARSE_UNRECOGNIZED:
fatal("Plugin returned an invalid response to the"
" openchannel.close_to hook: %.*s",
t->end - t->start, buffer + t->start);
case ADDRESS_PARSE_WRONG_NETWORK:
fatal("Plugin returned invalid response to the"
" openchannel.close_to hook: address %s is"
" not on network %s",
tal_hex(NULL, our_upfront_shutdown_script),
chainparams->network_name);
case ADDRESS_PARSE_SUCCESS:
errmsg = NULL;
}
} else
our_upfront_shutdown_script = NULL;
}
} else
our_upfront_shutdown_script = NULL;

subd_send_msg(openingd,
take(towire_opening_got_offer_reply(NULL, errmsg,
our_upfront_shutdown_script)));
}

REGISTER_SINGLE_PLUGIN_HOOK(openchannel,
openchannel_hook_cb,
openchannel_hook_serialize,
struct openchannel_hook_payload *);
REGISTER_PLUGIN_HOOK(openchannel,
openchannel_hook_deserialize,
openchannel_hook_final,
openchannel_hook_serialize,
struct openchannel_hook_payload *);

static void opening_got_offer(struct subd *openingd,
const u8 *msg,
Expand All @@ -892,6 +912,8 @@ static void opening_got_offer(struct subd *openingd,

payload = tal(openingd, struct openchannel_hook_payload);
payload->openingd = openingd;
payload->our_upfront_shutdown_script = NULL;
payload->errmsg = NULL;
if (!fromwire_opening_got_offer(payload, msg,
&payload->funding_satoshis,
&payload->push_msat,
Expand Down

0 comments on commit 11b6257

Please sign in to comment.