onchaind: use lowball fee instead of donating to miners.

As of bitcoind 0.16.1, you can't send a single-input OP_RETURN output,
as you get 'tx-too-small'.

	sendrawtx exit 26, gave error code: -26?error message:?tx-size-small (code 64)?'

So instead we use the minimum fee we can, but otherwise ignore it and
don't wait for it to be mined.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2018-06-20 16:20:44 +09:30 committed by Christian Decker
parent 0e6c0dbba2
commit c78afa9201
4 changed files with 46 additions and 20 deletions

View File

@ -1,3 +1,4 @@
#include <bitcoin/feerate.h>
#include <bitcoin/script.h>
#include <ccan/crypto/shachain/shachain.h>
#include <ccan/mem/mem.h>
@ -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. */
}

View File

@ -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,

View File

@ -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(); }

View File

@ -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('Propose handling THEIR_UNILATERAL/OUR_HTLC by IGNORING_TINY_PAYMENT .* after 6 blocks')
bitcoind.generate_block(5)
l1.daemon.wait_for_log('sendrawtx exit 0')
bitcoind.generate_block(1)
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")