diff --git a/common/utxo.c b/common/utxo.c index 9a7f29a84704..b2192f4a5d74 100644 --- a/common/utxo.c +++ b/common/utxo.c @@ -73,3 +73,21 @@ size_t utxo_spend_weight(const struct utxo *utxo, size_t min_witness_weight) return bitcoin_tx_input_weight(utxo->is_p2sh, wit_weight); } + +u32 utxo_is_immature(const struct utxo *utxo, u32 blockheight) +{ + if (utxo->is_in_coinbase) { + /* We got this from a block, it must have a known + * blockheight. */ + assert(utxo->blockheight); + + if (blockheight < *utxo->blockheight + 100) + return *utxo->blockheight + 99 - blockheight; + + else + return 0; + } else { + /* Non-coinbase outputs are always mature. */ + return 0; + } +} diff --git a/common/utxo.h b/common/utxo.h index 38544da68ff9..6c5365c8e32c 100644 --- a/common/utxo.h +++ b/common/utxo.h @@ -83,4 +83,11 @@ struct utxo *fromwire_utxo(const tal_t *ctx, const u8 **ptr, size_t *max); /* Estimate of (signed) UTXO weight in transaction */ size_t utxo_spend_weight(const struct utxo *utxo, size_t min_witness_weight); + +/** + * Determine how many blocks until a UTXO becomes mature. + * + * Returns 0 for non-coinbase outputs or the number of blocks to mature. + */ +u32 utxo_is_immature(const struct utxo *utxo, u32 blockheight); #endif /* LIGHTNING_COMMON_UTXO_H */ diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index e6826e98f46f..884a9b31f0d7 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -855,6 +855,9 @@ void try_reconnect(const tal_t *ctx UNNEEDED, struct peer *peer UNNEEDED, const struct wireaddr_internal *addrhint UNNEEDED) { fprintf(stderr, "try_reconnect called!\n"); abort(); } +/* Generated stub for utxo_is_immature */ +u32 utxo_is_immature(const struct utxo *utxo UNNEEDED, u32 blockheight UNNEEDED) +{ fprintf(stderr, "utxo_is_immature called!\n"); abort(); } /* Generated stub for watch_txid */ struct txwatch *watch_txid(const tal_t *ctx UNNEEDED, struct chain_topology *topo UNNEEDED, diff --git a/wallet/wallet.c b/wallet/wallet.c index 167edbea78f2..540b6d86fc6f 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -511,15 +511,9 @@ static bool deep_enough(u32 maxheight, const struct utxo *utxo, return false; } - /* If the utxo is a coinbase, we over-write the maxheight - * to the coinbase maxheight (current - 99) */ - if (utxo->is_in_coinbase) { - /* Nothing is spendable the first 100 blocks */ - if (current_blockheight < 100) - return false; - if (maxheight > current_blockheight - 99) - maxheight = current_blockheight - 99; - } + bool immature = utxo_is_immature(utxo, current_blockheight); + if (immature) + return false; /* If we require confirmations check that we have a * confirmation height and that it is below the required diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c index 90d33372dbdd..30b737880b88 100644 --- a/wallet/walletrpc.c +++ b/wallet/walletrpc.c @@ -272,11 +272,11 @@ static void json_add_utxo(struct json_stream *response, if (utxo->spendheight) json_add_string(response, "status", "spent"); else if (utxo->blockheight) { - if (utxo->is_in_coinbase - && *utxo->blockheight + 99 > current_height) { - json_add_string(response, "status", "immature"); - } else - json_add_string(response, "status", "confirmed"); + json_add_string(response, "status", + utxo_is_immature(utxo, current_height) + ? "immature" + : "confirmed"); + json_add_num(response, "blockheight", *utxo->blockheight); } else json_add_string(response, "status", "unconfirmed");