diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 05a1a0ce6..617e96759 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -1926,6 +1926,7 @@ int main(int argc, const char *argv[]) ld = tal(tmpctx, struct lightningd); ld->config = test_config; ld->hsm_capabilities = NULL; + ld->developer = true; memset(&ld->indexes[WAIT_SUBSYSTEM_HTLCS], 0, sizeof(ld->indexes[WAIT_SUBSYSTEM_HTLCS])); diff --git a/wallet/wallet.c b/wallet/wallet.c index 4de784e95..07ffaddf8 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1,6 +1,7 @@ #include "config.h" #include #include +#include #include #include #include @@ -8,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -451,7 +453,23 @@ bool wallet_update_output_status(struct wallet *w, return changes > 0; } -static struct utxo **gather_utxos(const tal_t *ctx, struct db_stmt *stmt STEALS) +static int cmp_utxo(struct utxo *const *a, + struct utxo *const *b, + void *unused) +{ + int ret = memcmp(&(*a)->outpoint.txid, &(*b)->outpoint.txid, + sizeof((*a)->outpoint.txid)); + if (ret) + return ret; + if ((*a)->outpoint.n < (*b)->outpoint.n) + return -1; + else if ((*a)->outpoint.n > (*b)->outpoint.n) + return 1; + return 0; +} + +static struct utxo **gather_utxos(const tal_t *ctx, + struct db_stmt *stmt STEALS) { struct utxo **results; @@ -463,6 +481,10 @@ static struct utxo **gather_utxos(const tal_t *ctx, struct db_stmt *stmt STEALS) } tal_free(stmt); + /* Make sure these are in order if we're trying to remove entropy */ + if (randbytes_overridden()) + asort(results, tal_count(results), cmp_utxo, NULL); + return results; } @@ -809,27 +831,53 @@ struct utxo *wallet_find_utxo(const tal_t *ctx, struct wallet *w, struct db_stmt *stmt; struct utxo *utxo; - stmt = db_prepare_v2(w->db, SQL("SELECT" - " prev_out_tx" - ", prev_out_index" - ", value" - ", type" - ", status" - ", keyindex" - ", channel_id" - ", peer_id" - ", commitment_point" - ", option_anchor_outputs" - ", confirmation_height" - ", spend_height" - ", scriptpubkey " - ", reserved_til" - ", csv_lock" - ", is_in_coinbase" - " FROM outputs" - " WHERE status = ?" - " OR (status = ? AND reserved_til <= ?)" - "ORDER BY RANDOM();")); + /* Make sure these are in order if we're trying to remove entropy! */ + if (w->ld->developer && getenv("CLN_DEV_ENTROPY_SEED")) { + stmt = db_prepare_v2(w->db, SQL("SELECT" + " prev_out_tx" + ", prev_out_index" + ", value" + ", type" + ", status" + ", keyindex" + ", channel_id" + ", peer_id" + ", commitment_point" + ", option_anchor_outputs" + ", confirmation_height" + ", spend_height" + ", scriptpubkey " + ", reserved_til" + ", csv_lock" + ", is_in_coinbase" + " FROM outputs" + " WHERE status = ?" + " OR (status = ? AND reserved_til <= ?)" + "ORDER BY prev_out_tx, prev_out_index;")); + } else { + stmt = db_prepare_v2(w->db, SQL("SELECT" + " prev_out_tx" + ", prev_out_index" + ", value" + ", type" + ", status" + ", keyindex" + ", channel_id" + ", peer_id" + ", commitment_point" + ", option_anchor_outputs" + ", confirmation_height" + ", spend_height" + ", scriptpubkey " + ", reserved_til" + ", csv_lock" + ", is_in_coinbase" + " FROM outputs" + " WHERE status = ?" + " OR (status = ? AND reserved_til <= ?)" + "ORDER BY RANDOM();")); + } + db_bind_int(stmt, output_status_in_db(OUTPUT_STATE_AVAILABLE)); db_bind_int(stmt, output_status_in_db(OUTPUT_STATE_RESERVED)); db_bind_u64(stmt, current_blockheight);