diff --git a/lightningd/chaintopology.c b/lightningd/chaintopology.c
index 7f08da9503c3..532c34cc6ead 100644
--- a/lightningd/chaintopology.c
+++ b/lightningd/chaintopology.c
@@ -59,8 +59,10 @@ static void filter_block_txs(struct chain_topology *topo, struct block *b)
 			out.index = tx->input[j].index;
 
 			txo = txowatch_hash_get(&topo->txowatches, &out);
-			if (txo)
+			if (txo) {
+				wallet_transaction_add(topo->wallet, tx, b->height, i);
 				txowatch_fire(txo, tx, j, b);
+			}
 		}
 
 		satoshi_owned = 0;
@@ -517,17 +519,18 @@ static void get_init_block(struct bitcoind *bitcoind,
 static void get_init_blockhash(struct bitcoind *bitcoind, u32 blockcount,
 			       struct chain_topology *topo)
 {
-	/* This can happen if bitcoind still syncing, or first_blocknum is MAX */
-	if (blockcount < topo->first_blocknum)
-		topo->first_blocknum = blockcount;
-
-	/* For fork protection (esp. because we don't handle our own first
-	 * block getting reorged out), we always go 100 blocks further back
-	 * than we need. */
-	if (topo->first_blocknum < 100)
-		topo->first_blocknum = 0;
-	else
-		topo->first_blocknum -= 100;
+	/* If bitcoind's current blockheight is below the requested height, just
+	 * go back to that height. This might be a new node catching up, or
+	 * bitcoind is processing a reorg. */
+	if (blockcount < topo->first_blocknum) {
+		if (bitcoind->ld->config.rescan < 0) {
+			/* Absolute blockheight, but bitcoind's blockheight isn't there yet */
+			topo->first_blocknum = blockcount - 1;
+		} else if (topo->first_blocknum == UINT32_MAX) {
+			/* Relative rescan, but we didn't know the blockheight */
+			topo->first_blocknum = blockcount - bitcoind->ld->config.rescan;
+		}
+	}
 
 	/* Rollback to the given blockheight, so we start track
 	 * correctly again */
diff --git a/lightningd/channel.c b/lightningd/channel.c
index 87325a885471..d43f5d19c6ce 100644
--- a/lightningd/channel.c
+++ b/lightningd/channel.c
@@ -265,6 +265,19 @@ struct channel *active_channel_by_id(struct lightningd *ld,
 	return peer_active_channel(peer);
 }
 
+struct channel *channel_by_dbid(struct lightningd *ld, const u64 dbid)
+{
+	struct peer *p;
+	struct channel *chan;
+	list_for_each(&ld->peers, p, list) {
+		list_for_each(&p->channels, chan, list) {
+			if (chan->dbid == dbid)
+				return chan;
+		}
+	}
+	return NULL;
+}
+
 void channel_set_last_tx(struct channel *channel,
 			 struct bitcoin_tx *tx,
 			 const secp256k1_ecdsa_signature *sig)
diff --git a/lightningd/channel.h b/lightningd/channel.h
index b178afbf80c8..291d037cd662 100644
--- a/lightningd/channel.h
+++ b/lightningd/channel.h
@@ -165,6 +165,8 @@ struct channel *active_channel_by_id(struct lightningd *ld,
 				     const struct pubkey *id,
 				     struct uncommitted_channel **uc);
 
+struct channel *channel_by_dbid(struct lightningd *ld, const u64 dbid);
+
 void channel_set_last_tx(struct channel *channel,
 			 struct bitcoin_tx *tx,
 			 const secp256k1_ecdsa_signature *sig);
diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c
index d671cf712780..e7b4109cdb22 100644
--- a/lightningd/lightningd.c
+++ b/lightningd/lightningd.c
@@ -30,6 +30,7 @@
 #include <lightningd/invoice.h>
 #include <lightningd/jsonrpc.h>
 #include <lightningd/log.h>
+#include <lightningd/onchain_control.h>
 #include <lightningd/options.h>
 #include <onchaind/onchain_wire.h>
 #include <signal.h>
@@ -275,7 +276,7 @@ int main(int argc, char *argv[])
 {
 	struct lightningd *ld;
 	bool newdir;
-	u32 first_blocknum;
+	u32 blockheight;
 
 	daemon_setup(argv[0], log_backtrace_print, log_backtrace_exit);
 	ld = new_lightningd(NULL);
@@ -350,10 +351,20 @@ int main(int argc, char *argv[])
 	if (!wallet_htlcs_reconnect(ld->wallet, &ld->htlcs_in, &ld->htlcs_out))
 		fatal("could not reconnect htlcs loaded from wallet, wallet may be inconsistent.");
 
-	/* Worst case, scan back to the first lightning deployment */
-	first_blocknum = wallet_first_blocknum(ld->wallet,
-					       get_chainparams(ld)
-					       ->when_lightning_became_cool);
+	/* 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
+	 * current height */
+	blockheight = wallet_blocks_height(ld->wallet, UINT32_MAX);
+
+	/* If we were asked to rescan from an absolute height (--rescan < 0)
+	 * then just go there. Otherwise take compute the diff to our current
+	 * height, lowerbounded by 0. */
+	if (ld->config.rescan < 0)
+		blockheight = -ld->config.rescan;
+	else if (blockheight < (u32)ld->config.rescan)
+		blockheight = 0;
+	else if (blockheight != UINT32_MAX)
+		blockheight -= ld->config.rescan;
 
 	db_commit_transaction(ld->wallet->db);
 
@@ -361,7 +372,10 @@ int main(int argc, char *argv[])
 	setup_topology(ld->topology,
 		       &ld->timers,
 		       ld->config.poll_time,
-		       first_blocknum);
+		       blockheight);
+
+	/* Replay transactions for all running onchainds */
+	onchaind_replay_channels(ld);
 
 	/* Create RPC socket (if any) */
 	setup_jsonrpc(ld, ld->rpc_filename);
diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h
index f1e9ebce912f..7f683677242d 100644
--- a/lightningd/lightningd.h
+++ b/lightningd/lightningd.h
@@ -72,6 +72,10 @@ struct config {
 
 	/* Do we let the funder set any fee rate they want */
 	bool ignore_fee_limits;
+
+	/* Number of blocks to rescan from the current head, or absolute
+	 * blockheight if rescan >= 500'000 */
+	s32 rescan;
 };
 
 struct lightningd {
diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c
index 293af7c8a43c..52ad3f4eb80b 100644
--- a/lightningd/onchain_control.c
+++ b/lightningd/onchain_control.c
@@ -3,13 +3,11 @@
 #include <errno.h>
 #include <inttypes.h>
 #include <lightningd/chaintopology.h>
-#include <lightningd/lightningd.h>
 #include <lightningd/log.h>
 #include <lightningd/onchain_control.h>
 #include <lightningd/peer_control.h>
 #include <lightningd/subd.h>
 #include <lightningd/watch.h>
-#include <onchaind/gen_onchain_wire.h>
 #include <onchaind/onchain_wire.h>
 
 /* We dump all the known preimages when onchaind starts up. */
@@ -47,21 +45,32 @@ static void onchaind_tell_fulfill(struct channel *channel)
 	}
 }
 
-static void handle_onchain_init_reply(struct channel *channel, const u8 *msg)
+static void handle_onchain_init_reply(struct channel *channel, const u8 *msg UNUSED)
 {
 	/* FIXME: We may already be ONCHAIN state when we implement restart! */
 	channel_set_state(channel, FUNDING_SPEND_SEEN, ONCHAIN);
+}
 
-	/* Tell it about any preimages we know. */
-	onchaind_tell_fulfill(channel);
+/**
+ * Notify onchaind about the depth change of the watched tx.
+ */
+static void onchain_tx_depth(struct channel *channel,
+			     const struct bitcoin_txid *txid,
+			     unsigned int depth)
+{
+	u8 *msg;
+	msg = towire_onchain_depth(channel, txid, depth);
+	subd_send_msg(channel->owner, take(msg));
 }
 
+/**
+ * Entrypoint for the txwatch callback, calls onchain_tx_depth.
+ */
 static enum watch_result onchain_tx_watched(struct channel *channel,
 					    const struct bitcoin_txid *txid,
 					    unsigned int depth)
 {
-	u8 *msg;
-
+	u32 blockheight = channel->peer->ld->topology->tip->height;
 	if (depth == 0) {
 		log_unusual(channel->log, "Chain reorganization!");
 		channel_set_owner(channel, NULL);
@@ -74,25 +83,48 @@ static enum watch_result onchain_tx_watched(struct channel *channel,
 		return KEEP_WATCHING;
 	}
 
-	msg = towire_onchain_depth(channel, txid, depth);
-	subd_send_msg(channel->owner, take(msg));
+	/* Store the channeltx so we can replay later */
+	wallet_channeltxs_add(channel->peer->ld->wallet, channel,
+			      WIRE_ONCHAIN_DEPTH, txid, 0, blockheight);
+
+	onchain_tx_depth(channel, txid, depth);
 	return KEEP_WATCHING;
 }
 
 static void watch_tx_and_outputs(struct channel *channel,
 				 const struct bitcoin_tx *tx);
 
+/**
+ * Notify onchaind that an output was spent and register new watches.
+ */
+static void onchain_txo_spent(struct channel *channel, const struct bitcoin_tx *tx, size_t input_num, u32 blockheight)
+{
+	u8 *msg;
+
+	watch_tx_and_outputs(channel, tx);
+
+	msg = towire_onchain_spent(channel, tx, input_num, blockheight);
+	subd_send_msg(channel->owner, take(msg));
+
+}
+
+/**
+ * Entrypoint for the txowatch callback, stores tx and calls onchain_txo_spent.
+ */
 static enum watch_result onchain_txo_watched(struct channel *channel,
 					     const struct bitcoin_tx *tx,
 					     size_t input_num,
 					     const struct block *block)
 {
-	u8 *msg;
+	struct bitcoin_txid txid;
+	bitcoin_txid(tx, &txid);
 
-	watch_tx_and_outputs(channel, tx);
+	/* Store the channeltx so we can replay later */
+	wallet_channeltxs_add(channel->peer->ld->wallet, channel,
+			      WIRE_ONCHAIN_SPENT, &txid, input_num,
+			      block->height);
 
-	msg = towire_onchain_spent(channel, tx, input_num, block->height);
-	subd_send_msg(channel->owner, take(msg));
+	onchain_txo_spent(channel, tx, input_num, block->height);
 
 	/* 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
@@ -201,7 +233,7 @@ static void handle_onchain_htlc_timeout(struct channel *channel, const u8 *msg)
 	onchain_failed_our_htlc(channel, &htlc, "timed out");
 }
 
-static void handle_irrevocably_resolved(struct channel *channel, const u8 *msg)
+static void handle_irrevocably_resolved(struct channel *channel, const u8 *msg UNUSED)
 {
 	/* FIXME: Implement check_htlcs to ensure no dangling hout->in ptrs! */
 	free_htlcs(channel->peer->ld, channel);
@@ -338,10 +370,9 @@ static void onchain_error(struct channel *channel,
 
 /* With a reorg, this can get called multiple times; each time we'll kill
  * onchaind (like any other owner), and restart */
-enum watch_result funding_spent(struct channel *channel,
-				const struct bitcoin_tx *tx,
-				size_t input_num UNUSED,
-				const struct block *block)
+enum watch_result onchaind_funding_spent(struct channel *channel,
+					 const struct bitcoin_tx *tx,
+					 u32 blockheight)
 {
 	u8 *msg;
 	struct bitcoin_txid our_last_txid;
@@ -411,7 +442,7 @@ enum watch_result funding_spent(struct channel *channel,
 				  &channel->channel_info.theirbase.htlc,
 				  &channel->channel_info.theirbase.delayed_payment,
 				  tx,
-				  block->height,
+				  blockheight,
 				  /* FIXME: config for 'reasonable depth' */
 				  3,
 				  channel->last_htlc_sigs,
@@ -429,8 +460,55 @@ enum watch_result funding_spent(struct channel *channel,
 		subd_send_msg(channel->owner, take(msg));
 	}
 
+	/* Tell it about any preimages we know. */
+	onchaind_tell_fulfill(channel);
+
 	watch_tx_and_outputs(channel, tx);
 
 	/* We keep watching until peer finally deleted, for reorgs. */
 	return KEEP_WATCHING;
 }
+
+void onchaind_replay_channels(struct lightningd *ld)
+{
+	u32 *onchaind_ids;
+	struct channeltx *txs;
+	struct channel *chan;
+
+	db_begin_transaction(ld->wallet->db);
+	onchaind_ids = wallet_onchaind_channels(ld->wallet, ld);
+
+	for (size_t i = 0; i < tal_count(onchaind_ids); i++) {
+		log_info(ld->log, "Restarting onchaind for channel %d",
+			 onchaind_ids[i]);
+
+		txs = wallet_channeltxs_get(ld->wallet, onchaind_ids,
+					    onchaind_ids[i]);
+		chan = channel_by_dbid(ld, onchaind_ids[i]);
+
+		for (size_t j = 0; j < tal_count(txs); j++) {
+			if (txs[j].type == WIRE_ONCHAIN_INIT) {
+				onchaind_funding_spent(chan, txs[j].tx,
+						       txs[j].blockheight);
+
+			} else if (txs[j].type == WIRE_ONCHAIN_SPENT) {
+				onchain_txo_spent(chan, txs[j].tx,
+						  txs[j].input_num,
+						  txs[j].blockheight);
+
+			} else if (txs[j].type == WIRE_ONCHAIN_DEPTH) {
+				onchain_tx_depth(chan, &txs[j].txid,
+						 txs[j].depth);
+
+			} else {
+				fatal("unknown message of type %d during "
+				      "onchaind replay",
+				      txs[j].type);
+			}
+		}
+		tal_free(txs);
+	}
+	tal_free(onchaind_ids);
+
+	db_commit_transaction(ld->wallet->db);
+}
diff --git a/lightningd/onchain_control.h b/lightningd/onchain_control.h
index 8b1b20bcab6f..7ecfdf8a26fa 100644
--- a/lightningd/onchain_control.h
+++ b/lightningd/onchain_control.h
@@ -2,14 +2,17 @@
 #define LIGHTNING_LIGHTNINGD_ONCHAIN_CONTROL_H
 #include "config.h"
 #include <ccan/short_types/short_types.h>
+#include <lightningd/lightningd.h>
+#include <onchaind/gen_onchain_wire.h>
 
 struct channel;
 struct bitcoin_tx;
 struct block;
 
-enum watch_result funding_spent(struct channel *channel,
-				const struct bitcoin_tx *tx,
-				size_t input_num,
-				const struct block *block);
+enum watch_result onchaind_funding_spent(struct channel *channel,
+					 const struct bitcoin_tx *tx,
+					 u32 blockheight);
+
+void onchaind_replay_channels(struct lightningd *ld);
 
 #endif /* LIGHTNING_LIGHTNINGD_ONCHAIN_CONTROL_H */
diff --git a/lightningd/options.c b/lightningd/options.c
index ec13b20dc988..b35cb8ee3b72 100644
--- a/lightningd/options.c
+++ b/lightningd/options.c
@@ -309,6 +309,10 @@ static void config_register_opts(struct lightningd *ld)
 	opt_register_arg("--fee-base", opt_set_u32, opt_show_u32,
 			 &ld->config.fee_base,
 			 "Millisatoshi minimum to charge for HTLC");
+	opt_register_arg("--rescan", opt_set_s32, opt_show_s32,
+			 &ld->config.rescan,
+			 "Number of blocks to rescan from the current head, or "
+			 "absolute blockheight if negative");
 	opt_register_arg("--fee-per-satoshi", opt_set_s32, opt_show_s32,
 			 &ld->config.fee_per_satoshi,
 			 "Microsatoshi fee for every satoshi in HTLC");
@@ -420,6 +424,9 @@ static const struct config testnet_config = {
 
 	/* Testnet sucks */
 	.ignore_fee_limits = true,
+
+	/* Rescan 5 hours of blocks on testnet, it's reorg happy */
+	.rescan = 30,
 };
 
 /* aka. "Dude, where's my coins?" */
@@ -481,6 +488,9 @@ static const struct config mainnet_config = {
 
 	/* Mainnet should have more stable fees */
 	.ignore_fee_limits = false,
+
+	/* Rescan 2.5 hours of blocks on startup, it's not so reorg happy */
+	.rescan = 15,
 };
 
 static void check_config(struct lightningd *ld)
diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c
index 820b4d3be6f6..a3a8aa0380c3 100644
--- a/lightningd/peer_control.c
+++ b/lightningd/peer_control.c
@@ -563,6 +563,20 @@ static enum watch_result funding_lockin_cb(struct channel *channel,
 	return DELETE_WATCH;
 }
 
+static enum watch_result funding_spent(struct channel *channel,
+				       const struct bitcoin_tx *tx,
+				       size_t inputnum UNUSED,
+				       const struct block *block)
+{
+	struct bitcoin_txid txid;
+	bitcoin_txid(tx, &txid);
+
+	wallet_channeltxs_add(channel->peer->ld->wallet, channel,
+			      WIRE_ONCHAIN_INIT, &txid, 0, block->height);
+
+	return onchaind_funding_spent(channel, tx, block->height);
+}
+
 void channel_watch_funding(struct lightningd *ld, struct channel *channel)
 {
 	/* FIXME: Remove arg from cb? */
diff --git a/lightningd/test/run-find_my_path.c b/lightningd/test/run-find_my_path.c
index 498a7aa54bc5..f10cddc54421 100644
--- a/lightningd/test/run-find_my_path.c
+++ b/lightningd/test/run-find_my_path.c
@@ -74,6 +74,9 @@ struct log_book *new_log_book(size_t max_mem UNNEEDED,
 /* Generated stub for new_topology */
 struct chain_topology *new_topology(struct lightningd *ld UNNEEDED, struct log *log UNNEEDED)
 { fprintf(stderr, "new_topology called!\n"); abort(); }
+/* Generated stub for onchaind_replay_channels */
+void onchaind_replay_channels(struct lightningd *ld UNNEEDED)
+{ fprintf(stderr, "onchaind_replay_channels called!\n"); abort(); }
 /* Generated stub for register_opts */
 void register_opts(struct lightningd *ld UNNEEDED)
 { fprintf(stderr, "register_opts called!\n"); abort(); }
@@ -104,12 +107,12 @@ struct txfilter *txfilter_new(const tal_t *ctx UNNEEDED)
 /* Generated stub for version */
 const char *version(void)
 { fprintf(stderr, "version called!\n"); abort(); }
+/* Generated stub for wallet_blocks_height */
+u32 wallet_blocks_height(struct wallet *w UNNEEDED, u32 def UNNEEDED)
+{ fprintf(stderr, "wallet_blocks_height 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_first_blocknum */
-u32 wallet_first_blocknum(struct wallet *w UNNEEDED, u32 first_possible UNNEEDED)
-{ fprintf(stderr, "wallet_first_blocknum 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,
diff --git a/tests/test_lightningd.py b/tests/test_lightningd.py
index ef5770a50471..f32acf59f48c 100644
--- a/tests/test_lightningd.py
+++ b/tests/test_lightningd.py
@@ -1448,12 +1448,14 @@ def test_onchain_unwatch(self):
 
         # 10 later, l1 should collect its to-self payment.
         bitcoind.generate_block(10)
-        l1.daemon.wait_for_log('Broadcasting OUR_DELAYED_RETURN_TO_WALLET .* to resolve OUR_UNILATERAL/DELAYED_OUTPUT_TO_US')
+        l1.daemon.wait_for_log('Broadcasting OUR_DELAYED_RETURN_TO_WALLET .* to resolve '
+                               'OUR_UNILATERAL/DELAYED_OUTPUT_TO_US')
         l1.daemon.wait_for_log('sendrawtx exit 0')
 
         # First time it sees it, onchaind cares.
         bitcoind.generate_block(1)
-        l1.daemon.wait_for_log('Resolved OUR_UNILATERAL/DELAYED_OUTPUT_TO_US by our proposal OUR_DELAYED_RETURN_TO_WALLET')
+        l1.daemon.wait_for_log('Resolved OUR_UNILATERAL/DELAYED_OUTPUT_TO_US by our proposal '
+                               'OUR_DELAYED_RETURN_TO_WALLET')
 
         # Now test unrelated onchain churn.
         # Daemon gets told about wallet; says it doesn't care.
@@ -1478,6 +1480,57 @@ def test_onchain_unwatch(self):
         # Note: for this test we leave onchaind running, so we can detect
         # any leaks!
 
+    @unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
+    def test_onchaind_replay(self):
+        disconnects = ['+WIRE_REVOKE_AND_ACK', 'permfail']
+        options = {'locktime-blocks': 201, 'cltv-delta': 101}
+        l1 = self.node_factory.get_node(options=options, disconnect=disconnects)
+        l2 = self.node_factory.get_node(options=options)
+        btc = l1.bitcoin
+
+        l1.rpc.connect(l2.info['id'], 'localhost', l2.info['port'])
+        self.fund_channel(l1, l2, 10**6)
+
+        rhash = l2.rpc.invoice(10**8, 'onchaind_replay', 'desc')['payment_hash']
+        routestep = {
+            'msatoshi': 10**8 - 1,
+            'id': l2.info['id'],
+            'delay': 101,
+            'channel': '1:1:1'
+        }
+        l1.rpc.sendpay(to_json([routestep]), rhash)
+        l1.daemon.wait_for_log(r'Disabling channel')
+        btc.rpc.generate(1)
+
+        # Wait for nodes to notice the failure, this seach needle is after the
+        # DB commit so we're sure the tx entries in onchaindtxs have been added
+        l1.daemon.wait_for_log("Deleting channel .* due to the funding outpoint being spent")
+        l2.daemon.wait_for_log("Deleting channel .* due to the funding outpoint being spent")
+
+        # We should at least have the init tx now
+        assert len(l1.db_query("SELECT * FROM channeltxs;")) > 0
+        assert len(l2.db_query("SELECT * FROM channeltxs;")) > 0
+
+        # Generate some blocks so we restart the onchaind from DB (we rescan
+        # last_height - 100)
+        btc.rpc.generate(100)
+        sync_blockheight([l1, l2])
+
+        # l1 should still have a running onchaind
+        assert len(l1.db_query("SELECT * FROM channeltxs;")) > 0
+
+        l2.rpc.stop()
+        l1.restart()
+
+        # Can't wait for it, it's after the "Server started" wait in restart()
+        assert l1.daemon.is_in_log(r'Restarting onchaind for channel')
+
+        # l1 should still notice that the funding was spent and that we should react to it
+        l1.daemon.wait_for_log("Propose handling OUR_UNILATERAL/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET")
+        sync_blockheight([l1])
+        btc.rpc.generate(10)
+        sync_blockheight([l1])
+
     @unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
     def test_onchain_dust_out(self):
         """Onchain handling of outgoing dust htlcs (they should fail)"""
@@ -3433,6 +3486,7 @@ def test_lockin_between_restart(self):
     def test_funding_while_offline(self):
         l1 = self.node_factory.get_node()
         addr = l1.rpc.newaddr()['address']
+        sync_blockheight([l1])
 
         # l1 goes down.
         l1.stop()
@@ -4287,6 +4341,40 @@ def test_disconnectpeer(self):
         self.assertRaisesRegex(ValueError, "Peer is not in gossip mode",
                                l1.rpc.disconnect, l3.info['id'])
 
+    def test_rescan(self):
+        """Test the rescan option
+        """
+        l1 = self.node_factory.get_node()
+        btc = l1.bitcoin
+
+        # The first start should start at current_height - 30 = 71, make sure
+        # it's not earlier
+        l1.daemon.wait_for_log(r'Adding block 101')
+        assert not l1.daemon.is_in_log(r'Adding block 70')
+
+        # Restarting with a higher rescan should go back further
+        l1.daemon.opts['rescan'] = 50
+        l1.restart()
+        l1.daemon.wait_for_log(r'Adding block 101')
+        assert l1.daemon.is_in_log(r'Adding block 51')
+        assert not l1.daemon.is_in_log(r'Adding block 50')
+
+        # Restarting with an absolute rescan should start from there
+        l1.daemon.opts['rescan'] = -31
+        l1.restart()
+        l1.daemon.wait_for_log(r'Adding block 101')
+        assert l1.daemon.is_in_log(r'Adding block 31')
+        assert not l1.daemon.is_in_log(r'Adding block 30')
+
+        # Restarting with a future absolute blockheight should just start with
+        # the current height
+        l1.daemon.opts['rescan'] = -500000
+        l1.stop()
+        btc.rpc.generate(4)
+        l1.daemon.start()
+        l1.daemon.wait_for_log(r'Adding block 105')
+        assert not l1.daemon.is_in_log(r'Adding block 102')
+
 
 if __name__ == '__main__':
     unittest.main(verbosity=2)
diff --git a/tests/utils.py b/tests/utils.py
index 0fe6d81ffc13..6d6cce60bac4 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -23,6 +23,7 @@
     "cltv-delta": 6,
     "cltv-final": 5,
     "locktime-blocks": 5,
+    "rescan": 1,
 }
 
 DEVELOPER = os.getenv("DEVELOPER", "0") == "1"
diff --git a/wallet/db.c b/wallet/db.c
index e5a7275d1376..f3383f833c31 100644
--- a/wallet/db.c
+++ b/wallet/db.c
@@ -306,6 +306,28 @@ char *dbmigrations[] = {
     "   SET faildetail = 'unspecified payment failure reason'"
     " WHERE status = 2;", /* PAYMENT_FAILED */
     /* -- Detailed payment faiure ends -- */
+    "CREATE TABLE channeltxs ("
+    /* The id serves as insertion order and short ID */
+    "  id INTEGER"
+    ", channel_id INTEGER REFERENCES channels(id) ON DELETE CASCADE"
+    ", type INTEGER"
+    ", transaction_id BLOB REFERENCES transactions(id) ON DELETE CASCADE"
+    /* The input_num is only used by the txo_watch, 0 if txwatch */
+    ", input_num INTEGER"
+    /* The height at which we sent the depth notice */
+    ", blockheight INTEGER REFERENCES blocks(height) ON DELETE CASCADE"
+    ", PRIMARY KEY(id)"
+    ");",
+    /* -- Set the correct rescan height for PR #1398 -- */
+    /* Delete blocks that are higher than our initial scan point, this is a
+     * no-op if we don't have a channel. */
+    "DELETE FROM blocks WHERE height > (SELECT MIN(first_blocknum) FROM channels);",
+    /* Now make sure we have the lower bound block with the first_blocknum
+     * height. This may introduce a block with NULL height if we didn't have any
+     * blocks, remove that in the next. */
+    "INSERT OR IGNORE INTO blocks (height) VALUES ((SELECT MIN(first_blocknum) FROM channels));",
+    "DELETE FROM blocks WHERE height IS NULL;",
+    /* -- End of  PR #1398 -- */
     NULL,
 };
 
diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c
index e132ea611240..cedcbb5d1e16 100644
--- a/wallet/test/run-wallet.c
+++ b/wallet/test/run-wallet.c
@@ -85,12 +85,6 @@ bool fromwire_gossip_getpeers_reply(const tal_t *ctx UNNEEDED, const void *p UNN
 /* Generated stub for fromwire_gossip_peer_connected */
 bool fromwire_gossip_peer_connected(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct pubkey *id UNNEEDED, struct wireaddr *addr UNNEEDED, struct crypto_state *crypto_state UNNEEDED, u64 *gossip_index UNNEEDED, u8 **gfeatures UNNEEDED, u8 **lfeatures UNNEEDED)
 { fprintf(stderr, "fromwire_gossip_peer_connected called!\n"); abort(); }
-/* Generated stub for funding_spent */
-enum watch_result funding_spent(struct channel *channel UNNEEDED,
-				const struct bitcoin_tx *tx UNNEEDED,
-				size_t input_num UNNEEDED,
-				const struct block *block UNNEEDED)
-{ fprintf(stderr, "funding_spent called!\n"); abort(); }
 /* Generated stub for get_feerate */
 u32 get_feerate(const struct chain_topology *topo UNNEEDED, enum feerate feerate UNNEEDED)
 { fprintf(stderr, "get_feerate called!\n"); abort(); }
@@ -281,6 +275,11 @@ struct json_result *new_json_result(const tal_t *ctx UNNEEDED)
 /* Generated stub for null_response */
 struct json_result *null_response(const tal_t *ctx UNNEEDED)
 { fprintf(stderr, "null_response called!\n"); abort(); }
+/* Generated stub for onchaind_funding_spent */
+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 outpointfilter_add */
 void outpointfilter_add(struct outpointfilter *of UNNEEDED,
 			const struct bitcoin_txid *txid UNNEEDED, const u32 outnum UNNEEDED)
diff --git a/wallet/wallet.c b/wallet/wallet.c
index 1125955457ca..1f1bfc124f8c 100644
--- a/wallet/wallet.c
+++ b/wallet/wallet.c
@@ -11,6 +11,7 @@
 #include <lightningd/log.h>
 #include <lightningd/peer_control.h>
 #include <lightningd/peer_htlcs.h>
+#include <onchaind/gen_onchain_wire.h>
 #include <string.h>
 
 #define SQLITE_MAX_UINT 0x7FFFFFFFFFFFFFFF
@@ -766,75 +767,18 @@ void wallet_channel_stats_load(struct wallet *w,
 	stats->out_msatoshi_fulfilled = sqlite3_column_int64(stmt, 7);
 }
 
-#ifdef COMPAT_V052
-/* Upgrade of db (or initial create): do we have anything to scan for? */
-static bool wallet_ever_used(struct wallet *w)
+u32 wallet_blocks_height(struct wallet *w, u32 def)
 {
-	sqlite3_stmt *stmt;
-	bool channel_utxos;
-
-	/* If we ever handed out an address. */
-	if (db_get_intvar(w->db, "bip32_max_index", 0) != 0)
-		return true;
-
-	/* Or if they do a unilateral close, the output to us provides a UTXO. */
-	stmt = db_query(__func__, w->db,
-			"SELECT COUNT(*) FROM outputs WHERE commitment_point IS NOT NULL;");
-	int ret = sqlite3_step(stmt);
-	assert(ret == SQLITE_ROW);
-	channel_utxos = (sqlite3_column_int(stmt, 0) != 0);
-	sqlite3_finalize(stmt);
-
-	return channel_utxos;
-}
-#endif
-
-/* We want the earlier of either:
- * 1. The first channel we're still watching (it might have closed),
- * 2. The last block we scanned for UTXO (might have new incoming payments)
- *
- * chaintopology actually subtracts another 100 blocks to make sure we
- * catch chain forks.
- */
-u32 wallet_first_blocknum(struct wallet *w, u32 first_possible)
-{
-	int err;
-	u32 first_channel, first_utxo;
-	sqlite3_stmt *stmt =
-	    db_query(__func__, w->db,
-		     "SELECT MIN(first_blocknum) FROM channels;");
-
-	/* If we ever opened a channel, this will give us the first block. */
-	err = sqlite3_step(stmt);
-	if (err == SQLITE_ROW && sqlite3_column_type(stmt, 0) != SQLITE_NULL)
-		first_channel = sqlite3_column_int(stmt, 0);
-	else
-		first_channel = UINT32_MAX;
-	sqlite3_finalize(stmt);
-
-#ifdef COMPAT_V052
-	/* This field was missing in older databases. */
-	first_utxo = db_get_intvar(w->db, "last_processed_block", 0);
-	if (first_utxo == 0) {
-		/* Don't know?  New db, or upgraded. */
-		if (wallet_ever_used(w))
-			/* Be conservative */
-			first_utxo = first_possible;
-		else
-			first_utxo = UINT32_MAX;
-	}
-#else
-	first_utxo = db_get_intvar(w->db, "last_processed_block", UINT32_MAX);
-#endif
-
-	/* Never go below the start of the Lightning Network */
-	if (first_utxo < first_possible)
-		first_utxo = first_possible;
+	u32 blockheight;
+	sqlite3_stmt *stmt = db_prepare(w->db, "SELECT MAX(height) FROM blocks;");
 
-	if (first_utxo < first_channel)
-		return first_utxo;
-	else
-		return first_channel;
+	/* If we ever processed a block we'll get the latest block in the chain */
+	if (sqlite3_step(stmt) == SQLITE_ROW && sqlite3_column_type(stmt, 0) != SQLITE_NULL) {
+		blockheight = sqlite3_column_int(stmt, 0);
+		sqlite3_finalize(stmt);
+		return blockheight;
+	} else
+		return def;
 }
 
 static void wallet_channel_config_insert(struct wallet *w,
@@ -2277,3 +2221,77 @@ struct bitcoin_txid *wallet_transactions_by_height(const tal_t *ctx,
 	return txids;
 }
 
+void wallet_channeltxs_add(struct wallet *w, struct channel *chan,
+			   const int type, const struct bitcoin_txid *txid,
+			   const u32 input_num, const u32 blockheight)
+{
+	sqlite3_stmt *stmt;
+	stmt = db_prepare(w->db, "INSERT INTO channeltxs ("
+			  "  channel_id"
+			  ", type"
+			  ", transaction_id"
+			  ", input_num"
+			  ", blockheight"
+			  ") VALUES (?, ?, ?, ?, ?);");
+	sqlite3_bind_int(stmt, 1, chan->dbid);
+	sqlite3_bind_int(stmt, 2, type);
+	sqlite3_bind_sha256(stmt, 3, &txid->shad.sha);
+	sqlite3_bind_int(stmt, 4, input_num);
+	sqlite3_bind_int(stmt, 5, blockheight);
+
+	db_exec_prepared(w->db, stmt);
+}
+
+u32 *wallet_onchaind_channels(struct wallet *w,
+			      const tal_t *ctx)
+{
+	sqlite3_stmt *stmt;
+	size_t count = 0;
+	u32 *channel_ids = tal_arr(ctx, u32, 0);
+	stmt = db_prepare(w->db, "SELECT DISTINCT(channel_id) FROM channeltxs WHERE type = ?;");
+	sqlite3_bind_int(stmt, 1, WIRE_ONCHAIN_INIT);
+
+	while (sqlite3_step(stmt) == SQLITE_ROW) {
+		count++;
+		tal_resize(&channel_ids, count);
+			channel_ids[count-1] = sqlite3_column_int64(stmt, 0);
+	}
+
+	return channel_ids;
+}
+
+struct channeltx *wallet_channeltxs_get(struct wallet *w, const tal_t *ctx,
+					u32 channel_id)
+{
+	sqlite3_stmt *stmt;
+	size_t count = 0;
+	struct channeltx *res = tal_arr(ctx, struct channeltx, 0);
+	stmt = db_prepare(w->db,
+			  "SELECT"
+			  "  c.type"
+			  ", c.blockheight"
+			  ", t.rawtx"
+			  ", c.input_num"
+			  ", c.blockheight - t.blockheight + 1 AS depth"
+			  ", t.id as txid "
+			  "FROM channeltxs c "
+			  "JOIN transactions t ON t.id == c.transaction_id "
+			  "WHERE channel_id = ? "
+			  "ORDER BY c.id ASC;");
+	sqlite3_bind_int(stmt, 1, channel_id);
+
+	while (sqlite3_step(stmt) == SQLITE_ROW) {
+		count++;
+		tal_resize(&res, count);
+
+		res[count-1].channel_id = channel_id;
+		res[count-1].type = sqlite3_column_int(stmt, 0);
+		res[count-1].blockheight = sqlite3_column_int(stmt, 1);
+		res[count-1].tx = sqlite3_column_tx(ctx, stmt, 2);
+		res[count-1].input_num = sqlite3_column_int(stmt, 3);
+		res[count-1].depth = sqlite3_column_int(stmt, 4);
+		sqlite3_column_sha256(stmt, 5, &res[count-1].txid.shad.sha);
+	}
+
+	return res;
+}
diff --git a/wallet/wallet.h b/wallet/wallet.h
index 0e41591f72e5..f754efad7e9b 100644
--- a/wallet/wallet.h
+++ b/wallet/wallet.h
@@ -128,6 +128,16 @@ struct channel_stats {
 	u64 out_msatoshi_offered, out_msatoshi_fulfilled;
 };
 
+struct channeltx {
+	u32 channel_id;
+	int type;
+	u32 blockheight;
+	struct bitcoin_txid txid;
+	struct bitcoin_tx *tx;
+	u32 input_num;
+	u32 depth;
+};
+
 /**
  * wallet_new - Constructor for a new sqlite3 based wallet
  *
@@ -304,12 +314,15 @@ void wallet_channel_stats_incr_out_fulfilled(struct wallet *w, u64 cdbid, u64 ms
 void wallet_channel_stats_load(struct wallet *w, u64 cdbid, struct channel_stats *stats);
 
 /**
- * wallet_first_blocknum - get first block we're interested in.
+ * Retrieve the blockheight of the last block processed by lightningd.
+ *
+ * Will return either the maximal blockheight or the default value if the wallet
+ * was never used before.
  *
  * @w: wallet to load from.
- * @first_possible: when c-lightning may have been active from
+ * @def: the default value to return if we've never used the wallet before
  */
-u32 wallet_first_blocknum(struct wallet *w, u32 first_possible);
+u32 wallet_blocks_height(struct wallet *w, u32 def);
 
 /**
  * wallet_extract_owned_outputs - given a tx, extract all of our outputs
@@ -836,4 +849,23 @@ struct bitcoin_txid *wallet_transactions_by_height(const tal_t *ctx,
 						   struct wallet *w,
 						   const u32 blockheight);
 
+/**
+ * Store transactions of interest in the database to replay on restart
+ */
+void wallet_channeltxs_add(struct wallet *w, struct channel *chan,
+			    const int type, const struct bitcoin_txid *txid,
+			   const u32 input_num, const u32 blockheight);
+
+/**
+ * List channels for which we had an onchaind running
+ */
+u32 *wallet_onchaind_channels(struct wallet *w,
+			      const tal_t *ctx);
+
+/**
+ * Get transactions that we'd like to replay for a channel.
+ */
+struct channeltx *wallet_channeltxs_get(struct wallet *w, const tal_t *ctx,
+					u32 channel_id);
+
 #endif /* LIGHTNING_WALLET_WALLET_H */