From 9176ee628c38e14564c6c9516feba7cc44e72d08 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 21 Feb 2018 07:29:09 +1030 Subject: [PATCH] lightningd/closing_control: routines to control closingd (move from peer_control.c) Signed-off-by: Rusty Russell --- lightningd/Makefile | 1 + lightningd/closing_control.c | 241 +++++++++++++++++++++++++++++++++ lightningd/closing_control.h | 15 +++ lightningd/peer_control.c | 251 ++--------------------------------- lightningd/peer_control.h | 10 ++ wallet/test/run-wallet.c | 22 +-- 6 files changed, 283 insertions(+), 257 deletions(-) create mode 100644 lightningd/closing_control.c create mode 100644 lightningd/closing_control.h diff --git a/lightningd/Makefile b/lightningd/Makefile index 3a6388f10..f33efd0fd 100644 --- a/lightningd/Makefile +++ b/lightningd/Makefile @@ -51,6 +51,7 @@ LIGHTNINGD_SRC := \ lightningd/build_utxos.c \ lightningd/chaintopology.c \ lightningd/channel.c \ + lightningd/closing_control.c \ lightningd/connect_control.c \ lightningd/gossip_control.c \ lightningd/gossip_msg.c \ diff --git a/lightningd/closing_control.c b/lightningd/closing_control.c new file mode 100644 index 000000000..264403115 --- /dev/null +++ b/lightningd/closing_control.c @@ -0,0 +1,241 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Is this better than the last tx we were holding? This can happen + * even without closingd misbehaving, if we have multiple, + * interrupted, rounds of negotiation. */ +static bool better_closing_fee(struct lightningd *ld, + struct channel *channel, + const struct bitcoin_tx *tx) +{ + u64 weight, fee, last_fee, ideal_fee, min_fee; + s64 old_diff, new_diff; + size_t i; + + /* Calculate actual fee (adds in eliminated outputs) */ + fee = channel->funding_satoshi; + for (i = 0; i < tal_count(tx->output); i++) + fee -= tx->output[i].amount; + + last_fee = channel->funding_satoshi; + for (i = 0; i < tal_count(channel->last_tx); i++) + last_fee -= channel->last_tx->output[i].amount; + + log_debug(channel->log, "Their actual closing tx fee is %"PRIu64 + " vs previous %"PRIu64, fee, last_fee); + + /* Weight once we add in sigs. */ + weight = measure_tx_weight(tx) + 74 * 2; + + min_fee = get_feerate(ld->topology, FEERATE_SLOW) * weight / 1000; + if (fee < min_fee) { + log_debug(channel->log, "... That's below our min %"PRIu64 + " for weight %"PRIu64" at feerate %u", + min_fee, weight, + get_feerate(ld->topology, FEERATE_SLOW)); + return false; + } + + ideal_fee = get_feerate(ld->topology, FEERATE_NORMAL) * weight / 1000; + + /* We prefer fee which is closest to our ideal. */ + old_diff = imaxabs((s64)ideal_fee - (s64)last_fee); + new_diff = imaxabs((s64)ideal_fee - (s64)fee); + + /* In case of a tie, prefer new over old: this covers the preference + * for a mutual close over a unilateral one. */ + log_debug(channel->log, "... That's %s our ideal %"PRIu64, + new_diff < old_diff + ? "closer to" + : new_diff > old_diff + ? "further from" + : "same distance to", + ideal_fee); + + return new_diff <= old_diff; +} + +static void peer_received_closing_signature(struct channel *channel, + const u8 *msg) +{ + secp256k1_ecdsa_signature sig; + struct bitcoin_tx *tx; + struct lightningd *ld = channel->peer->ld; + + if (!fromwire_closing_received_signature(msg, msg, NULL, &sig, &tx)) { + channel_internal_error(channel, "Bad closing_received_signature %s", + tal_hex(msg, msg)); + return; + } + + /* FIXME: Make sure signature is correct! */ + if (better_closing_fee(ld, channel, tx)) { + channel_set_last_tx(channel, tx, &sig); + /* TODO(cdecker) Selectively save updated fields to DB */ + wallet_channel_save(ld->wallet, channel); + } + + /* OK, you can continue now. */ + subd_send_msg(channel->owner, + take(towire_closing_received_signature_reply(channel))); +} + +static void peer_closing_complete(struct channel *channel, const u8 *msg) +{ + /* FIXME: We should save this, to return to gossipd */ + u64 gossip_index; + + if (!fromwire_closing_complete(msg, NULL, &gossip_index)) { + channel_internal_error(channel, "Bad closing_complete %s", + tal_hex(msg, msg)); + return; + } + + /* Retransmission only, ignore closing. */ + if (channel->state == CLOSINGD_COMPLETE) + return; + + drop_to_chain(channel->peer->ld, channel); + channel_set_state(channel, CLOSINGD_SIGEXCHANGE, CLOSINGD_COMPLETE); +} + +static unsigned closing_msg(struct subd *sd, const u8 *msg, const int *fds) +{ + enum closing_wire_type t = fromwire_peektype(msg); + + switch (t) { + case WIRE_CLOSING_RECEIVED_SIGNATURE: + peer_received_closing_signature(sd->channel, msg); + break; + + case WIRE_CLOSING_COMPLETE: + peer_closing_complete(sd->channel, msg); + break; + + /* We send these, not receive them */ + case WIRE_CLOSING_INIT: + case WIRE_CLOSING_RECEIVED_SIGNATURE_REPLY: + break; + } + + return 0; +} + +void peer_start_closingd(struct channel *channel, + struct crypto_state *cs, + u64 gossip_index, + int peer_fd, int gossip_fd, + bool reconnected) +{ + const tal_t *tmpctx = tal_tmpctx(channel); + u8 *initmsg, *local_scriptpubkey; + u64 minfee, startfee, feelimit; + u64 num_revocations; + u64 funding_msatoshi, our_msatoshi, their_msatoshi; + struct lightningd *ld = channel->peer->ld; + + if (channel->local_shutdown_idx == -1 + || !channel->remote_shutdown_scriptpubkey) { + channel_internal_error(channel, + "Can't start closing: local %s remote %s", + channel->local_shutdown_idx == -1 + ? "not shutdown" : "shutdown", + channel->remote_shutdown_scriptpubkey + ? "shutdown" : "not shutdown"); + tal_free(tmpctx); + return; + } + + channel_set_owner(channel, new_channel_subd(ld, + "lightning_closingd", + channel, channel->log, + closing_wire_type_name, closing_msg, + channel_errmsg, + take(&peer_fd), take(&gossip_fd), + NULL)); + if (!channel->owner) { + log_unusual(channel->log, "Could not subdaemon closing: %s", + strerror(errno)); + channel_fail_transient(channel, "Failed to subdaemon closing"); + tal_free(tmpctx); + return; + } + + local_scriptpubkey = p2wpkh_for_keyidx(tmpctx, ld, + channel->local_shutdown_idx); + if (!local_scriptpubkey) { + channel_internal_error(channel, + "Can't generate local shutdown scriptpubkey"); + tal_free(tmpctx); + return; + } + + /* BOLT #2: + * + * A sending node MUST set `fee_satoshis` lower than or equal + * to the base fee of the final commitment transaction as + * calculated in [BOLT + * #3](03-transactions.md#fee-calculation). + */ + feelimit = commit_tx_base_fee(channel->channel_info.feerate_per_kw[LOCAL], + 0); + + minfee = commit_tx_base_fee(get_feerate(ld->topology, FEERATE_SLOW), 0); + startfee = commit_tx_base_fee(get_feerate(ld->topology, FEERATE_NORMAL), + 0); + + if (startfee > feelimit) + startfee = feelimit; + if (minfee > feelimit) + minfee = feelimit; + + num_revocations + = revocations_received(&channel->their_shachain.chain); + + /* BOLT #3: + * + * The amounts for each output MUST BE rounded down to whole satoshis. + */ + /* Convert unit */ + funding_msatoshi = channel->funding_satoshi * 1000; + /* What is not ours is theirs */ + our_msatoshi = channel->our_msatoshi; + their_msatoshi = funding_msatoshi - our_msatoshi; + initmsg = towire_closing_init(tmpctx, + cs, + gossip_index, + &channel->seed, + &channel->funding_txid, + channel->funding_outnum, + channel->funding_satoshi, + &channel->channel_info.remote_fundingkey, + channel->funder, + our_msatoshi / 1000, /* Rounds down */ + their_msatoshi / 1000, /* Rounds down */ + channel->our_config.dust_limit_satoshis, + minfee, feelimit, startfee, + local_scriptpubkey, + channel->remote_shutdown_scriptpubkey, + reconnected, + channel->next_index[LOCAL], + channel->next_index[REMOTE], + num_revocations, + deprecated_apis); + + /* We don't expect a response: it will give us feedback on + * signatures sent and received, then closing_complete. */ + subd_send_msg(channel->owner, take(initmsg)); + tal_free(tmpctx); +} diff --git a/lightningd/closing_control.h b/lightningd/closing_control.h new file mode 100644 index 000000000..a5661e5ff --- /dev/null +++ b/lightningd/closing_control.h @@ -0,0 +1,15 @@ +#ifndef LIGHTNING_LIGHTNINGD_CLOSING_CONTROL_H +#define LIGHTNING_LIGHTNINGD_CLOSING_CONTROL_H +#include "config.h" +#include + +struct channel_id; +struct crypto_state; + +void peer_start_closingd(struct channel *channel, + struct crypto_state *cs, + u64 gossip_index, + int peer_fd, int gossip_fd, + bool reconnected); + +#endif /* LIGHTNING_LIGHTNINGD_CLOSING_CONTROL_H */ diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 9fa75e0b6..59080b510 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -11,8 +11,6 @@ #include #include #include -#include -#include #include #include #include @@ -30,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -54,11 +53,6 @@ static void copy_to_parent_log(const char *prefix, const char *str, const u8 *io, struct log *parent_log); -static void peer_start_closingd(struct channel *channel, - struct crypto_state *cs, - u64 gossip_index, - int peer_fd, int gossip_fd, - bool reconnected); static void destroy_peer(struct peer *peer) { @@ -162,13 +156,13 @@ void drop_to_chain(struct lightningd *ld, struct channel *channel) remove_sig(channel->last_tx); } -static void channel_errmsg(struct channel *channel, - int peer_fd, int gossip_fd, - const struct crypto_state *cs, - u64 gossip_index, - const struct channel_id *channel_id, - const char *desc, - const u8 *err_for_them) +void channel_errmsg(struct channel *channel, + int peer_fd, int gossip_fd, + const struct crypto_state *cs, + u64 gossip_index, + const struct channel_id *channel_id, + const char *desc, + const u8 *err_for_them) { struct lightningd *ld = channel->peer->ld; u8 *msg; @@ -991,7 +985,7 @@ static unsigned int onchain_msg(struct subd *sd, const u8 *msg, const int *fds) return 0; } -static u8 *p2wpkh_for_keyidx(const tal_t *ctx, struct lightningd *ld, u64 keyidx) +u8 *p2wpkh_for_keyidx(const tal_t *ctx, struct lightningd *ld, u64 keyidx) { struct pubkey shutdownkey; @@ -1356,233 +1350,6 @@ static void peer_got_shutdown(struct channel *channel, const u8 *msg) wallet_channel_save(ld->wallet, channel); } -/* Is this better than the last tx we were holding? This can happen - * even without closingd misbehaving, if we have multiple, - * interrupted, rounds of negotiation. */ -static bool better_closing_fee(struct lightningd *ld, - struct channel *channel, - const struct bitcoin_tx *tx) -{ - u64 weight, fee, last_fee, ideal_fee, min_fee; - s64 old_diff, new_diff; - size_t i; - - /* Calculate actual fee (adds in eliminated outputs) */ - fee = channel->funding_satoshi; - for (i = 0; i < tal_count(tx->output); i++) - fee -= tx->output[i].amount; - - last_fee = channel->funding_satoshi; - for (i = 0; i < tal_count(channel->last_tx); i++) - last_fee -= channel->last_tx->output[i].amount; - - log_debug(channel->log, "Their actual closing tx fee is %"PRIu64 - " vs previous %"PRIu64, fee, last_fee); - - /* Weight once we add in sigs. */ - weight = measure_tx_weight(tx) + 74 * 2; - - min_fee = get_feerate(ld->topology, FEERATE_SLOW) * weight / 1000; - if (fee < min_fee) { - log_debug(channel->log, "... That's below our min %"PRIu64 - " for weight %"PRIu64" at feerate %u", - min_fee, weight, - get_feerate(ld->topology, FEERATE_SLOW)); - return false; - } - - ideal_fee = get_feerate(ld->topology, FEERATE_NORMAL) * weight / 1000; - - /* We prefer fee which is closest to our ideal. */ - old_diff = imaxabs((s64)ideal_fee - (s64)last_fee); - new_diff = imaxabs((s64)ideal_fee - (s64)fee); - - /* In case of a tie, prefer new over old: this covers the preference - * for a mutual close over a unilateral one. */ - log_debug(channel->log, "... That's %s our ideal %"PRIu64, - new_diff < old_diff - ? "closer to" - : new_diff > old_diff - ? "further from" - : "same distance to", - ideal_fee); - - return new_diff <= old_diff; -} - -static void peer_received_closing_signature(struct channel *channel, - const u8 *msg) -{ - secp256k1_ecdsa_signature sig; - struct bitcoin_tx *tx; - struct lightningd *ld = channel->peer->ld; - - if (!fromwire_closing_received_signature(msg, msg, NULL, &sig, &tx)) { - channel_internal_error(channel, "Bad closing_received_signature %s", - tal_hex(msg, msg)); - return; - } - - /* FIXME: Make sure signature is correct! */ - if (better_closing_fee(ld, channel, tx)) { - channel_set_last_tx(channel, tx, &sig); - /* TODO(cdecker) Selectively save updated fields to DB */ - wallet_channel_save(ld->wallet, channel); - } - - /* OK, you can continue now. */ - subd_send_msg(channel->owner, - take(towire_closing_received_signature_reply(channel))); -} - -static void peer_closing_complete(struct channel *channel, const u8 *msg) -{ - /* FIXME: We should save this, to return to gossipd */ - u64 gossip_index; - - if (!fromwire_closing_complete(msg, NULL, &gossip_index)) { - channel_internal_error(channel, "Bad closing_complete %s", - tal_hex(msg, msg)); - return; - } - - /* Retransmission only, ignore closing. */ - if (channel->state == CLOSINGD_COMPLETE) - return; - - drop_to_chain(channel->peer->ld, channel); - channel_set_state(channel, CLOSINGD_SIGEXCHANGE, CLOSINGD_COMPLETE); -} - -static unsigned closing_msg(struct subd *sd, const u8 *msg, const int *fds) -{ - enum closing_wire_type t = fromwire_peektype(msg); - - switch (t) { - case WIRE_CLOSING_RECEIVED_SIGNATURE: - peer_received_closing_signature(sd->channel, msg); - break; - - case WIRE_CLOSING_COMPLETE: - peer_closing_complete(sd->channel, msg); - break; - - /* We send these, not receive them */ - case WIRE_CLOSING_INIT: - case WIRE_CLOSING_RECEIVED_SIGNATURE_REPLY: - break; - } - - return 0; -} - -static void peer_start_closingd(struct channel *channel, - struct crypto_state *cs, - u64 gossip_index, - int peer_fd, int gossip_fd, - bool reconnected) -{ - const tal_t *tmpctx = tal_tmpctx(channel); - u8 *initmsg, *local_scriptpubkey; - u64 minfee, startfee, feelimit; - u64 num_revocations; - u64 funding_msatoshi, our_msatoshi, their_msatoshi; - struct lightningd *ld = channel->peer->ld; - - if (channel->local_shutdown_idx == -1 - || !channel->remote_shutdown_scriptpubkey) { - channel_internal_error(channel, - "Can't start closing: local %s remote %s", - channel->local_shutdown_idx == -1 - ? "not shutdown" : "shutdown", - channel->remote_shutdown_scriptpubkey - ? "shutdown" : "not shutdown"); - tal_free(tmpctx); - return; - } - - channel_set_owner(channel, new_channel_subd(ld, - "lightning_closingd", - channel, channel->log, - closing_wire_type_name, closing_msg, - channel_errmsg, - take(&peer_fd), take(&gossip_fd), - NULL)); - if (!channel->owner) { - log_unusual(channel->log, "Could not subdaemon closing: %s", - strerror(errno)); - channel_fail_transient(channel, "Failed to subdaemon closing"); - tal_free(tmpctx); - return; - } - - local_scriptpubkey = p2wpkh_for_keyidx(tmpctx, ld, - channel->local_shutdown_idx); - if (!local_scriptpubkey) { - channel_internal_error(channel, - "Can't generate local shutdown scriptpubkey"); - tal_free(tmpctx); - return; - } - - /* BOLT #2: - * - * A sending node MUST set `fee_satoshis` lower than or equal - * to the base fee of the final commitment transaction as - * calculated in [BOLT - * #3](03-transactions.md#fee-calculation). - */ - feelimit = commit_tx_base_fee(channel->channel_info.feerate_per_kw[LOCAL], - 0); - - minfee = commit_tx_base_fee(get_feerate(ld->topology, FEERATE_SLOW), 0); - startfee = commit_tx_base_fee(get_feerate(ld->topology, FEERATE_NORMAL), - 0); - - if (startfee > feelimit) - startfee = feelimit; - if (minfee > feelimit) - minfee = feelimit; - - num_revocations - = revocations_received(&channel->their_shachain.chain); - - /* BOLT #3: - * - * The amounts for each output MUST BE rounded down to whole satoshis. - */ - /* Convert unit */ - funding_msatoshi = channel->funding_satoshi * 1000; - /* What is not ours is theirs */ - our_msatoshi = channel->our_msatoshi; - their_msatoshi = funding_msatoshi - our_msatoshi; - initmsg = towire_closing_init(tmpctx, - cs, - gossip_index, - &channel->seed, - &channel->funding_txid, - channel->funding_outnum, - channel->funding_satoshi, - &channel->channel_info.remote_fundingkey, - channel->funder, - our_msatoshi / 1000, /* Rounds down */ - their_msatoshi / 1000, /* Rounds down */ - channel->our_config.dust_limit_satoshis, - minfee, feelimit, startfee, - local_scriptpubkey, - channel->remote_shutdown_scriptpubkey, - reconnected, - channel->next_index[LOCAL], - channel->next_index[REMOTE], - num_revocations, - deprecated_apis); - - /* We don't expect a response: it will give us feedback on - * signatures sent and received, then closing_complete. */ - subd_send_msg(channel->owner, take(initmsg)); - tal_free(tmpctx); -} - static void peer_start_closingd_after_shutdown(struct channel *channel, const u8 *msg, const int *fds) diff --git a/lightningd/peer_control.h b/lightningd/peer_control.h index 015b4ba07..8327cd70d 100644 --- a/lightningd/peer_control.h +++ b/lightningd/peer_control.h @@ -90,6 +90,16 @@ void peer_sent_nongossip(struct lightningd *ld, /* Peer has failed to open; return to gossipd. */ void opening_failed(struct peer *peer, const u8 *msg TAKES); +void channel_errmsg(struct channel *channel, + int peer_fd, int gossip_fd, + const struct crypto_state *cs, + u64 gossip_index, + const struct channel_id *channel_id, + const char *desc, + const u8 *err_for_them); + +u8 *p2wpkh_for_keyidx(const tal_t *ctx, struct lightningd *ld, u64 keyidx); + void setup_listeners(struct lightningd *ld); /* We've loaded peers from database, set them going. */ diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index ea7b24357..e12feba75 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -50,9 +50,6 @@ void broadcast_tx(struct chain_topology *topo UNNEEDED, /* Generated stub for channel_wire_type_name */ const char *channel_wire_type_name(int e UNNEEDED) { fprintf(stderr, "channel_wire_type_name called!\n"); abort(); } -/* Generated stub for closing_wire_type_name */ -const char *closing_wire_type_name(int e UNNEEDED) -{ fprintf(stderr, "closing_wire_type_name called!\n"); abort(); } /* Generated stub for command_fail */ void command_fail(struct command *cmd UNNEEDED, const char *fmt UNNEEDED, ...) { fprintf(stderr, "command_fail called!\n"); abort(); } @@ -97,12 +94,6 @@ bool fromwire_channel_got_shutdown(const tal_t *ctx UNNEEDED, const void *p UNNE /* Generated stub for fromwire_channel_shutdown_complete */ bool fromwire_channel_shutdown_complete(const void *p UNNEEDED, size_t *plen UNNEEDED, struct crypto_state *crypto_state UNNEEDED, u64 *gossip_index UNNEEDED) { fprintf(stderr, "fromwire_channel_shutdown_complete called!\n"); abort(); } -/* Generated stub for fromwire_closing_complete */ -bool fromwire_closing_complete(const void *p UNNEEDED, size_t *plen UNNEEDED, u64 *gossip_index UNNEEDED) -{ fprintf(stderr, "fromwire_closing_complete called!\n"); abort(); } -/* Generated stub for fromwire_closing_received_signature */ -bool fromwire_closing_received_signature(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, struct bitcoin_tx **tx UNNEEDED) -{ fprintf(stderr, "fromwire_closing_received_signature called!\n"); abort(); } /* Generated stub for fromwire_gossip_getpeers_reply */ bool fromwire_gossip_getpeers_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, struct pubkey **id UNNEEDED, struct wireaddr **addr UNNEEDED) { fprintf(stderr, "fromwire_gossip_getpeers_reply called!\n"); abort(); } @@ -355,6 +346,13 @@ void peer_htlcs(const tal_t *ctx UNNEEDED, /* Generated stub for peer_sending_commitsig */ void peer_sending_commitsig(struct channel *channel UNNEEDED, const u8 *msg UNNEEDED) { fprintf(stderr, "peer_sending_commitsig called!\n"); abort(); } +/* Generated stub for peer_start_closingd */ +void peer_start_closingd(struct channel *channel UNNEEDED, + struct crypto_state *cs UNNEEDED, + u64 gossip_index UNNEEDED, + int peer_fd UNNEEDED, int gossip_fd UNNEEDED, + bool reconnected UNNEEDED) +{ fprintf(stderr, "peer_start_closingd called!\n"); abort(); } /* Generated stub for sanitize_error */ char *sanitize_error(const tal_t *ctx UNNEEDED, const u8 *errmsg UNNEEDED, struct channel_id *channel_id UNNEEDED) @@ -391,12 +389,6 @@ u8 *towire_channel_init(const tal_t *ctx UNNEEDED, const struct bitcoin_blkid *c /* Generated stub for towire_channel_send_shutdown */ u8 *towire_channel_send_shutdown(const tal_t *ctx UNNEEDED, const u8 *scriptpubkey UNNEEDED) { fprintf(stderr, "towire_channel_send_shutdown called!\n"); abort(); } -/* Generated stub for towire_closing_init */ -u8 *towire_closing_init(const tal_t *ctx UNNEEDED, const struct crypto_state *crypto_state UNNEEDED, u64 gossip_index UNNEEDED, const struct privkey *seed UNNEEDED, const struct bitcoin_txid *funding_txid UNNEEDED, u16 funding_txout UNNEEDED, u64 funding_satoshi UNNEEDED, const struct pubkey *remote_fundingkey UNNEEDED, enum side funder UNNEEDED, u64 local_msatoshi UNNEEDED, u64 remote_msatoshi UNNEEDED, u64 our_dust_limit UNNEEDED, u64 min_fee_satoshi UNNEEDED, u64 fee_limit_satoshi UNNEEDED, u64 initial_fee_satoshi UNNEEDED, const u8 *local_scriptpubkey UNNEEDED, const u8 *remote_scriptpubkey UNNEEDED, bool reconnected UNNEEDED, u64 next_index_local UNNEEDED, u64 next_index_remote UNNEEDED, u64 revocations_received UNNEEDED, bool deprecated_api UNNEEDED) -{ fprintf(stderr, "towire_closing_init called!\n"); abort(); } -/* Generated stub for towire_closing_received_signature_reply */ -u8 *towire_closing_received_signature_reply(const tal_t *ctx UNNEEDED) -{ fprintf(stderr, "towire_closing_received_signature_reply called!\n"); abort(); } /* Generated stub for towire_error */ u8 *towire_error(const tal_t *ctx UNNEEDED, const struct channel_id *channel_id UNNEEDED, const u8 *data UNNEEDED) { fprintf(stderr, "towire_error called!\n"); abort(); }