diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index 9430b1c86..514d9f4d5 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -366,26 +366,8 @@ int main(int argc, char *argv[]) ld->ini_autocleaninvoice_cycle, ld->ini_autocleaninvoice_expiredby); - /* Load peers from database */ - if (!wallet_channels_load_active(ld, ld->wallet)) - fatal("Could not load channels from the database"); - - /* TODO(cdecker) Move this into common location for initialization */ - struct peer *peer; - list_for_each(&ld->peers, peer, list) { - struct channel *channel; - - list_for_each(&peer->channels, channel, list) { - if (!wallet_htlcs_load_for_channel(ld->wallet, - channel, - &ld->htlcs_in, - &ld->htlcs_out)) { - fatal("could not load htlcs for channel"); - } - } - } - if (!wallet_htlcs_reconnect(ld->wallet, &ld->htlcs_in, &ld->htlcs_out)) - fatal("could not reconnect htlcs loaded from wallet, wallet may be inconsistent."); + /* Pull peers, channels and HTLCs from db. */ + load_channels_from_wallet(ld); /* Get the blockheight we are currently at, UINT32_MAX is used to signal * an unitialized wallet and that we should start off of bitcoind's diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 7c7c1902e..cba4f5130 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -945,6 +945,33 @@ void activate_peers(struct lightningd *ld) activate_peer(p); } +/* Pull peers, channels and HTLCs from db, and wire them up. */ +void load_channels_from_wallet(struct lightningd *ld) +{ + struct peer *peer; + + /* Load peers from database */ + if (!wallet_channels_load_active(ld, ld->wallet)) + fatal("Could not load channels from the database"); + + /* This is a poor-man's db join :( */ + list_for_each(&ld->peers, peer, list) { + struct channel *channel; + + list_for_each(&peer->channels, channel, list) { + if (!wallet_htlcs_load_for_channel(ld->wallet, + channel, + &ld->htlcs_in, + &ld->htlcs_out)) { + fatal("could not load htlcs for channel"); + } + } + } + + /* Now connect HTLC pointers together */ + htlcs_reconnect(ld, &ld->htlcs_in, &ld->htlcs_out); +} + static void json_disconnect(struct command *cmd, const char *buffer, const jsmntok_t *params) { diff --git a/lightningd/peer_control.h b/lightningd/peer_control.h index 860f7bb33..56ea372ad 100644 --- a/lightningd/peer_control.h +++ b/lightningd/peer_control.h @@ -89,4 +89,7 @@ void activate_peers(struct lightningd *ld); void drop_to_chain(struct lightningd *ld, struct channel *channel, bool cooperative); void channel_watch_funding(struct lightningd *ld, struct channel *channel); + +/* Pull peers, channels and HTLCs from db, and wire them up. */ +void load_channels_from_wallet(struct lightningd *ld); #endif /* LIGHTNING_LIGHTNINGD_PEER_CONTROL_H */ diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 8f3e43a28..db7652feb 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -1671,6 +1671,48 @@ void htlcs_notify_new_block(struct lightningd *ld, u32 height) } while (removed); } +/** + * htlcs_reconnect -- Link outgoing HTLCs to their origins after initial db load + * + * For each outgoing HTLC find the incoming HTLC that triggered it. If + * we are the origin of the transfer then we cannot resolve the + * incoming HTLC in which case we just leave it `NULL`. + */ +void htlcs_reconnect(struct lightningd *ld, + struct htlc_in_map *htlcs_in, + struct htlc_out_map *htlcs_out) +{ + struct htlc_in_map_iter ini; + struct htlc_out_map_iter outi; + struct htlc_in *hin; + struct htlc_out *hout; + + for (hout = htlc_out_map_first(htlcs_out, &outi); hout; + hout = htlc_out_map_next(htlcs_out, &outi)) { + + if (hout->origin_htlc_id == 0) { + continue; + } + + for (hin = htlc_in_map_first(htlcs_in, &ini); hin; + hin = htlc_in_map_next(htlcs_in, &ini)) { + if (hout->origin_htlc_id == hin->dbid) { + log_debug(ld->log, + "Found corresponding htlc_in %" PRIu64 + " for htlc_out %" PRIu64, + hin->dbid, hout->dbid); + hout->in = hin; + break; + } + } + + if (!hout->in) + fatal("Unable to find corresponding htlc_in %"PRIu64" for htlc_out %"PRIu64, + hout->origin_htlc_id, hout->dbid); + } +} + + #if DEVELOPER static void json_dev_ignore_htlcs(struct command *cmd, const char *buffer, const jsmntok_t *params) diff --git a/lightningd/peer_htlcs.h b/lightningd/peer_htlcs.h index f1083315e..a36c01b96 100644 --- a/lightningd/peer_htlcs.h +++ b/lightningd/peer_htlcs.h @@ -60,4 +60,8 @@ void onchain_fulfilled_htlc(struct channel *channel, void htlcs_notify_new_block(struct lightningd *ld, u32 height); +void htlcs_reconnect(struct lightningd *ld, + struct htlc_in_map *htlcs_in, + struct htlc_out_map *htlcs_out); + #endif /* LIGHTNING_LIGHTNINGD_PEER_HTLCS_H */ diff --git a/lightningd/test/run-find_my_path.c b/lightningd/test/run-find_my_path.c index 82fa522f3..672223ef0 100644 --- a/lightningd/test/run-find_my_path.c +++ b/lightningd/test/run-find_my_path.c @@ -71,6 +71,9 @@ void htlcs_notify_new_block(struct lightningd *ld UNNEEDED, u32 height UNNEEDED) /* Generated stub for json_escape */ struct json_escaped *json_escape(const tal_t *ctx UNNEEDED, const char *str TAKES UNNEEDED) { fprintf(stderr, "json_escape called!\n"); abort(); } +/* Generated stub for load_channels_from_wallet */ +void load_channels_from_wallet(struct lightningd *ld UNNEEDED) +{ fprintf(stderr, "load_channels_from_wallet called!\n"); abort(); } /* Generated stub for log_ */ void log_(struct log *log UNNEEDED, enum log_level level UNNEEDED, const char *fmt UNNEEDED, ...) @@ -126,20 +129,6 @@ const char *version(void) /* Generated stub for wallet_blocks_heights */ void wallet_blocks_heights(struct wallet *w UNNEEDED, u32 def UNNEEDED, u32 *min UNNEEDED, u32 *max UNNEEDED) { fprintf(stderr, "wallet_blocks_heights called!\n"); abort(); } -/* Generated stub for wallet_channels_load_active */ -bool wallet_channels_load_active(const tal_t *ctx UNNEEDED, struct wallet *w UNNEEDED) -{ fprintf(stderr, "wallet_channels_load_active called!\n"); abort(); } -/* Generated stub for wallet_htlcs_load_for_channel */ -bool wallet_htlcs_load_for_channel(struct wallet *wallet UNNEEDED, - struct channel *chan UNNEEDED, - struct htlc_in_map *htlcs_in UNNEEDED, - struct htlc_out_map *htlcs_out UNNEEDED) -{ fprintf(stderr, "wallet_htlcs_load_for_channel called!\n"); abort(); } -/* Generated stub for wallet_htlcs_reconnect */ -bool wallet_htlcs_reconnect(struct wallet *wallet UNNEEDED, - struct htlc_in_map *htlcs_in UNNEEDED, - struct htlc_out_map *htlcs_out UNNEEDED) -{ fprintf(stderr, "wallet_htlcs_reconnect called!\n"); abort(); } /* Generated stub for wallet_invoice_autoclean */ void wallet_invoice_autoclean(struct wallet * wallet UNNEEDED, u64 cycle_seconds UNNEEDED, diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 41dcee370..dee09cd69 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -12,6 +12,7 @@ static void db_log_(struct log *log UNUSED, enum log_level level UNUSED, const c #include "wallet/wallet.c" #include "lightningd/htlc_end.c" #include "lightningd/peer_control.c" +#include "lightningd/peer_htlcs.c" #include "lightningd/channel.c" #include "wallet/db.c" @@ -69,12 +70,30 @@ void delay_then_reconnect(struct channel *channel UNNEEDED, u32 seconds_delay UN /* Generated stub for fatal */ void fatal(const char *fmt UNNEEDED, ...) { fprintf(stderr, "fatal called!\n"); abort(); } +/* Generated stub for fromwire_channel_got_commitsig */ +bool fromwire_channel_got_commitsig(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *commitnum UNNEEDED, u32 *feerate UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, secp256k1_ecdsa_signature **htlc_signature UNNEEDED, struct added_htlc **added UNNEEDED, struct secret **shared_secret UNNEEDED, struct fulfilled_htlc **fulfilled UNNEEDED, struct failed_htlc ***failed UNNEEDED, struct changed_htlc **changed UNNEEDED, struct bitcoin_tx **tx UNNEEDED) +{ fprintf(stderr, "fromwire_channel_got_commitsig called!\n"); abort(); } +/* Generated stub for fromwire_channel_got_revoke */ +bool fromwire_channel_got_revoke(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *revokenum UNNEEDED, struct secret *per_commitment_secret UNNEEDED, struct pubkey *next_per_commit_point UNNEEDED, u32 *feerate UNNEEDED, struct changed_htlc **changed UNNEEDED) +{ fprintf(stderr, "fromwire_channel_got_revoke called!\n"); abort(); } +/* Generated stub for fromwire_channel_offer_htlc_reply */ +bool fromwire_channel_offer_htlc_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *id UNNEEDED, u16 *failure_code UNNEEDED, u8 **failurestr UNNEEDED) +{ fprintf(stderr, "fromwire_channel_offer_htlc_reply called!\n"); abort(); } +/* Generated stub for fromwire_channel_sending_commitsig */ +bool fromwire_channel_sending_commitsig(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *commitnum UNNEEDED, u32 *feerate UNNEEDED, struct changed_htlc **changed UNNEEDED, secp256k1_ecdsa_signature *commit_sig UNNEEDED, secp256k1_ecdsa_signature **htlc_sigs UNNEEDED) +{ fprintf(stderr, "fromwire_channel_sending_commitsig called!\n"); abort(); } /* Generated stub for fromwire_connect_peer_connected */ bool fromwire_connect_peer_connected(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct pubkey *id UNNEEDED, struct wireaddr_internal *addr UNNEEDED, struct crypto_state *crypto_state UNNEEDED, u8 **gfeatures UNNEEDED, u8 **lfeatures UNNEEDED) { fprintf(stderr, "fromwire_connect_peer_connected called!\n"); abort(); } +/* Generated stub for fromwire_gossip_resolve_channel_reply */ +bool fromwire_gossip_resolve_channel_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct pubkey **keys UNNEEDED) +{ fprintf(stderr, "fromwire_gossip_resolve_channel_reply called!\n"); abort(); } /* Generated stub for fromwire_hsm_sign_commitment_tx_reply */ bool fromwire_hsm_sign_commitment_tx_reply(const void *p UNNEEDED, secp256k1_ecdsa_signature *sig UNNEEDED) { fprintf(stderr, "fromwire_hsm_sign_commitment_tx_reply called!\n"); abort(); } +/* Generated stub for get_block_height */ +u32 get_block_height(const struct chain_topology *topo UNNEEDED) +{ fprintf(stderr, "get_block_height called!\n"); abort(); } /* Generated stub for invoices_autoclean_set */ void invoices_autoclean_set(struct invoices *invoices UNNEEDED, u64 cycle_seconds UNNEEDED, @@ -275,6 +294,9 @@ enum watch_result onchaind_funding_spent(struct channel *channel UNNEEDED, const struct bitcoin_tx *tx UNNEEDED, u32 blockheight UNNEEDED) { fprintf(stderr, "onchaind_funding_spent called!\n"); abort(); } +/* Generated stub for onion_type_name */ +const char *onion_type_name(int e UNNEEDED) +{ fprintf(stderr, "onion_type_name called!\n"); abort(); } /* Generated stub for opening_peer_no_active_channels */ void opening_peer_no_active_channels(struct peer *peer UNNEEDED) { fprintf(stderr, "opening_peer_no_active_channels called!\n"); abort(); } @@ -297,6 +319,24 @@ void outpointfilter_remove(struct outpointfilter *of UNNEEDED, bool param(struct command *cmd UNNEEDED, const char *buffer UNNEEDED, const jsmntok_t params[] UNNEEDED, ...) { fprintf(stderr, "param called!\n"); abort(); } +/* Generated stub for parse_onionpacket */ +struct onionpacket *parse_onionpacket( + const tal_t *ctx UNNEEDED, + const void *src UNNEEDED, + const size_t srclen + ) +{ fprintf(stderr, "parse_onionpacket called!\n"); abort(); } +/* Generated stub for payment_failed */ +void payment_failed(struct lightningd *ld UNNEEDED, const struct htlc_out *hout UNNEEDED, + const char *localfail UNNEEDED) +{ fprintf(stderr, "payment_failed called!\n"); abort(); } +/* Generated stub for payment_store */ +void payment_store(struct lightningd *ld UNNEEDED, const struct sha256 *payment_hash UNNEEDED) +{ fprintf(stderr, "payment_store called!\n"); abort(); } +/* Generated stub for payment_succeeded */ +void payment_succeeded(struct lightningd *ld UNNEEDED, struct htlc_out *hout UNNEEDED, + const struct preimage *rval UNNEEDED) +{ fprintf(stderr, "payment_succeeded called!\n"); abort(); } /* Generated stub for peer_start_channeld */ void peer_start_channeld(struct channel *channel UNNEEDED, const struct crypto_state *cs UNNEEDED, @@ -317,6 +357,20 @@ void peer_start_openingd(struct peer *peer UNNEEDED, int peer_fd UNNEEDED, int gossip_fd UNNEEDED, const u8 *msg UNNEEDED) { fprintf(stderr, "peer_start_openingd called!\n"); abort(); } +/* Generated stub for process_onionpacket */ +struct route_step *process_onionpacket( + const tal_t * ctx UNNEEDED, + const struct onionpacket *packet UNNEEDED, + const u8 *shared_secret UNNEEDED, + const u8 *assocdata UNNEEDED, + const size_t assocdatalen + ) +{ fprintf(stderr, "process_onionpacket called!\n"); abort(); } +/* Generated stub for serialize_onionpacket */ +u8 *serialize_onionpacket( + const tal_t *ctx UNNEEDED, + const struct onionpacket *packet UNNEEDED) +{ fprintf(stderr, "serialize_onionpacket called!\n"); abort(); } /* Generated stub for subd_release_channel */ void subd_release_channel(struct subd *owner UNNEEDED, void *channel UNNEEDED) { fprintf(stderr, "subd_release_channel called!\n"); abort(); } @@ -334,6 +388,24 @@ void subd_send_msg(struct subd *sd UNNEEDED, const u8 *msg_out UNNEEDED) /* Generated stub for towire_channel_dev_reenable_commit */ u8 *towire_channel_dev_reenable_commit(const tal_t *ctx UNNEEDED) { fprintf(stderr, "towire_channel_dev_reenable_commit called!\n"); abort(); } +/* Generated stub for towire_channel_fail_htlc */ +u8 *towire_channel_fail_htlc(const tal_t *ctx UNNEEDED, const struct failed_htlc *failed_htlc UNNEEDED) +{ fprintf(stderr, "towire_channel_fail_htlc called!\n"); abort(); } +/* Generated stub for towire_channel_fulfill_htlc */ +u8 *towire_channel_fulfill_htlc(const tal_t *ctx UNNEEDED, const struct fulfilled_htlc *fulfilled_htlc UNNEEDED) +{ fprintf(stderr, "towire_channel_fulfill_htlc called!\n"); abort(); } +/* Generated stub for towire_channel_got_commitsig_reply */ +u8 *towire_channel_got_commitsig_reply(const tal_t *ctx UNNEEDED) +{ fprintf(stderr, "towire_channel_got_commitsig_reply called!\n"); abort(); } +/* Generated stub for towire_channel_got_revoke_reply */ +u8 *towire_channel_got_revoke_reply(const tal_t *ctx UNNEEDED) +{ fprintf(stderr, "towire_channel_got_revoke_reply called!\n"); abort(); } +/* Generated stub for towire_channel_offer_htlc */ +u8 *towire_channel_offer_htlc(const tal_t *ctx UNNEEDED, u64 amount_msat UNNEEDED, u32 cltv_expiry UNNEEDED, const struct sha256 *payment_hash UNNEEDED, const u8 onion_routing_packet[1366]) +{ fprintf(stderr, "towire_channel_offer_htlc called!\n"); abort(); } +/* Generated stub for towire_channel_sending_commitsig_reply */ +u8 *towire_channel_sending_commitsig_reply(const tal_t *ctx UNNEEDED) +{ fprintf(stderr, "towire_channel_sending_commitsig_reply called!\n"); abort(); } /* Generated stub for towire_channel_send_shutdown */ u8 *towire_channel_send_shutdown(const tal_t *ctx UNNEEDED) { fprintf(stderr, "towire_channel_send_shutdown called!\n"); abort(); } @@ -348,9 +420,15 @@ u8 *towire_errorfmt(const tal_t *ctx UNNEEDED, const struct channel_id *channel UNNEEDED, const char *fmt UNNEEDED, ...) { fprintf(stderr, "towire_errorfmt called!\n"); abort(); } +/* Generated stub for towire_gossip_resolve_channel_request */ +u8 *towire_gossip_resolve_channel_request(const tal_t *ctx UNNEEDED, const struct short_channel_id *channel_id UNNEEDED) +{ fprintf(stderr, "towire_gossip_resolve_channel_request called!\n"); abort(); } /* Generated stub for towire_hsm_sign_commitment_tx */ u8 *towire_hsm_sign_commitment_tx(const tal_t *ctx UNNEEDED, const struct pubkey *peer_id UNNEEDED, u64 channel_dbid UNNEEDED, const struct bitcoin_tx *tx UNNEEDED, const struct pubkey *remote_funding_key UNNEEDED, u64 funding_amount UNNEEDED) { fprintf(stderr, "towire_hsm_sign_commitment_tx called!\n"); abort(); } +/* Generated stub for towire_onchain_known_preimage */ +u8 *towire_onchain_known_preimage(const tal_t *ctx UNNEEDED, const struct preimage *preimage UNNEEDED) +{ fprintf(stderr, "towire_onchain_known_preimage called!\n"); abort(); } /* Generated stub for watch_txid */ struct txwatch *watch_txid(const tal_t *ctx UNNEEDED, struct chain_topology *topo UNNEEDED, @@ -903,10 +981,9 @@ static bool test_htlc_crud(struct lightningd *ld, const tal_t *ctx) CHECK_MSG(wallet_htlcs_load_for_channel(w, chan, htlcs_in, htlcs_out), "Failed loading HTLCs"); - - CHECK_MSG(wallet_htlcs_reconnect(w, htlcs_in, htlcs_out), - "Unable to reconnect htlcs."); db_commit_transaction(w->db); + + htlcs_reconnect(w->ld, htlcs_in, htlcs_out); CHECK(!wallet_err); hin = htlc_in_map_get(htlcs_in, &in.key); diff --git a/wallet/wallet.c b/wallet/wallet.c index 0f6b350f8..500a745fd 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1383,45 +1383,6 @@ bool wallet_htlcs_load_for_channel(struct wallet *wallet, return ok; } -bool wallet_htlcs_reconnect(struct wallet *wallet, - struct htlc_in_map *htlcs_in, - struct htlc_out_map *htlcs_out) -{ - struct htlc_in_map_iter ini; - struct htlc_out_map_iter outi; - struct htlc_in *hin; - struct htlc_out *hout; - - for (hout = htlc_out_map_first(htlcs_out, &outi); hout; - hout = htlc_out_map_next(htlcs_out, &outi)) { - - if (hout->origin_htlc_id == 0) { - continue; - } - - for (hin = htlc_in_map_first(htlcs_in, &ini); hin; - hin = htlc_in_map_next(htlcs_in, &ini)) { - if (hout->origin_htlc_id == hin->dbid) { - log_debug(wallet->log, - "Found corresponding htlc_in %" PRIu64 - " for htlc_out %" PRIu64, - hin->dbid, hout->dbid); - hout->in = hin; - break; - } - } - - if (!hout->in) { - log_broken( - wallet->log, - "Unable to find corresponding htlc_in %"PRIu64" for htlc_out %"PRIu64, - hout->origin_htlc_id, hout->dbid); - } - - } - return true; -} - bool wallet_invoice_create(struct wallet *wallet, struct invoice *pinvoice, u64 *msatoshi TAKES, diff --git a/wallet/wallet.h b/wallet/wallet.h index d93795be2..28df8f217 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -480,7 +480,7 @@ void wallet_htlc_update(struct wallet *wallet, const u64 htlc_dbid, * may not have been loaded yet. In the latter case the pay_command * does not exist anymore since we restarted. * - * Use `wallet_htlcs_reconnect` to wire htlc_out instances to the + * Use `htlcs_reconnect` to wire htlc_out instances to the * corresponding htlc_in after loading all channels. */ bool wallet_htlcs_load_for_channel(struct wallet *wallet, @@ -488,16 +488,6 @@ bool wallet_htlcs_load_for_channel(struct wallet *wallet, struct htlc_in_map *htlcs_in, struct htlc_out_map *htlcs_out); -/** - * wallet_htlcs_reconnect -- Link outgoing HTLCs to their origins - * - * For each outgoing HTLC find the incoming HTLC that triggered it. If - * we are the origin of the transfer then we cannot resolve the - * incoming HTLC in which case we just leave it `NULL`. - */ -bool wallet_htlcs_reconnect(struct wallet *wallet, - struct htlc_in_map *htlcs_in, - struct htlc_out_map *htlcs_out); /* /!\ This is a DB ENUM, please do not change the numbering of any * already defined elements (adding is ok) /!\ */