From 3aca5c87e3f341c86c78f7b35806dc017f00a5ee Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 9 Nov 2016 18:52:15 +1030 Subject: [PATCH] init: rebroadcast anchors on restart if we haven't seen them. It's possible that we won't have sent the anchor, but state is committed in db. And our current philosophy is that we retransmit all the txs dumbly, all the time. Our --restart --timeout-anchor test trigger this case, too, so re-enable that now. Signed-off-by: Rusty Russell --- daemon/lightningd.c | 3 +++ daemon/peer.c | 32 ++++++++++++++++++++++++++++---- daemon/peer.h | 1 + daemon/test/Makefile | 6 ++---- 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/daemon/lightningd.c b/daemon/lightningd.c index e8b828d9f..419b6c264 100644 --- a/daemon/lightningd.c +++ b/daemon/lightningd.c @@ -554,6 +554,9 @@ int main(int argc, char *argv[]) /* If we loaded peers from database, reconnect now. */ reconnect_peers(dstate); + + /* And send out anchors again if we're waiting. */ + rebroadcast_anchors(dstate); for (;;) { struct timer *expired; diff --git a/daemon/peer.c b/daemon/peer.c index ebfdc537c..ea3eb36ea 100644 --- a/daemon/peer.c +++ b/daemon/peer.c @@ -512,7 +512,7 @@ out: } /* Creation the bitcoin anchor tx, spending output user provided. */ -static void bitcoin_create_anchor(struct peer *peer) +static bool bitcoin_create_anchor(struct peer *peer) { struct bitcoin_tx *tx = bitcoin_tx(peer, 1, 1); size_t i; @@ -530,8 +530,10 @@ static void bitcoin_create_anchor(struct peer *peer) tx->input[0].amount = tal_dup(tx->input, u64, &peer->anchor.input->in_amount); - wallet_add_signed_input(peer->dstate, &peer->anchor.input->walletkey, - tx, 0); + if (!wallet_add_signed_input(peer->dstate, + &peer->anchor.input->walletkey, + tx, 0)) + return false; bitcoin_txid(tx, &peer->anchor.txid); peer->anchor.tx = tx; @@ -542,6 +544,7 @@ static void bitcoin_create_anchor(struct peer *peer) /* To avoid malleation, all inputs must be segwit! */ for (i = 0; i < tx->input_count; i++) assert(tx->input[i].witness); + return true; } static bool open_pkt_in(struct peer *peer, const Pkt *pkt) @@ -577,7 +580,11 @@ static bool open_pkt_in(struct peer *peer, const Pkt *pkt) &peer->remote.commitkey); if (peer->local.offer_anchor) { - bitcoin_create_anchor(peer); + if (!bitcoin_create_anchor(peer)) { + db_abort_transaction(peer); + err = pkt_err(peer, "Own anchor unavailable"); + return peer_comms_err(peer, err); + } /* FIXME: Redundant with peer->local.offer_anchor? */ peer->anchor.ours = true; @@ -4419,6 +4426,23 @@ void reconnect_peers(struct lightningd_state *dstate) try_reconnect(peer); } +/* We may have gone down before broadcasting the anchor. Try again. */ +void rebroadcast_anchors(struct lightningd_state *dstate) +{ + struct peer *peer; + + list_for_each(&dstate->peers, peer, list) { + if (!state_is_waiting_for_anchor(peer->state)) + continue; + if (!peer->anchor.ours) + continue; + if (!bitcoin_create_anchor(peer)) + peer_fail(peer, __func__); + else + broadcast_tx(peer, peer->anchor.tx, NULL); + } +} + static void json_add_abstime(struct json_result *response, const char *id, const struct abs_locktime *t) diff --git a/daemon/peer.h b/daemon/peer.h index 4eec22630..a77bf5469 100644 --- a/daemon/peer.h +++ b/daemon/peer.h @@ -291,5 +291,6 @@ struct bitcoin_tx *peer_create_close_tx(const tal_t *ctx, void debug_dump_peers(struct lightningd_state *dstate); void reconnect_peers(struct lightningd_state *dstate); +void rebroadcast_anchors(struct lightningd_state *dstate); void cleanup_peers(struct lightningd_state *dstate); #endif /* LIGHTNING_DAEMON_PEER_H */ diff --git a/daemon/test/Makefile b/daemon/test/Makefile index cf0bd0e7f..ccaadce21 100644 --- a/daemon/test/Makefile +++ b/daemon/test/Makefile @@ -18,11 +18,9 @@ daemon-test.sh-0-mutual-close-with-htlcs: daemon-test.sh-0-manual-commit daemon-test.sh-0-manual-commit: daemon-test.sh-0-normal daemon-test.sh-0-normal: daemon-test-setup-0 -#FIXME: daemon-test.sh-1-timeout-anchor\ --restart -# This doesn't work because we don't retransmit anchor! - daemon-test.sh-1-steal\ --restart: daemon-test.sh-1-dump-onchain\ --restart -daemon-test.sh-1-dump-onchain\ --restart: daemon-test.sh-1-different-fee-rates\ --restart +daemon-test.sh-1-dump-onchain\ --restart: daemon-test.sh-1-timeout-anchor\ --restart +daemon-test.sh-1-timeout-anchor\ --restart: daemon-test.sh-1-different-fee-rates\ --restart daemon-test.sh-1-different-fee-rates\ --restart: daemon-test.sh-1-mutual-close-with-htlcs\ --restart daemon-test.sh-1-mutual-close-with-htlcs\ --restart: daemon-test.sh-1-manual-commit\ --restart daemon-test.sh-1-manual-commit\ --restart: daemon-test.sh-1-normal\ --restart