diff --git a/onchaind/onchain.c b/onchaind/onchain.c index b763fe0fa..86ec76aa6 100644 --- a/onchaind/onchain.c +++ b/onchaind/onchain.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -274,13 +275,31 @@ static struct bitcoin_tx *tx_to_us(const tal_t *ctx, + 1 + 3 + 73 + 0 + tal_len(wscript)) / 1000; - /* Result is trivial? Spent to OP_RETURN to avoid leaving dust. */ + /* Result is trivial? Spend with small feerate, but don't wait + * around for it as it might not confirm. */ if (tx->output[0].amount < dust_limit_satoshis + fee) { - tx->output[0].amount = 0; - tx->output[0].script = scriptpubkey_opreturn(tx->output); - *tx_type = DONATING_TO_MINERS; - } else - tx->output[0].amount -= fee; + /* FIXME: We should use SIGHASH_NONE so others can take it */ + fee = feerate_floor() * (measure_tx_weight(tx) + + 1 + 3 + 73 + 0 + tal_len(wscript)) + / 1000; + /* This shouldn't happen (we don't set feerate below floor!), + * but just in case. */ + if (tx->output[0].amount < dust_limit_satoshis + fee) { + fee = tx->output[0].amount - dust_limit_satoshis; + status_broken("TX %s can't afford minimal feerate" + "; setting fee to %"PRIu64, + tx_type_name(*tx_type), + fee); + } else + status_unusual("TX %s amount %"PRIu64" too small to" + " pay reasonable fee, using minimal fee" + " and ignoring", + tx_type_name(*tx_type), + out->satoshi); + + *tx_type = IGNORING_TINY_PAYMENT; + } + tx->output[0].amount -= fee; sign_tx_input(tx, 0, NULL, wscript, privkey, pubkey, &sig); tx->input[0].witness = bitcoin_witness_sig_and_element(tx->input, @@ -361,6 +380,13 @@ static void proposal_meets_depth(struct tracked_output *out) wire_sync_write(REQ_FD, take(towire_onchain_broadcast_tx(NULL, out->proposal->tx))); + + /* Don't wait for this if we're ignoring the tiny payment. */ + if (out->proposal->tx_type == IGNORING_TINY_PAYMENT) { + ignore_output(out); + out->proposal = tal_free(out->proposal); + } + /* We will get a callback when it's in a block. */ } diff --git a/onchaind/onchain_types.h b/onchaind/onchain_types.h index 78cd342fa..58f8ba750 100644 --- a/onchaind/onchain_types.h +++ b/onchaind/onchain_types.h @@ -36,7 +36,7 @@ enum tx_type { OUR_PENALTY_TX, /* Amount too small, we're just spending it to close UTXO */ - DONATING_TO_MINERS, + IGNORING_TINY_PAYMENT, /* Special type for marking outputs as resolved by self. */ SELF, diff --git a/onchaind/test/run-grind_feerate.c b/onchaind/test/run-grind_feerate.c index d67e5961a..0fbb8006f 100644 --- a/onchaind/test/run-grind_feerate.c +++ b/onchaind/test/run-grind_feerate.c @@ -108,6 +108,10 @@ bool per_commit_point(const struct sha256 *shaseed UNNEEDED, void status_failed(enum status_failreason code UNNEEDED, const char *fmt UNNEEDED, ...) { fprintf(stderr, "status_failed called!\n"); abort(); } +/* Generated stub for status_fmt */ +void status_fmt(enum log_level level UNNEEDED, const char *fmt UNNEEDED, ...) + +{ fprintf(stderr, "status_fmt called!\n"); abort(); } /* Generated stub for status_setup_sync */ void status_setup_sync(int fd UNNEEDED) { fprintf(stderr, "status_setup_sync called!\n"); abort(); } diff --git a/tests/test_lightningd.py b/tests/test_lightningd.py index 118db2de2..ce1d43273 100644 --- a/tests/test_lightningd.py +++ b/tests/test_lightningd.py @@ -2206,26 +2206,22 @@ class LightningDTests(BaseLightningDTests): l2.daemon.wait_for_log(' to ONCHAIN') # Wait for timeout. - l1.daemon.wait_for_log('Propose handling THEIR_UNILATERAL/OUR_HTLC by DONATING_TO_MINERS .* after 6 blocks') - bitcoind.generate_block(6) - - l1.daemon.wait_for_log('sendrawtx exit 0') - bitcoind.generate_block(1) + l1.daemon.wait_for_log('Propose handling THEIR_UNILATERAL/OUR_HTLC by IGNORING_TINY_PAYMENT .* after 6 blocks') + bitcoind.generate_block(5) - l1.daemon.wait_for_log('Resolved THEIR_UNILATERAL/OUR_HTLC by our proposal DONATING_TO_MINERS') + l1.daemon.wait_for_logs(['Broadcasting IGNORING_TINY_PAYMENT .* to resolve THEIR_UNILATERAL/OUR_HTLC', + 'sendrawtx exit 0', + 'Ignoring output 0 of .*: THEIR_UNILATERAL/OUR_HTLC']) # 100 deep and l2 forgets. - bitcoind.generate_block(91) - sync_blockheight([l2]) + bitcoind.generate_block(93) + sync_blockheight([l1, l2]) assert not l2.daemon.is_in_log('onchaind complete, forgetting peer') + assert not l1.daemon.is_in_log('onchaind complete, forgetting peer') bitcoind.generate_block(1) l2.daemon.wait_for_log('onchaind complete, forgetting peer') - # l1 forgets 100 blocks after DONATING_TO_MINERS. - bitcoind.generate_block(6) - sync_blockheight([l1]) - assert not l1.daemon.is_in_log('onchaind complete, forgetting peer') - bitcoind.generate_block(1) + # l1 does not wait for ignored payment. l1.daemon.wait_for_log('onchaind complete, forgetting peer') @unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1 for dev_fail")