(node_factory, bitcoind, executor)
| 2216 | @unittest.skipIf(os.environ.get("TEST_CHECK_DBSTMTS", None) == "1", |
| 2217 | "We kill l2, dblog plugin replay will be unreliable") |
| 2218 | def test_channel_persistence(node_factory, bitcoind, executor): |
| 2219 | # Start two nodes and open a channel (to remember). l2 will |
| 2220 | # mysteriously die while committing the first HTLC so we can |
| 2221 | # check that HTLCs reloaded from the DB work. |
| 2222 | # Feerates identical so we don't get gratuitous commit to update them |
| 2223 | disable_commit_after = 1 |
| 2224 | if EXPERIMENTAL_DUAL_FUND: |
| 2225 | disable_commit_after = 2 |
| 2226 | |
| 2227 | l1 = node_factory.get_node(may_reconnect=True, feerates=(7500, 7500, 7500, |
| 2228 | 7500)) |
| 2229 | l2 = node_factory.get_node(options={'dev-disable-commit-after': disable_commit_after}, |
| 2230 | may_reconnect=True) |
| 2231 | l1.rpc.connect(l2.info['id'], 'localhost', l2.port) |
| 2232 | |
| 2233 | # Neither node should have a channel open, they are just connected |
| 2234 | for n in (l1, l2): |
| 2235 | assert(n.db_query('SELECT COUNT(id) as count FROM channels;')[0]['count'] == 0) |
| 2236 | |
| 2237 | l1.fundchannel(l2, 100000) |
| 2238 | |
| 2239 | peers = l1.rpc.listpeers()['peers'] |
| 2240 | assert(only_one(peers[0]['channels'])['state'] == 'CHANNELD_NORMAL') |
| 2241 | |
| 2242 | # Both nodes should now have exactly one channel in the database |
| 2243 | for n in (l1, l2): |
| 2244 | assert(n.db_query('SELECT COUNT(id) as count FROM channels;')[0]['count'] == 1) |
| 2245 | |
| 2246 | # Fire off a sendpay request, it'll get interrupted by a restart |
| 2247 | executor.submit(l1.pay, l2, 10000) |
| 2248 | # Wait for it to be committed to, i.e., stored in the DB |
| 2249 | l1.daemon.wait_for_log('peer_in WIRE_CHANNEL_READY') |
| 2250 | l1.daemon.wait_for_log('peer_in WIRE_COMMITMENT_SIGNED') |
| 2251 | |
| 2252 | # Stop l2, l1 will reattempt to connect |
| 2253 | print("Killing l2 in mid HTLC") |
| 2254 | l2.daemon.kill() |
| 2255 | |
| 2256 | # Clear the disconnect and timer stop so we can proceed normally |
| 2257 | del l2.daemon.opts['dev-disable-commit-after'] |
| 2258 | |
| 2259 | # Wait for l1 to notice |
| 2260 | wait_for(lambda: 'connected' not in only_one(l1.rpc.listpeers()['peers'][0]['channels'])) |
| 2261 | |
| 2262 | # Now restart l2 and it should reload peers/channels from the DB |
| 2263 | l2.start() |
| 2264 | wait_for(lambda: len(l2.rpc.listpeers()['peers']) == 1) |
| 2265 | |
| 2266 | # Wait for the restored HTLC to finish |
| 2267 | wait_for(lambda: only_one(l1.rpc.listpeers()['peers'][0]['channels'])['to_us_msat'] == 99990000) |
| 2268 | |
| 2269 | wait_for(lambda: len([p for p in l1.rpc.listpeers()['peers'] if p['connected']])) |
| 2270 | wait_for(lambda: len([p for p in l2.rpc.listpeers()['peers'] if p['connected']])) |
| 2271 | |
| 2272 | # Now make sure this is really functional by sending a payment |
| 2273 | l1.pay(l2, 10000) |
| 2274 | |
| 2275 | # L1 doesn't actually update to_us_msat until it receives |
nothing calls this directly
no test coverage detected