From c930bd72e58a9d6289ca093a9ae73d1d6077548c Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 3 Dec 2020 11:51:35 +1030 Subject: [PATCH 1/5] common/daemon: remove notifiers on root at cleanup. Under some circumstances, valgrind complains. Signed-off-by: Rusty Russell --- common/daemon.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/common/daemon.c b/common/daemon.c index 7d8ee1e244ca..09ef0b228244 100644 --- a/common/daemon.c +++ b/common/daemon.c @@ -119,6 +119,12 @@ static void add_steal_notifiers(const tal_t *root) for (const tal_t *i = tal_first(root); i; i = tal_next(i)) add_steal_notifiers(i); } + +static void remove_steal_notifiers(void) +{ + /* We remove this from root, assuming everything else freed. */ + tal_del_notifier(NULL, add_steal_notifier); +} #endif void daemon_setup(const char *argv0, @@ -155,6 +161,10 @@ void daemon_setup(const char *argv0, void daemon_shutdown(void) { common_shutdown(); + +#if DEVELOPER && BACKTRACE_SUPPORTED + remove_steal_notifiers(); +#endif } void daemon_maybe_debug(char *argv[]) From 94656ea7fd6063c8ea2295f2849faf99d13e7a1c Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 3 Dec 2020 11:51:59 +1030 Subject: [PATCH 2/5] onchaind: test stressful input. In particular, this made valgrind OOM, and chewed much CPU. I dumped the input and output into a file to allow easy replay. This will break as soon as we change onchaind's wire format, but it will serve its purpose until then! Signed-off-by: Rusty Russell --- onchaind/test/Makefile | 15 ++ onchaind/test/onchainstress-data.gz | Bin 0 -> 25268 bytes onchaind/test/run-onchainstress.c | 224 ++++++++++++++++++++++++++++ 3 files changed, 239 insertions(+) create mode 100644 onchaind/test/onchainstress-data.gz create mode 100644 onchaind/test/run-onchainstress.c diff --git a/onchaind/test/Makefile b/onchaind/test/Makefile index 4405874bb173..d1a67783a055 100644 --- a/onchaind/test/Makefile +++ b/onchaind/test/Makefile @@ -21,6 +21,21 @@ update-mocks: $(ONCHAIND_TEST_SRC:%=update-mocks/%) $(ONCHAIND_TEST_PROGRAMS): $(ONCHAIND_TEST_COMMON_OBJS) $(BITCOIN_OBJS) +# This needs many more objs: +onchaind/test/run-onchainstress: \ + common/htlc_tx.o \ + common/derive_basepoints.o \ + common/daemon.o \ + common/htlc_wire.o \ + common/initial_commit_tx.o \ + common/key_derive.o \ + common/keyset.o \ + common/permute_tx.o \ + common/subdaemon.o \ + common/wallet.o \ + wire/towire.o \ + wire/fromwire.o + # Test objects depend on ../ src and headers. $(ONCHAIND_TEST_OBJS): $(ONCHAIND_HEADERS) $(ONCHAIND_SRC) diff --git a/onchaind/test/onchainstress-data.gz b/onchaind/test/onchainstress-data.gz new file mode 100644 index 0000000000000000000000000000000000000000..fa43fb21a13ec2194885a59fc4ad988ef6f2a7db GIT binary patch literal 25268 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 +#include +#include +#include +#include + +volatile bool logging_io; +struct backtrace_state *backtrace_state; + +/* AUTOGENERATED MOCKS START */ +/* Generated stub for dup_onionreply */ +struct onionreply *dup_onionreply(const tal_t *ctx UNNEEDED, + const struct onionreply *r TAKES UNNEEDED) +{ fprintf(stderr, "dup_onionreply called!\n"); abort(); } +/* Generated stub for fromwire_bip32_key_version */ +void fromwire_bip32_key_version(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, + struct bip32_key_version *version UNNEEDED) +{ fprintf(stderr, "fromwire_bip32_key_version called!\n"); abort(); } +/* Generated stub for fromwire_chain_coin_mvt */ +void fromwire_chain_coin_mvt(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct chain_coin_mvt *mvt UNNEEDED) +{ fprintf(stderr, "fromwire_chain_coin_mvt called!\n"); abort(); } +/* Generated stub for fromwire_ext_key */ +void fromwire_ext_key(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct ext_key *bip32 UNNEEDED) +{ fprintf(stderr, "fromwire_ext_key called!\n"); abort(); } +/* Generated stub for fromwire_node_id */ +void fromwire_node_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct node_id *id UNNEEDED) +{ fprintf(stderr, "fromwire_node_id called!\n"); abort(); } +/* Generated stub for fromwire_onionreply */ +struct onionreply *fromwire_onionreply(const tal_t *ctx UNNEEDED, + const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_onionreply called!\n"); abort(); } +/* Generated stub for fromwire_utxo */ +struct utxo *fromwire_utxo(const tal_t *ctx UNNEEDED, const u8 **ptr UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_utxo called!\n"); abort(); } +/* Generated stub for master_badmsg */ +void master_badmsg(u32 type_expected UNNEEDED, const u8 *msg) +{ fprintf(stderr, "master_badmsg called!\n"); abort(); } +/* Generated stub for memleak_find_allocations */ +struct htable *memleak_find_allocations(const tal_t *ctx UNNEEDED, + const void *exclude1 UNNEEDED, + const void *exclude2 UNNEEDED) +{ fprintf(stderr, "memleak_find_allocations called!\n"); abort(); } +/* Generated stub for memleak_get */ +const void *memleak_get(struct htable *memtable UNNEEDED, const uintptr_t **backtrace UNNEEDED) +{ fprintf(stderr, "memleak_get called!\n"); abort(); } +/* Generated stub for memleak_init */ +void memleak_init(void) +{ fprintf(stderr, "memleak_init called!\n"); abort(); } +/* Generated stub for memleak_remove_region */ +void memleak_remove_region(struct htable *memtable UNNEEDED, + const void *p UNNEEDED, size_t bytelen UNNEEDED) +{ fprintf(stderr, "memleak_remove_region called!\n"); abort(); } +/* Generated stub for new_coin_penalty_sat */ +struct chain_coin_mvt *new_coin_penalty_sat(const tal_t *ctx UNNEEDED, + const char *account_name UNNEEDED, + const struct bitcoin_txid *txid UNNEEDED, + const struct bitcoin_txid *out_txid UNNEEDED, + u32 vout UNNEEDED, + u32 blockheight UNNEEDED, + struct amount_sat amount UNNEEDED) +{ fprintf(stderr, "new_coin_penalty_sat called!\n"); abort(); } +/* Generated stub for new_coin_withdrawal */ +struct chain_coin_mvt *new_coin_withdrawal(const tal_t *ctx UNNEEDED, + const char *account_name UNNEEDED, + const struct bitcoin_txid *tx_txid UNNEEDED, + const struct bitcoin_txid *out_txid UNNEEDED, + u32 vout UNNEEDED, + u32 blockheight UNNEEDED, + struct amount_msat amount UNNEEDED) +{ fprintf(stderr, "new_coin_withdrawal called!\n"); abort(); } +/* Generated stub for status_failed */ +void status_failed(enum status_failreason code UNNEEDED, + const char *fmt UNNEEDED, ...) +{ fprintf(stderr, "status_failed called!\n"); abort(); } +/* Generated stub for status_vfmt */ +void status_vfmt(enum log_level level UNNEEDED, + const struct node_id *peer UNNEEDED, + const char *fmt UNNEEDED, va_list ap UNNEEDED) +{ fprintf(stderr, "status_vfmt called!\n"); abort(); } +/* Generated stub for towire_bip32_key_version */ +void towire_bip32_key_version(u8 **cursor UNNEEDED, const struct bip32_key_version *version UNNEEDED) +{ fprintf(stderr, "towire_bip32_key_version called!\n"); abort(); } +/* Generated stub for towire_ext_key */ +void towire_ext_key(u8 **pptr UNNEEDED, const struct ext_key *bip32 UNNEEDED) +{ fprintf(stderr, "towire_ext_key called!\n"); abort(); } +/* Generated stub for towire_node_id */ +void towire_node_id(u8 **pptr UNNEEDED, const struct node_id *id UNNEEDED) +{ fprintf(stderr, "towire_node_id called!\n"); abort(); } +/* Generated stub for towire_onionreply */ +void towire_onionreply(u8 **cursor UNNEEDED, const struct onionreply *r UNNEEDED) +{ fprintf(stderr, "towire_onionreply called!\n"); abort(); } +/* Generated stub for towire_utxo */ +void towire_utxo(u8 **pptr UNNEEDED, const struct utxo *utxo UNNEEDED) +{ fprintf(stderr, "towire_utxo called!\n"); abort(); } +/* Generated stub for version */ +const char *version(void) +{ fprintf(stderr, "version called!\n"); abort(); } +/* AUTOGENERATED MOCKS END */ + +#if DEVELOPER +/* Generated stub for dev_disconnect_init */ +void dev_disconnect_init(int fd UNNEEDED) +{ fprintf(stderr, "dev_disconnect_init called!\n"); abort(); } +#endif + +/* Noops */ +void status_setup_sync(int fd UNNEEDED) +{ +} +void status_fmt(enum log_level level, + const struct node_id *peer, + const char *fmt, ...) +{ +} +void *notleak_(const void *ptr UNNEEDED, bool plus_children UNNEEDED) +{ + return (void *)ptr; +} +void peer_billboard(bool perm UNNEEDED, const char *fmt UNNEEDED, ...) +{ +} +struct chain_coin_mvt *new_coin_chain_fees(const tal_t *ctx UNNEEDED, + const char *account_name UNNEEDED, + const struct bitcoin_txid *tx_txid UNNEEDED, + u32 blockheight UNNEEDED, + struct amount_msat amount UNNEEDED) +{ + return NULL; +} + +/* Generated stub for new_coin_chain_fees_sat */ +struct chain_coin_mvt *new_coin_chain_fees_sat(const tal_t *ctx UNNEEDED, + const char *account_name UNNEEDED, + const struct bitcoin_txid *tx_txid UNNEEDED, + u32 blockheight UNNEEDED, + struct amount_sat amount UNNEEDED) +{ + return NULL; +} +/* Generated stub for new_coin_journal_entry */ +struct chain_coin_mvt *new_coin_journal_entry(const tal_t *ctx UNNEEDED, + const char *account_name UNNEEDED, + const struct bitcoin_txid *txid UNNEEDED, + const struct bitcoin_txid *out_txid UNNEEDED, + u32 vout UNNEEDED, + u32 blockheight UNNEEDED, + struct amount_msat amount UNNEEDED, + bool is_credit UNNEEDED) +{ + return NULL; +} +struct chain_coin_mvt *new_coin_onchain_htlc_sat(const tal_t *ctx UNNEEDED, + const char *account_name UNNEEDED, + const struct bitcoin_txid *txid UNNEEDED, + const struct bitcoin_txid *out_txid UNNEEDED, + u32 vout UNNEEDED, + struct sha256 payment_hash UNNEEDED, + u32 blockheight UNNEEDED, + struct amount_sat amount UNNEEDED, + bool is_credit UNNEEDED) +{ + return NULL; +} +struct chain_coin_mvt *new_coin_withdrawal_sat(const tal_t *ctx UNNEEDED, + const char *account_name UNNEEDED, + const struct bitcoin_txid *tx_txid UNNEEDED, + const struct bitcoin_txid *out_txid UNNEEDED, + u32 vout UNNEEDED, + u32 blockheight UNNEEDED, + struct amount_sat amount UNNEEDED) +{ + return NULL; +} +void towire_chain_coin_mvt(u8 **pptr UNNEEDED, const struct chain_coin_mvt *mvt UNNEEDED) +{ +} + +bool wire_sync_write(int fd, const void *msg TAKES) +{ + if (taken(msg)) + tal_free(msg); + return true; +} + +u8 *wire_sync_read(const tal_t *ctx, int fd) +{ + char line[5000]; + u8 *ret; + static gzFile stream; + size_t hexlen; + + /* Don't run this under valgrind in CI: takes too long! */ + if (getenv("VALGRIND") && streq(getenv("VALGRIND"), "1")) + goto exit; + + if (!stream) { + stream = gzopen("onchaind/test/onchainstress-data.gz", "rb"); + if (!stream) + err(1, "opening onchaind/test/onchainstress-data.gz"); + } + + do { + if (!gzgets(stream, line, sizeof(line))) + goto exit; + } while (!strstarts(line, "read ")); + + /* Ignore prefix and \n at end */ + hexlen = strlen(line) - strlen("read ") - 1; + ret = tal_arr(ctx, u8, hex_data_size(hexlen)); + if (!hex_decode(line + strlen("read "), hexlen, ret, tal_bytelen(ret))) + errx(1, "Bad hex string '%s'", line); + return ret; + +exit: + daemon_shutdown(); + /* Free top-level ctx pointer! */ + while (tal_first(NULL)) + tal_free(tal_first(NULL)); + exit(0); +} From 4b468a31c7fada268753f7ac5d64e6ad3d26d166 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 3 Dec 2020 11:52:01 +1030 Subject: [PATCH 3/5] bitcoin_tx_check: don't rely on tmpctx. We assert() this in onchaind while grinding fees; better to free newtx. Before this we hit 530MB, after a mere 2.5MB. Signed-off-by: Rusty Russell Changelog-Fixed: onchaind uses much less memory on unilateral closes for old channels. --- bitcoin/tx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/bitcoin/tx.c b/bitcoin/tx.c index 88aca4004692..0d0c757cf90c 100644 --- a/bitcoin/tx.c +++ b/bitcoin/tx.c @@ -256,6 +256,7 @@ bool bitcoin_tx_check(const struct bitcoin_tx *tx) if (written != tal_bytelen(newtx)) return false; + tal_free(newtx); return true; } From 4f24e14fdbba982123125d0e40f72c8b7d3b48f3 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 3 Dec 2020 11:52:01 +1030 Subject: [PATCH 4/5] onchaind: speed up HTLC matching by skipping identical CLTVs. We try signatures to see which HTLC (we can have many) is the right one; we can trivially match htlcs against commitment tx outputs, but the CTLV can vary, and that's inside the htlc tx itself. By sorting them, it's easy to skip comparing duplicates: Time before: 2m32.547s Time after: 1m6.984s Signed-off-by: Rusty Russell --- onchaind/onchaind.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/onchaind/onchaind.c b/onchaind/onchaind.c index 731d662cefc3..fe88ffb10c37 100644 --- a/onchaind/onchaind.c +++ b/onchaind/onchaind.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -2263,6 +2264,12 @@ static size_t resolve_our_htlc_ourcommit(struct tracked_output *out, /* These htlcs are all possibilities, but signature will only match * one with the correct cltv: check which that is. */ for (i = 0; i < tal_count(matches); i++) { + /* Skip over duplicate HTLCs, since we only need one. */ + if (i > 0 + && (htlcs[matches[i]].cltv_expiry + == htlcs[matches[i-1]].cltv_expiry)) + continue; + /* BOLT #5: * * ## HTLC Output Handling: Local Commitment, Local Offers @@ -3640,6 +3647,16 @@ static void handle_unknown_commitment(const struct tx_parts *tx, wait_for_resolved(outs); } +static int cmp_htlc_cltv(const struct htlc_stub *a, + const struct htlc_stub *b, void *unused) +{ + if (a->cltv_expiry < b->cltv_expiry) + return -1; + else if (a->cltv_expiry > b->cltv_expiry) + return 1; + return 0; +} + int main(int argc, char *argv[]) { setup_locale(); @@ -3731,6 +3748,9 @@ int main(int argc, char *argv[]) master_badmsg(WIRE_ONCHAIND_HTLC, msg); } + /* Sort by CLTV, so matches are in CLTV order (and easy to skip dups) */ + asort(htlcs, tal_count(htlcs), cmp_htlc_cltv, NULL); + outs = tal_arr(ctx, struct tracked_output *, 0); wally_tx_input_get_txid(tx->inputs[0], &tmptxid); new_tracked_output(&outs, &tmptxid, From ea4d6dc0e82648e2a723341883dd3ea9f753fd2f Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 3 Dec 2020 11:52:01 +1030 Subject: [PATCH 5/5] onchaind: cap max_possible_feerate using commitment transaction. The commitment tx uses the same feerate as the HTLC txs (which we have to grind to find), but we can't use it directly since the fee could be increased by the presence of dust HTLCs. We can still use it to cap the maximum though. Time before: 1m6.984s Time after: 0m15.794s Signed-off-by: Rusty Russell Changelog-Fixed: onchaind is much faster when unilaterally closing old channels. --- onchaind/onchaind.c | 51 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/onchaind/onchaind.c b/onchaind/onchaind.c index fe88ffb10c37..ccdbdf836241 100644 --- a/onchaind/onchaind.c +++ b/onchaind/onchaind.c @@ -143,6 +143,55 @@ static bool wally_tx_output_scripteq(const struct wally_tx_output *out, return memeq(out->script, out->script_len, script, tal_bytelen(script)); } +/* The feerate for the HTLC txs (which we grind) are the same as the + * feerate for the main tx. However, there may be dust HTLCs which + * were added to the fee, so we can only estimate a maximum feerate */ +static void trim_maximum_feerate(struct amount_sat funding, + const struct tx_parts *commitment) +{ + size_t weight; + struct amount_sat fee = funding; + + /* FIXME: This doesn't work for elements? */ + if (chainparams->is_elements) + return; + + weight = bitcoin_tx_core_weight(tal_count(commitment->inputs), + tal_count(commitment->outputs)); + + /* BOLT #3: + * ## Commitment Transaction + *... + * * `txin[0]` script bytes: 0 + * * `txin[0]` witness: `0 ` + */ + /* Account for witness (1 byte count + 1 empty + sig + sig) */ + assert(tal_count(commitment->inputs) == 1); + weight += bitcoin_tx_input_weight(false, 1 + 1 + 2 * bitcoin_tx_input_sig_weight()); + + for (size_t i = 0; i < tal_count(commitment->outputs); i++) { + struct amount_asset amt; + weight += bitcoin_tx_output_weight(commitment->outputs[i] + ->script_len); + + amt = wally_tx_output_get_amount(commitment->outputs[i]); + if (!amount_asset_is_main(&amt)) + continue; + if (!amount_sat_sub(&fee, fee, amount_asset_to_sat(&amt))) { + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Unable to subtract fee"); + } + } + + status_debug("reducing max_possible_feerate from %u...", + max_possible_feerate); + /* This is naive, but simple. */ + while (amount_sat_greater(amount_tx_fee(max_possible_feerate, weight), + fee)) + max_possible_feerate--; + status_debug("... to %u", max_possible_feerate); +} + static void send_coin_mvt(struct chain_coin_mvt *mvt TAKES) { wire_sync_write(REQ_FD, @@ -3767,6 +3816,8 @@ int main(int argc, char *argv[]) type_to_string(tmpctx, struct pubkey, &old_remote_per_commit_point)); + trim_maximum_feerate(funding, tx); + /* BOLT #5: * * There are three ways a channel can end: