mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 15:14:23 +01:00
onchaind: use lightningd to send "delayed_output_to_us" from HTLC txs.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -1240,7 +1240,7 @@ static void propose_resolution_at_block(struct tracked_output *out,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Modern style: we don't create tx outselves, but tell lightningd. */
|
/* Modern style: we don't create tx outselves, but tell lightningd. */
|
||||||
static void UNNEEDED propose_resolution_to_master(struct tracked_output *out,
|
static void propose_resolution_to_master(struct tracked_output *out,
|
||||||
const u8 *send_message TAKES,
|
const u8 *send_message TAKES,
|
||||||
unsigned int block_required,
|
unsigned int block_required,
|
||||||
enum tx_type tx_type)
|
enum tx_type tx_type)
|
||||||
@@ -1704,12 +1704,11 @@ static void resolve_htlc_tx(struct tracked_output ***outs,
|
|||||||
u32 tx_blockheight)
|
u32 tx_blockheight)
|
||||||
{
|
{
|
||||||
struct tracked_output *out;
|
struct tracked_output *out;
|
||||||
struct bitcoin_tx *tx;
|
|
||||||
struct amount_sat amt;
|
struct amount_sat amt;
|
||||||
struct amount_asset asset;
|
struct amount_asset asset;
|
||||||
struct bitcoin_outpoint outpoint;
|
struct bitcoin_outpoint outpoint;
|
||||||
enum tx_type tx_type = OUR_DELAYED_RETURN_TO_WALLET;
|
u8 *msg;
|
||||||
u8 *wscript = bitcoin_wscript_htlc_tx(htlc_tx, to_self_delay[LOCAL],
|
u8 *wscript = bitcoin_wscript_htlc_tx(tmpctx, to_self_delay[LOCAL],
|
||||||
&keyset->self_revocation_key,
|
&keyset->self_revocation_key,
|
||||||
&keyset->self_delayed_payment_key);
|
&keyset->self_delayed_payment_key);
|
||||||
|
|
||||||
@@ -1736,21 +1735,14 @@ static void resolve_htlc_tx(struct tracked_output ***outs,
|
|||||||
DELAYED_OUTPUT_TO_US,
|
DELAYED_OUTPUT_TO_US,
|
||||||
NULL, NULL, NULL);
|
NULL, NULL, NULL);
|
||||||
|
|
||||||
/* BOLT #3:
|
msg = towire_onchaind_spend_to_us(NULL,
|
||||||
*
|
&outpoint, amt,
|
||||||
* ## HTLC-Timeout and HTLC-Success Transactions
|
rel_blockheight(out, to_self_delay[LOCAL]),
|
||||||
*
|
commit_num,
|
||||||
* These HTLC transactions are almost identical, except the
|
wscript);
|
||||||
* HTLC-timeout transaction is timelocked.
|
propose_resolution_to_master(out, take(msg),
|
||||||
*
|
rel_blockheight(out, to_self_delay[LOCAL]),
|
||||||
* ... to collect the output, the local node uses an input with
|
OUR_DELAYED_RETURN_TO_WALLET);
|
||||||
* nSequence `to_self_delay` and a witness stack `<local_delayedsig>
|
|
||||||
* 0`
|
|
||||||
*/
|
|
||||||
tx = tx_to_us(*outs, delayed_payment_to_us, out, to_self_delay[LOCAL],
|
|
||||||
0, NULL, 0, wscript, &tx_type, htlc_feerate);
|
|
||||||
|
|
||||||
propose_resolution(out, tx, to_self_delay[LOCAL], tx_type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BOLT #5:
|
/* BOLT #5:
|
||||||
|
|||||||
@@ -285,6 +285,9 @@ u8 *towire_onchaind_missing_htlc_output(const tal_t *ctx UNNEEDED, const struct
|
|||||||
/* Generated stub for towire_onchaind_notify_coin_mvt */
|
/* Generated stub for towire_onchaind_notify_coin_mvt */
|
||||||
u8 *towire_onchaind_notify_coin_mvt(const tal_t *ctx UNNEEDED, const struct chain_coin_mvt *mvt UNNEEDED)
|
u8 *towire_onchaind_notify_coin_mvt(const tal_t *ctx UNNEEDED, const struct chain_coin_mvt *mvt UNNEEDED)
|
||||||
{ fprintf(stderr, "towire_onchaind_notify_coin_mvt called!\n"); abort(); }
|
{ fprintf(stderr, "towire_onchaind_notify_coin_mvt called!\n"); abort(); }
|
||||||
|
/* Generated stub for towire_onchaind_spend_to_us */
|
||||||
|
u8 *towire_onchaind_spend_to_us(const tal_t *ctx UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED, struct amount_sat outpoint_amount UNNEEDED, u32 minblock UNNEEDED, u64 commit_num UNNEEDED, const u8 *wscript UNNEEDED)
|
||||||
|
{ fprintf(stderr, "towire_onchaind_spend_to_us called!\n"); abort(); }
|
||||||
/* Generated stub for towire_onchaind_unwatch_tx */
|
/* Generated stub for towire_onchaind_unwatch_tx */
|
||||||
u8 *towire_onchaind_unwatch_tx(const tal_t *ctx UNNEEDED, const struct bitcoin_txid *txid UNNEEDED)
|
u8 *towire_onchaind_unwatch_tx(const tal_t *ctx UNNEEDED, const struct bitcoin_txid *txid UNNEEDED)
|
||||||
{ fprintf(stderr, "towire_onchaind_unwatch_tx called!\n"); abort(); }
|
{ fprintf(stderr, "towire_onchaind_unwatch_tx called!\n"); abort(); }
|
||||||
|
|||||||
@@ -317,6 +317,9 @@ u8 *towire_onchaind_missing_htlc_output(const tal_t *ctx UNNEEDED, const struct
|
|||||||
/* Generated stub for towire_onchaind_notify_coin_mvt */
|
/* Generated stub for towire_onchaind_notify_coin_mvt */
|
||||||
u8 *towire_onchaind_notify_coin_mvt(const tal_t *ctx UNNEEDED, const struct chain_coin_mvt *mvt UNNEEDED)
|
u8 *towire_onchaind_notify_coin_mvt(const tal_t *ctx UNNEEDED, const struct chain_coin_mvt *mvt UNNEEDED)
|
||||||
{ fprintf(stderr, "towire_onchaind_notify_coin_mvt called!\n"); abort(); }
|
{ fprintf(stderr, "towire_onchaind_notify_coin_mvt called!\n"); abort(); }
|
||||||
|
/* Generated stub for towire_onchaind_spend_to_us */
|
||||||
|
u8 *towire_onchaind_spend_to_us(const tal_t *ctx UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED, struct amount_sat outpoint_amount UNNEEDED, u32 minblock UNNEEDED, u64 commit_num UNNEEDED, const u8 *wscript UNNEEDED)
|
||||||
|
{ fprintf(stderr, "towire_onchaind_spend_to_us called!\n"); abort(); }
|
||||||
/* Generated stub for towire_onchaind_unwatch_tx */
|
/* Generated stub for towire_onchaind_unwatch_tx */
|
||||||
u8 *towire_onchaind_unwatch_tx(const tal_t *ctx UNNEEDED, const struct bitcoin_txid *txid UNNEEDED)
|
u8 *towire_onchaind_unwatch_tx(const tal_t *ctx UNNEEDED, const struct bitcoin_txid *txid UNNEEDED)
|
||||||
{ fprintf(stderr, "towire_onchaind_unwatch_tx called!\n"); abort(); }
|
{ fprintf(stderr, "towire_onchaind_unwatch_tx called!\n"); abort(); }
|
||||||
|
|||||||
@@ -1304,7 +1304,9 @@ def test_penalty_htlc_tx_fulfill(node_factory, bitcoind, chainparams):
|
|||||||
'OUR_UNILATERAL/THEIR_HTLC')
|
'OUR_UNILATERAL/THEIR_HTLC')
|
||||||
|
|
||||||
bitcoind.generate_block(1)
|
bitcoind.generate_block(1)
|
||||||
l2.daemon.wait_for_log('Propose handling OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET .* after 5 blocks')
|
((_, txid, blocks),) = l2.wait_for_onchaind_tx('OUR_DELAYED_RETURN_TO_WALLET',
|
||||||
|
'OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US')
|
||||||
|
assert blocks == 4
|
||||||
|
|
||||||
# l3 comes back up, sees cheat, penalizes l2 (revokes the htlc they've offered;
|
# l3 comes back up, sees cheat, penalizes l2 (revokes the htlc they've offered;
|
||||||
# notes that they've successfully claimed to_local and the fulfilled htlc)
|
# notes that they've successfully claimed to_local and the fulfilled htlc)
|
||||||
@@ -1497,20 +1499,17 @@ def test_penalty_htlc_tx_timeout(node_factory, bitcoind, chainparams):
|
|||||||
'OUR_UNILATERAL/THEIR_HTLC')
|
'OUR_UNILATERAL/THEIR_HTLC')
|
||||||
|
|
||||||
bitcoind.generate_block(1, wait_for_mempool=1)
|
bitcoind.generate_block(1, wait_for_mempool=1)
|
||||||
l2.daemon.wait_for_log('Propose handling OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET .* after 5 blocks')
|
((_, txid, blocks),) = l2.wait_for_onchaind_tx('OUR_DELAYED_RETURN_TO_WALLET',
|
||||||
|
'OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US')
|
||||||
# after 5 blocks, l2 reclaims both their DELAYED_OUTPUT_TO_US and their delayed output
|
assert blocks == 4
|
||||||
bitcoind.generate_block(5, wait_for_mempool=0)
|
|
||||||
sync_blockheight(bitcoind, [l2])
|
|
||||||
l2.daemon.wait_for_logs(['Broadcasting OUR_DELAYED_RETURN_TO_WALLET .* to resolve OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US',
|
|
||||||
'Broadcasting OUR_DELAYED_RETURN_TO_WALLET .* to resolve OUR_UNILATERAL/DELAYED_OUTPUT_TO_US'])
|
|
||||||
|
|
||||||
|
# At depth 5, l2 reclaims both their DELAYED_OUTPUT_TO_US and their delayed output
|
||||||
|
bitcoind.generate_block(4)
|
||||||
bitcoind.generate_block(10, wait_for_mempool=2)
|
bitcoind.generate_block(10, wait_for_mempool=2)
|
||||||
l2.wait_for_onchaind_broadcast('OUR_HTLC_TIMEOUT_TX',
|
l2.wait_for_onchaind_broadcast('OUR_HTLC_TIMEOUT_TX',
|
||||||
'OUR_UNILATERAL/OUR_HTLC')
|
'OUR_UNILATERAL/OUR_HTLC')
|
||||||
|
|
||||||
bitcoind.generate_block(1, wait_for_mempool=1)
|
bitcoind.generate_block(1, wait_for_mempool=1)
|
||||||
l2.daemon.wait_for_log('Propose handling OUR_HTLC_TIMEOUT_TX/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET .* after 5 blocks')
|
|
||||||
|
|
||||||
# l3 comes back up, sees cheat, penalizes l2 (revokes the htlc they've offered;
|
# l3 comes back up, sees cheat, penalizes l2 (revokes the htlc they've offered;
|
||||||
# notes that they've successfully claimed to_local and the fulfilled htlc)
|
# notes that they've successfully claimed to_local and the fulfilled htlc)
|
||||||
@@ -2114,6 +2113,10 @@ def test_onchain_timeout(node_factory, bitcoind, executor):
|
|||||||
bitcoind.generate_block(1)
|
bitcoind.generate_block(1)
|
||||||
l1.wait_for_onchaind_broadcast('OUR_HTLC_TIMEOUT_TX',
|
l1.wait_for_onchaind_broadcast('OUR_HTLC_TIMEOUT_TX',
|
||||||
'OUR_UNILATERAL/OUR_HTLC')
|
'OUR_UNILATERAL/OUR_HTLC')
|
||||||
|
bitcoind.generate_block(1, wait_for_mempool=1)
|
||||||
|
((rawtx, txid, blocks),) = l1.wait_for_onchaind_tx('OUR_DELAYED_RETURN_TO_WALLET',
|
||||||
|
'OUR_HTLC_TIMEOUT_TX/DELAYED_OUTPUT_TO_US')
|
||||||
|
assert blocks == 4
|
||||||
|
|
||||||
# We use 3 blocks for "reasonable depth"
|
# We use 3 blocks for "reasonable depth"
|
||||||
bitcoind.generate_block(3)
|
bitcoind.generate_block(3)
|
||||||
@@ -2122,13 +2125,11 @@ def test_onchain_timeout(node_factory, bitcoind, executor):
|
|||||||
with pytest.raises(RpcError, match=r'WIRE_PERMANENT_CHANNEL_FAILURE: timed out'):
|
with pytest.raises(RpcError, match=r'WIRE_PERMANENT_CHANNEL_FAILURE: timed out'):
|
||||||
payfuture.result(TIMEOUT)
|
payfuture.result(TIMEOUT)
|
||||||
|
|
||||||
# 2 later, l1 spends HTLC (5 blocks total).
|
# 1 later, l1 spends HTLC (depth = 5 blocks).
|
||||||
bitcoind.generate_block(2)
|
bitcoind.generate_block(1)
|
||||||
l1.wait_for_onchaind_broadcast('OUR_DELAYED_RETURN_TO_WALLET',
|
|
||||||
'OUR_HTLC_TIMEOUT_TX/DELAYED_OUTPUT_TO_US')
|
|
||||||
|
|
||||||
# 89 later, l2 is done.
|
# 89 later, l2 is done.
|
||||||
bitcoind.generate_block(89)
|
bitcoind.generate_block(89, wait_for_mempool=txid)
|
||||||
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
|
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
|
||||||
|
|
||||||
# Now, 100 blocks and l1 should be done.
|
# Now, 100 blocks and l1 should be done.
|
||||||
@@ -2240,18 +2241,20 @@ def test_onchain_middleman_simple(node_factory, bitcoind):
|
|||||||
t.join(timeout=1)
|
t.join(timeout=1)
|
||||||
assert not t.is_alive()
|
assert not t.is_alive()
|
||||||
|
|
||||||
|
((_, txid, blocks),) = l2.wait_for_onchaind_tx('OUR_DELAYED_RETURN_TO_WALLET',
|
||||||
|
'OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US')
|
||||||
|
assert blocks == 4
|
||||||
|
|
||||||
# Three more, l2 can spend to-us.
|
# Three more, l2 can spend to-us.
|
||||||
bitcoind.generate_block(3)
|
bitcoind.generate_block(3)
|
||||||
l2.wait_for_onchaind_broadcast('OUR_DELAYED_RETURN_TO_WALLET',
|
l2.wait_for_onchaind_broadcast('OUR_DELAYED_RETURN_TO_WALLET',
|
||||||
'OUR_UNILATERAL/DELAYED_OUTPUT_TO_US')
|
'OUR_UNILATERAL/DELAYED_OUTPUT_TO_US')
|
||||||
|
|
||||||
# One more block, HTLC tx is now spendable.
|
# One more block, HTLC tx is now spendable.
|
||||||
l1.bitcoin.generate_block(1)
|
bitcoind.generate_block(1, wait_for_mempool=1)
|
||||||
l2.wait_for_onchaind_broadcast('OUR_DELAYED_RETURN_TO_WALLET',
|
|
||||||
'OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US')
|
|
||||||
|
|
||||||
# 100 blocks after last spend, l2 should be done.
|
# 100 blocks after last spend, l2 should be done.
|
||||||
l1.bitcoin.generate_block(100)
|
l1.bitcoin.generate_block(100, wait_for_mempool=txid)
|
||||||
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
|
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
|
||||||
|
|
||||||
# Verify accounting for l1 & l2
|
# Verify accounting for l1 & l2
|
||||||
@@ -3089,16 +3092,15 @@ def test_permfail_htlc_in(node_factory, bitcoind, executor):
|
|||||||
|
|
||||||
# OK, l1 sees l2 fulfill htlc.
|
# OK, l1 sees l2 fulfill htlc.
|
||||||
l1.daemon.wait_for_log('THEIR_UNILATERAL/OUR_HTLC gave us preimage')
|
l1.daemon.wait_for_log('THEIR_UNILATERAL/OUR_HTLC gave us preimage')
|
||||||
l2.daemon.wait_for_log('Propose handling OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET .* after 5 blocks')
|
((_, txid, blocks),) = l2.wait_for_onchaind_tx('OUR_DELAYED_RETURN_TO_WALLET',
|
||||||
bitcoind.generate_block(5)
|
'OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US')
|
||||||
|
assert blocks == 4
|
||||||
l2.wait_for_onchaind_broadcast('OUR_DELAYED_RETURN_TO_WALLET',
|
bitcoind.generate_block(4)
|
||||||
'OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US')
|
|
||||||
|
|
||||||
t.cancel()
|
t.cancel()
|
||||||
|
|
||||||
# Now, 100 blocks it should be done.
|
# Now, 100 blocks it should be done.
|
||||||
bitcoind.generate_block(95)
|
bitcoind.generate_block(95, wait_for_mempool=txid)
|
||||||
l1.daemon.wait_for_log('onchaind complete, forgetting peer')
|
l1.daemon.wait_for_log('onchaind complete, forgetting peer')
|
||||||
assert not l2.daemon.is_in_log('onchaind complete, forgetting peer')
|
assert not l2.daemon.is_in_log('onchaind complete, forgetting peer')
|
||||||
bitcoind.generate_block(5)
|
bitcoind.generate_block(5)
|
||||||
|
|||||||
@@ -363,12 +363,14 @@ def test_htlc_out_timeout(node_factory, bitcoind, executor):
|
|||||||
l1.daemon.wait_for_log('sendrawtx exit 0')
|
l1.daemon.wait_for_log('sendrawtx exit 0')
|
||||||
bitcoind.generate_block(1)
|
bitcoind.generate_block(1)
|
||||||
|
|
||||||
l1.daemon.wait_for_log('Propose handling OUR_HTLC_TIMEOUT_TX/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET .* after 5 blocks')
|
((rawtx, txid, blocks),) = l1.wait_for_onchaind_tx('OUR_DELAYED_RETURN_TO_WALLET',
|
||||||
|
'OUR_HTLC_TIMEOUT_TX/DELAYED_OUTPUT_TO_US')
|
||||||
|
assert blocks == 4
|
||||||
bitcoind.generate_block(4)
|
bitcoind.generate_block(4)
|
||||||
|
|
||||||
# It should now claim both the to-local and htlc-timeout-tx outputs.
|
# It should now claim both the to-local and htlc-timeout-tx outputs.
|
||||||
l1.daemon.wait_for_logs(['Broadcasting OUR_DELAYED_RETURN_TO_WALLET',
|
l1.daemon.wait_for_logs(['Broadcasting OUR_DELAYED_RETURN_TO_WALLET',
|
||||||
'Broadcasting OUR_DELAYED_RETURN_TO_WALLET',
|
'sendrawtx exit 0.*{}'.format(rawtx),
|
||||||
'sendrawtx exit 0',
|
|
||||||
'sendrawtx exit 0'])
|
'sendrawtx exit 0'])
|
||||||
|
|
||||||
# Now, 100 blocks it should be done.
|
# Now, 100 blocks it should be done.
|
||||||
@@ -424,14 +426,15 @@ def test_htlc_in_timeout(node_factory, bitcoind, executor):
|
|||||||
# L2 will collect HTLC (iff no shadow route)
|
# L2 will collect HTLC (iff no shadow route)
|
||||||
l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/THEIR_HTLC by OUR_HTLC_SUCCESS_TX .* after 0 blocks')
|
l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/THEIR_HTLC by OUR_HTLC_SUCCESS_TX .* after 0 blocks')
|
||||||
l2.daemon.wait_for_log('sendrawtx exit 0')
|
l2.daemon.wait_for_log('sendrawtx exit 0')
|
||||||
bitcoind.generate_block(1)
|
bitcoind.generate_block(1, wait_for_mempool=1)
|
||||||
l2.daemon.wait_for_log('Propose handling OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET .* after 5 blocks')
|
((rawtx, txid, blocks),) = l2.wait_for_onchaind_tx('OUR_DELAYED_RETURN_TO_WALLET',
|
||||||
|
'OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US')
|
||||||
|
assert blocks == 4
|
||||||
bitcoind.generate_block(4)
|
bitcoind.generate_block(4)
|
||||||
l2.daemon.wait_for_log('Broadcasting OUR_DELAYED_RETURN_TO_WALLET')
|
l2.daemon.wait_for_log('sendrawtx exit 0.*{}'.format(rawtx))
|
||||||
l2.daemon.wait_for_log('sendrawtx exit 0')
|
|
||||||
|
|
||||||
# Now, 100 blocks it should be both done.
|
# Now, 100 blocks it should be both done.
|
||||||
bitcoind.generate_block(100)
|
bitcoind.generate_block(100, wait_for_mempool=txid)
|
||||||
l1.daemon.wait_for_log('onchaind complete, forgetting peer')
|
l1.daemon.wait_for_log('onchaind complete, forgetting peer')
|
||||||
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
|
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user