diff --git a/lightningd/build_utxos.c b/lightningd/build_utxos.c
index 1a7b9162a..fb7ec09fd 100644
--- a/lightningd/build_utxos.c
+++ b/lightningd/build_utxos.c
@@ -167,80 +167,33 @@ static const struct json_command addfunds_command = {
 };
 AUTODATA(json_command, &addfunds_command);
 
-static void unreserve_utxo(struct lightningd *ld, const struct utxo *unres)
-{
-	assert(wallet_update_output_status(ld->wallet, &unres->txid,
-					   unres->outnum, output_state_reserved,
-					   output_state_available));
-}
-
-static void destroy_utxos(const struct utxo **utxos, struct lightningd *ld)
-{
-	size_t i;
-
-	for (i = 0; i < tal_count(utxos); i++)
-		unreserve_utxo(ld, utxos[i]);
-}
-
-void confirm_utxos(struct lightningd *ld, const struct utxo **utxos)
-{
-	tal_del_destructor2(utxos, destroy_utxos, ld);
-}
-
 const struct utxo **build_utxos(const tal_t *ctx,
 				struct lightningd *ld, u64 satoshi_out,
 				u32 feerate_per_kw, u64 dust_limit,
 				u64 *change_satoshis, u32 *change_keyindex)
 {
-	size_t i = 0;
-	struct utxo **available;
-	const struct utxo **utxos = tal_arr(ctx, const struct utxo *, 0);
-	/* We assume two outputs for the weight. */
-	u64 satoshi_in = 0, weight = (4 + (8 + 22) * 2 + 4) * 4;
+	u64 satoshi_in = 0;
+	u64 fee_estimate = 0;
 	u64 bip32_max_index = db_get_intvar(ld->wallet->db, "bip32_max_index", 0);
+	const struct utxo **utxos =
+		wallet_select_coins(ctx, ld->wallet, satoshi_out, feerate_per_kw, &fee_estimate);
 
-	tal_add_destructor2(utxos, destroy_utxos, ld);
-
-	db_begin_transaction(ld->wallet->db);
-	available = wallet_get_utxos(utxos, ld->wallet, output_state_available);
-
-	for (i=0; i<tal_count(available); i++) {
-		u64 fee;
+	/* Oops, didn't have enough coins available */
+	if (!utxos)
+		return NULL;
 
-		tal_resize(&utxos, i+1);
-		utxos[i] = tal_steal(utxos, available[i]);
-
-		assert(wallet_update_output_status(
-		    ld->wallet, &available[i]->txid, available[i]->outnum,
-		    output_state_available, output_state_reserved));
-
-		/* Add this input's weight. */
-		weight += (32 + 4 + 4) * 4;
-		if (utxos[i]->is_p2sh)
-			weight += 22 * 4;
-		/* Account for witness (1 byte count + sig + key */
-		weight += 1 + (1 + 73 + 1 + 33);
-
-		fee = weight * feerate_per_kw / 1000;
+	/* How much are we actually claiming? */
+	for (size_t i=0; i<tal_count(utxos); i++)
 		satoshi_in += utxos[i]->amount;
 
-		if (satoshi_in >= fee + satoshi_out) {
-			/* We simply eliminate change if it's dust. */
-			*change_satoshis = satoshi_in - (fee + satoshi_out);
-			if (*change_satoshis < dust_limit) {
-				*change_satoshis = 0;
-				*change_keyindex = 0;
-			} else {
-				*change_keyindex = bip32_max_index + 1;
-				db_set_intvar(ld->wallet->db, "bip32_max_index", *change_keyindex);
-			}
-
-			db_commit_transaction(ld->wallet->db);
-			tal_free(available);
-			return utxos;
-		}
+	/* Do we need a change output? */
+	*change_satoshis = satoshi_in - (fee_estimate + satoshi_out);
+	if (*change_satoshis < dust_limit) {
+		*change_satoshis = 0;
+		*change_keyindex = 0;
+	} else {
+		*change_keyindex = bip32_max_index + 1;
+		db_set_intvar(ld->wallet->db, "bip32_max_index", *change_keyindex);
 	}
-	db_rollback_transaction(ld->wallet->db);
-	tal_free(available);
-	return tal_free(utxos);
+	return utxos;
 }
diff --git a/lightningd/build_utxos.h b/lightningd/build_utxos.h
index 9fa0fde91..706fcaf8b 100644
--- a/lightningd/build_utxos.h
+++ b/lightningd/build_utxos.h
@@ -11,6 +11,4 @@ const struct utxo **build_utxos(const tal_t *ctx,
 				u32 feerate_per_kw, u64 dust_limit,
 				u64 *change_satoshis, u32 *change_keyindex);
 
-/* Once we've spent them, mark them confirmed. */
-void confirm_utxos(struct lightningd *ld, const struct utxo **utxos);
 #endif /* LIGHTNING_LIGHTNINGD_BUILD_UTXOS_H */
diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c
index d674e6ba8..3158db3f3 100644
--- a/lightningd/peer_control.c
+++ b/lightningd/peer_control.c
@@ -850,6 +850,7 @@ static bool opening_got_hsm_funding_sig(struct subd *hsm, const u8 *resp,
 	/* Start normal channel daemon. */
 	peer_start_channeld(fc->peer, GETTING_SIG_FROM_HSM, NULL);
 
+	wallet_confirm_utxos(fc->peer->ld->wallet, fc->utxomap);
 	tal_free(fc);
 	return true;
 }
diff --git a/wallet/wallet.c b/wallet/wallet.c
index c895110a5..7e25b4042 100644
--- a/wallet/wallet.c
+++ b/wallet/wallet.c
@@ -92,3 +92,85 @@ struct utxo **wallet_get_utxos(const tal_t *ctx, struct wallet *w, const enum ou
 
 	return results;
 }
+
+/**
+ * unreserve_utxo - Mark a reserved UTXO as available again
+ */
+static void unreserve_utxo(struct wallet *w, const struct utxo *unres)
+{
+	if (!wallet_update_output_status(w, &unres->txid, unres->outnum,
+					 output_state_reserved,
+					 output_state_available)) {
+		fatal("Unable to unreserve output: %s", w->db->err);
+	}
+}
+
+/**
+ * destroy_utxos - Destructor for an array of pointers to utxo
+ */
+static void destroy_utxos(const struct utxo **utxos, struct wallet *w)
+{
+	for (size_t i = 0; i < tal_count(utxos); i++)
+		unreserve_utxo(w, utxos[i]);
+}
+
+void wallet_confirm_utxos(struct wallet *w, const struct utxo **utxos)
+{
+	tal_del_destructor2(utxos, destroy_utxos, w);
+	for (size_t i = 0; i < tal_count(utxos); i++) {
+		if (!wallet_update_output_status(
+			w, &utxos[i]->txid, utxos[i]->outnum,
+			output_state_reserved, output_state_spent)) {
+			fatal("Unable to mark output as spent: %s", w->db->err);
+		}
+	}
+}
+
+const struct utxo **wallet_select_coins(const tal_t *ctx, struct wallet *w,
+					const u64 value,
+					const u32 feerate_per_kw,
+					u64 *fee_estimate)
+{
+	size_t i = 0;
+	struct utxo **available;
+	const struct utxo **utxos = tal_arr(ctx, const struct utxo *, 0);
+
+	/* We assume two outputs for the weight. */
+	u64 satoshi_in = 0, weight = (4 + (8 + 22) * 2 + 4) * 4;
+	tal_add_destructor2(utxos, destroy_utxos, w);
+
+	db_begin_transaction(w->db);
+	available = wallet_get_utxos(ctx, w, output_state_available);
+
+	for (i = 0; i < tal_count(available); i++) {
+		tal_resize(&utxos, i + 1);
+		utxos[i] = tal_steal(utxos, available[i]);
+
+		if (!wallet_update_output_status(
+			w, &available[i]->txid, available[i]->outnum,
+			output_state_available, output_state_reserved))
+			fatal("Unable to reserve output: %s", w->db->err);
+
+		weight += (32 + 4 + 4) * 4;
+		if (utxos[i]->is_p2sh)
+			weight += 22 * 4;
+
+		/* Account for witness (1 byte count + sig + key */
+		weight += 1 + (1 + 73 + 1 + 33);
+		*fee_estimate = weight * feerate_per_kw / 1000;
+		satoshi_in += utxos[i]->amount;
+		if (satoshi_in >= *fee_estimate + value)
+			break;
+	}
+	tal_free(available);
+
+	if (satoshi_in < *fee_estimate + value) {
+		/* Could not collect enough inputs, cleanup and bail */
+		utxos = tal_free(utxos);
+		db_rollback_transaction(w->db);
+	} else {
+		/* Commit the db transaction to persist markings */
+		db_commit_transaction(w->db);
+	}
+	return utxos;
+}
diff --git a/wallet/wallet.h b/wallet/wallet.h
index 36e13d51a..9f21ea2f7 100644
--- a/wallet/wallet.h
+++ b/wallet/wallet.h
@@ -74,4 +74,18 @@ bool wallet_update_output_status(struct wallet *w,
 struct utxo **wallet_get_utxos(const tal_t *ctx, struct wallet *w,
 			      const enum output_status state);
 
+const struct utxo **wallet_select_coins(const tal_t *ctx, struct wallet *w,
+					const u64 value,
+					const u32 feerate_per_kw,
+					u64 *fee_estimate);
+
+/**
+ * wallet_confirm_utxos - Once we've spent a set of utxos, mark them confirmed.
+ *
+ * May be called once the transaction spending these UTXOs has been
+ * broadcast. If something fails use `tal_free(utxos)` instead to undo
+ * the reservation.
+ */
+void wallet_confirm_utxos(struct wallet *w, const struct utxo **utxos);
+
 #endif /* WALLET_WALLET_H */