|
1 | | -import unittest |
2 | 1 | import logging |
3 | 2 | from unittest import mock |
4 | 3 | import asyncio |
5 | 4 | import dataclasses |
6 | 5 |
|
7 | 6 | from aiorpcx import timeout_after |
8 | 7 |
|
9 | | -from electrum import storage, bitcoin, keystore, wallet |
| 8 | +import electrum.fee_policy |
| 9 | +from electrum import keystore, wallet, lnutil |
10 | 10 | from electrum import SimpleConfig |
11 | 11 | from electrum import util |
12 | | -from electrum.address_synchronizer import TX_HEIGHT_UNCONFIRMED, TX_HEIGHT_UNCONF_PARENT, TX_HEIGHT_LOCAL |
| 12 | +from electrum.address_synchronizer import TX_HEIGHT_UNCONFIRMED |
13 | 13 | from electrum.transaction import Transaction, PartialTxInput, PartialTxOutput, TxOutpoint |
14 | 14 | from electrum.logging import console_stderr_handler, Logger |
15 | 15 | from electrum.submarine_swaps import SwapManager, SwapData |
16 | | -from electrum.lnsweep import SweepInfo |
| 16 | +from electrum.lnsweep import SweepInfo, sweep_ctx_anchor |
17 | 17 | from electrum.fee_policy import FeeTimeEstimates |
18 | 18 |
|
19 | 19 | from . import ElectrumTestCase |
@@ -87,6 +87,28 @@ def is_connected(self): |
87 | 87 | name='swap claim', |
88 | 88 | can_be_batched=True, |
89 | 89 | ) |
| 90 | +anchor_chan_ctx = Transaction( |
| 91 | + "02000000000101d24af3b7adefff5a068f736d64842c18da7087b41ba43ab5b999c545c5f1606501000000008d0d5d8" |
| 92 | + "0024a010000000000002200207b95cb2555b3f8fc246d26ac38023ec8edf423d70b41dfe17efc89baa6e0cc72740003" |
| 93 | + "000000000022002075f8af76a5b5c4b25e4aee3a4f96a190a168bde5d9761de8d45d3e49cd6f1d82040047304402200" |
| 94 | + "6524eb2f467bf1eacd2116ea79a80c182eb95e18d0fa24fc5c600581ec4aa5f02206f50bdfc3577ca3bc9892eade7d8" |
| 95 | + "1a9b06b9a8803296fad689af9fee9375191d0147304402202112d08ffa79010b1d698ca9fb0790119a42f7b70e183a2" |
| 96 | + "a05dbf79c32806d3b022001cd3e3aec8c1142c8689e9e679c684ea82dcde8c86cf8e55466c743b3647b1f0147522103" |
| 97 | + "0551e6017a0e9dbffd468c2a08ecf8446b532f0a6d5db291eb77026f2ef3deb421034f986fd43561d52a96b19fbdd0c" |
| 98 | + "296f0442034d3f3f63fc394320a95750d42a852ae08572d20" |
| 99 | +) |
| 100 | +chan_multisig_key = lnutil.Keypair( |
| 101 | + privkey="4c8b2c19d6528f54a4c900d87b3d8dbf746314925d126e0abf8e2ed965a9302f", |
| 102 | + pubkey="034f986fd43561d52a96b19fbdd0c296f0442034d3f3f63fc394320a95750d42a8", |
| 103 | +) |
| 104 | +anchor_txin = sweep_ctx_anchor(ctx=anchor_chan_ctx, multisig_key=chan_multisig_key) |
| 105 | +ANCHOR_SWEEP_INFO = SweepInfo( |
| 106 | + name='local_anchor', |
| 107 | + cltv_abs=None, |
| 108 | + txin=anchor_txin, |
| 109 | + txout=None, |
| 110 | + can_be_batched=True, |
| 111 | +) |
90 | 112 |
|
91 | 113 |
|
92 | 114 | class TestTxBatcher(ElectrumTestCase): |
@@ -226,6 +248,38 @@ async def test_sweep_from_submarine_swap(self, mock_save_db): |
226 | 248 | assert new_tx.inputs()[0].prevout == tx.inputs()[0].prevout == txin.prevout |
227 | 249 | assert output1 in new_tx.outputs() |
228 | 250 |
|
| 251 | + async def test_to_sweep_after_anchor_sweep_conditions(self): |
| 252 | + # create wallet |
| 253 | + wallet = self._create_wallet() |
| 254 | + wallet.txbatcher.add_sweep_input('lnwatcher', ANCHOR_SWEEP_INFO) |
| 255 | + anchor_batch = wallet.txbatcher.tx_batches['lnwatcher'] |
| 256 | + |
| 257 | + # does not return sweep info if prev_tx is not in db |
| 258 | + to_sweep_no_tx = anchor_batch._to_sweep_after(tx=None) |
| 259 | + assert not to_sweep_no_tx |
| 260 | + |
| 261 | + # returns sweep input if anchor_chan_ctx conf < 1 |
| 262 | + wallet.adb.db.transactions[anchor_chan_ctx.txid()] = anchor_chan_ctx |
| 263 | + to_sweep_no_conf = anchor_batch._to_sweep_after(tx=None) |
| 264 | + assert to_sweep_no_conf[anchor_txin.prevout] == ANCHOR_SWEEP_INFO |
| 265 | + assert len(to_sweep_no_conf) == 1 |
| 266 | + |
| 267 | + # does not return sweep input if ctx fee is already higher than target fee |
| 268 | + with mock.patch.object(wallet.adb, 'get_tx_fee', return_value=2000), \ |
| 269 | + mock.patch.object(electrum.fee_policy.FeePolicy, 'estimate_fee', return_value=1000): |
| 270 | + to_sweep_high_fee = anchor_batch._to_sweep_after(tx=None) |
| 271 | + assert not to_sweep_high_fee |
| 272 | + |
| 273 | + # after the ctx is confirmed the anchor claim shouldn't be broadcast anymore |
| 274 | + wallet.adb.receive_tx_callback(anchor_chan_ctx, tx_height=1) |
| 275 | + tx_mined_status = wallet.adb.get_tx_height(anchor_chan_ctx.txid()) |
| 276 | + wallet.adb.add_verified_tx(anchor_chan_ctx.txid(), dataclasses.replace(tx_mined_status, conf=1)) |
| 277 | + assert anchor_txin.prevout in anchor_batch.batch_inputs |
| 278 | + to_sweep_ctx_conf = anchor_batch._to_sweep_after(tx=None) |
| 279 | + assert not to_sweep_ctx_conf |
| 280 | + assert not anchor_batch.batch_inputs |
| 281 | + assert wallet.txbatcher.tx_batches['lnwatcher'] == anchor_batch |
| 282 | + |
229 | 283 | async def _wait_for_base_tx(self, txbatch, should_be_none=False): |
230 | 284 | async with timeout_after(10): |
231 | 285 | while True: |
|
0 commit comments