daemon/chaintopology: don't leave outgoing txs in peer structure.

The peer structure is only for the old daemon; instead move the list
of all outgoing txs for rebroadcasting into struct topology (still
owned by peers, so they are removed when it exits).

One subtlety: on exit, struct topology is free before the peers,
so they end up removing from a freed list.  Thus we actually free
every outgoing tx manually on topology free.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2017-03-02 22:51:49 +10:30
parent e6efcdf5bd
commit d34dade8bb
4 changed files with 45 additions and 34 deletions

View File

@ -70,6 +70,9 @@ struct topology {
struct block_map block_map;
u64 feerate;
bool startup;
/* Bitcoin transctions we're broadcasting */
struct list_head outgoing_txs;
};
static void start_poll_chaintip(struct lightningd_state *dstate);
@ -123,15 +126,12 @@ static void add_tx_to_block(struct block *b, const struct sha256_double *txid, c
static bool we_broadcast(struct lightningd_state *dstate,
const struct sha256_double *txid)
{
struct peer *peer;
struct topology *topo = dstate->topology;
struct outgoing_tx *otx;
list_for_each(&dstate->peers, peer, list) {
struct outgoing_tx *otx;
list_for_each(&peer->outgoing_txs, otx, list) {
if (structeq(&otx->txid, txid))
return true;
}
list_for_each(&topo->outgoing_txs, otx, list) {
if (structeq(&otx->txid, txid))
return true;
}
return false;
}
@ -270,7 +270,8 @@ static void rebroadcast_txs(struct lightningd_state *dstate,
/* Copy txs now (peers may go away, and they own txs). */
size_t num_txs = 0;
struct txs_to_broadcast *txs;
struct peer *peer;
struct topology *topo = dstate->topology;
struct outgoing_tx *otx;
if (dstate->dev_no_broadcast)
return;
@ -280,17 +281,13 @@ static void rebroadcast_txs(struct lightningd_state *dstate,
/* Put any txs we want to broadcast in ->txs. */
txs->txs = tal_arr(txs, const char *, 0);
list_for_each(&dstate->peers, peer, list) {
struct outgoing_tx *otx;
list_for_each(&topo->outgoing_txs, otx, list) {
if (block_for_tx(dstate, &otx->txid))
continue;
list_for_each(&peer->outgoing_txs, otx, list) {
if (block_for_tx(dstate, &otx->txid))
continue;
tal_resize(&txs->txs, num_txs+1);
txs->txs[num_txs] = tal_strdup(txs, otx->hextx);
num_txs++;
}
tal_resize(&txs->txs, num_txs+1);
txs->txs[num_txs] = tal_strdup(txs, otx->hextx);
num_txs++;
}
/* Let this do the dirty work. */
@ -300,19 +297,22 @@ static void rebroadcast_txs(struct lightningd_state *dstate,
static void destroy_outgoing_tx(struct outgoing_tx *otx)
{
list_del_from(&otx->peer->outgoing_txs, &otx->list);
list_del(&otx->list);
}
static void broadcast_done(struct bitcoind *bitcoind,
int exitstatus, const char *msg,
struct outgoing_tx *otx)
{
struct lightningd_state *dstate = tal_parent(bitcoind);
struct topology *topo = dstate->topology;
if (otx->failed && exitstatus != 0) {
otx->failed(otx->peer, exitstatus, msg);
tal_free(otx);
} else {
/* For continual rebroadcasting */
list_add_tail(&otx->peer->outgoing_txs, &otx->list);
list_add_tail(&topo->outgoing_txs, &otx->list);
tal_add_destructor(otx, destroy_outgoing_tx);
}
}
@ -608,15 +608,28 @@ static const struct json_command dev_broadcast_command = {
};
AUTODATA(json_command, &dev_broadcast_command);
/* On shutdown, peers get deleted last. That frees from our list, so
* do it now instead. */
static void destroy_outgoing_txs(struct topology *topo)
{
struct outgoing_tx *otx;
while ((otx = list_pop(&topo->outgoing_txs, struct outgoing_tx, list)))
tal_free(otx);
}
void setup_topology(struct lightningd_state *dstate)
{
dstate->topology = tal(dstate, struct topology);
block_map_init(&dstate->topology->block_map);
list_head_init(&dstate->topology->outgoing_txs);
dstate->topology->startup = true;
dstate->topology->feerate = 0;
bitcoind_getblockcount(dstate->bitcoind, get_init_blockhash, NULL);
tal_add_destructor(dstate->topology, destroy_outgoing_txs);
/* Once it gets topology, it calls io_break() and we return. */
io_loop(NULL, NULL);
assert(!dstate->topology->startup);

View File

@ -1,6 +1,8 @@
#ifndef LIGHTNING_DAEMON_CHAINTOPOLOGY_H
#define LIGHTNING_DAEMON_CHAINTOPOLOGY_H
#include "config.h"
#include <bitcoin/shadouble.h>
#include <ccan/list/list.h>
#include <ccan/short_types/short_types.h>
#include <stddef.h>
@ -10,6 +12,15 @@ struct peer;
struct sha256_double;
struct txwatch;
/* Off topology->outgoing_txs */
struct outgoing_tx {
struct list_node list;
struct peer *peer;
const char *hextx;
struct sha256_double txid;
void (*failed)(struct peer *peer, int exitstatus, const char *err);
};
/* Information relevant to locating a TX in a blockchain. */
struct txlocator {

View File

@ -2752,7 +2752,6 @@ struct peer *new_peer(struct lightningd_state *dstate,
peer->outpkt = tal_arr(peer, Pkt *, 0);
peer->open_jsoncmd = NULL;
peer->commit_jsoncmd = NULL;
list_head_init(&peer->outgoing_txs);
list_head_init(&peer->their_commits);
peer->anchor.ok_depth = -1;
peer->order_counter = 0;

View File

@ -77,15 +77,6 @@ struct peer_visible_state {
struct channel_state *staging_cstate;
};
/* Off peer->outgoing_txs */
struct outgoing_tx {
struct list_node list;
struct peer *peer;
const char *hextx;
struct sha256_double txid;
void (*failed)(struct peer *peer, int exitstatus, const char *err);
};
struct peer {
/* dstate->peers list */
struct list_node list;
@ -207,9 +198,6 @@ struct peer {
/* Things we're watching for (see watches.c) */
struct list_head watches;
/* Bitcoin transctions we're broadcasting (see chaintopology.c) */
struct list_head outgoing_txs;
/* Timeout for collecting changes before sending commit. */
struct oneshot *commit_timer;