chaintopology: watch UTXOs which need closeinfo when we remove blocks.

Normal wallet txs get reconfirmed as blocks come in, but ones which need
closeinfo are more fragile, so we do it manually using txwatch for them.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2018-08-13 12:37:46 +09:30 committed by Christian Decker
parent 05f12edf60
commit f8052a6c1a
2 changed files with 47 additions and 1 deletions

View File

@ -222,6 +222,49 @@ void broadcast_tx(struct chain_topology *topo,
bitcoind_sendrawtx(topo->bitcoind, otx->hextx, broadcast_done, otx); bitcoind_sendrawtx(topo->bitcoind, otx->hextx, broadcast_done, otx);
} }
static enum watch_result closeinfo_txid_confirmed(struct lightningd *ld,
struct channel *channel,
const struct bitcoin_txid *txid,
unsigned int depth)
{
/* We delete ourselves first time, so should not be reorged out!! */
assert(depth > 0);
/* Subtle: depth 1 == current block. */
wallet_confirm_tx(ld->wallet, txid,
get_block_height(ld->topology) + 1 - depth);
return DELETE_WATCH;
}
/* We need to know if close_info UTXOs (which the wallet doesn't natively know
* how to spend, so is not in the normal path) get reconfirmed.
*
* This can happen on startup (where we manually unwind 100 blocks) or on a
* reorg. The db NULLs out the confirmation_height, so we can't easily figure
* out just the new ones (and removing the ON DELETE SET NULL clause is
* non-trivial).
*
* So every time, we just set a notification for every tx in this class we're
* not already watching: there are not usually many, nor many reorgs, so the
* redundancy is OK.
*/
static void watch_for_utxo_reconfirmation(struct chain_topology *topo,
struct wallet *wallet)
{
struct utxo **unconfirmed;
unconfirmed = wallet_get_unconfirmed_closeinfo_utxos(tmpctx, wallet);
for (size_t i = 0; i < tal_count(unconfirmed); i++) {
assert(unconfirmed[i]->close_info != NULL);
assert(unconfirmed[i]->blockheight == NULL);
if (find_txwatch(topo, &unconfirmed[i]->txid, NULL))
continue;
notleak(watch_txid(topo, topo, NULL, &unconfirmed[i]->txid,
closeinfo_txid_confirmed));
}
}
static const char *feerate_name(enum feerate feerate) static const char *feerate_name(enum feerate feerate)
{ {
return feerate == FEERATE_IMMEDIATE ? "Immediate" return feerate == FEERATE_IMMEDIATE ? "Immediate"
@ -458,6 +501,8 @@ static void remove_tip(struct chain_topology *topo)
txwatch_fire(topo, &txs[i], 0); txwatch_fire(topo, &txs[i], 0);
wallet_block_remove(topo->wallet, b); wallet_block_remove(topo->wallet, b);
/* This may have unconfirmed txs: reconfirm as we add blocks. */
watch_for_utxo_reconfirmation(topo, topo->wallet);
block_map_del(&topo->block_map, b); block_map_del(&topo->block_map, b);
tal_free(b); tal_free(b);
} }
@ -545,6 +590,8 @@ static void get_init_blockhash(struct bitcoind *bitcoind, u32 blockcount,
/* Rollback to the given blockheight, so we start track /* Rollback to the given blockheight, so we start track
* correctly again */ * correctly again */
wallet_blocks_rollback(topo->wallet, topo->max_blockheight); wallet_blocks_rollback(topo->wallet, topo->max_blockheight);
/* This may have unconfirmed txs: reconfirm as we add blocks. */
watch_for_utxo_reconfirmation(topo, topo->wallet);
/* Get up to speed with topology. */ /* Get up to speed with topology. */
bitcoind_getblockhash(bitcoind, topo->max_blockheight, bitcoind_getblockhash(bitcoind, topo->max_blockheight,

View File

@ -1112,7 +1112,6 @@ def test_permfail_htlc_out(node_factory, bitcoind, executor):
wait_for(lambda: l2.rpc.listpeers()['peers'] == []) wait_for(lambda: l2.rpc.listpeers()['peers'] == [])
@pytest.mark.xfail(strict=True)
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1") @unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
def test_permfail(node_factory, bitcoind): def test_permfail(node_factory, bitcoind):
l1, l2 = node_factory.line_graph(2) l1, l2 = node_factory.line_graph(2)