Skip to content

Commit 10698b9

Browse files
committed
wallet: make utxo order deterministic if CLN_DEV_ENTROPY_SEED set.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
1 parent 82d1d35 commit 10698b9

2 files changed

Lines changed: 71 additions & 22 deletions

File tree

wallet/test/run-wallet.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1926,6 +1926,7 @@ int main(int argc, const char *argv[])
19261926
ld = tal(tmpctx, struct lightningd);
19271927
ld->config = test_config;
19281928
ld->hsm_capabilities = NULL;
1929+
ld->developer = true;
19291930
memset(&ld->indexes[WAIT_SUBSYSTEM_HTLCS], 0,
19301931
sizeof(ld->indexes[WAIT_SUBSYSTEM_HTLCS]));
19311932

wallet/wallet.c

Lines changed: 70 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
#include "config.h"
22
#include <bitcoin/script.h>
33
#include <ccan/array_size/array_size.h>
4+
#include <ccan/asort/asort.h>
45
#include <ccan/cast/cast.h>
56
#include <ccan/mem/mem.h>
67
#include <ccan/tal/str/str.h>
78
#include <channeld/channeld_wiregen.h>
89
#include <common/clock_time.h>
910
#include <common/memleak.h>
1011
#include <common/onionreply.h>
12+
#include <common/randbytes.h>
1113
#include <common/trace.h>
1214
#include <db/bindings.h>
1315
#include <db/common.h>
@@ -451,7 +453,23 @@ bool wallet_update_output_status(struct wallet *w,
451453
return changes > 0;
452454
}
453455

454-
static struct utxo **gather_utxos(const tal_t *ctx, struct db_stmt *stmt STEALS)
456+
static int cmp_utxo(struct utxo *const *a,
457+
struct utxo *const *b,
458+
void *unused)
459+
{
460+
int ret = memcmp(&(*a)->outpoint.txid, &(*b)->outpoint.txid,
461+
sizeof((*a)->outpoint.txid));
462+
if (ret)
463+
return ret;
464+
if ((*a)->outpoint.n < (*b)->outpoint.n)
465+
return -1;
466+
else if ((*a)->outpoint.n > (*b)->outpoint.n)
467+
return 1;
468+
return 0;
469+
}
470+
471+
static struct utxo **gather_utxos(const tal_t *ctx,
472+
struct db_stmt *stmt STEALS)
455473
{
456474
struct utxo **results;
457475

@@ -463,6 +481,10 @@ static struct utxo **gather_utxos(const tal_t *ctx, struct db_stmt *stmt STEALS)
463481
}
464482
tal_free(stmt);
465483

484+
/* Make sure these are in order if we're trying to remove entropy */
485+
if (randbytes_overridden())
486+
asort(results, tal_count(results), cmp_utxo, NULL);
487+
466488
return results;
467489
}
468490

@@ -809,27 +831,53 @@ struct utxo *wallet_find_utxo(const tal_t *ctx, struct wallet *w,
809831
struct db_stmt *stmt;
810832
struct utxo *utxo;
811833

812-
stmt = db_prepare_v2(w->db, SQL("SELECT"
813-
" prev_out_tx"
814-
", prev_out_index"
815-
", value"
816-
", type"
817-
", status"
818-
", keyindex"
819-
", channel_id"
820-
", peer_id"
821-
", commitment_point"
822-
", option_anchor_outputs"
823-
", confirmation_height"
824-
", spend_height"
825-
", scriptpubkey "
826-
", reserved_til"
827-
", csv_lock"
828-
", is_in_coinbase"
829-
" FROM outputs"
830-
" WHERE status = ?"
831-
" OR (status = ? AND reserved_til <= ?)"
832-
"ORDER BY RANDOM();"));
834+
/* Make sure these are in order if we're trying to remove entropy! */
835+
if (w->ld->developer && getenv("CLN_DEV_ENTROPY_SEED")) {
836+
stmt = db_prepare_v2(w->db, SQL("SELECT"
837+
" prev_out_tx"
838+
", prev_out_index"
839+
", value"
840+
", type"
841+
", status"
842+
", keyindex"
843+
", channel_id"
844+
", peer_id"
845+
", commitment_point"
846+
", option_anchor_outputs"
847+
", confirmation_height"
848+
", spend_height"
849+
", scriptpubkey "
850+
", reserved_til"
851+
", csv_lock"
852+
", is_in_coinbase"
853+
" FROM outputs"
854+
" WHERE status = ?"
855+
" OR (status = ? AND reserved_til <= ?)"
856+
"ORDER BY prev_out_tx, prev_out_index;"));
857+
} else {
858+
stmt = db_prepare_v2(w->db, SQL("SELECT"
859+
" prev_out_tx"
860+
", prev_out_index"
861+
", value"
862+
", type"
863+
", status"
864+
", keyindex"
865+
", channel_id"
866+
", peer_id"
867+
", commitment_point"
868+
", option_anchor_outputs"
869+
", confirmation_height"
870+
", spend_height"
871+
", scriptpubkey "
872+
", reserved_til"
873+
", csv_lock"
874+
", is_in_coinbase"
875+
" FROM outputs"
876+
" WHERE status = ?"
877+
" OR (status = ? AND reserved_til <= ?)"
878+
"ORDER BY RANDOM();"));
879+
}
880+
833881
db_bind_int(stmt, output_status_in_db(OUTPUT_STATE_AVAILABLE));
834882
db_bind_int(stmt, output_status_in_db(OUTPUT_STATE_RESERVED));
835883
db_bind_u64(stmt, current_blockheight);

0 commit comments

Comments
 (0)