From 8a8dabaa58b4479683f4caf8e8e9ef7ca746cce6 Mon Sep 17 00:00:00 2001 From: Michael Schmoock Date: Wed, 28 Oct 2020 11:46:12 +0100 Subject: [PATCH] feat: adds state change cause and message This adds a `state_change` 'cause' to a channel. A 'cause' is some initial 'reason' a channel was created or closed by: /* Anything other than the reasons below. Should not happen. */ REASON_UNKNOWN, /* Unconscious internal reasons, e.g. dev fail of a channel. */ REASON_LOCAL, /* The operator or a plugin opened or closed a channel by intention. */ REASON_USER, /* The remote closed or funded a channel with us by intention. */ REASON_REMOTE, /* E.g. We need to close a channel because of bad signatures and such. */ REASON_PROTOCOL, /* A channel was closed onchain, while we were offline. */ /* Note: This is very likely a conscious remote decision. */ REASON_ONCHAIN If a 'cause' is known and a subsequent state change is made with `REASON_UNKNOWN` the preceding cause will be used as reason, since a lot (all `REASON_UNKNOWN`) state changes are a subsequent consequences of a prior cause: local, user, remote, protocol or onchain. Changelog-Added: Plugins: Channel closure resaon/cause to channel_state_changed notification --- lightningd/channel.c | 58 ++++++++++++++++++--- lightningd/channel.h | 17 +++++- lightningd/channel_control.c | 26 +++++++-- lightningd/channel_state.h | 21 ++++++++ lightningd/closing_control.c | 11 +++- lightningd/notification.c | 19 +++++-- lightningd/notification.h | 4 +- lightningd/onchain_control.c | 21 ++++++-- lightningd/peer_control.c | 21 +++++--- lightningd/peer_htlcs.c | 31 ++++++----- lightningd/test/run-invoice-select-inchan.c | 9 +++- wallet/db_postgres_sqlgen.c | 2 +- wallet/db_sqlite3_sqlgen.c | 2 +- wallet/statements_gettextgen.po | 4 +- wallet/test/run-wallet.c | 4 +- 15 files changed, 199 insertions(+), 51 deletions(-) diff --git a/lightningd/channel.c b/lightningd/channel.c index 61dcb2e51..c944a7329 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -289,6 +289,11 @@ struct channel *new_channel(struct peer *peer, u64 dbid, channel->rr_number = peer->ld->rr_counter++; tal_add_destructor(channel, destroy_channel); + channel->closer = NUM_SIDES; + channel->state_change_cause = REASON_USER; + if (opener == REMOTE) + channel->state_change_cause = REASON_REMOTE; + /* Make sure we see any spends using this key */ txfilter_add_scriptpubkey(peer->ld->owned_txfilter, take(p2wpkh_for_keyidx(NULL, peer->ld, @@ -420,10 +425,25 @@ void channel_set_last_tx(struct channel *channel, void channel_set_state(struct channel *channel, enum channel_state old_state, - enum channel_state state) + enum channel_state state, + enum state_change reason, + char *why) { struct channel_id cid; + /* set closer, if known */ + if (state > CHANNELD_NORMAL && channel->closer == NUM_SIDES) { + if (reason == REASON_LOCAL) channel->closer = LOCAL; + if (reason == REASON_USER) channel->closer = LOCAL; + if (reason == REASON_REMOTE) channel->closer = REMOTE; + } + + /* use or update state_change_cause, if known */ + if (reason != REASON_UNKNOWN) + channel->state_change_cause = reason; + else + reason = channel->state_change_cause; + log_info(channel->log, "State changed from %s to %s", channel_state_name(channel), channel_state_str(state)); if (channel->state != old_state) @@ -443,11 +463,29 @@ void channel_set_state(struct channel *channel, &cid, channel->scid, old_state, - state); + state, + reason, + why); } } -void channel_fail_permanent(struct channel *channel, const char *fmt, ...) +const char *channel_change_state_reason_str(enum state_change reason) +{ + switch (reason) { + case REASON_UNKNOWN: return "unknown"; + case REASON_LOCAL: return "local"; + case REASON_USER: return "user"; + case REASON_REMOTE: return "remote"; + case REASON_PROTOCOL: return "protocol"; + case REASON_ONCHAIN: return "onchain"; + } + abort(); +} + +void channel_fail_permanent(struct channel *channel, + enum state_change reason, + const char *fmt, + ...) { struct lightningd *ld = channel->peer->ld; va_list ap; @@ -470,7 +508,11 @@ void channel_fail_permanent(struct channel *channel, const char *fmt, ...) drop_to_chain(ld, channel, false); if (channel_active(channel)) - channel_set_state(channel, channel->state, AWAITING_UNILATERAL); + channel_set_state(channel, + channel->state, + AWAITING_UNILATERAL, + reason, + why); tal_free(why); } @@ -512,9 +554,9 @@ void channel_internal_error(struct channel *channel, const char *fmt, ...) /* Don't expose internal error causes to remove unless doing dev */ #if DEVELOPER - channel_fail_permanent(channel, "Internal error: %s", why); + channel_fail_permanent(channel, REASON_LOCAL, "Internal error: %s", why); #else - channel_fail_permanent(channel, "Internal error"); + channel_fail_permanent(channel, REASON_LOCAL, "Internal error"); #endif tal_free(why); } @@ -545,7 +587,9 @@ static void err_and_reconnect(struct channel *channel, #if DEVELOPER if (dev_disconnect_permanent(channel->peer->ld)) { - channel_fail_permanent(channel, "dev_disconnect permfail"); + channel_fail_permanent(channel, + REASON_LOCAL, + "dev_disconnect permfail"); return; } #endif diff --git a/lightningd/channel.h b/lightningd/channel.h index 7b7d1e6af..4d544631a 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -151,6 +151,12 @@ struct channel { /* PSBT, for v2 channels. Saved until it's sent */ struct wally_psbt *psbt; + + /* the one that initiated a bilateral close, NUM_SIDES if unknown. */ + enum side closer; + + /* Last known state_change cause */ + enum state_change state_change_cause; }; struct channel *new_channel(struct peer *peer, u64 dbid, @@ -222,7 +228,10 @@ void channel_fail_reconnect_later(struct channel *channel, const char *fmt,...) PRINTF_FMT(2,3); /* Channel has failed, give up on it. */ -void channel_fail_permanent(struct channel *channel, const char *fmt, ...); +void channel_fail_permanent(struct channel *channel, + enum state_change reason, + const char *fmt, + ...); /* Forget the channel. This is only used for the case when we "receive" error * during CHANNELD_AWAITING_LOCKIN if we are "fundee". */ void channel_fail_forget(struct channel *channel, const char *fmt, ...); @@ -231,7 +240,11 @@ void channel_internal_error(struct channel *channel, const char *fmt, ...); void channel_set_state(struct channel *channel, enum channel_state old_state, - enum channel_state state); + enum channel_state state, + enum state_change reason, + char *why); + +const char *channel_change_state_reason_str(enum state_change reason); /* Find a channel which is not onchain, if any */ struct channel *peer_active_channel(struct peer *peer); diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index bc35e24d4..757ea3456 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -136,7 +136,11 @@ static void lockin_complete(struct channel *channel) return; } - channel_set_state(channel, CHANNELD_AWAITING_LOCKIN, CHANNELD_NORMAL); + channel_set_state(channel, + CHANNELD_AWAITING_LOCKIN, + CHANNELD_NORMAL, + REASON_UNKNOWN, + "Lockin complete"); /* Fees might have changed (and we use IMMEDIATE once we're funded), * so update now. */ @@ -224,7 +228,9 @@ static void peer_got_shutdown(struct channel *channel, const u8 *msg) */ if (!is_p2pkh(scriptpubkey, NULL) && !is_p2sh(scriptpubkey, NULL) && !is_p2wpkh(scriptpubkey, NULL) && !is_p2wsh(scriptpubkey, NULL)) { - channel_fail_permanent(channel, "Bad shutdown scriptpubkey %s", + channel_fail_permanent(channel, + REASON_PROTOCOL, + "Bad shutdown scriptpubkey %s", tal_hex(channel, scriptpubkey)); return; } @@ -232,7 +238,10 @@ static void peer_got_shutdown(struct channel *channel, const u8 *msg) /* If we weren't already shutting down, we are now */ if (channel->state != CHANNELD_SHUTTING_DOWN) channel_set_state(channel, - channel->state, CHANNELD_SHUTTING_DOWN); + channel->state, + CHANNELD_SHUTTING_DOWN, + REASON_REMOTE, + "Peer closes channel"); /* TODO(cdecker) Selectively save updated fields to DB */ wallet_channel_save(ld->wallet, channel); @@ -265,7 +274,9 @@ static void channel_fail_fallen_behind(struct channel *channel, const u8 *msg) } /* Peer sees this, so send a generic msg about unilateral close. */ - channel_fail_permanent(channel, "Awaiting unilateral close"); + channel_fail_permanent(channel, + REASON_LOCAL, + "Awaiting unilateral close"); } static void peer_start_closingd_after_shutdown(struct channel *channel, @@ -283,7 +294,11 @@ static void peer_start_closingd_after_shutdown(struct channel *channel, /* This sets channel->owner, closes down channeld. */ peer_start_closingd(channel, pps, false, NULL); - channel_set_state(channel, CHANNELD_SHUTTING_DOWN, CLOSINGD_SIGEXCHANGE); + channel_set_state(channel, + CHANNELD_SHUTTING_DOWN, + CLOSINGD_SIGEXCHANGE, + REASON_UNKNOWN, + "Start closingd"); } static void forget(struct channel *channel) @@ -638,6 +653,7 @@ void peer_start_channeld(struct channel *channel, num_revocations-1, &last_remote_per_commit_secret)) { channel_fail_permanent(channel, + REASON_LOCAL, "Could not get revocation secret %"PRIu64, num_revocations-1); return; diff --git a/lightningd/channel_state.h b/lightningd/channel_state.h index f1bcd1bc3..bfd319ab8 100644 --- a/lightningd/channel_state.h +++ b/lightningd/channel_state.h @@ -33,4 +33,25 @@ enum channel_state { }; #define CHANNEL_STATE_MAX CLOSED +enum state_change { + /* Anything other than the reasons below. Should not happen. */ + REASON_UNKNOWN, + + /* Unconscious internal reasons, e.g. dev fail of a channel. */ + REASON_LOCAL, + + /* The operator or a plugin opened or closed a channel by intention. */ + REASON_USER, + + /* The remote closed or funded a channel with us by intention. */ + REASON_REMOTE, + + /* E.g. We need to close a channel because of bad signatures and such. */ + REASON_PROTOCOL, + + /* A channel was closed onchain, while we were offline. */ + /* Note: This is very likely a conscious remote decision. */ + REASON_ONCHAIN +}; + #endif /* LIGHTNING_LIGHTNINGD_CHANNEL_STATE_H */ diff --git a/lightningd/closing_control.c b/lightningd/closing_control.c index b38590b67..31b44c9ed 100644 --- a/lightningd/closing_control.c +++ b/lightningd/closing_control.c @@ -137,7 +137,11 @@ static void peer_closing_complete(struct channel *channel, const u8 *msg) /* Channel gets dropped to chain cooperatively. */ drop_to_chain(channel->peer->ld, channel, true); - channel_set_state(channel, CLOSINGD_SIGEXCHANGE, CLOSINGD_COMPLETE); + channel_set_state(channel, + CLOSINGD_SIGEXCHANGE, + CLOSINGD_COMPLETE, + REASON_UNKNOWN, + "Closing complete"); } static unsigned closing_msg(struct subd *sd, const u8 *msg, const int *fds UNUSED) @@ -256,7 +260,9 @@ void peer_start_closingd(struct channel *channel, &channel->funding), type_to_string(tmpctx, struct amount_msat, &channel->our_msat)); - channel_fail_permanent(channel, "our_msat overflow on closing"); + channel_fail_permanent(channel, + REASON_LOCAL, + "our_msat overflow on closing"); return; } @@ -274,6 +280,7 @@ void peer_start_closingd(struct channel *channel, num_revocations-1, &last_remote_per_commit_secret)) { channel_fail_permanent(channel, + REASON_LOCAL, "Could not get revocation secret %"PRIu64, num_revocations-1); return; diff --git a/lightningd/notification.c b/lightningd/notification.c index a6de02c1e..d0a22f3cd 100644 --- a/lightningd/notification.c +++ b/lightningd/notification.c @@ -215,7 +215,9 @@ static void channel_state_changed_notification_serialize(struct json_stream *str struct channel_id *cid, struct short_channel_id *scid, enum channel_state old_state, - enum channel_state new_state) + enum channel_state new_state, + enum state_change cause, + char *message) { json_object_start(stream, "channel_state_changed"); json_add_node_id(stream, "peer_id", peer_id); @@ -226,6 +228,11 @@ static void channel_state_changed_notification_serialize(struct json_stream *str json_add_null(stream, "short_channel_id"); json_add_string(stream, "old_state", channel_state_str(old_state)); json_add_string(stream, "new_state", channel_state_str(new_state)); + json_add_string(stream, "cause", channel_change_state_reason_str(cause)); + if (message != NULL) + json_add_string(stream, "message", message); + else + json_add_null(stream, "message"); json_object_end(stream); } @@ -238,18 +245,22 @@ void notify_channel_state_changed(struct lightningd *ld, struct channel_id *cid, struct short_channel_id *scid, enum channel_state old_state, - enum channel_state new_state) + enum channel_state new_state, + enum state_change cause, + char *message) { void (*serialize)(struct json_stream *, struct node_id *, struct channel_id *, struct short_channel_id *, enum channel_state, - enum channel_state) = channel_state_changed_notification_gen.serialize; + enum channel_state, + enum state_change, + char *message) = channel_state_changed_notification_gen.serialize; struct jsonrpc_notification *n = jsonrpc_notification_start(NULL, channel_state_changed_notification_gen.topic); - serialize(n->stream, peer_id, cid, scid, old_state, new_state); + serialize(n->stream, peer_id, cid, scid, old_state, new_state, cause, message); jsonrpc_notification_end(n); plugins_notify(ld->plugins, take(n)); } diff --git a/lightningd/notification.h b/lightningd/notification.h index ce9f056d1..44a62a0a4 100644 --- a/lightningd/notification.h +++ b/lightningd/notification.h @@ -64,7 +64,9 @@ void notify_channel_state_changed(struct lightningd *ld, struct channel_id *cid, struct short_channel_id *scid, enum channel_state old_state, - enum channel_state new_state); + enum channel_state new_state, + enum state_change cause, + char *message); void notify_forward_event(struct lightningd *ld, const struct htlc_in *in, diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 52c4264b4..92c6f70bd 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -72,7 +72,11 @@ static void onchaind_tell_fulfill(struct channel *channel) static void handle_onchain_init_reply(struct channel *channel, const u8 *msg UNUSED) { /* FIXME: We may already be ONCHAIN state when we implement restart! */ - channel_set_state(channel, FUNDING_SPEND_SEEN, ONCHAIN); + channel_set_state(channel, + FUNDING_SPEND_SEEN, + ONCHAIN, + REASON_UNKNOWN, + "Onchain init reply"); } /** @@ -560,11 +564,22 @@ enum watch_result onchaind_funding_spent(struct channel *channel, struct pubkey final_key; int hsmfd; u32 feerates[3]; + enum state_change reason; - channel_fail_permanent(channel, "Funding transaction spent"); + /* use REASON_ONCHAIN or closer's reason, if known */ + reason = REASON_ONCHAIN; + if (channel->closer != NUM_SIDES) + reason = REASON_UNKNOWN; /* will use last cause as reason */ + + channel_fail_permanent(channel, reason, "Funding transaction spent"); /* We could come from almost any state. */ - channel_set_state(channel, channel->state, FUNDING_SPEND_SEEN); + /* NOTE(mschmoock) above comment is wrong, since we failed above! */ + channel_set_state(channel, + channel->state, + FUNDING_SPEND_SEEN, + reason, + "Onchain funding spend"); hsmfd = hsm_get_client_fd(ld, &channel->peer->id, channel->dbid, diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 791e10129..4c6f6e6a1 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -287,8 +287,8 @@ close_command_timeout(struct close_command *cc) if (!deprecated_apis) json_notify_fmt(cc->cmd, LOG_INFORM, "Timed out, forcing close."); - channel_fail_permanent(cc->channel, - "Forcibly closed by 'close' command timeout"); + channel_fail_permanent(cc->channel, REASON_USER, + "Forcibly closed by `close` command timeout"); } /* Construct a close command structure and add to ld. */ @@ -491,7 +491,9 @@ void channel_errmsg(struct channel *channel, channel->owner->name, err_for_them ? "sent" : "received", desc); else - channel_fail_permanent(channel, "%s: %s ERROR %s", + channel_fail_permanent(channel, + err_for_them ? REASON_LOCAL : REASON_PROTOCOL, + "%s: %s ERROR %s", channel->owner->name, err_for_them ? "sent" : "received", desc); } @@ -1022,6 +1024,7 @@ peer_connected_hook_cb(struct peer_connected_hook_payload *payload STEALS, #if DEVELOPER if (dev_disconnect_permanent(ld)) { channel_fail_permanent(channel, + REASON_LOCAL, "dev_disconnect permfail"); error = channel->error; goto send_error; @@ -1199,7 +1202,9 @@ static enum watch_result funding_depth_cb(struct lightningd *ld, if (!mk_short_channel_id(&scid, loc->blkheight, loc->index, channel->funding_outnum)) { - channel_fail_permanent(channel, "Invalid funding scid %u:%u:%u", + channel_fail_permanent(channel, + REASON_LOCAL, + "Invalid funding scid %u:%u:%u", loc->blkheight, loc->index, channel->funding_outnum); return DELETE_WATCH; @@ -1518,7 +1523,9 @@ static struct command_result *json_close(struct command *cmd, case CHANNELD_NORMAL: case CHANNELD_AWAITING_LOCKIN: channel_set_state(channel, - channel->state, CHANNELD_SHUTTING_DOWN); + channel->state, CHANNELD_SHUTTING_DOWN, + REASON_USER, + "User or plugin invoked close command"); /* fallthrough */ case CHANNELD_SHUTTING_DOWN: if (channel->owner) @@ -2104,7 +2111,9 @@ static struct command_result *json_dev_fail(struct command *cmd, "Could not find active channel with peer"); } - channel_fail_permanent(channel, "Failing due to dev-fail command"); + channel_fail_permanent(channel, + REASON_USER, + "Failing due to dev-fail command"); return command_success(cmd, json_stream_success(cmd)); } diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 83bc4d0b5..560a4cee2 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -2099,10 +2099,11 @@ void peer_got_revoke(struct channel *channel, const u8 *msg) shachain_index(revokenum), &per_commitment_secret)) { channel_fail_permanent(channel, - "Bad per_commitment_secret %s for %"PRIu64, - type_to_string(msg, struct secret, - &per_commitment_secret), - revokenum); + REASON_PROTOCOL, + "Bad per_commitment_secret %s for %"PRIu64, + type_to_string(msg, struct secret, + &per_commitment_secret), + revokenum); return; } @@ -2320,11 +2321,12 @@ void htlcs_notify_new_block(struct lightningd *ld, u32 height) continue; channel_fail_permanent(hout->key.channel, - "Offered HTLC %"PRIu64 - " %s cltv %u hit deadline", - hout->key.id, - htlc_state_name(hout->hstate), - hout->cltv_expiry); + REASON_PROTOCOL, + "Offered HTLC %"PRIu64 + " %s cltv %u hit deadline", + hout->key.id, + htlc_state_name(hout->hstate), + hout->cltv_expiry); removed = true; } /* Iteration while removing is safe, but can skip entries! */ @@ -2368,11 +2370,12 @@ void htlcs_notify_new_block(struct lightningd *ld, u32 height) continue; channel_fail_permanent(channel, - "Fulfilled HTLC %"PRIu64 - " %s cltv %u hit deadline", - hin->key.id, - htlc_state_name(hin->hstate), - hin->cltv_expiry); + REASON_PROTOCOL, + "Fulfilled HTLC %"PRIu64 + " %s cltv %u hit deadline", + hin->key.id, + htlc_state_name(hin->hstate), + hin->cltv_expiry); removed = true; } /* Iteration while removing is safe, but can skip entries! */ diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index b47f45f66..5488dc367 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -46,7 +46,10 @@ void broadcast_tx(struct chain_topology *topo UNNEEDED, void channel_fail_forget(struct channel *channel UNNEEDED, const char *fmt UNNEEDED, ...) { fprintf(stderr, "channel_fail_forget called!\n"); abort(); } /* Generated stub for channel_fail_permanent */ -void channel_fail_permanent(struct channel *channel UNNEEDED, const char *fmt UNNEEDED, ...) +void channel_fail_permanent(struct channel *channel UNNEEDED, + enum state_change reason UNNEEDED, + const char *fmt UNNEEDED, + ...) { fprintf(stderr, "channel_fail_permanent called!\n"); abort(); } /* Generated stub for channel_fail_reconnect */ void channel_fail_reconnect(struct channel *channel UNNEEDED, @@ -72,7 +75,9 @@ void channel_set_billboard(struct channel *channel UNNEEDED, bool perm UNNEEDED, /* Generated stub for channel_set_state */ void channel_set_state(struct channel *channel UNNEEDED, enum channel_state old_state UNNEEDED, - enum channel_state state UNNEEDED) + enum channel_state state UNNEEDED, + enum state_change reason UNNEEDED, + char *why UNNEEDED) { fprintf(stderr, "channel_set_state called!\n"); abort(); } /* Generated stub for channel_state_name */ const char *channel_state_name(const struct channel *channel UNNEEDED) diff --git a/wallet/db_postgres_sqlgen.c b/wallet/db_postgres_sqlgen.c index 0c44a217a..28386a68b 100644 --- a/wallet/db_postgres_sqlgen.c +++ b/wallet/db_postgres_sqlgen.c @@ -1660,4 +1660,4 @@ struct db_query db_postgres_queries[] = { #endif /* LIGHTNINGD_WALLET_GEN_DB_POSTGRES */ -// SHA256STAMP:8a260050ced7606fcad6e15df51a42a442f3119ad82d8e86fa2d348a2a45ee1a +// SHA256STAMP:bb84a713ee593a4ac2441ae971851f3b466e8c2bd6cf3cbf6261f3d4d0fb803d diff --git a/wallet/db_sqlite3_sqlgen.c b/wallet/db_sqlite3_sqlgen.c index 46635bcdf..69e876f17 100644 --- a/wallet/db_sqlite3_sqlgen.c +++ b/wallet/db_sqlite3_sqlgen.c @@ -1660,4 +1660,4 @@ struct db_query db_sqlite3_queries[] = { #endif /* LIGHTNINGD_WALLET_GEN_DB_SQLITE3 */ -// SHA256STAMP:8a260050ced7606fcad6e15df51a42a442f3119ad82d8e86fa2d348a2a45ee1a +// SHA256STAMP:bb84a713ee593a4ac2441ae971851f3b466e8c2bd6cf3cbf6261f3d4d0fb803d diff --git a/wallet/statements_gettextgen.po b/wallet/statements_gettextgen.po index e806d2d42..d33d152ef 100644 --- a/wallet/statements_gettextgen.po +++ b/wallet/statements_gettextgen.po @@ -1090,7 +1090,7 @@ msgstr "" msgid "not a valid SQL statement" msgstr "" -#: wallet/test/run-wallet.c:1365 +#: wallet/test/run-wallet.c:1367 msgid "INSERT INTO channels (id) VALUES (1);" msgstr "" -# SHA256STAMP:9d0158f039940ef277ed6fc3a27b3695dec7f9869ea11e0f9eea8313a5849f08 +# SHA256STAMP:1ad776f09062dbee2206b358b64812c1a5bf4a4e2a1de08c1c5dc659481df667 diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 8566d1787..b5f56b0f3 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -440,7 +440,9 @@ void notify_channel_state_changed(struct lightningd *ld UNNEEDED, struct channel_id *cid UNNEEDED, struct short_channel_id *scid UNNEEDED, enum channel_state old_state UNNEEDED, - enum channel_state new_state UNNEEDED) + enum channel_state new_state UNNEEDED, + enum state_change cause UNNEEDED, + char *message UNNEEDED) { fprintf(stderr, "notify_channel_state_changed called!\n"); abort(); } /* Generated stub for notify_connect */ void notify_connect(struct lightningd *ld UNNEEDED, struct node_id *nodeid UNNEEDED,