diff --git a/electrum/lnsweep.py b/electrum/lnsweep.py index 08bc7d399..5ee1b65f2 100644 --- a/electrum/lnsweep.py +++ b/electrum/lnsweep.py @@ -39,7 +39,6 @@ HTLCTX_INPUT_OUTPUT_INDEX = 0 class SweepInfo(NamedTuple): name: str - csv_delay: int cltv_abs: Optional[int] # set to None only if the script has no cltv txin: PartialTxInput txout: Optional[PartialTxOutput] # only for first-stage htlc tx @@ -48,6 +47,10 @@ class SweepInfo(NamedTuple): def is_anchor(self): return self.name in ['local_anchor', 'remote_anchor'] + @property + def csv_delay(self): + return self.txin.get_block_based_relative_locktime() or 0 + def sweep_their_ctx_watchtower( chan: 'Channel', @@ -253,7 +256,6 @@ def sweep_their_htlctx_justice( prevout = htlc_tx.txid() + f':{output_idx}' index_to_sweepinfo[prevout] = SweepInfo( name=f'second-stage-htlc:{output_idx}', - csv_delay=0, cltv_abs=None, txin=txin, txout=None, @@ -331,7 +333,6 @@ def sweep_our_ctx( if txin := sweep_ctx_anchor(ctx=ctx, multisig_key=our_conf.multisig_key): txs[txin.prevout.to_str()] = SweepInfo( name='local_anchor', - csv_delay=0, cltv_abs=None, txin=txin, txout=None, @@ -353,7 +354,6 @@ def sweep_our_ctx( prevout = ctx.txid() + ':%d'%output_idx txs[prevout] = SweepInfo( name='our_ctx_to_local', - csv_delay=to_self_delay, cltv_abs=None, txin=txin, txout=None, @@ -387,10 +387,8 @@ def sweep_our_ctx( if actual_htlc_tx is None: name = 'offered-htlc' if htlc_direction == SENT else 'received-htlc' prevout = ctx.txid() + f':{ctx_output_idx}' - csv_delay = 1 if chan.has_anchors() else 0 txs[prevout] = SweepInfo( name=name, - csv_delay=csv_delay, cltv_abs=htlc_tx.locktime, txin=htlc_tx.inputs()[0], txout=htlc_tx.outputs()[0], @@ -413,7 +411,6 @@ def sweep_our_ctx( ): txs[actual_htlc_tx.txid() + f':{output_idx}'] = SweepInfo( name=f'second-stage-htlc:{output_idx}', - csv_delay=to_self_delay, cltv_abs=0, txin=sweep_txin, txout=None, @@ -553,7 +550,6 @@ def sweep_their_ctx_to_remote_backup( if txin := sweep_ctx_anchor(ctx=ctx, multisig_key=our_ms_funding_keypair): txs[txin.prevout.to_str()] = SweepInfo( name='remote_anchor', - csv_delay=0, cltv_abs=None, txin=txin, txout=None, @@ -561,7 +557,6 @@ def sweep_their_ctx_to_remote_backup( ) # to_remote - csv_delay = 1 our_payment_privkey = ecc.ECPrivkey(our_payment_pubkey.privkey) output_idxs = ctx.get_output_idxs_from_address(to_remote_address) if output_idxs: @@ -575,7 +570,6 @@ def sweep_their_ctx_to_remote_backup( ): txs[prevout] = SweepInfo( name='their_ctx_to_remote_backup', - csv_delay=csv_delay, cltv_abs=None, txin=txin, txout=None, @@ -633,7 +627,6 @@ def sweep_their_ctx( if txin := sweep_ctx_anchor(ctx=ctx, multisig_key=our_conf.multisig_key): txs[txin.prevout.to_str()] = SweepInfo( name='remote_anchor', - csv_delay=0, cltv_abs=None, txin=txin, txout=None, @@ -646,7 +639,6 @@ def sweep_their_ctx( if txin := sweep_their_ctx_justice(chan, ctx, per_commitment_secret): txs[txin.prevout.to_str()] = SweepInfo( name='to_local_for_revoked_ctx', - csv_delay=0, cltv_abs=None, txin=txin, txout=None, @@ -655,12 +647,10 @@ def sweep_their_ctx( # to_remote if chan.has_anchors(): - csv_delay = 1 sweep_to_remote = True our_payment_privkey = ecc.ECPrivkey(our_conf.payment_basepoint.privkey) else: assert chan.is_static_remotekey_enabled() - csv_delay = 0 sweep_to_remote = False our_payment_privkey = None @@ -679,7 +669,6 @@ def sweep_their_ctx( # todo: we might not want to sweep this at all, if we add it to the wallet addresses txs[prevout] = SweepInfo( name='their_ctx_to_remote', - csv_delay=csv_delay, cltv_abs=None, txin=txin, txout=None, @@ -705,7 +694,6 @@ def sweep_their_ctx( has_anchors=chan.has_anchors()) cltv_abs = htlc.cltv_abs if is_received_htlc and not is_revocation else 0 - csv_delay = 1 if chan.has_anchors() else 0 prevout = ctx.txid() + ':%d'%ctx_output_idx if txin := sweep_their_ctx_htlc( ctx=ctx, @@ -719,7 +707,6 @@ def sweep_their_ctx( ): txs[prevout] = SweepInfo( name=f'their_ctx_htlc_{ctx_output_idx}{"_for_revoked_ctx" if is_revocation else ""}', - csv_delay=csv_delay, cltv_abs=cltv_abs, txin=txin, txout=None, diff --git a/electrum/submarine_swaps.py b/electrum/submarine_swaps.py index 314bb0a0c..ece5f20fa 100644 --- a/electrum/submarine_swaps.py +++ b/electrum/submarine_swaps.py @@ -430,12 +430,10 @@ class SwapManager(Logger): return txin, locktime = self.create_claim_txin(txin=txin, swap=swap) # note: there is no csv in the script, we just set this so that txbatcher waits for one confirmation - csv = 1 if swap.is_reverse else 0 name = 'swap claim' if swap.is_reverse else 'swap refund' - can_be_batched = bool(csv) if swap.is_reverse else True + can_be_batched = True sweep_info = SweepInfo( txin=txin, - csv_delay=csv, cltv_abs=locktime, txout=None, name=name, @@ -1128,7 +1126,7 @@ class SwapManager(Logger): sig_dummy = b'\x00' * 71 # DER-encoded ECDSA sig, with low S and low R witness = [sig_dummy, preimage, witness_script] txin.witness_sizehint = len(construct_witness(witness)) - txin.nsequence = 0xffffffff - 2 + txin.nsequence = 1 if swap.is_reverse else 0xffffffff - 2 @classmethod def create_claim_txin( diff --git a/electrum/txbatcher.py b/electrum/txbatcher.py index c5be42d06..0d49aea5d 100644 --- a/electrum/txbatcher.py +++ b/electrum/txbatcher.py @@ -102,10 +102,8 @@ class TxBatcher(Logger): @locked def add_sweep_input(self, key: str, sweep_info: 'SweepInfo', fee_policy_descriptor: str): - # sanity check csv_delay (note: values differ for swaps) - assert sweep_info.csv_delay >= (sweep_info.txin.get_block_based_relative_locktime() or 0) if sweep_info.txin and sweep_info.txout: - # todo: don't use name, detect sighash + # detect legacy htlc using name and csv delay if sweep_info.name in ['received-htlc', 'offered-htlc'] and sweep_info.csv_delay == 0: if sweep_info.txin.prevout not in self._legacy_htlcs: self.logger.info(f'received {sweep_info.name}') diff --git a/tests/test_txbatcher.py b/tests/test_txbatcher.py index 10f83ab57..b5d3b9da0 100644 --- a/tests/test_txbatcher.py +++ b/tests/test_txbatcher.py @@ -194,7 +194,6 @@ class TestTxBatcher(ElectrumTestCase): txin, locktime = SwapManager.create_claim_txin(txin=txin, swap=swap_data) sweep_info = SweepInfo( txin=txin, - csv_delay=0, cltv_abs=locktime, txout=None, name='swap claim',