Skip to content

Commit c78afa9

Browse files
rustyrussellcdecker
authored andcommitted
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 <[email protected]>
1 parent 0e6c0db commit c78afa9

File tree

4 files changed

+46
-20
lines changed

4 files changed

+46
-20
lines changed

onchaind/onchain.c

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include <bitcoin/feerate.h>
12
#include <bitcoin/script.h>
23
#include <ccan/crypto/shachain/shachain.h>
34
#include <ccan/mem/mem.h>
@@ -274,13 +275,31 @@ static struct bitcoin_tx *tx_to_us(const tal_t *ctx,
274275
+ 1 + 3 + 73 + 0 + tal_len(wscript))
275276
/ 1000;
276277

277-
/* Result is trivial? Spent to OP_RETURN to avoid leaving dust. */
278+
/* Result is trivial? Spend with small feerate, but don't wait
279+
* around for it as it might not confirm. */
278280
if (tx->output[0].amount < dust_limit_satoshis + fee) {
279-
tx->output[0].amount = 0;
280-
tx->output[0].script = scriptpubkey_opreturn(tx->output);
281-
*tx_type = DONATING_TO_MINERS;
282-
} else
283-
tx->output[0].amount -= fee;
281+
/* FIXME: We should use SIGHASH_NONE so others can take it */
282+
fee = feerate_floor() * (measure_tx_weight(tx)
283+
+ 1 + 3 + 73 + 0 + tal_len(wscript))
284+
/ 1000;
285+
/* This shouldn't happen (we don't set feerate below floor!),
286+
* but just in case. */
287+
if (tx->output[0].amount < dust_limit_satoshis + fee) {
288+
fee = tx->output[0].amount - dust_limit_satoshis;
289+
status_broken("TX %s can't afford minimal feerate"
290+
"; setting fee to %"PRIu64,
291+
tx_type_name(*tx_type),
292+
fee);
293+
} else
294+
status_unusual("TX %s amount %"PRIu64" too small to"
295+
" pay reasonable fee, using minimal fee"
296+
" and ignoring",
297+
tx_type_name(*tx_type),
298+
out->satoshi);
299+
300+
*tx_type = IGNORING_TINY_PAYMENT;
301+
}
302+
tx->output[0].amount -= fee;
284303

285304
sign_tx_input(tx, 0, NULL, wscript, privkey, pubkey, &sig);
286305
tx->input[0].witness = bitcoin_witness_sig_and_element(tx->input,
@@ -361,6 +380,13 @@ static void proposal_meets_depth(struct tracked_output *out)
361380
wire_sync_write(REQ_FD,
362381
take(towire_onchain_broadcast_tx(NULL,
363382
out->proposal->tx)));
383+
384+
/* Don't wait for this if we're ignoring the tiny payment. */
385+
if (out->proposal->tx_type == IGNORING_TINY_PAYMENT) {
386+
ignore_output(out);
387+
out->proposal = tal_free(out->proposal);
388+
}
389+
364390
/* We will get a callback when it's in a block. */
365391
}
366392

onchaind/onchain_types.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ enum tx_type {
3636
OUR_PENALTY_TX,
3737

3838
/* Amount too small, we're just spending it to close UTXO */
39-
DONATING_TO_MINERS,
39+
IGNORING_TINY_PAYMENT,
4040

4141
/* Special type for marking outputs as resolved by self. */
4242
SELF,

onchaind/test/run-grind_feerate.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ bool per_commit_point(const struct sha256 *shaseed UNNEEDED,
108108
void status_failed(enum status_failreason code UNNEEDED,
109109
const char *fmt UNNEEDED, ...)
110110
{ fprintf(stderr, "status_failed called!\n"); abort(); }
111+
/* Generated stub for status_fmt */
112+
void status_fmt(enum log_level level UNNEEDED, const char *fmt UNNEEDED, ...)
113+
114+
{ fprintf(stderr, "status_fmt called!\n"); abort(); }
111115
/* Generated stub for status_setup_sync */
112116
void status_setup_sync(int fd UNNEEDED)
113117
{ fprintf(stderr, "status_setup_sync called!\n"); abort(); }

tests/test_lightningd.py

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2206,26 +2206,22 @@ def test_onchain_all_dust(self):
22062206
l2.daemon.wait_for_log(' to ONCHAIN')
22072207

22082208
# Wait for timeout.
2209-
l1.daemon.wait_for_log('Propose handling THEIR_UNILATERAL/OUR_HTLC by DONATING_TO_MINERS .* after 6 blocks')
2210-
bitcoind.generate_block(6)
2211-
2212-
l1.daemon.wait_for_log('sendrawtx exit 0')
2213-
bitcoind.generate_block(1)
2209+
l1.daemon.wait_for_log('Propose handling THEIR_UNILATERAL/OUR_HTLC by IGNORING_TINY_PAYMENT .* after 6 blocks')
2210+
bitcoind.generate_block(5)
22142211

2215-
l1.daemon.wait_for_log('Resolved THEIR_UNILATERAL/OUR_HTLC by our proposal DONATING_TO_MINERS')
2212+
l1.daemon.wait_for_logs(['Broadcasting IGNORING_TINY_PAYMENT .* to resolve THEIR_UNILATERAL/OUR_HTLC',
2213+
'sendrawtx exit 0',
2214+
'Ignoring output 0 of .*: THEIR_UNILATERAL/OUR_HTLC'])
22162215

22172216
# 100 deep and l2 forgets.
2218-
bitcoind.generate_block(91)
2219-
sync_blockheight([l2])
2217+
bitcoind.generate_block(93)
2218+
sync_blockheight([l1, l2])
22202219
assert not l2.daemon.is_in_log('onchaind complete, forgetting peer')
2220+
assert not l1.daemon.is_in_log('onchaind complete, forgetting peer')
22212221
bitcoind.generate_block(1)
22222222
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
22232223

2224-
# l1 forgets 100 blocks after DONATING_TO_MINERS.
2225-
bitcoind.generate_block(6)
2226-
sync_blockheight([l1])
2227-
assert not l1.daemon.is_in_log('onchaind complete, forgetting peer')
2228-
bitcoind.generate_block(1)
2224+
# l1 does not wait for ignored payment.
22292225
l1.daemon.wait_for_log('onchaind complete, forgetting peer')
22302226

22312227
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1 for dev_fail")

0 commit comments

Comments
 (0)