diff --git a/lightningd/Makefile b/lightningd/Makefile index f7c1bb496..09b040953 100644 --- a/lightningd/Makefile +++ b/lightningd/Makefile @@ -148,7 +148,7 @@ check-makefile: check-lightningd-makefile check-lightningd-makefile: @for f in lightningd/*.h lightningd/*/*.h; do if ! echo $(LIGHTNINGD_HEADERS_NOGEN) $(LIGHTNINGD_HEADERS_GEN) "" | grep -q "$$f "; then echo $$f not mentioned in LIGHTNINGD_HEADERS_NOGEN or LIGHTNINGD_HEADERS_GEN >&2; exit 1; fi; done -lightningd/lightningd: $(LIGHTNINGD_OBJS) $(LIGHTNINGD_OLD_OBJS) $(LIGHTNINGD_OLD_LIB_OBJS) $(LIGHTNINGD_LIB_OBJS) $(LIGHTNINGD_JSMN_OBJS) $(CORE_OBJS) $(CORE_TX_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS) $(WIRE_ONION_OBJS) $(CCAN_OBJS) $(CCAN_SHACHAIN48_OBJ) $(LIGHTNINGD_HSM_CONTROL_OBJS) $(LIGHTNINGD_HANDSHAKE_CONTROL_OBJS) $(LIGHTNINGD_GOSSIP_CONTROL_OBJS) $(LIBBASE58_OBJS) $(LIGHTNINGD_OPENING_CONTROL_OBJS) $(LIGHTNINGD_CHANNEL_CONTROL_OBJS) $(LIGHTNINGD_CLOSING_CONTROL_OBJS) $(WALLET_LIB_OBJS) libsecp256k1.a libsodium.a libwallycore.a +lightningd/lightningd: $(LIGHTNINGD_OBJS) $(LIGHTNINGD_OLD_OBJS) $(LIGHTNINGD_OLD_LIB_OBJS) $(LIGHTNINGD_LIB_OBJS) $(LIGHTNINGD_JSMN_OBJS) $(CORE_OBJS) $(CORE_TX_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS) $(WIRE_ONION_OBJS) $(CCAN_OBJS) $(CCAN_SHACHAIN48_OBJ) $(LIGHTNINGD_HSM_CONTROL_OBJS) $(LIGHTNINGD_HANDSHAKE_CONTROL_OBJS) $(LIGHTNINGD_GOSSIP_CONTROL_OBJS) $(LIBBASE58_OBJS) $(LIGHTNINGD_OPENING_CONTROL_OBJS) $(LIGHTNINGD_CHANNEL_CONTROL_OBJS) $(LIGHTNINGD_CLOSING_CONTROL_OBJS) $(LIGHTNINGD_ONCHAIN_CONTROL_OBJS) $(WALLET_LIB_OBJS) libsecp256k1.a libsodium.a libwallycore.a clean: lightningd-clean diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 1fde8cbf0..ea55c707d 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -213,8 +214,8 @@ void peer_fail_transient(struct peer *peer, const char *fmt, ...) return; } - /* Reconnect unless we've dropped to chain. */ - if (!peer_on_chain(peer)) { + /* Reconnect unless we've dropped/are dropping to chain. */ + if (!peer_on_chain(peer) && peer->state != CLOSINGD_COMPLETE) { peer_reconnect(peer); return; } @@ -1013,6 +1014,283 @@ static enum watch_result funding_announce_cb(struct peer *peer, return DELETE_WATCH; } +static void peer_onchain_finished(struct subd *subd, int status) +{ + /* Moved on? Eg. reorg, and it has a new onchaind. */ + if (subd->peer->owner != subd) + return; + + if (status != 0) { + log_broken(subd->peer->log, "onchaind died status %i", status); + subd->peer->owner = NULL; + return; + } + + /* FIXME: Remove peer from db. */ + log_info(subd->peer->log, "onchaind complete, forgetting peer"); + + /* Peer is gone. */ + tal_free(subd->peer); +} + +static int handle_onchain_init_reply(struct peer *peer, const u8 *msg) +{ + u8 state; + + if (!fromwire_onchain_init_reply(msg, NULL, &state)) { + log_broken(peer->log, "Invalid onchain_init_reply"); + return -1; + } + + if (!peer_state_on_chain(state)) { + log_broken(peer->log, "Invalid onchain_init_reply state %u (%s)", + state, peer_state_name(state)); + return -1; + } + + /* We could come from almost any state. */ + peer_set_condition(peer, peer->state, state); + return 0; +} + +static enum watch_result onchain_tx_watched(struct peer *peer, + const struct bitcoin_tx *tx, + unsigned int depth, + void *unused) +{ + u8 *msg; + struct sha256_double txid; + + if (depth == 0) { + struct subd *old_onchaind = peer->owner; + log_unusual(peer->log, "Chain reorganization!"); + peer->owner = NULL; + tal_free(old_onchaind); + + /* FIXME! + topology_rescan(peer->ld->topology, peer->funding_txid); + */ + + /* We will most likely be freed, so this is a noop */ + return KEEP_WATCHING; + } + + bitcoin_txid(tx, &txid); + msg = towire_onchain_depth(peer, &txid, depth); + subd_send_msg(peer->owner, take(msg)); + return KEEP_WATCHING; +} + +static void watch_tx_and_outputs(struct peer *peer, + const struct bitcoin_tx *tx); + +static enum watch_result onchain_txo_watched(struct peer *peer, + const struct bitcoin_tx *tx, + size_t input_num, + const struct block *block, + void *unused) +{ + u8 *msg; + + watch_tx_and_outputs(peer, tx); + + msg = towire_onchain_spent(peer, tx, input_num, block->height); + subd_send_msg(peer->owner, take(msg)); + + /* We don't need to keep watching: If this output is double-spent + * (reorg), we'll get a zero depth cb to onchain_tx_watched, and + * restart onchaind. */ + return DELETE_WATCH; +} + +/* To avoid races, we watch the tx and all outputs. */ +static void watch_tx_and_outputs(struct peer *peer, + const struct bitcoin_tx *tx) +{ + struct sha256_double txid; + struct txwatch *txw; + + bitcoin_txid(tx, &txid); + + /* Make txwatch a parent of txo watches, so we can unwatch together. */ + txw = watch_tx(peer->owner, peer->ld->topology, peer, tx, + onchain_tx_watched, NULL); + + for (size_t i = 0; i < tal_count(tx->output); i++) + watch_txo(txw, peer->ld->topology, peer, &txid, i, + onchain_txo_watched, NULL); +} + +static int handle_onchain_broadcast_tx(struct peer *peer, const u8 *msg) +{ + struct bitcoin_tx *tx; + + tx = tal(msg, struct bitcoin_tx); + if (!fromwire_onchain_broadcast_tx(msg, NULL, tx)) { + log_broken(peer->log, "Invalid onchain_broadcast_tx"); + return -1; + } + + /* We don't really care if it fails, we'll respond via watch. */ + broadcast_tx(peer->ld->topology, peer, tx, NULL); + return 0; +} + +static int handle_onchain_unwatch_tx(struct peer *peer, const u8 *msg) +{ + /* FIXME: unwatch tx and children here. */ + return 0; +} + +static int handle_extracted_preimage(struct peer *peer, const u8 *msg) +{ + struct preimage preimage; + + if (!fromwire_onchain_extracted_preimage(msg, NULL, &preimage)) { + log_broken(peer->log, "Invalid extracted_preimage"); + return -1; + } + + onchain_fulfilled_htlc(peer, &preimage); + return 0; +} + +static int onchain_msg(struct subd *sd, const u8 *msg, const int *fds) +{ + enum onchain_wire_type t = fromwire_peektype(msg); + + switch (t) { + /* We let peer_onchain_finished handle these. */ + case WIRE_ONCHAIN_BAD_COMMAND: + case WIRE_ONCHAIN_INTERNAL_ERROR: + case WIRE_ONCHAIN_CRYPTO_FAILED: + break; + + case WIRE_ONCHAIN_INIT_REPLY: + return handle_onchain_init_reply(sd->peer, msg); + + case WIRE_ONCHAIN_BROADCAST_TX: + return handle_onchain_broadcast_tx(sd->peer, msg); + + case WIRE_ONCHAIN_UNWATCH_TX: + return handle_onchain_unwatch_tx(sd->peer, msg); + + case WIRE_ONCHAIN_EXTRACTED_PREIMAGE: + return handle_extracted_preimage(sd->peer, msg); + + /* We send these, not receive them */ + case WIRE_ONCHAIN_INIT: + case WIRE_ONCHAIN_SPENT: + case WIRE_ONCHAIN_DEPTH: + case WIRE_ONCHAIN_HTLC: + case WIRE_ONCHAIN_KNOWN_PREIMAGE: + break; + } + + return 0; +} + +static u8 *p2wpkh_for_keyidx(const tal_t *ctx, struct lightningd *ld, u64 keyidx) +{ + struct pubkey shutdownkey; + + if (!bip32_pubkey(ld->bip32_base, &shutdownkey, keyidx)) + return NULL; + + return scriptpubkey_p2wpkh(ctx, &shutdownkey); +} + +/* With a reorg, this can get called multiple times; each time we'll kill + * onchaind (like any other owner), and restart */ +static enum watch_result funding_spent(struct peer *peer, + const struct bitcoin_tx *tx, + size_t input_num, + const struct block *block, + void *unused) +{ + u8 *msg, *scriptpubkey; + struct sha256_double our_last_txid; + s64 keyindex; + struct pubkey ourkey; + + peer_fail_permanent_str(peer, "Funding transaction spent"); + peer->owner = new_subd(peer->ld, peer->ld, + "lightningd_onchain", peer, + onchain_wire_type_name, + onchain_msg, + peer_onchain_finished, + NULL, NULL); + + if (!peer->owner) { + log_broken(peer->log, "Could not subdaemon onchain: %s", + strerror(errno)); + return KEEP_WATCHING; + } + + /* We re-use this key to send other outputs to. */ + if (peer->local_shutdown_idx >= 0) + keyindex = peer->local_shutdown_idx; + else { + /* FIXME: Save to db */ + keyindex = wallet_get_newindex(peer->ld); + if (keyindex < 0) { + log_broken(peer->log, "Could not get keyindex"); + return KEEP_WATCHING; + } + } + scriptpubkey = p2wpkh_for_keyidx(peer, peer->ld, keyindex); + if (!scriptpubkey) { + peer_internal_error(peer, + "Can't get shutdown script %"PRIu64, + keyindex); + return DELETE_WATCH; + } + + if (!bip32_pubkey(peer->ld->bip32_base, &ourkey, keyindex)) { + peer_internal_error(peer, + "Can't get shutdown key %"PRIu64, + keyindex); + return DELETE_WATCH; + } + + /* This could be a mutual close, but it doesn't matter. */ + bitcoin_txid(peer->last_tx, &our_last_txid); + + msg = towire_onchain_init(peer, peer->seed, &peer->their_shachain.chain, + peer->funding_satoshi, + &peer->channel_info->old_remote_per_commit, + &peer->channel_info->remote_per_commit, + peer->our_config.to_self_delay, + peer->channel_info->their_config.to_self_delay, + peer->channel_info->feerate_per_kw, + peer->our_config.dust_limit_satoshis, + &peer->channel_info->theirbase.revocation, + &our_last_txid, + scriptpubkey, + peer->remote_shutdown_scriptpubkey, + &ourkey, + peer->funder, + &peer->channel_info->theirbase.payment, + &peer->channel_info->theirbase.delayed_payment, + tx, + block->height, + peer->last_htlc_sigs, + tal_count(peer->htlcs)); + subd_send_msg(peer->owner, take(msg)); + + /* FIXME: Don't queue all at once, use an empty cb... */ + for (size_t i = 0; i < tal_count(peer->htlcs); i++) { + msg = towire_onchain_htlc(peer, peer->htlcs+i); + subd_send_msg(peer->owner, take(msg)); + } + + /* FIXME: Send any known HTLC preimage for live HTLCs! */ + watch_tx_and_outputs(peer, tx); + + /* We keep watching until peer finally deleted, for reorgs. */ + return KEEP_WATCHING; +} + static enum watch_result funding_lockin_cb(struct peer *peer, const struct bitcoin_tx *tx, unsigned int depth, @@ -1116,6 +1394,11 @@ static void opening_got_hsm_funding_sig(struct funding_channel *fc, watch_tx(fc->peer, fc->peer->ld->topology, fc->peer, tx, funding_lockin_cb, NULL); + /* FIXME: Remove arg from cb? */ + watch_txo(fc->peer, fc->peer->ld->topology, fc->peer, + fc->peer->funding_txid, fc->peer->funding_outnum, + funding_spent, NULL); + /* We could defer until after funding locked, but makes testing * harder. */ tal_del_destructor(fc, fail_fundchannel_command); @@ -1215,16 +1498,6 @@ static int peer_got_funding_locked(struct peer *peer, const u8 *msg) return 0; } -static u8 *p2wpkh_for_keyidx(const tal_t *ctx, struct lightningd *ld, u64 keyidx) -{ - struct pubkey shutdownkey; - - if (!bip32_pubkey(ld->bip32_base, &shutdownkey, keyidx)) - return NULL; - - return scriptpubkey_p2wpkh(ctx, &shutdownkey); -} - static int peer_got_shutdown(struct peer *peer, const u8 *msg) { u8 *scriptpubkey; @@ -1945,6 +2218,10 @@ static bool opening_fundee_finished(struct subd *opening, watch_txid(peer, peer->ld->topology, peer, peer->funding_txid, funding_lockin_cb, NULL); + /* FIXME: Remove arg from cb? */ + watch_txo(peer, peer->ld->topology, peer, peer->funding_txid, + peer->funding_outnum, funding_spent, NULL); + /* Unowned. */ peer->owner = NULL; diff --git a/lightningd/peer_control.h b/lightningd/peer_control.h index eb768f72a..019e7f8b1 100644 --- a/lightningd/peer_control.h +++ b/lightningd/peer_control.h @@ -117,12 +117,17 @@ static inline bool peer_can_remove_htlc(const struct peer *peer) || peer->state == ONCHAIND_OUR_UNILATERAL; } +static inline bool peer_state_on_chain(enum peer_state state) +{ + return state == ONCHAIND_CHEATED + || state == ONCHAIND_THEIR_UNILATERAL + || state == ONCHAIND_OUR_UNILATERAL + || state == ONCHAIND_MUTUAL; +} + static inline bool peer_on_chain(const struct peer *peer) { - return peer->state == ONCHAIND_CHEATED - || peer->state == ONCHAIND_THEIR_UNILATERAL - || peer->state == ONCHAIND_OUR_UNILATERAL - || peer->state == ONCHAIND_MUTUAL; + return peer_state_on_chain(peer->state); } /* BOLT #2: diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 265117f18..5fdba9d98 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -687,6 +687,20 @@ out: return true; } +static void fulfill_our_htlc_out(struct peer *peer, struct htlc_out *hout, + const struct preimage *preimage) +{ + hout->preimage = tal_dup(hout, struct preimage, preimage); + htlc_out_check(hout, __func__); + + /* FIXME: Save to db */ + + if (hout->in) + fulfill_htlc(hout->in, preimage); + else + payment_succeeded(peer->ld, hout, preimage); +} + static bool peer_fulfilled_our_htlc(struct peer *peer, const struct fulfilled_htlc *fulfilled) { @@ -703,19 +717,34 @@ static bool peer_fulfilled_our_htlc(struct peer *peer, if (!htlc_out_update_state(peer, hout, RCVD_REMOVE_COMMIT)) return false; - hout->preimage = tal_dup(hout, struct preimage, - &fulfilled->payment_preimage); - htlc_out_check(hout, __func__); - - /* FIXME: Save to db */ - - if (hout->in) - fulfill_htlc(hout->in, &fulfilled->payment_preimage); - else - payment_succeeded(peer->ld, hout, &fulfilled->payment_preimage); + fulfill_our_htlc_out(peer, hout, &fulfilled->payment_preimage); return true; } +void onchain_fulfilled_htlc(struct peer *peer, const struct preimage *preimage) +{ + struct htlc_out_map_iter outi; + struct htlc_out *hout; + struct sha256 payment_hash; + + sha256(&payment_hash, preimage, sizeof(*preimage)); + + /* FIXME: use db to look this up! */ + for (hout = htlc_out_map_first(&peer->ld->htlcs_out, &outi); + hout; + hout = htlc_out_map_next(&peer->ld->htlcs_out, &outi)) { + if (hout->key.peer != peer) + continue; + + if (!structeq(&hout->payment_hash, &payment_hash)) + continue; + + fulfill_our_htlc_out(peer, hout, preimage); + /* We keep going: this is something of a leak, but onchain + * we have no real way of distinguishing HTLCs anyway */ + } +} + static bool peer_failed_our_htlc(struct peer *peer, const struct failed_htlc *failed) { diff --git a/lightningd/peer_htlcs.h b/lightningd/peer_htlcs.h index d39f1f585..6116d1bb4 100644 --- a/lightningd/peer_htlcs.h +++ b/lightningd/peer_htlcs.h @@ -11,6 +11,8 @@ struct channel_info { struct channel_config their_config; struct pubkey remote_fundingkey; struct basepoints theirbase; + /* The old_remote_per_commit is for the locked-in remote commit_tx, + * and the remote_per_commit is for the commit_tx we're modifying now. */ struct pubkey remote_per_commit, old_remote_per_commit; u32 feerate_per_kw; }; @@ -38,4 +40,6 @@ enum onion_type send_htlc_out(struct peer *out, u64 amount, u32 cltv, struct htlc_in *in, struct pay_command *pc, struct htlc_out **houtp); + +void onchain_fulfilled_htlc(struct peer *peer, const struct preimage *preimage); #endif /* LIGHTNING_LIGHTNINGD_PEER_HTLCS_H */