diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index 11662e650..823e697c0 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -267,6 +267,15 @@ int main(int argc, char *argv[]) /* FIXME: Load from peers. */ 0); + /* Load peers from database */ + wallet_channels_load_active(ld->wallet, &ld->peers); + struct peer *peer; + list_for_each(&ld->peers, peer, list) { + populate_peer(ld, peer); + peer->seed = tal(peer, struct privkey); + derive_peer_seed(ld, peer->seed, &peer->id); + } + /* Create RPC socket (if any) */ setup_jsonrpc(&ld->dstate, ld->dstate.rpc_filename); diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 68e146dd6..f8b8da969 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -550,6 +550,23 @@ static struct wallet_channel *peer_channel_new(struct wallet *w, return wc; } +void populate_peer(struct lightningd *ld, struct peer *peer) +{ + const char *idname; + struct pubkey *id = &peer->id; + idname = type_to_string(peer, struct pubkey, id); + + peer->ld = ld; + + /* Max 128k per peer. */ + peer->log_book = new_log_book(peer, 128*1024, + get_log_level(ld->dstate.log_book)); + peer->log = new_log(peer, peer->log_book, "peer %s:", idname); + set_log_outfn(peer->log_book, copy_to_parent_log, peer); + tal_free(idname); + tal_add_destructor(peer, destroy_peer); +} + void add_peer(struct lightningd *ld, u64 unique_id, int fd, const struct pubkey *id, const struct crypto_state *cs) @@ -598,14 +615,6 @@ void add_peer(struct lightningd *ld, u64 unique_id, /* peer->channel gets populated as soon as we start opening a channel */ peer->channel = NULL; - idname = type_to_string(peer, struct pubkey, id); - - /* Max 128k per peer. */ - peer->log_book = new_log_book(peer, 128*1024, - get_log_level(ld->dstate.log_book)); - peer->log = new_log(peer, peer->log_book, "peer %s:", idname); - set_log_outfn(peer->log_book, copy_to_parent_log, peer); - /* FIXME: Don't assume protocol here! */ if (!netaddr_from_fd(fd, SOCK_STREAM, IPPROTO_TCP, &peer->netaddr)) { log_unusual(ld->log, "Failed to get netaddr for outgoing: %s", @@ -613,11 +622,14 @@ void add_peer(struct lightningd *ld, u64 unique_id, tal_free(peer); return; } + list_add_tail(&ld->peers, &peer->list); + populate_peer(ld, peer); + + idname = type_to_string(peer, struct pubkey, id); netname = netaddr_name(idname, &peer->netaddr); log_info(peer->log, "Connected from %s", netname); + tal_free(idname); - list_add_tail(&ld->peers, &peer->list); - tal_add_destructor(peer, destroy_peer); /* Let gossip handle it from here. */ peer->owner = peer->ld->gossip; diff --git a/lightningd/peer_control.h b/lightningd/peer_control.h index 443afcb33..437aa7bb9 100644 --- a/lightningd/peer_control.h +++ b/lightningd/peer_control.h @@ -158,6 +158,18 @@ void add_peer(struct lightningd *ld, u64 unique_id, int fd, const struct pubkey *id, const struct crypto_state *cs); +/** + * populate_peer -- Populate daemon fields in a peer + * + * @ld: the daemon to wire the peer into + * @peer: the peer to populate + * + * Creating a new peer, or loading a peer from the database we need to + * populate a number of fields, e.g., the logging handler and the + * pointer to the daemon. populate_peer does exactly that. + */ +void populate_peer(struct lightningd *ld, struct peer *peer); + /* Could be configurable. */ #define OUR_CHANNEL_FLAGS CHANNEL_FLAGS_ANNOUNCE_CHANNEL diff --git a/tests/test_lightningd.py b/tests/test_lightningd.py index aa0301414..79e955f02 100644 --- a/tests/test_lightningd.py +++ b/tests/test_lightningd.py @@ -47,10 +47,10 @@ def setupBitcoind(): bitcoind.rpc.generate(1) -def wait_for(success, timeout=30): +def wait_for(success, timeout=30, interval=0.1): start_time = time.time() while not success() and time.time() < start_time + timeout: - pass + time.sleep(interval) if time.time() > start_time + timeout: raise ValueError("Error waiting for {}", success) @@ -875,17 +875,21 @@ class LightningDTests(BaseLightningDTests): for n in (l1, l2): assert(n.db_query('SELECT COUNT(id) as count FROM channels;')[0]['count'] == 1) - l1.daemon.stop() - - # Let the other side notice, then stop it - wait_for(lambda: not l2.rpc.getpeers()['peers'][0]['connected']) l2.daemon.stop() + # Let the other side notice, then stop it + wait_for(lambda: not l1.rpc.getpeers()['peers'][0]['connected']) + #l1.daemon.stop() + # Now restart l1 and it should reload peers/channels from the DB - l1.daemon.start() + l2.daemon.start() + wait_for(lambda: len(l2.rpc.getpeers()['peers']) == 1) - #wait_for(lambda: len(l1.rpc.getpeers()['peers']) == 1) + wait_for(lambda: len([p for p in l1.rpc.getpeers()['peers'] if p['connected']]), interval=1) + wait_for(lambda: len([p for p in l2.rpc.getpeers()['peers'] if p['connected']]), interval=1) + # Now make sure this is really functional by sending a payment + self.pay(l1, l2, 10000) class LegacyLightningDTests(BaseLightningDTests): diff --git a/wallet/wallet.c b/wallet/wallet.c index 96cdef60e..34e148119 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -591,6 +591,27 @@ bool wallet_channel_load(struct wallet *w, const u64 id, return ok; } +bool wallet_channels_load_active(struct wallet *w, struct list_head *peers) +{ + bool ok = true; + /* Channels are active if they have reached at least the + * opening state and they are not marked as complete */ + sqlite3_stmt *stmt = db_query( + __func__, w->db, "SELECT %s FROM channels WHERE state >= %d AND state != %d;", + channel_fields, OPENINGD, CLOSINGD_COMPLETE); + + int count = 0; + while (ok && stmt && sqlite3_step(stmt) == SQLITE_ROW) { + struct wallet_channel *c = talz(w, struct wallet_channel); + ok &= wallet_stmt2channel(w, stmt, c); + list_add(peers, &c->peer->list); + count++; + } + log_debug(w->log, "Loaded %d channels from DB", count); + sqlite3_finalize(stmt); + return ok; +} + static char* db_serialize_signature(const tal_t *ctx, secp256k1_ecdsa_signature* sig) { u8 buf[64]; diff --git a/wallet/wallet.h b/wallet/wallet.h index 22510f40c..cc56f9484 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -4,6 +4,7 @@ #include "config.h" #include "db.h" #include +#include #include #include #include @@ -197,4 +198,16 @@ bool wallet_channel_config_load(struct wallet *w, const u64 id, */ bool wallet_peer_by_nodeid(struct wallet *w, const struct pubkey *nodeid, struct peer *peer); + +/** + * wlalet_channels_load_active -- Load persisted active channels into the peers + * + * @w: wallet to load from + * @peers: list_head to load channels/peers into + * + * Be sure to call this only once on startup since it'll append peers + * loaded from the database to the list without checking. + */ +bool wallet_channels_load_active(struct wallet *w, struct list_head *peers); + #endif /* WALLET_WALLET_H */