Test that the penalizing node claims any published HTLC transactions Node topology: l1 <-> l2 <-> l3 <-> l4 l4 pushes money to l1, who doesn't fulfill (freezing htlc across l2-l3) we snapshot l2 l2 pushes money to l3 (updating state) l2 + l3 go offline;
(node_factory, bitcoind, chainparams, anchors)
| 1195 | @pytest.mark.slow_test |
| 1196 | @pytest.mark.parametrize("anchors", [False, True]) |
| 1197 | def test_penalty_htlc_tx_fulfill(node_factory, bitcoind, chainparams, anchors): |
| 1198 | """ Test that the penalizing node claims any published |
| 1199 | HTLC transactions |
| 1200 | |
| 1201 | Node topology: |
| 1202 | l1 <-> l2 <-> l3 <-> l4 |
| 1203 | |
| 1204 | l4 pushes money to l1, who doesn't fulfill (freezing htlc across l2-l3) |
| 1205 | we snapshot l2 |
| 1206 | l2 pushes money to l3 (updating state) |
| 1207 | l2 + l3 go offline; l2 is backed up from snapshot |
| 1208 | l1 fails the channel with l2, fulfilling the stranded htlc onchain |
| 1209 | l2 comes back online, force closes channel with l3 |
| 1210 | |
| 1211 | block chain advances, l2 broadcasts their htlc fulfill tx |
| 1212 | l3 comes back online, sees l2's cheat. takes funds from htlc fulfill tx. |
| 1213 | some blocks are mined. the dust settles. |
| 1214 | |
| 1215 | we check the accounting. |
| 1216 | """ |
| 1217 | |
| 1218 | if chainparams['elements'] and anchors: |
| 1219 | pytest.skip('elementsd anchors unsupported') |
| 1220 | |
| 1221 | # We track channel balances, to verify that accounting is ok. |
| 1222 | coin_mvt_plugin = os.path.join(os.getcwd(), 'tests/plugins/coin_movements.py') |
| 1223 | balance_snaps = os.path.join(os.getcwd(), 'tests/plugins/balance_snaps.py') |
| 1224 | |
| 1225 | opts = {'may_reconnect': True, |
| 1226 | 'dev-no-reconnect': None} |
| 1227 | if anchors: |
| 1228 | commitfee = 3755 |
| 1229 | else: |
| 1230 | commitfee = 11005 |
| 1231 | opts = {**opts, 'dev-force-features': "-23"} |
| 1232 | |
| 1233 | l1, l2, l3, l4 = node_factory.line_graph(4, |
| 1234 | opts=[{'disconnect': ['-WIRE_UPDATE_FULFILL_HTLC'], |
| 1235 | **opts}, |
| 1236 | {'plugin': [coin_mvt_plugin, balance_snaps], |
| 1237 | 'disable-mpp': None, |
| 1238 | 'broken_log': 'onchaind.*: Unknown spend', |
| 1239 | **opts}, |
| 1240 | {'plugin': [coin_mvt_plugin, balance_snaps], |
| 1241 | **opts}, |
| 1242 | opts], |
| 1243 | wait_for_announce=True) |
| 1244 | |
| 1245 | channel_id = first_channel_id(l2, l3) |
| 1246 | |
| 1247 | # push some money so that 1 + 4 can both send htlcs |
| 1248 | inv = l2.rpc.invoice(10**9 // 2, '1', 'balancer') |
| 1249 | l1.rpc.xpay(inv['bolt11']) |
| 1250 | wait_for(lambda: only_one(l1.rpc.listpeerchannels()['channels'])['htlcs'] == []) |
| 1251 | |
| 1252 | inv = l4.rpc.invoice(10**9 // 2, '1', 'balancer') |
| 1253 | l2.rpc.xpay(inv['bolt11']) |
| 1254 | wait_for(lambda: only_one(l1.rpc.listpeerchannels()['channels'])['htlcs'] == []) |
nothing calls this directly
no test coverage detected