From 47c07f77b4e14b46df7b71913641129b5f2034e8 Mon Sep 17 00:00:00 2001 From: Janus Date: Tue, 4 Dec 2018 20:53:41 +0100 Subject: [PATCH] lnsweep: fix create_sweeptxs_for_their_just_revoked_ctx in the case where an htlc is failed, it could happen that we use the wrong list of htlcs to generate sweep tx'es. we would use the pending list instead of the committed list. observed by sending 12300sat and then 123000sat, the second payment fails and an AssertionError was triggered cause the htlc output could not be found in the ctx. added some documentation to clarify the behaviour of lnchan.included_htlcs. --- electrum/lnchan.py | 12 ++++++++++++ electrum/lnsweep.py | 8 ++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/electrum/lnchan.py b/electrum/lnchan.py index cf5025c3d..0ba13dfe7 100644 --- a/electrum/lnchan.py +++ b/electrum/lnchan.py @@ -635,6 +635,18 @@ class Channel(PrintError): def htlcs(self, subject, only_pending): """ only_pending: require the htlc's settlement to be pending (needs additional signatures/acks) + + sets returned with True and False are disjunct + + only_pending true: + skipped if settled or failed + <=> + included if not settled and not failed + only_pending false: + skipped if not (settled or failed) + <=> + included if not not (settled or failed) + included if settled or failed """ update_log = self.log[subject] res = [] diff --git a/electrum/lnsweep.py b/electrum/lnsweep.py index 56d2f2496..cc9aeb658 100644 --- a/electrum/lnsweep.py +++ b/electrum/lnsweep.py @@ -103,9 +103,10 @@ def create_sweeptxs_for_their_just_revoked_ctx(chan: 'Channel', ctx: Transaction privkey=other_revocation_privkey, is_revocation=True) return direct_sweep_tx, secondstage_sweep_tx, htlc_tx + ctn = extract_ctn_from_tx_and_chan(ctx, chan) + assert ctn == chan.config[REMOTE].ctn # received HTLCs, in their ctx - # TODO consider carefully if "included_htlcs" is what we need here - received_htlcs = list(chan.included_htlcs(REMOTE, LOCAL)) # type: List[UpdateAddHtlc] + received_htlcs = chan.included_htlcs(REMOTE, LOCAL, False) for htlc in received_htlcs: direct_sweep_tx, secondstage_sweep_tx, htlc_tx = create_sweeptx_for_htlc(htlc, is_received_htlc=True) if direct_sweep_tx: @@ -113,8 +114,7 @@ def create_sweeptxs_for_their_just_revoked_ctx(chan: 'Channel', ctx: Transaction if secondstage_sweep_tx: txs.append((htlc_tx.txid(), EncumberedTransaction(f'their_htlctx_{bh2u(htlc.payment_hash)}', secondstage_sweep_tx, csv_delay=0, cltv_expiry=0))) # offered HTLCs, in their ctx - # TODO consider carefully if "included_htlcs" is what we need here - offered_htlcs = list(chan.included_htlcs(REMOTE, REMOTE)) # type: List[UpdateAddHtlc] + offered_htlcs = chan.included_htlcs(REMOTE, REMOTE, False) for htlc in offered_htlcs: direct_sweep_tx, secondstage_sweep_tx, htlc_tx = create_sweeptx_for_htlc(htlc, is_received_htlc=False) if direct_sweep_tx: