diff --git a/Makefile b/Makefile index e67f0ca74d26..324f86cc158f 100644 --- a/Makefile +++ b/Makefile @@ -569,7 +569,7 @@ check-tmpctx: @if git grep -n 'tal_free[(]tmpctx)' | grep -Ev '^ccan/|/test/|^common/setup.c:|^common/utils.c:'; then echo "Don't free tmpctx!">&2; exit 1; fi check-discouraged-functions: - @if git grep -E "[^a-z_/](fgets|fputs|gets|scanf|sprintf)\(" -- "*.c" "*.h" ":(exclude)ccan/" ":(exclude)contrib/"; then exit 1; fi + @if git grep -nE "[^a-z_/](fgets|fputs|gets|scanf|sprintf|randombytes_buf|time_now)\(" -- "*.c" "*.h" ":(exclude)ccan/" ":(exclude)contrib/" | grep -Fv '/* discouraged:'; then exit 1; fi # Don't access amount_msat and amount_sat members directly without a good reason # since it risks overflow. diff --git a/bitcoin/script.c b/bitcoin/script.c index 63974644a34c..18461a8396b4 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -187,17 +187,6 @@ u8 *scriptpubkey_p2pkh(const tal_t *ctx, const struct bitcoin_address *addr) return script; } -u8 *scriptpubkey_opreturn_padded(const tal_t *ctx) -{ - u8 *script = tal_arr(ctx, u8, 0); - u8 random[20]; - randombytes_buf(random, sizeof(random)); - - add_op(&script, OP_RETURN); - script_push_bytes(&script, random, sizeof(random)); - return script; -} - /* Create an input script which spends p2pkh */ u8 *bitcoin_redeem_p2pkh(const tal_t *ctx, const struct pubkey *pubkey, const struct bitcoin_signature *sig) diff --git a/bitcoin/script.h b/bitcoin/script.h index 5b96d696ff15..c0a005c17d57 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -27,12 +27,6 @@ u8 *scriptpubkey_p2sh_hash(const tal_t *ctx, const struct ripemd160 *redeemhash) /* Create an output script using p2pkh */ u8 *scriptpubkey_p2pkh(const tal_t *ctx, const struct bitcoin_address *addr); -/* Create a prunable output script with 20 random bytes. - * This is needed since a spend from a p2wpkh to an `OP_RETURN` without - * any other outputs would result in a transaction smaller than the - * minimum size. */ -u8 *scriptpubkey_opreturn_padded(const tal_t *ctx); - /* Create an input script which spends p2pkh */ u8 *bitcoin_redeem_p2pkh(const tal_t *ctx, const struct pubkey *pubkey, const struct bitcoin_signature *sig); diff --git a/bitcoin/short_channel_id.c b/bitcoin/short_channel_id.c index cc1de68c4377..98fe4748b714 100644 --- a/bitcoin/short_channel_id.c +++ b/bitcoin/short_channel_id.c @@ -1,7 +1,7 @@ #include "config.h" #include #include -#include +#include #include #include @@ -104,6 +104,6 @@ struct short_channel_id fromwire_short_channel_id(const u8 **cursor, size_t *max struct short_channel_id random_scid(void) { struct short_channel_id scid; - randombytes_buf(&scid, sizeof(scid)); + randbytes(&scid, sizeof(scid)); return scid; } diff --git a/bitcoin/test/Makefile b/bitcoin/test/Makefile index 7b15ab9ae07f..fd29ff5907ce 100644 --- a/bitcoin/test/Makefile +++ b/bitcoin/test/Makefile @@ -2,7 +2,7 @@ BITCOIN_TEST_SRC := $(wildcard bitcoin/test/run-*.c) BITCOIN_TEST_OBJS := $(BITCOIN_TEST_SRC:.c=.o) BITCOIN_TEST_PROGRAMS := $(BITCOIN_TEST_OBJS:.o=) -BITCOIN_TEST_COMMON_OBJS := common/utils.o common/setup.o common/autodata.o +BITCOIN_TEST_COMMON_OBJS := common/utils.o common/setup.o common/autodata.o common/clock_time.o $(BITCOIN_TEST_PROGRAMS): $(BITCOIN_TEST_COMMON_OBJS) bitcoin/chainparams.o $(BITCOIN_TEST_OBJS): $(CCAN_HEADERS) $(BITCOIN_HEADERS) $(BITCOIN_SRC) diff --git a/bitcoin/test/run-secret_eq_consttime.c b/bitcoin/test/run-secret_eq_consttime.c index 4f21ee191f11..bfba7ceb5029 100644 --- a/bitcoin/test/run-secret_eq_consttime.c +++ b/bitcoin/test/run-secret_eq_consttime.c @@ -22,7 +22,7 @@ static struct timerel const_time_test(struct secret *s1, struct secret *s2, size_t off) { - struct timeabs start, end; + struct timemono start, end; int result = 0; memset(s1, 0, RUNS * sizeof(*s1)); @@ -31,16 +31,16 @@ static struct timerel const_time_test(struct secret *s1, for (size_t i = 0; i < RUNS; i++) s2[i].data[off] = i; - start = time_now(); + start = time_mono(); for (size_t i = 0; i < RUNS; i++) result += secret_eq_consttime(&s1[i], &s2[i]); - end = time_now(); + end = time_mono(); if (result != RUNS / 256) errx(1, "Expected %u successes at offset %zu, not %u!", RUNS / 256, off, result); - return time_between(end, start); + return timemono_between(end, start); } static inline bool secret_eq_nonconst(const struct secret *a, @@ -53,7 +53,7 @@ static struct timerel nonconst_time_test(struct secret *s1, struct secret *s2, size_t off) { - struct timeabs start, end; + struct timemono start, end; int result = 0; memset(s1, 0, RUNS * sizeof(*s1)); @@ -62,16 +62,16 @@ static struct timerel nonconst_time_test(struct secret *s1, for (size_t i = 0; i < RUNS; i++) s2[i].data[off] = i; - start = time_now(); + start = time_mono(); for (size_t i = 0; i < RUNS; i++) result += secret_eq_nonconst(&s1[i], &s2[i]); - end = time_now(); + end = time_mono(); if (result != RUNS / 256) errx(1, "Expected %u successes at offset %zu, not %u!", RUNS / 256, off, result); - return time_between(end, start); + return timemono_between(end, start); } static struct secret *s1, *s2; diff --git a/channeld/Makefile b/channeld/Makefile index 7edcd460ae4d..cd7aae387548 100644 --- a/channeld/Makefile +++ b/channeld/Makefile @@ -48,6 +48,7 @@ CHANNELD_COMMON_OBJS := \ common/channel_config.o \ common/channel_id.o \ common/channel_type.o \ + common/clock_time.o \ common/cryptomsg.o \ common/daemon.o \ common/daemon_conn.o \ @@ -84,6 +85,7 @@ CHANNELD_COMMON_OBJS := \ common/psbt_open.o \ common/psbt_internal.o \ common/pseudorand.o \ + common/randbytes.o \ common/read_peer_msg.o \ common/setup.o \ common/status.o \ diff --git a/channeld/full_channel.c b/channeld/full_channel.c index 699ccdf40ca4..cf27c69c11ad 100644 --- a/channeld/full_channel.c +++ b/channeld/full_channel.c @@ -17,12 +17,6 @@ /* Needs to be at end, since it doesn't include its own hdrs */ #include "full_channel_error_names_gen.h" -static void memleak_help_htlcmap(struct htable *memtable, - struct htlc_map *htlcs) -{ - memleak_scan_htable(memtable, &htlcs->raw); -} - /* This is a dangerous thing! Because we apply HTLCs in many places * in bulk, we can temporarily go negative. You must check balance_ok() * at the end! */ @@ -113,11 +107,9 @@ struct channel *new_full_channel(const tal_t *ctx, option_wumbo, opener); - if (channel) { - channel->htlcs = tal(channel, struct htlc_map); - htlc_map_init(channel->htlcs); - memleak_add_helper(channel->htlcs, memleak_help_htlcmap); - } + if (channel) + channel->htlcs = new_htable(channel, htlc_map); + return channel; } diff --git a/channeld/test/Makefile b/channeld/test/Makefile index 67bc5a79769f..7e447f598439 100644 --- a/channeld/test/Makefile +++ b/channeld/test/Makefile @@ -21,6 +21,7 @@ CHANNELD_TEST_COMMON_OBJS := \ common/msg_queue.o \ common/permute_tx.o \ common/pseudorand.o \ + common/randbytes.o \ common/setup.o \ common/utils.o diff --git a/channeld/test/run-commit_tx.c b/channeld/test/run-commit_tx.c index 5f0a636bdd4b..4df740c41ec4 100644 --- a/channeld/test/run-commit_tx.c +++ b/channeld/test/run-commit_tx.c @@ -15,6 +15,7 @@ static bool print_superverbose; #include #include #include +#include #include #include diff --git a/cli/Makefile b/cli/Makefile index 82dea907ea61..05c07100d9d1 100644 --- a/cli/Makefile +++ b/cli/Makefile @@ -10,6 +10,7 @@ LIGHTNING_CLI_COMMON_OBJS := \ common/configdir.o \ common/configvar.o \ common/json_parse_simple.o \ + common/memleak.o \ common/status_levels.o \ common/utils.o \ common/version.o diff --git a/cli/test/Makefile b/cli/test/Makefile index 6f9c9bea6579..3f587e8c098b 100644 --- a/cli/test/Makefile +++ b/cli/test/Makefile @@ -15,6 +15,7 @@ CLI_TEST_COMMON_OBJS := \ common/htlc_state.o \ common/json_parse_simple.o \ common/pseudorand.o \ + common/randbytes.o \ common/memleak.o \ common/msg_queue.o \ common/setup.o \ diff --git a/closingd/Makefile b/closingd/Makefile index 1c3953c14f20..c48d4db0f392 100644 --- a/closingd/Makefile +++ b/closingd/Makefile @@ -25,6 +25,7 @@ CLOSINGD_COMMON_OBJS := \ common/bigsize.o \ common/bip32.o \ common/channel_id.o \ + common/clock_time.o \ common/close_tx.o \ common/cryptomsg.o \ common/daemon.o \ @@ -47,6 +48,7 @@ CLOSINGD_COMMON_OBJS := \ common/psbt_keypath.o \ common/psbt_open.o \ common/pseudorand.o \ + common/randbytes.o \ common/status_wiregen.o \ common/read_peer_msg.o \ common/setup.o \ diff --git a/common/Makefile b/common/Makefile index dec98e099b26..b8b50eff7b0a 100644 --- a/common/Makefile +++ b/common/Makefile @@ -21,6 +21,7 @@ COMMON_SRC_NOGEN := \ common/channel_config.c \ common/channel_id.c \ common/channel_type.c \ + common/clock_time.c \ common/close_tx.c \ common/codex32.c \ common/coin_mvt.c \ @@ -85,6 +86,7 @@ COMMON_SRC_NOGEN := \ common/psbt_keypath.c \ common/psbt_open.c \ common/pseudorand.c \ + common/randbytes.c \ common/random_select.c \ common/read_peer_msg.c \ common/route.c \ diff --git a/common/blindedpath.h b/common/blindedpath.h index b84869351070..b0c96e0dd2cb 100644 --- a/common/blindedpath.h +++ b/common/blindedpath.h @@ -23,7 +23,7 @@ struct tlv_encrypted_data_tlv_payment_relay; * @next_path_privkey: (out) e(i+1), the next blinding secret (optional) * @node_alias: (out) the blinded pubkey of the node to tell the recipient. * - * You create a blinding secret using randombytes_buf(), then call this + * You create a blinding secret using randbytes(), then call this * iteratively for each node in the path. */ u8 *encrypt_tlv_encrypted_data(const tal_t *ctx, diff --git a/common/clock_time.c b/common/clock_time.c new file mode 100644 index 000000000000..e3a982d77e4f --- /dev/null +++ b/common/clock_time.c @@ -0,0 +1,36 @@ +#include "config.h" +#include +#include + +static bool used = false; +static struct timeabs dev_override; + +bool clock_time_overridden(void) +{ + return dev_override.ts.tv_sec != 0; +} + +struct timeabs clock_time(void) +{ + used = true; + if (!clock_time_overridden()) + return time_now(); /* discouraged: use clock_time so we can override */ + + return dev_override; +} + +struct timeabs clock_time_progresses_(u64 *progress) +{ + if (!clock_time_overridden()) + return clock_time(); + + return timeabs_add(dev_override, time_from_sec((*progress)++)); +} + +void dev_override_clock_time(struct timeabs now) +{ + assert(!used); + + dev_override = now; + assert(clock_time_overridden()); +} diff --git a/common/clock_time.h b/common/clock_time.h new file mode 100644 index 000000000000..a267abf461d9 --- /dev/null +++ b/common/clock_time.h @@ -0,0 +1,19 @@ +#ifndef LIGHTNING_COMMON_CLOCK_TIME_H +#define LIGHTNING_COMMON_CLOCK_TIME_H +#include "config.h" +#include +#include + +/* We use this instead of time_now, for overriding when we want reproducibility */ +struct timeabs clock_time(void); + +/* If you need a clock that progresses even when reproducible, use this. */ +#define clock_time_progresses() ({static u64 progress; clock_time_progresses_(&progress);}) +struct timeabs clock_time_progresses_(u64 *progress); + +/* dev setting to override time */ +void dev_override_clock_time(struct timeabs now); + +/* Did someone override time? */ +bool clock_time_overridden(void); +#endif /* LIGHTNING_COMMON_CLOCK_TIME_H */ diff --git a/common/coin_mvt.c b/common/coin_mvt.c index 4e9ec871e0a6..b15663aaaf17 100644 --- a/common/coin_mvt.c +++ b/common/coin_mvt.c @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include #include @@ -154,6 +154,12 @@ static enum mvt_tag mvt_tag_in_db(enum mvt_tag mvt_tag) abort(); } +/* This puts the coin movements in order */ +u64 coinmvt_current_time(void) +{ + return clock_time_progresses().ts.tv_sec; +} + const char *mvt_tag_str(enum mvt_tag tag) { assert((unsigned)tag < NUM_MVT_TAGS); @@ -337,7 +343,7 @@ static struct chain_coin_mvt *new_chain_coin_mvt_sat(const tal_t *ctx, assert(ok); return new_chain_coin_mvt(ctx, channel, account_name, - time_now().ts.tv_sec, tx_txid, + coinmvt_current_time(), tx_txid, outpoint, payment_hash, blockheight, tags, direction, amt_msat, /* All amounts that are sat are @@ -392,7 +398,7 @@ struct chain_coin_mvt *new_coin_channel_close(const tal_t *ctx, tags = mk_mvt_tags(MVT_CHANNEL_CLOSE); mvt = new_chain_coin_mvt(ctx, channel, alt_account, - time_now().ts.tv_sec, txid, + coinmvt_current_time(), txid, out, NULL, blockheight, tags, COIN_DEBIT, amount, @@ -420,7 +426,7 @@ struct chain_coin_mvt *new_coin_channel_open_proposed(const tal_t *ctx, if (is_leased) mvt_tag_set(&tags, MVT_LEASED); - mvt = new_chain_coin_mvt(ctx, channel, NULL, time_now().ts.tv_sec, + mvt = new_chain_coin_mvt(ctx, channel, NULL, coinmvt_current_time(), NULL, out, NULL, 0, tags, COIN_CREDIT, amount, output_val, 0); @@ -473,7 +479,7 @@ struct chain_coin_mvt *new_coin_channel_open(const tal_t *ctx, bool is_leased) { return new_coin_channel_open_general(ctx, channel, NULL, - time_now().ts.tv_sec, + coinmvt_current_time(), out, peer_id, blockheight, amount, output_val, is_opener, is_leased); } @@ -515,7 +521,7 @@ struct chain_coin_mvt *new_coin_external_spend(const tal_t *ctx, struct mvt_tags tags) { return new_chain_coin_mvt(ctx, NULL, ACCOUNT_NAME_EXTERNAL, - time_now().ts.tv_sec, txid, + coinmvt_current_time(), txid, outpoint, NULL, blockheight, tags, COIN_CREDIT, AMOUNT_MSAT(0), amount, 0); @@ -583,7 +589,7 @@ struct channel_coin_mvt *new_coin_channel_push(const tal_t *ctx, struct mvt_tags tags) { return new_coin_channel_push_general(ctx, channel, NULL, - time_now().ts.tv_sec, + coinmvt_current_time(), direction, amount, tags); } @@ -730,6 +736,10 @@ void fromwire_chain_coin_mvt(const u8 **cursor, size_t *max, struct chain_coin_m } else mvt->peer_id = NULL; mvt->timestamp = fromwire_u64(cursor, max); + + /* Align onchaind's timestamps with ours if we're deterministic */ + if (clock_time_overridden()) + mvt->timestamp = coinmvt_current_time(); } struct mvt_tags mk_mvt_tags_(enum mvt_tag tag, ...) diff --git a/common/coin_mvt.h b/common/coin_mvt.h index e9a41b3251cd..fb20f5aaaebe 100644 --- a/common/coin_mvt.h +++ b/common/coin_mvt.h @@ -348,4 +348,7 @@ bool mvt_tag_parse(const char *buf, size_t len, enum mvt_tag *tag); void towire_chain_coin_mvt(u8 **pptr, const struct chain_coin_mvt *mvt); void fromwire_chain_coin_mvt(const u8 **cursor, size_t *max, struct chain_coin_mvt *mvt); +/* Time helper for deterministic timestamps: always moves forwards */ +u64 coinmvt_current_time(void); + #endif /* LIGHTNING_COMMON_COIN_MVT_H */ diff --git a/common/configdir.c b/common/configdir.c index 248c8e73e010..0926c44fd569 100644 --- a/common/configdir.c +++ b/common/configdir.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -36,8 +37,7 @@ static char *opt_set_abspath(const char *arg, char **p) /* Tal wrappers for opt. */ static void *opt_allocfn(size_t size) { - return tal_arr_label(NULL, char, size, - TAL_LABEL(opt_allocfn_notleak, "")); + return notleak(tal_arr(NULL, char, size)); } static void *tal_reallocfn(void *ptr, size_t size) diff --git a/common/daemon.c b/common/daemon.c index c3adac2a0255..dc0a7b829398 100644 --- a/common/daemon.c +++ b/common/daemon.c @@ -5,8 +5,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -198,6 +200,7 @@ void daemon_shutdown(void) bool daemon_developer_mode(char *argv[]) { bool developer = false, debug = false; + const char *entropy_override, *time_override; for (int i = 1; argv[i]; i++) { if (streq(argv[i], "--dev-debug-self")) @@ -222,6 +225,21 @@ bool daemon_developer_mode(char *argv[]) kill(getpid(), SIGSTOP); } + /* We can override cryptographic randomness with this var in development + * mode, for reproducible results */ + entropy_override = getenv("CLN_DEV_ENTROPY_SEED"); + if (entropy_override) + dev_override_randbytes(argv[0], atol(entropy_override)); + + /* We can also control TIME ITSELF! */ + time_override = getenv("CLN_DEV_SET_TIME"); + if (time_override) { + struct timeabs t; + t.ts.tv_nsec = 0; + t.ts.tv_sec = atol(time_override); + dev_override_clock_time(t); + } + /* This checks for any tal_steal loops, but it's not free: * only use if we're already using the fairly heavy memleak * detection. */ diff --git a/common/memleak.c b/common/memleak.c index 7ac0da7c7bf3..de321a9a7c66 100644 --- a/common/memleak.c +++ b/common/memleak.c @@ -58,9 +58,6 @@ struct tal_backtrace { void *notleak_(void *ptr, bool plus_children) { const char *name; - /* If we're not tracking, don't do anything. */ - if (!memleak_track) - return cast_const(void *, ptr); /* We use special tal names to mark notleak */ name = tal_name(ptr); @@ -69,12 +66,14 @@ void *notleak_(void *ptr, bool plus_children) /* Don't mark more than once! */ if (!strstr(name, "**NOTLEAK")) { + /* Don't use tmpctx: it might not be set up yet! */ if (plus_children) - name = tal_fmt(tmpctx, "%s **NOTLEAK_IGNORE_CHILDREN**", + name = tal_fmt(NULL, "%s **NOTLEAK_IGNORE_CHILDREN**", name); else - name = tal_fmt(tmpctx, "%s **NOTLEAK**", name); + name = tal_fmt(NULL, "%s **NOTLEAK**", name); tal_set_name(ptr, name); + tal_free(name); } return cast_const(void *, ptr); @@ -331,8 +330,7 @@ static void call_memleak_helpers(struct htable *memtable, const tal_t *p) if (strends(name, "struct memleak_helper")) { const struct memleak_helper *mh = i; mh->cb(memtable, p); - } else if (strends(name, " **NOTLEAK**") - || strends(name, "_notleak")) { + } else if (strends(name, " **NOTLEAK**")) { memleak_ptr(memtable, i); memleak_scan_obj(memtable, i); } else if (strends(name, diff --git a/common/memleak.h b/common/memleak.h index a15413b23f34..b9782e651ceb 100644 --- a/common/memleak.h +++ b/common/memleak.h @@ -109,6 +109,18 @@ void memleak_scan_region(struct htable *memtable, const void *p, size_t len); /* Objects inside this htable (which is opaque to memleak) are not leaks. */ void memleak_scan_htable(struct htable *memtable, const struct htable *ht); +/* Allocate a htable, set up memleak scan automatically (assumes &p->raw == p) */ +#define new_htable(ctx, type) \ + ({ \ + const struct htable *raw; \ + struct type *p = tal(ctx, struct type); \ + type##_init(p); \ + raw = &p->raw; \ + assert((void *)raw == (void *)p); \ + memleak_add_helper(raw, memleak_scan_htable); \ + p; \ + }) + /* Objects inside this uintmap (which is opaque to memleak) are not leaks. */ #define memleak_scan_uintmap(memtable, umap) \ memleak_scan_intmap_(memtable, uintmap_unwrap_(umap)) diff --git a/common/onion_message.c b/common/onion_message.c index c781866ee78c..e673538f5af6 100644 --- a/common/onion_message.c +++ b/common/onion_message.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -68,7 +69,7 @@ struct blinded_path *blinded_path_from_encdata_tlvs(const tal_t *ctx, assert(nhops > 0); assert(tal_count(ids) > 0); - randombytes_buf(&first_blinding, sizeof(first_blinding)); + randbytes(&first_blinding, sizeof(first_blinding)); if (!pubkey_from_privkey(&first_blinding, &path->first_path_key)) abort(); sciddir_or_pubkey_from_pubkey(&path->first_node_id, &ids[0]); diff --git a/common/pseudorand.c b/common/pseudorand.c index 831be2bb584b..050906605225 100644 --- a/common/pseudorand.c +++ b/common/pseudorand.c @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include static struct isaac64_ctx isaac64; @@ -19,7 +19,7 @@ static void init_if_needed(void) unsigned char seedbuf[16]; struct sha256 sha; - randombytes_buf(seedbuf, sizeof(seedbuf)); + randbytes(seedbuf, sizeof(seedbuf)); memcpy(&siphashseed, seedbuf, sizeof(siphashseed)); /* In case isaac is reversible, don't leak seed. */ @@ -29,25 +29,42 @@ static void init_if_needed(void) } } -uint64_t pseudorand(uint64_t max) +uint64_t pseudorand_(uint64_t max, uint64_t *offset) { init_if_needed(); assert(max); + + /* We try to avoid being order-dependent here. */ + if (randbytes_overridden()) { + uint64_t rand; + randbytes_(&rand, sizeof(rand), offset); + return rand % max; + } return isaac64_next_uint(&isaac64, max); } -uint64_t pseudorand_u64(void) +uint64_t pseudorand_u64_(uint64_t *offset) { init_if_needed(); + if (randbytes_overridden()) { + uint64_t rand; + randbytes_(&rand, sizeof(rand), offset); + return rand; + } return isaac64_next_uint64(&isaac64); } -double pseudorand_double(void) +double pseudorand_double_(uint64_t *offset) { init_if_needed(); + if (randbytes_overridden()) { + uint64_t rand; + randbytes_(&rand, sizeof(rand), offset); + return rand / (double)UINT64_MAX; + } return isaac64_next_double(&isaac64); } diff --git a/common/pseudorand.h b/common/pseudorand.h index a34220055560..e0303eaf094b 100644 --- a/common/pseudorand.h +++ b/common/pseudorand.h @@ -7,18 +7,21 @@ /** * pseudorand - pseudo (guessable!) random number between 0 and max-1. */ -uint64_t pseudorand(uint64_t max); +#define pseudorand(max) ({static uint64_t offset; pseudorand_((max), &offset);}) +uint64_t pseudorand_(uint64_t max, uint64_t *offset); /** - * pseudorand - pseudo (guessable!) random number between 0 and UINT64_MAX. + * pseudorand_u64 - pseudo (guessable!) random number between 0 and UINT64_MAX. */ -uint64_t pseudorand_u64(void); +#define pseudorand_u64() ({static uint64_t offset; pseudorand_u64_(&offset);}) +uint64_t pseudorand_u64_(uint64_t *offset); /** * pseudorand - pseudo (guessable!) random number between 0 (inclusive) and 1 * (exclusive). */ -double pseudorand_double(void); +#define pseudorand_double() ({static uint64_t offset; pseudorand_double_(&offset);}) +double pseudorand_double_(uint64_t *offset); /** * Get the siphash seed for hash tables. diff --git a/common/randbytes.c b/common/randbytes.c new file mode 100644 index 000000000000..fd38cdf7009f --- /dev/null +++ b/common/randbytes.c @@ -0,0 +1,64 @@ +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static bool used = false; +static u64 dev_seed = 0; + +bool randbytes_overridden(void) +{ + return dev_seed != 0; +} + +void randbytes_(void *bytes, size_t num_bytes, u64 *offset) +{ + static u64 offset_init; + be64 pattern; + + used = true; + if (!randbytes_overridden()) { + randombytes_buf(bytes, num_bytes); /* discouraged: use randbytes() */ + return; + } + + /* First time, start callers at different offsets */ + if (*offset == 0) { + *offset = offset_init; + offset_init += 1000; + } + + /* Somewhat recognizable pattern */ + pattern = cpu_to_be64(dev_seed + (*offset)++); + for (size_t i = 0; i < num_bytes; i += sizeof(pattern)) { + size_t copy = num_bytes - i; + if (copy > sizeof(pattern)) + copy = sizeof(pattern); + + memcpy((u8 *)bytes + i, &pattern, copy); + } +} + +/* We want different seeds for each plugin (hence argv0), and for each + * lightmingd instance, (hence seed from environment) */ +void dev_override_randbytes(const char *argv0, long int seed) +{ + struct siphash_seed hashseed; + assert(!used); + + hashseed.u.u64[0] = seed; + hashseed.u.u64[1] = 0; + + dev_seed = siphash24(&hashseed, argv0, strlen(argv0)); + assert(randbytes_overridden()); +} diff --git a/common/randbytes.h b/common/randbytes.h new file mode 100644 index 000000000000..18aa485eecf3 --- /dev/null +++ b/common/randbytes.h @@ -0,0 +1,20 @@ +#ifndef LIGHTNING_COMMON_RANDBYTES_H +#define LIGHTNING_COMMON_RANDBYTES_H +#include "config.h" +#include +#include +#include + +/* Usually the libsodium routine randombytes_buf, but dev options can make this deterministic */ +#define randbytes(bytes, num_bytes) \ + do { \ + static u64 offset; \ + randbytes_((bytes), (num_bytes), &offset); \ + } while(0) + +void randbytes_(void *bytes, size_t num_bytes, u64 *offset); + +void dev_override_randbytes(const char *argv0, long int seed); + +bool randbytes_overridden(void); +#endif /* LIGHTNING_COMMON_RANDBYTES_H */ diff --git a/common/sphinx.c b/common/sphinx.c index c254e63170bc..39a2c47bc598 100644 --- a/common/sphinx.c +++ b/common/sphinx.c @@ -6,13 +6,13 @@ #include #include #include +#include #include #include #include -#include #define BLINDING_FACTOR_SIZE 32 @@ -567,7 +567,7 @@ struct onionpacket *create_onionpacket( if (sp->session_key == NULL) { sp->session_key = tal(sp, struct secret); - randombytes_buf(sp->session_key, sizeof(struct secret)); + randbytes(sp->session_key, sizeof(struct secret)); } params = generate_hop_params(ctx, sp->session_key->data, sp); diff --git a/common/test/Makefile b/common/test/Makefile index 75331d62e6dc..8c26954a206b 100644 --- a/common/test/Makefile +++ b/common/test/Makefile @@ -5,11 +5,14 @@ COMMON_TEST_PROGRAMS := $(COMMON_TEST_OBJS:.o=) COMMON_TEST_COMMON_OBJS := \ common/autodata.o \ + common/memleak.o \ + common/randbytes.o \ + common/clock_time.o \ common/setup.o \ common/utils.o $(COMMON_TEST_PROGRAMS): $(COMMON_TEST_COMMON_OBJS) $(BITCOIN_OBJS) -$(COMMON_TEST_OBJS): $(COMMON_HEADERS) $(WIRE_HEADERS) $(COMMON_SRC) +$(COMMON_TEST_OBJS): $(COMMON_HEADERS) $(WIRE_HEADERS) $(COMMON_SRC) common/test/Makefile ALL_C_SOURCES += $(COMMON_TEST_SRC) ALL_TEST_PROGRAMS += $(COMMON_TEST_PROGRAMS) @@ -31,6 +34,7 @@ common/test/run-json: \ common/lease_rates.o \ common/node_id.o \ common/pseudorand.o \ + common/randbytes.o \ common/wireaddr.o \ wire/fromwire.o \ wire/onion_wiregen.o \ @@ -44,6 +48,7 @@ common/test/run-route common/test/run-route-specific common/test/run-route-inflo common/gossmap.o \ common/node_id.o \ common/pseudorand.o \ + common/randbytes.o \ common/route.o \ gossipd/gossip_store_wiregen.o \ wire/fromwire.o \ @@ -117,13 +122,14 @@ common/test/run-splice_script: \ common/test/run-trace: \ common/amount.o \ - common/memleak.o \ common/pseudorand.o \ + common/randbytes.o \ common/trace.o \ wire/fromwire.o \ wire/towire.o common/test/run-htable: \ + common/randbytes.o \ common/pseudorand.o common/test/run-shutdown_scriptpubkey: wire/towire.o wire/fromwire.o diff --git a/common/test/run-amount.c b/common/test/run-amount.c index 0e9f295dc0c2..f76484ef3436 100644 --- a/common/test/run-amount.c +++ b/common/test/run-amount.c @@ -1,5 +1,6 @@ #include "config.h" #include "../amount.c" +#include #include #include diff --git a/common/test/run-base64.c b/common/test/run-base64.c index c36c08bb3fc3..e71371c9873b 100644 --- a/common/test/run-base64.c +++ b/common/test/run-base64.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include diff --git a/common/test/run-bigsize.c b/common/test/run-bigsize.c index 9b181261e6c6..d11ad50ab0c5 100644 --- a/common/test/run-bigsize.c +++ b/common/test/run-bigsize.c @@ -4,6 +4,7 @@ #include #include #include +#include #include static const char *reason; diff --git a/common/test/run-blindedpath_enctlv.c b/common/test/run-blindedpath_enctlv.c index c9408cba2dd5..d2552ad4e727 100644 --- a/common/test/run-blindedpath_enctlv.c +++ b/common/test/run-blindedpath_enctlv.c @@ -3,6 +3,7 @@ #include "../blinding.c" #include "../hmac.c" #include +#include #include #include diff --git a/common/test/run-bolt11.c b/common/test/run-bolt11.c index e4fbbd797cbd..3cc516a35a6a 100644 --- a/common/test/run-bolt11.c +++ b/common/test/run-bolt11.c @@ -6,10 +6,10 @@ #include "../features.c" #include "../node_id.c" #include "../hash_u5.c" -#include "../memleak.c" #include "../wire/fromwire.c" #include "../wire/towire.c" #include +#include #include /* AUTOGENERATED MOCKS START */ diff --git a/common/test/run-bolt12-encode-test.c b/common/test/run-bolt12-encode-test.c index e7de25fdd381..5ca641f93012 100644 --- a/common/test/run-bolt12-encode-test.c +++ b/common/test/run-bolt12-encode-test.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include diff --git a/common/test/run-bolt12-format-string-test.c b/common/test/run-bolt12-format-string-test.c index dc8384750a09..d38bd6ed6210 100644 --- a/common/test/run-bolt12-format-string-test.c +++ b/common/test/run-bolt12-format-string-test.c @@ -8,6 +8,7 @@ #include #include #include +#include #include /* AUTOGENERATED MOCKS START */ diff --git a/common/test/run-bolt12-offer-decode.c b/common/test/run-bolt12-offer-decode.c index 5296e8fd6c22..d15f24338ab5 100644 --- a/common/test/run-bolt12-offer-decode.c +++ b/common/test/run-bolt12-offer-decode.c @@ -14,6 +14,7 @@ #include #include #include +#include #include /* AUTOGENERATED MOCKS START */ diff --git a/common/test/run-bolt12_decode.c b/common/test/run-bolt12_decode.c index 4702d23f251c..ce80438f2c0a 100644 --- a/common/test/run-bolt12_decode.c +++ b/common/test/run-bolt12_decode.c @@ -7,6 +7,7 @@ #include #include #include +#include #include /* AUTOGENERATED MOCKS START */ diff --git a/common/test/run-bolt12_merkle-json.c b/common/test/run-bolt12_merkle-json.c index 4c0910d3f57f..1cd8e8bcdf93 100644 --- a/common/test/run-bolt12_merkle-json.c +++ b/common/test/run-bolt12_merkle-json.c @@ -11,6 +11,7 @@ #include #include #include +#include #include /* AUTOGENERATED MOCKS START */ diff --git a/common/test/run-bolt12_merkle.c b/common/test/run-bolt12_merkle.c index 43265ef4d74f..4d2f0bc6d639 100644 --- a/common/test/run-bolt12_merkle.c +++ b/common/test/run-bolt12_merkle.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include diff --git a/common/test/run-bolt12_period.c b/common/test/run-bolt12_period.c index 514e47fe734f..1fad5d142007 100644 --- a/common/test/run-bolt12_period.c +++ b/common/test/run-bolt12_period.c @@ -5,6 +5,7 @@ #include #include #include +#include #include /* AUTOGENERATED MOCKS START */ diff --git a/common/test/run-channel_type.c b/common/test/run-channel_type.c index 46edef12b3ee..2cac84ac8f41 100644 --- a/common/test/run-channel_type.c +++ b/common/test/run-channel_type.c @@ -2,6 +2,7 @@ #include "../channel_type.c" #include "../features.c" #include +#include #include #include #include diff --git a/common/test/run-codex32.c b/common/test/run-codex32.c index 2aed32315799..24929672c643 100644 --- a/common/test/run-codex32.c +++ b/common/test/run-codex32.c @@ -8,6 +8,7 @@ #include #include #include +#include #include /* AUTOGENERATED MOCKS START */ diff --git a/common/test/run-coin_mvt.c b/common/test/run-coin_mvt.c index e7512c089b55..99651ccbb54e 100644 --- a/common/test/run-coin_mvt.c +++ b/common/test/run-coin_mvt.c @@ -1,6 +1,7 @@ #include "config.h" #include "../coin_mvt.c" #include +#include #include #include diff --git a/common/test/run-cryptomsg.c b/common/test/run-cryptomsg.c index 42fa16e89c1b..e3218eb0b863 100644 --- a/common/test/run-cryptomsg.c +++ b/common/test/run-cryptomsg.c @@ -1,5 +1,6 @@ #include "config.h" #include +#include #include #include #include diff --git a/common/test/run-deprecation.c b/common/test/run-deprecation.c index fe1a4cd0579c..fa1378c8648b 100644 --- a/common/test/run-deprecation.c +++ b/common/test/run-deprecation.c @@ -6,6 +6,7 @@ static const char *test_next_version; #include "../deprecation.c" #include +#include #include #include #include diff --git a/common/test/run-derive_basepoints.c b/common/test/run-derive_basepoints.c index 861a65d63531..cb896ad7795a 100644 --- a/common/test/run-derive_basepoints.c +++ b/common/test/run-derive_basepoints.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include diff --git a/common/test/run-features.c b/common/test/run-features.c index e6936d5a8be8..ef38a0cfc353 100644 --- a/common/test/run-features.c +++ b/common/test/run-features.c @@ -1,8 +1,9 @@ #include "config.h" #include "../features.c" -#include "../memleak.c" #include +#include #include +#include /* AUTOGENERATED MOCKS START */ /* Generated stub for amount_asset_is_main */ diff --git a/common/test/run-gossmap-fp16.c b/common/test/run-gossmap-fp16.c index 274eccf3a3fd..539b129b5293 100644 --- a/common/test/run-gossmap-fp16.c +++ b/common/test/run-gossmap-fp16.c @@ -1,5 +1,6 @@ #include "config.h" #include "../fp16.c" +#include #include #include #include diff --git a/common/test/run-htable.c b/common/test/run-htable.c index 64ac0b568555..267ad8c03f10 100644 --- a/common/test/run-htable.c +++ b/common/test/run-htable.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include diff --git a/common/test/run-ip_port_parsing.c b/common/test/run-ip_port_parsing.c index 026a06f8f5d4..c7c5ba226530 100644 --- a/common/test/run-ip_port_parsing.c +++ b/common/test/run-ip_port_parsing.c @@ -4,6 +4,7 @@ #include #include +#include #include /* AUTOGENERATED MOCKS START */ diff --git a/common/test/run-json.c b/common/test/run-json.c index b5fdecdb3c64..10733adaedbb 100644 --- a/common/test/run-json.c +++ b/common/test/run-json.c @@ -4,7 +4,9 @@ #include #include #include +#include #include +#include #include #include #include diff --git a/common/test/run-json_filter.c b/common/test/run-json_filter.c index 54138cbe6999..d682b82130b3 100644 --- a/common/test/run-json_filter.c +++ b/common/test/run-json_filter.c @@ -6,6 +6,7 @@ #include "../json_stream.c" #include #include +#include #include #include diff --git a/common/test/run-json_remove.c b/common/test/run-json_remove.c index f1c16a28cbe4..8a15653ebfae 100644 --- a/common/test/run-json_remove.c +++ b/common/test/run-json_remove.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include diff --git a/common/test/run-json_scan.c b/common/test/run-json_scan.c index a80dad990606..40ddb9bd4541 100644 --- a/common/test/run-json_scan.c +++ b/common/test/run-json_scan.c @@ -2,6 +2,7 @@ #include "../json_parse.c" #include "../json_parse_simple.c" #include +#include #include #include diff --git a/common/test/run-json_stream-filter.c b/common/test/run-json_stream-filter.c index 1e484b475868..6f6fe060f834 100644 --- a/common/test/run-json_stream-filter.c +++ b/common/test/run-json_stream-filter.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include diff --git a/common/test/run-key_derive.c b/common/test/run-key_derive.c index f30fcdfb2e18..6b158f74413d 100644 --- a/common/test/run-key_derive.c +++ b/common/test/run-key_derive.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include diff --git a/common/test/run-lease_rates.c b/common/test/run-lease_rates.c index 31da81c7d317..f995eb88c2f6 100644 --- a/common/test/run-lease_rates.c +++ b/common/test/run-lease_rates.c @@ -1,6 +1,7 @@ #include "config.h" #include "../amount.c" #include "../lease_rates.c" +#include #include #include diff --git a/common/test/run-marginal_feerate.c b/common/test/run-marginal_feerate.c index e0514cfdd83f..097852ceabc8 100644 --- a/common/test/run-marginal_feerate.c +++ b/common/test/run-marginal_feerate.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include "../fee_states.c" diff --git a/common/test/run-param.c b/common/test/run-param.c index 3cb94bf854c7..ddb5cab1e6a2 100644 --- a/common/test/run-param.c +++ b/common/test/run-param.c @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include diff --git a/common/test/run-psbt_diff.c b/common/test/run-psbt_diff.c index 6d355697792d..1c107851ac66 100644 --- a/common/test/run-psbt_diff.c +++ b/common/test/run-psbt_diff.c @@ -1,4 +1,5 @@ #include "config.h" +#include #include #include #include "../amount.c" @@ -37,9 +38,9 @@ u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) /* Generated stub for fromwire_u8_array */ void fromwire_u8_array(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, u8 *arr UNNEEDED, size_t num UNNEEDED) { fprintf(stderr, "fromwire_u8_array called!\n"); abort(); } -/* Generated stub for pseudorand_u64 */ -uint64_t pseudorand_u64(void) -{ fprintf(stderr, "pseudorand_u64 called!\n"); abort(); } +/* Generated stub for pseudorand_u64_ */ +uint64_t pseudorand_u64_(uint64_t *offset UNNEEDED) +{ fprintf(stderr, "pseudorand_u64_ called!\n"); abort(); } /* Generated stub for towire */ void towire(u8 **pptr UNNEEDED, const void *data UNNEEDED, size_t len UNNEEDED) { fprintf(stderr, "towire called!\n"); abort(); } diff --git a/common/test/run-route-infloop.c b/common/test/run-route-infloop.c index c2e532fe5191..7556fd2f93af 100644 --- a/common/test/run-route-infloop.c +++ b/common/test/run-route-infloop.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include diff --git a/common/test/run-route-specific.c b/common/test/run-route-specific.c index d661d85b488a..fef067c7cc13 100644 --- a/common/test/run-route-specific.c +++ b/common/test/run-route-specific.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include diff --git a/common/test/run-route.c b/common/test/run-route.c index 9175bbac760c..0c63a8f50c33 100644 --- a/common/test/run-route.c +++ b/common/test/run-route.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include diff --git a/common/test/run-route_blinding_test.c b/common/test/run-route_blinding_test.c index 3358319dfae3..2b3ef812f77e 100644 --- a/common/test/run-route_blinding_test.c +++ b/common/test/run-route_blinding_test.c @@ -10,8 +10,10 @@ #include #include #include +#include #include #include +#include #include #include #include diff --git a/common/test/run-shutdown_scriptpubkey.c b/common/test/run-shutdown_scriptpubkey.c index db543a9d8d60..c98610d28277 100644 --- a/common/test/run-shutdown_scriptpubkey.c +++ b/common/test/run-shutdown_scriptpubkey.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include diff --git a/common/test/run-splice_script.c b/common/test/run-splice_script.c index c3bd63fcb2fc..082f46ceab49 100644 --- a/common/test/run-splice_script.c +++ b/common/test/run-splice_script.c @@ -6,6 +6,7 @@ #include "../json_stream.c" #include "../json_parse_simple.c" #include +#include #include #include #include diff --git a/common/test/run-tlv_span.c b/common/test/run-tlv_span.c index 4055ec9bcaae..eb3ede4b6cb4 100644 --- a/common/test/run-tlv_span.c +++ b/common/test/run-tlv_span.c @@ -2,6 +2,7 @@ #include "../bolt12.c" #include "../bigsize.c" #include "../../wire/fromwire.c" +#include #include #include diff --git a/common/test/run-tlv_unknown.c b/common/test/run-tlv_unknown.c index fdecc469965d..071b10432e1d 100644 --- a/common/test/run-tlv_unknown.c +++ b/common/test/run-tlv_unknown.c @@ -5,6 +5,7 @@ #include "../../wire/towire.c" #include "../bigsize.c" #include "../bolt12.c" +#include #include #include diff --git a/common/test/run-version.c b/common/test/run-version.c index 0e04b4cb061a..3b46f56e2289 100644 --- a/common/test/run-version.c +++ b/common/test/run-version.c @@ -1,9 +1,13 @@ #include "config.h" #include "../version.c" +#include #include #include #include +/* AUTOGENERATED MOCKS START */ +/* AUTOGENERATED MOCKS END */ + int main(int argc, char *argv[]) { common_setup(argv[0]); diff --git a/common/test/run-wireaddr.c b/common/test/run-wireaddr.c index 6d3bd76f232c..3ca99163d718 100644 --- a/common/test/run-wireaddr.c +++ b/common/test/run-wireaddr.c @@ -1,6 +1,7 @@ #include "config.h" #include #include +#include #include #include diff --git a/common/trace.c b/common/trace.c index eade3171f790..1be745bed474 100644 --- a/common/trace.c +++ b/common/trace.c @@ -77,7 +77,7 @@ static void init_span(struct span *s, const char *name, struct span *parent) { - struct timeabs now = time_now(); + struct timeabs now = time_now(); /* discouraged: but tracing wants non-dev time */ s->key = key; s->id = pseudorand_u64(); @@ -184,15 +184,11 @@ static inline void trace_check_tree(void) {} static void trace_init(void) { const char *dev_trace_file; - const char notleak_name[] = "struct span **NOTLEAK**"; if (active_spans) return; - active_spans = tal_arrz(NULL, struct span, 1); - /* We're usually too early for memleak to be initialized, so mark - * this notleak manually! */ - tal_set_name(active_spans, notleak_name); + active_spans = notleak(tal_arrz(NULL, struct span, 1)); current = NULL; dev_trace_file = getenv("CLN_DEV_TRACE_FILE"); @@ -372,7 +368,7 @@ void trace_span_end(const void *key) trace_check_tree(); - struct timeabs now = time_now(); + struct timeabs now = time_now(); /* discouraged: but tracing wants non-dev time */ s->end_time = (now.ts.tv_sec * 1000000) + now.ts.tv_nsec / 1000; DTRACE_PROBE1(lightningd, span_end, s->id); if (trace_to_file) { diff --git a/connectd/Makefile b/connectd/Makefile index 781172e186de..0300e27623ee 100644 --- a/connectd/Makefile +++ b/connectd/Makefile @@ -48,6 +48,7 @@ CONNECTD_COMMON_OBJS := \ common/blinding.o \ common/blindedpath.o \ common/channel_id.o \ + common/clock_time.o \ common/cryptomsg.o \ common/daemon.o \ common/daemon_conn.o \ @@ -72,6 +73,7 @@ CONNECTD_COMMON_OBJS := \ common/per_peer_state.o \ common/psbt_open.o \ common/pseudorand.o \ + common/randbytes.o \ common/sciddir_or_pubkey.o \ common/setup.o \ common/sphinx.o \ diff --git a/connectd/connectd.c b/connectd/connectd.c index de841c3ff3c1..15224912419d 100644 --- a/connectd/connectd.c +++ b/connectd/connectd.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -26,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -149,7 +151,7 @@ static struct peer *new_peer(struct daemon *daemon, peer->draining = false; peer->peer_in_lastmsg = -1; peer->peer_outq = msg_queue_new(peer, false); - peer->last_recv_time = time_now(); + peer->last_recv_time = time_mono(); peer->is_websocket = is_websocket; peer->dev_writes_enabled = NULL; peer->dev_read_enabled = true; @@ -1498,7 +1500,7 @@ setup_listeners(const tal_t *ctx, if (sodium_mlock(&random, sizeof(random)) != 0) status_failed(STATUS_FAIL_INTERNAL_ERROR, "Could not lock the random prf key memory."); - randombytes_buf((void * const)&random, 32); + randbytes((void * const)&random, 32); /* generate static tor node address, take first 32 bytes from secret of node_id plus 32 random bytes from sodiom */ struct sha256 sha; struct secret ss; @@ -1523,7 +1525,7 @@ setup_listeners(const tal_t *ctx, localaddr, 0); /* get rid of blob data on our side of tor and add jitter */ - randombytes_buf((void * const)proposed_wireaddr[i].u.torservice.blob, TOR_V3_BLOBLEN); + randbytes((void * const)proposed_wireaddr[i].u.torservice.blob, TOR_V3_BLOBLEN); if (!(proposed_listen_announce[i] & ADDR_ANNOUNCE)) { continue; @@ -2004,9 +2006,6 @@ static void dev_connect_memleak(struct daemon *daemon, const u8 *msg) /* Now delete daemon and those which it has pointers to. */ memleak_scan_obj(memtable, daemon); - memleak_scan_htable(memtable, &daemon->peers->raw); - memleak_scan_htable(memtable, &daemon->scid_htable->raw); - memleak_scan_htable(memtable, &daemon->important_ids->raw); found_leak = dump_memleak(memtable, memleak_status_broken, NULL); daemon_conn_send(daemon->master, @@ -2194,7 +2193,7 @@ static void dev_report_fds(struct daemon *daemon, const u8 *msg) void update_recent_timestamp(struct daemon *daemon, struct gossmap *gossmap) { /* 2 hours allows for some clock drift, not too much gossip */ - u32 recent = time_now().ts.tv_sec - 7200; + u32 recent = clock_time().ts.tv_sec - 7200; /* Only update every minute */ if (daemon->gossip_recent_time + 60 > recent) @@ -2419,14 +2418,6 @@ static struct io_plan *recv_gossip(struct io_conn *conn, return daemon_conn_read_next(conn, daemon->gossipd); } -/*~ This is a hook used by the memleak code: it can't see pointers - * inside hash tables, so we give it a hint here. */ -static void memleak_daemon_cb(struct htable *memtable, struct daemon *daemon) -{ - memleak_scan_htable(memtable, &daemon->peers->raw); - memleak_scan_htable(memtable, &daemon->connecting->raw); -} - static void gossipd_failed(struct daemon_conn *gossipd) { status_failed(STATUS_FAIL_GOSSIP_IO, "gossipd exited?"); @@ -2446,14 +2437,13 @@ int main(int argc, char *argv[]) daemon = tal(NULL, struct daemon); daemon->developer = developer; daemon->connection_counter = 1; - daemon->peers = tal(daemon, struct peer_htable); + /* htable_new is our helper which allocates a htable, initializes it + * and set up the memleak callback so our memleak code can see objects + * inside it */ + daemon->peers = new_htable(daemon, peer_htable); daemon->listeners = tal_arr(daemon, struct io_listener *, 0); - peer_htable_init(daemon->peers); - memleak_add_helper(daemon, memleak_daemon_cb); - daemon->connecting = tal(daemon, struct connecting_htable); - connecting_htable_init(daemon->connecting); - daemon->important_ids = tal(daemon, struct important_id_htable); - important_id_htable_init(daemon->important_ids); + daemon->connecting = new_htable(daemon, connecting_htable); + daemon->important_ids = new_htable(daemon, important_id_htable); timers_init(&daemon->timers, time_mono()); daemon->gossmap_raw = NULL; daemon->shutting_down = false; @@ -2463,8 +2453,7 @@ int main(int argc, char *argv[]) daemon->dev_exhausted_fds = false; /* We generally allow 1MB per second per peer, except for dev testing */ daemon->gossip_stream_limit = 1000000; - daemon->scid_htable = tal(daemon, struct scid_htable); - scid_htable_init(daemon->scid_htable); + daemon->scid_htable = new_htable(daemon, scid_htable); /* stdin == control */ daemon->master = daemon_conn_new(daemon, STDIN_FILENO, recv_req, NULL, diff --git a/connectd/connectd.h b/connectd/connectd.h index d3fb0c33abf7..752443f7f591 100644 --- a/connectd/connectd.h +++ b/connectd/connectd.h @@ -95,7 +95,7 @@ struct peer { struct oneshot *ping_timer; /* Last time we received traffic */ - struct timeabs last_recv_time; + struct timemono last_recv_time; /* How long have we been ignoring peer input? */ struct timemono peer_in_lasttime; diff --git a/connectd/handshake.c b/connectd/handshake.c index 3a11dead0ec0..ad388a62182c 100644 --- a/connectd/handshake.c +++ b/connectd/handshake.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -14,7 +15,6 @@ #include #include #include -#include #ifndef SUPERVERBOSE #define SUPERVERBOSE(...) @@ -194,7 +194,7 @@ static struct keypair generate_key(void) struct keypair k; do { - randombytes_buf(k.priv.secret.data, sizeof(k.priv.secret.data)); + randbytes(k.priv.secret.data, sizeof(k.priv.secret.data)); } while (!secp256k1_ec_pubkey_create(secp256k1_ctx, &k.pub.pubkey, k.priv.secret.data)); return k; diff --git a/connectd/multiplex.c b/connectd/multiplex.c index d7cbf80e2b59..643c34fbfdf1 100644 --- a/connectd/multiplex.c +++ b/connectd/multiplex.c @@ -646,8 +646,8 @@ static void send_ping(struct peer *peer) /* If it's still sending us traffic, maybe ping reply is backed up? * That's OK, ping is just to make sure it's still alive, and clearly * it is. */ - if (time_before(peer->last_recv_time, - timeabs_sub(time_now(), time_from_sec(60)))) { + if (timemono_before(peer->last_recv_time, + timemono_sub(time_mono(), time_from_sec(60)))) { /* Already have a ping in flight? */ if (peer->expecting_pong != PONG_UNEXPECTED) { status_peer_debug(&peer->id, "Last ping unreturned: hanging up"); @@ -1260,7 +1260,7 @@ static struct io_plan *read_body_from_peer_done(struct io_conn *peer_conn, } /* We got something! */ - peer->last_recv_time = time_now(); + peer->last_recv_time = time_mono(); /* Don't process packets while we're closing */ if (peer->draining) diff --git a/connectd/test/Makefile b/connectd/test/Makefile index c624f32190c2..2569e8c96c3a 100644 --- a/connectd/test/Makefile +++ b/connectd/test/Makefile @@ -8,6 +8,7 @@ CONNECTD_TEST_COMMON_OBJS := \ common/autodata.o \ common/features.o \ common/pseudorand.o \ + common/randbytes.o \ common/setup.o \ common/utils.o diff --git a/connectd/test/run-crc32_of_update.c b/connectd/test/run-crc32_of_update.c index efcaaf4792d7..ca5cd84df387 100644 --- a/connectd/test/run-crc32_of_update.c +++ b/connectd/test/run-crc32_of_update.c @@ -7,6 +7,7 @@ int unused_main(int argc, char *argv[]); #include #include #include +#include #include #include #include diff --git a/connectd/test/run-initiator-success.c b/connectd/test/run-initiator-success.c index 26aeb40cceff..f9a45fc73847 100644 --- a/connectd/test/run-initiator-success.c +++ b/connectd/test/run-initiator-success.c @@ -114,10 +114,10 @@ void towire_u8_array(u8 **pptr UNNEEDED, const u8 *arr UNNEEDED, size_t num UNNE /* AUTOGENERATED MOCKS END */ /* No randomness please, we want to replicate test vectors. */ -#include +#include -static void seed_randomness(u8 *secret, size_t len); -#define randombytes_buf(secret, len) seed_randomness((secret), (len)) +static void seed_randomness(u8 *secret, size_t len, u64 *offset); +#define randbytes_(secret, len, offset) seed_randomness((secret), (len), (offset)) struct handshake; static struct io_plan *test_write(struct io_conn *conn, @@ -188,7 +188,7 @@ const void *trc; static struct pubkey rs_pub, ls_pub, e_pub; static struct privkey ls_priv, e_priv; -static void seed_randomness(u8 *secret, size_t len) +static void seed_randomness(u8 *secret, size_t len, u64 *offset) { assert(len == sizeof(e_priv)); memcpy(secret, &e_priv, len); diff --git a/connectd/test/run-netaddress.c b/connectd/test/run-netaddress.c index c69ed2510325..4fee8f6a3f75 100644 --- a/connectd/test/run-netaddress.c +++ b/connectd/test/run-netaddress.c @@ -1,6 +1,7 @@ #include "config.h" #include #include +#include #include #include #include diff --git a/connectd/test/run-responder-success.c b/connectd/test/run-responder-success.c index ed1dfb175e35..e349a9a5ae6e 100644 --- a/connectd/test/run-responder-success.c +++ b/connectd/test/run-responder-success.c @@ -114,10 +114,10 @@ void towire_u8_array(u8 **pptr UNNEEDED, const u8 *arr UNNEEDED, size_t num UNNE /* AUTOGENERATED MOCKS END */ /* No randomness please, we want to replicate test vectors. */ -#include +#include -static void seed_randomness(u8 *secret, size_t len); -#define randombytes_buf(secret, len) seed_randomness((secret), (len)) +static void seed_randomness(u8 *secret, size_t len, u64 *offset); +#define randbytes_(secret, len, offset) seed_randomness((secret), (len), (offset)) struct handshake; static struct io_plan *test_write(struct io_conn *conn, @@ -187,7 +187,7 @@ extern secp256k1_context *secp256k1_ctx; static struct pubkey ls_pub, e_pub; static struct privkey ls_priv, e_priv; -static void seed_randomness(u8 *secret, size_t len) +static void seed_randomness(u8 *secret, size_t len, u64 *offset) { assert(len == sizeof(e_priv)); memcpy(secret, &e_priv, len); diff --git a/connectd/test/run-websocket.c b/connectd/test/run-websocket.c index 25f126e927d2..393534b036a1 100644 --- a/connectd/test/run-websocket.c +++ b/connectd/test/run-websocket.c @@ -1,6 +1,7 @@ #include "config.h" #include #include +#include #include #include #include diff --git a/contrib/msggen/msggen/schema.json b/contrib/msggen/msggen/schema.json index 69c33acf4aa8..0ead982d8a9a 100644 --- a/contrib/msggen/msggen/schema.json +++ b/contrib/msggen/msggen/schema.json @@ -16749,6 +16749,359 @@ ], "resources": [ "Main web site: " + ], + "examples": [ + { + "request": { + "id": "example:listchainmoves#1", + "method": "listchainmoves", + "params": {} + }, + "response": { + "chainmoves": [ + { + "created_index": 1, + "account_id": "wallet", + "credit_msat": 200000000000, + "debit_msat": 0, + "timestamp": 1758192762, + "primary_tag": "deposit", + "extra_tags": [], + "utxo": "994185cba7723715c0aa1d1859ce2781116776cea917035c90f8f04c9f4e095e:1", + "output_msat": 200000000000, + "blockheight": 104 + }, + { + "created_index": 2, + "account_id": "252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7", + "credit_msat": 0, + "debit_msat": 0, + "timestamp": 1758192777, + "primary_tag": "channel_open", + "extra_tags": [], + "utxo": "542906c8a9d90596592459a9484f4286a3200f6540599c83b43af2ac4166c6ca:1", + "peer_id": "nodeid010101010101010101010101010101010101010101010101010101010101", + "output_msat": 1000000000, + "blockheight": 109 + }, + { + "created_index": 3, + "account_id": "wallet", + "credit_msat": 2000000000, + "debit_msat": 0, + "timestamp": 1758192780, + "primary_tag": "deposit", + "extra_tags": [], + "utxo": "19e9e42f2f2097ea1dc18d7eb670bc53c90cbe31bb1daba8e94abf3c6b60d2dc:1", + "output_msat": 2000000000, + "blockheight": 110 + }, + { + "created_index": 4, + "account_id": "wallet", + "credit_msat": 0, + "debit_msat": 200000000000, + "timestamp": 1738530000, + "primary_tag": "withdrawal", + "extra_tags": [], + "utxo": "994185cba7723715c0aa1d1859ce2781116776cea917035c90f8f04c9f4e095e:1", + "spending_txid": "94418b652c9a0d79129552d317dcc37cb55afda1387257a22c7f16aa3981b7bc", + "output_msat": 200000000000, + "blockheight": 111 + }, + { + "created_index": 5, + "account_id": "wallet", + "credit_msat": 198995073000, + "debit_msat": 0, + "timestamp": 1738530000, + "primary_tag": "deposit", + "extra_tags": [], + "utxo": "94418b652c9a0d79129552d317dcc37cb55afda1387257a22c7f16aa3981b7bc:1", + "output_msat": 198995073000, + "blockheight": 111 + }, + { + "created_index": 6, + "account_id": "a397dd9b3e44afcb67f3f3ce1d649b74a8ade63e35505985e4cc1828634f69a2", + "credit_msat": 1000000000, + "debit_msat": 0, + "timestamp": 1738530000, + "primary_tag": "channel_open", + "extra_tags": [ + "opener" + ], + "utxo": "94418b652c9a0d79129552d317dcc37cb55afda1387257a22c7f16aa3981b7bc:0", + "peer_id": "nodeid030303030303030303030303030303030303030303030303030303030303", + "output_msat": 1000000000, + "blockheight": 111 + }, + { + "created_index": 7, + "account_id": "wallet", + "credit_msat": 2000000000, + "debit_msat": 0, + "timestamp": 1758192792, + "primary_tag": "deposit", + "extra_tags": [], + "utxo": "b6d0090efbeb347fa59f90b321d6906cdf86779c15477582979fa427249f71f5:1", + "output_msat": 2000000000, + "blockheight": 114 + }, + { + "created_index": 8, + "account_id": "wallet", + "credit_msat": 0, + "debit_msat": 198995073000, + "timestamp": 1758192795, + "primary_tag": "withdrawal", + "extra_tags": [], + "utxo": "94418b652c9a0d79129552d317dcc37cb55afda1387257a22c7f16aa3981b7bc:1", + "spending_txid": "32de3d1592062670eb8630875a28705cc1988b7f83f8c712bf9d39be2152efec", + "output_msat": 198995073000, + "blockheight": 115 + }, + { + "created_index": 9, + "account_id": "wallet", + "credit_msat": 197990453000, + "debit_msat": 0, + "timestamp": 1758192795, + "primary_tag": "deposit", + "extra_tags": [], + "utxo": "32de3d1592062670eb8630875a28705cc1988b7f83f8c712bf9d39be2152efec:0", + "output_msat": 197990453000, + "blockheight": 115 + }, + { + "created_index": 10, + "account_id": "f8fc83a432cbfb2fffe222cc06727fdd977b5dd10ebd6707158e799e6f522d9f", + "credit_msat": 1000000000, + "debit_msat": 0, + "timestamp": 1758192795, + "primary_tag": "channel_open", + "extra_tags": [ + "opener" + ], + "utxo": "32de3d1592062670eb8630875a28705cc1988b7f83f8c712bf9d39be2152efec:1", + "peer_id": "nodeid050505050505050505050505050505050505050505050505050505050505", + "output_msat": 1000000000, + "blockheight": 115 + }, + { + "created_index": 11, + "account_id": "wallet", + "credit_msat": 486914000, + "debit_msat": 0, + "timestamp": 1738520000, + "primary_tag": "deposit", + "extra_tags": [], + "utxo": "874b26d4c523a902fdc44b88ec000eb5c3fe8754c9d44190a140561e24e77781:0", + "output_msat": 486914000, + "blockheight": 121 + }, + { + "created_index": 12, + "account_id": "a397dd9b3e44afcb67f3f3ce1d649b74a8ade63e35505985e4cc1828634f69a2", + "credit_msat": 0, + "debit_msat": 489809898, + "timestamp": 1738520000, + "primary_tag": "channel_close", + "extra_tags": [], + "utxo": "94418b652c9a0d79129552d317dcc37cb55afda1387257a22c7f16aa3981b7bc:0", + "spending_txid": "txid010101010101010101010101010101010101010101010101010101010101", + "output_msat": 1000000000, + "output_count": 2, + "blockheight": 121 + }, + { + "created_index": 13, + "account_id": "external", + "credit_msat": 510190000, + "debit_msat": 0, + "timestamp": 1738520000, + "primary_tag": "to_them", + "extra_tags": [], + "utxo": "874b26d4c523a902fdc44b88ec000eb5c3fe8754c9d44190a140561e24e77781:1", + "originating_account": "channelid0230000230000230000230000230000230000230000230000230000", + "output_msat": 510190000, + "blockheight": 121 + }, + { + "created_index": 14, + "account_id": "wallet", + "credit_msat": 2000000000, + "debit_msat": 0, + "timestamp": 1758192808, + "primary_tag": "deposit", + "extra_tags": [], + "utxo": "c9c9bec064382b6a6fb2a30d8923949b3c9f732465542b96e9ad1b5eebda4c7d:0", + "output_msat": 2000000000, + "blockheight": 122 + }, + { + "created_index": 15, + "account_id": "wallet", + "credit_msat": 0, + "debit_msat": 197990453000, + "timestamp": 1738500000, + "primary_tag": "withdrawal", + "extra_tags": [], + "utxo": "32de3d1592062670eb8630875a28705cc1988b7f83f8c712bf9d39be2152efec:0", + "spending_txid": "0137213d852e76d48f0270a78218d2f562ac0a8974f814cab66376537cfd1682", + "output_msat": 197990453000, + "blockheight": 123 + }, + { + "created_index": 16, + "account_id": "wallet", + "credit_msat": 196985833000, + "debit_msat": 0, + "timestamp": 1738500000, + "primary_tag": "deposit", + "extra_tags": [], + "utxo": "0137213d852e76d48f0270a78218d2f562ac0a8974f814cab66376537cfd1682:1", + "output_msat": 196985833000, + "blockheight": 123 + }, + { + "created_index": 17, + "account_id": "channelid0230200230200230200230200230200230200230200230200230200", + "credit_msat": 1000000000, + "debit_msat": 0, + "timestamp": 1738500000, + "primary_tag": "channel_open", + "extra_tags": [ + "opener" + ], + "utxo": "0137213d852e76d48f0270a78218d2f562ac0a8974f814cab66376537cfd1682:0", + "peer_id": "nodeid030303030303030303030303030303030303030303030303030303030303", + "output_msat": 1000000000, + "blockheight": 123 + } + ] + } + }, + { + "request": { + "id": "example:listchainmoves#2", + "method": "listchainmoves", + "params": { + "index": "created", + "start": 10 + } + }, + "response": { + "chainmoves": [ + { + "created_index": 10, + "account_id": "f8fc83a432cbfb2fffe222cc06727fdd977b5dd10ebd6707158e799e6f522d9f", + "credit_msat": 1000000000, + "debit_msat": 0, + "timestamp": 1758192795, + "primary_tag": "channel_open", + "extra_tags": [ + "opener" + ], + "utxo": "32de3d1592062670eb8630875a28705cc1988b7f83f8c712bf9d39be2152efec:1", + "peer_id": "nodeid050505050505050505050505050505050505050505050505050505050505", + "output_msat": 1000000000, + "blockheight": 115 + }, + { + "created_index": 11, + "account_id": "wallet", + "credit_msat": 486914000, + "debit_msat": 0, + "timestamp": 1738520000, + "primary_tag": "deposit", + "extra_tags": [], + "utxo": "874b26d4c523a902fdc44b88ec000eb5c3fe8754c9d44190a140561e24e77781:0", + "output_msat": 486914000, + "blockheight": 121 + }, + { + "created_index": 12, + "account_id": "a397dd9b3e44afcb67f3f3ce1d649b74a8ade63e35505985e4cc1828634f69a2", + "credit_msat": 0, + "debit_msat": 489809898, + "timestamp": 1738520000, + "primary_tag": "channel_close", + "extra_tags": [], + "utxo": "94418b652c9a0d79129552d317dcc37cb55afda1387257a22c7f16aa3981b7bc:0", + "spending_txid": "txid010101010101010101010101010101010101010101010101010101010101", + "output_msat": 1000000000, + "output_count": 2, + "blockheight": 121 + }, + { + "created_index": 13, + "account_id": "external", + "credit_msat": 510190000, + "debit_msat": 0, + "timestamp": 1738520000, + "primary_tag": "to_them", + "extra_tags": [], + "utxo": "874b26d4c523a902fdc44b88ec000eb5c3fe8754c9d44190a140561e24e77781:1", + "originating_account": "channelid0230000230000230000230000230000230000230000230000230000", + "output_msat": 510190000, + "blockheight": 121 + }, + { + "created_index": 14, + "account_id": "wallet", + "credit_msat": 2000000000, + "debit_msat": 0, + "timestamp": 1758192808, + "primary_tag": "deposit", + "extra_tags": [], + "utxo": "c9c9bec064382b6a6fb2a30d8923949b3c9f732465542b96e9ad1b5eebda4c7d:0", + "output_msat": 2000000000, + "blockheight": 122 + }, + { + "created_index": 15, + "account_id": "wallet", + "credit_msat": 0, + "debit_msat": 197990453000, + "timestamp": 1738500000, + "primary_tag": "withdrawal", + "extra_tags": [], + "utxo": "32de3d1592062670eb8630875a28705cc1988b7f83f8c712bf9d39be2152efec:0", + "spending_txid": "0137213d852e76d48f0270a78218d2f562ac0a8974f814cab66376537cfd1682", + "output_msat": 197990453000, + "blockheight": 123 + }, + { + "created_index": 16, + "account_id": "wallet", + "credit_msat": 196985833000, + "debit_msat": 0, + "timestamp": 1738500000, + "primary_tag": "deposit", + "extra_tags": [], + "utxo": "0137213d852e76d48f0270a78218d2f562ac0a8974f814cab66376537cfd1682:1", + "output_msat": 196985833000, + "blockheight": 123 + }, + { + "created_index": 17, + "account_id": "channelid0230200230200230200230200230200230200230200230200230200", + "credit_msat": 1000000000, + "debit_msat": 0, + "timestamp": 1738500000, + "primary_tag": "channel_open", + "extra_tags": [ + "opener" + ], + "utxo": "0137213d852e76d48f0270a78218d2f562ac0a8974f814cab66376537cfd1682:0", + "peer_id": "nodeid030303030303030303030303030303030303030303030303030303030303", + "output_msat": 1000000000, + "blockheight": 123 + } + ] + } + } ] }, "listchannelmoves.json": { @@ -16898,6 +17251,242 @@ ], "resources": [ "Main web site: " + ], + "examples": [ + { + "request": { + "id": "example:listchannelmoves#1", + "method": "listchannelmoves", + "params": {} + }, + "response": { + "channelmoves": [ + { + "created_index": 1, + "account_id": "252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7", + "credit_msat": 500000000, + "debit_msat": 0, + "timestamp": 1738520000, + "primary_tag": "invoice", + "payment_hash": "paymenthashdelpay10101010101010101010101010101010101010101010101", + "fees_msat": 0 + }, + { + "created_index": 2, + "account_id": "a397dd9b3e44afcb67f3f3ce1d649b74a8ade63e35505985e4cc1828634f69a2", + "credit_msat": 0, + "debit_msat": 500000000, + "timestamp": 1738520000, + "primary_tag": "invoice", + "payment_hash": "8a46ab91013146df39e98ad7c89505fbb5419f110e928f7a393e8304f3057df7", + "part_id": 0, + "group_id": 1, + "fees_msat": 0 + }, + { + "created_index": 3, + "account_id": "f8fc83a432cbfb2fffe222cc06727fdd977b5dd10ebd6707158e799e6f522d9f", + "credit_msat": 0, + "debit_msat": 500000000, + "timestamp": 1758192801, + "primary_tag": "invoice", + "payment_hash": "88969daaf02214a1928e6eb62a237a8ee557f3da93b2c44f3901432c88f4334b", + "part_id": 0, + "group_id": 1, + "fees_msat": 0 + }, + { + "created_index": 4, + "account_id": "a397dd9b3e44afcb67f3f3ce1d649b74a8ade63e35505985e4cc1828634f69a2", + "credit_msat": 0, + "debit_msat": 10000, + "timestamp": 1758192801, + "primary_tag": "routed", + "payment_hash": "paymenthashinvl0310031003100310031003100310031003100310031003100", + "fees_msat": 1 + }, + { + "created_index": 5, + "account_id": "252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7", + "credit_msat": 10001, + "debit_msat": 0, + "timestamp": 1758192801, + "primary_tag": "routed", + "payment_hash": "paymenthashinvl0310031003100310031003100310031003100310031003100", + "fees_msat": 1 + }, + { + "created_index": 6, + "account_id": "a397dd9b3e44afcb67f3f3ce1d649b74a8ade63e35505985e4cc1828634f69a2", + "credit_msat": 0, + "debit_msat": 10000, + "timestamp": 1758192801, + "primary_tag": "routed", + "payment_hash": "paymenthashkey01k101k101k101k101k101k101k101k101k101k101k101k101", + "fees_msat": 1 + }, + { + "created_index": 7, + "account_id": "252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7", + "credit_msat": 10001, + "debit_msat": 0, + "timestamp": 1758192801, + "primary_tag": "routed", + "payment_hash": "paymenthashkey01k101k101k101k101k101k101k101k101k101k101k101k101", + "fees_msat": 1 + }, + { + "created_index": 8, + "account_id": "a397dd9b3e44afcb67f3f3ce1d649b74a8ade63e35505985e4cc1828634f69a2", + "credit_msat": 0, + "debit_msat": 10000101, + "timestamp": 1758192802, + "primary_tag": "routed", + "payment_hash": "paymenthashkey02k201k201k201k201k201k201k201k201k201k201k201k201", + "fees_msat": 101 + }, + { + "created_index": 9, + "account_id": "252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7", + "credit_msat": 10000202, + "debit_msat": 0, + "timestamp": 1758192802, + "primary_tag": "routed", + "payment_hash": "paymenthashkey02k201k201k201k201k201k201k201k201k201k201k201k201", + "fees_msat": 101 + }, + { + "created_index": 10, + "account_id": "a397dd9b3e44afcb67f3f3ce1d649b74a8ade63e35505985e4cc1828634f69a2", + "credit_msat": 0, + "debit_msat": 10000, + "timestamp": 1758192802, + "primary_tag": "routed", + "payment_hash": "paymenthashkey03k301k301k301k301k301k301k301k301k301k301k301k301", + "fees_msat": 1 + }, + { + "created_index": 11, + "account_id": "252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7", + "credit_msat": 10001, + "debit_msat": 0, + "timestamp": 1758192802, + "primary_tag": "routed", + "payment_hash": "paymenthashkey03k301k301k301k301k301k301k301k301k301k301k301k301", + "fees_msat": 1 + }, + { + "created_index": 12, + "account_id": "a397dd9b3e44afcb67f3f3ce1d649b74a8ade63e35505985e4cc1828634f69a2", + "credit_msat": 0, + "debit_msat": 50000, + "timestamp": 1758192802, + "primary_tag": "routed", + "payment_hash": "paymenthashinvl0320032003200320032003200320032003200320032003200", + "fees_msat": 1 + }, + { + "created_index": 13, + "account_id": "252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7", + "credit_msat": 50001, + "debit_msat": 0, + "timestamp": 1758192802, + "primary_tag": "routed", + "payment_hash": "paymenthashinvl0320032003200320032003200320032003200320032003200", + "fees_msat": 1 + }, + { + "created_index": 14, + "account_id": "a397dd9b3e44afcb67f3f3ce1d649b74a8ade63e35505985e4cc1828634f69a2", + "credit_msat": 0, + "debit_msat": 100000, + "timestamp": 1758192803, + "primary_tag": "invoice", + "payment_hash": "paymenthashinvl0330033003300330033003300330033003300330033003300", + "part_id": 0, + "group_id": 1, + "fees_msat": 0 + }, + { + "created_index": 15, + "account_id": "a397dd9b3e44afcb67f3f3ce1d649b74a8ade63e35505985e4cc1828634f69a2", + "credit_msat": 0, + "debit_msat": 10001, + "timestamp": 1758192803, + "primary_tag": "routed", + "payment_hash": "61b929204f4db4f38e0412b2bd4c3c03668dad3575fb05f4e15a2214046c2bff", + "fees_msat": 1 + }, + { + "created_index": 16, + "account_id": "252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7", + "credit_msat": 10002, + "debit_msat": 0, + "timestamp": 1758192803, + "primary_tag": "routed", + "payment_hash": "61b929204f4db4f38e0412b2bd4c3c03668dad3575fb05f4e15a2214046c2bff", + "fees_msat": 1 + }, + { + "created_index": 17, + "account_id": "252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7", + "credit_msat": 0, + "debit_msat": 1000000, + "timestamp": 1758192821, + "primary_tag": "invoice", + "payment_hash": "paymenthashsdinvsi10si10si10si10si10si10si10si10si10si10si10si10", + "part_id": 0, + "group_id": 1, + "fees_msat": 0 + }, + { + "created_index": 18, + "account_id": "252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7", + "credit_msat": 1000, + "debit_msat": 0, + "timestamp": 1758192821, + "primary_tag": "invoice", + "payment_hash": "paymenthashinvl0270027002700270027002700270027002700270027002700", + "fees_msat": 0 + } + ] + } + }, + { + "request": { + "id": "example:listchannelmoves#2", + "method": "listchannelmoves", + "params": { + "index": "created", + "start": 10, + "limit": 2 + } + }, + "response": { + "channelmoves": [ + { + "created_index": 10, + "account_id": "a397dd9b3e44afcb67f3f3ce1d649b74a8ade63e35505985e4cc1828634f69a2", + "credit_msat": 0, + "debit_msat": 10000, + "timestamp": 1758192802, + "primary_tag": "routed", + "payment_hash": "paymenthashkey03k301k301k301k301k301k301k301k301k301k301k301k301", + "fees_msat": 1 + }, + { + "created_index": 11, + "account_id": "252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7", + "credit_msat": 10001, + "debit_msat": 0, + "timestamp": 1758192802, + "primary_tag": "routed", + "payment_hash": "paymenthashkey03k301k301k301k301k301k301k301k301k301k301k301k301", + "fees_msat": 1 + } + ] + } + } ] }, "listchannels.json": { diff --git a/contrib/pyln-testing/pyln/testing/fixtures.py b/contrib/pyln-testing/pyln/testing/fixtures.py index 215c54022325..7db4b66e8057 100644 --- a/contrib/pyln-testing/pyln/testing/fixtures.py +++ b/contrib/pyln-testing/pyln/testing/fixtures.py @@ -125,36 +125,40 @@ def node_cls(): @pytest.fixture -def bitcoind(directory, teardown_checks): +def bitcoind(request, directory, teardown_checks): chaind = network_daemons[env('TEST_NETWORK', 'regtest')] bitcoind = chaind(bitcoin_dir=directory) - try: - bitcoind.start() - except Exception: - bitcoind.stop() - raise - - info = bitcoind.rpc.getnetworkinfo() - - # FIXME: include liquid-regtest in this check after elementsd has been - # updated - if info['version'] < 200100 and env('TEST_NETWORK') != 'liquid-regtest': - bitcoind.rpc.stop() - raise ValueError("bitcoind is too old. At least version 20100 (v0.20.1)" - " is needed, current version is {}".format(info['version'])) - elif info['version'] < 160000: - bitcoind.rpc.stop() - raise ValueError("elementsd is too old. At least version 160000 (v0.16.0)" - " is needed, current version is {}".format(info['version'])) - - info = bitcoind.rpc.getblockchaininfo() - # Make sure we have some spendable funds - if info['blocks'] < 101: - bitcoind.generate_block(101 - info['blocks']) - elif bitcoind.rpc.getwalletinfo()['balance'] < 1: - logging.debug("Insufficient balance, generating 1 block") - bitcoind.generate_block(1) + # @pytest.mark.parametrize('bitcoind', [False], indirect=True) if you don't + # want bitcoind started! + if getattr(request, 'param', True): + try: + bitcoind.start() + except Exception: + bitcoind.stop() + raise + + info = bitcoind.rpc.getnetworkinfo() + + # FIXME: include liquid-regtest in this check after elementsd has been + # updated + if info['version'] < 200100 and env('TEST_NETWORK') != 'liquid-regtest': + bitcoind.rpc.stop() + raise ValueError("bitcoind is too old. At least version 20100 (v0.20.1)" + " is needed, current version is {}".format(info['version'])) + elif info['version'] < 160000: + bitcoind.rpc.stop() + raise ValueError("elementsd is too old. At least version 160000 (v0.16.0)" + " is needed, current version is {}".format(info['version'])) + + info = bitcoind.rpc.getblockchaininfo() + + # Make sure we have some spendable funds + if info['blocks'] < 101: + bitcoind.generate_block(101 - info['blocks']) + elif bitcoind.rpc.getwalletinfo()['balance'] < 1: + logging.debug("Insufficient balance, generating 1 block") + bitcoind.generate_block(1) yield bitcoind diff --git a/contrib/pyln-testing/pyln/testing/utils.py b/contrib/pyln-testing/pyln/testing/utils.py index 2317c96c315f..0ecd81bcff93 100644 --- a/contrib/pyln-testing/pyln/testing/utils.py +++ b/contrib/pyln-testing/pyln/testing/utils.py @@ -407,6 +407,7 @@ def __init__(self, bitcoin_dir="/tmp/bitcoind-test", rpcport=None): self.bitcoin_dir = bitcoin_dir self.rpcport = rpcport self.prefix = 'bitcoind' + self.canned_blocks = None regtestdir = os.path.join(bitcoin_dir, 'regtest') if not os.path.exists(regtestdir): @@ -442,15 +443,18 @@ def __del__(self): if self.reserved_rpcport is not None: drop_unused_port(self.reserved_rpcport) - def start(self): + def start(self, wallet_file=None): TailableProc.start(self) self.wait_for_log("Done loading", timeout=TIMEOUT) logging.info("BitcoinD started") - try: - self.rpc.createwallet("lightningd-tests") - except JSONRPCError: - self.rpc.loadwallet("lightningd-tests") + if wallet_file: + self.rpc.restorewallet("lightningd-tests", wallet_file) + else: + try: + self.rpc.createwallet("lightningd-tests") + except JSONRPCError: + self.rpc.loadwallet("lightningd-tests") def stop(self): for p in self.proxies: @@ -464,6 +468,10 @@ def get_proxy(self): proxy.start() return proxy + def set_canned_blocks(self, blocks): + """Set blocks as an array of blocks to "generate", or None to reset""" + self.canned_blocks = blocks + # wait_for_mempool can be used to wait for the mempool before generating blocks: # True := wait for at least 1 transation # int > 0 := wait for at least N transactions @@ -478,6 +486,16 @@ def generate_block(self, numblocks=1, wait_for_mempool=0, to_addr=None, needfeer else: wait_for(lambda: len(self.rpc.getrawmempool()) >= wait_for_mempool) + # Use canned blocks if we have them (fails if we run out!). + if self.canned_blocks is not None: + ret = [] + while numblocks > 0: + self.rpc.submitblock(self.canned_blocks[0]) + ret.append(self.rpc.getbestblockhash()) + numblocks -= 1 + del self.canned_blocks[0] + return ret + mempool = self.rpc.getrawmempool(True) logging.debug("Generating {numblocks}, confirming {lenmempool} transactions: {mempool}".format( numblocks=numblocks, @@ -505,6 +523,21 @@ def generate_block(self, numblocks=1, wait_for_mempool=0, to_addr=None, needfeer return self.rpc.generatetoaddress(numblocks, to_addr) + def send_and_mine_block(self, addr, sats): + """Sometimes we want the txid. We assume it's the first tx for canned blocks""" + if self.canned_blocks: + self.generate_block(1) + # Find which non-coinbase txs sent to this address: return txid + for txid in self.rpc.getblock(self.rpc.getbestblockhash())['tx'][1:]: + for out in self.rpc.getrawtransaction(txid, 1)['vout']: + if out['scriptPubKey'].get('address') == addr: + return txid + assert False, f"No address {addr} in block {self.rpc.getblock(self.rpc.getbestblockhash())}" + + txid = self.rpc.sendtoaddress(addr, sats / 10**8) + self.generate_block(1) + return txid + def simple_reorg(self, height, shift=0): """ Reorganize chain by creating a fork at height=[height] and re-mine all mempool @@ -522,6 +555,7 @@ def simple_reorg(self, height, shift=0): forward to h1. 2. Set [height]=h2 and [shift]= h1-h2 """ + assert self.canned_blocks is None hashes = [] fee_delta = 1000000 orig_len = self.rpc.getblockcount() @@ -555,7 +589,7 @@ def save_blocks(self): """Bundle up blocks into an array, for restore_blocks""" blocks = [] numblocks = self.rpc.getblockcount() - for bnum in range(1, numblocks): + for bnum in range(1, numblocks + 1): bhash = self.rpc.getblockhash(bnum) blocks.append(self.rpc.getblock(bhash, False)) return blocks @@ -887,6 +921,10 @@ def __init__(self, node_id, lightning_dir, bitcoind, executor, valgrind, may_fai self.daemon.opts['grpc-port'] = grpc_port self.grpc_port = grpc_port or 9736 + # If bitcoind is serving canned blocks, it will keep initialblockdownload on true! + if self.bitcoin.canned_blocks is not None: + self.daemon.opts['dev-ignore-ibd'] = True + def _create_rpc(self, jsonschemas): """Prepares anything related to the RPC. """ @@ -982,10 +1020,12 @@ def openchannel(self, remote_node, capacity=FUNDAMOUNT, addrtype="bech32", confi def fundwallet(self, sats, addrtype="bech32", mine_block=True): addr = self.rpc.newaddr(addrtype)[addrtype] - txid = self.bitcoin.rpc.sendtoaddress(addr, sats / 10**8) if mine_block: - self.bitcoin.generate_block(1) + txid = self.bitcoin.send_and_mine_block(addr, sats) self.daemon.wait_for_log('Owning output .* txid {} CONFIRMED'.format(txid)) + else: + txid = self.bitcoin.rpc.sendtoaddress(addr, sats / 10**8) + return addr, txid def fundbalancedchannel(self, remote_node, total_capacity=FUNDAMOUNT, announce=True): @@ -1113,8 +1153,7 @@ def has_funds_on_addr(addr): # We should not have funds on that address yet, we just generated it. assert not has_funds_on_addr(addr) - self.bitcoin.rpc.sendtoaddress(addr, (amount + 1000000) / 10**8) - self.bitcoin.generate_block(1) + self.bitcoin.send_and_mine_block(addr, amount + 1000000) # Now we should. wait_for(lambda: has_funds_on_addr(addr)) @@ -1129,10 +1168,18 @@ def has_funds_on_addr(addr): **kwargs) blockid = self.bitcoin.generate_block(1, wait_for_mempool=res['txid'])[0] + txnum = None for i, txid in enumerate(self.bitcoin.rpc.getblock(blockid)['tx']): if txid == res['txid']: txnum = i + if txnum is None: + print(f"mempool = {self.bitcoin.rpc.getrawmempool()}") + print(f"txs:") + for txid in self.bitcoin.rpc.getblock(blockid)['tx'][1:]: + print(f"txid {txid}: {self.bitcoin.rpc.getrawtransaction(txid)} {self.bitcoin.rpc.getrawtransaction(txid, 1)}") + assert False, f"txid {res['txid']} not found" + scid = "{}x{}x{}".format(self.bitcoin.rpc.getblockcount(), txnum, res['outnum']) diff --git a/devtools/Makefile b/devtools/Makefile index a80ebe4ab631..be005a77357b 100644 --- a/devtools/Makefile +++ b/devtools/Makefile @@ -29,6 +29,7 @@ DEVTOOLS_COMMON_OBJS := \ common/bolt11.o \ common/blockheight_states.o \ common/channel_id.o \ + common/clock_time.o \ common/decode_array.o \ common/features.o \ common/fee_states.o \ @@ -42,6 +43,7 @@ DEVTOOLS_COMMON_OBJS := \ common/per_peer_state.o \ common/psbt_open.o \ common/pseudorand.o \ + common/randbytes.o \ common/sciddir_or_pubkey.o \ common/setup.o \ common/utils.o \ @@ -83,7 +85,7 @@ devtools/gossipwith: $(DEVTOOLS_COMMON_OBJS) $(JSMN_OBJS) $(BITCOIN_OBJS) wire/f $(DEVTOOLS_OBJS) $(DEVTOOLS_TOOL_OBJS): wire/wire.h -devtools/mkcommit: $(DEVTOOLS_COMMON_OBJS) $(BITCOIN_OBJS) common/derive_basepoints.o common/channel_type.o common/keyset.o common/key_derive.o common/initial_commit_tx.o common/permute_tx.o wire/fromwire.o wire/towire.o devtools/mkcommit.o channeld/full_channel.o common/initial_channel.o common/htlc_state.o common/pseudorand.o common/htlc_tx.o channeld/commit_tx.o common/htlc_trim.o +devtools/mkcommit: $(DEVTOOLS_COMMON_OBJS) $(BITCOIN_OBJS) common/derive_basepoints.o common/channel_type.o common/keyset.o common/key_derive.o common/initial_commit_tx.o common/permute_tx.o wire/fromwire.o wire/towire.o devtools/mkcommit.o channeld/full_channel.o common/initial_channel.o common/htlc_state.o common/pseudorand.o common/randbytes.o common/htlc_tx.o channeld/commit_tx.o common/htlc_trim.o devtools/mkfunding: $(DEVTOOLS_COMMON_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o common/key_derive.o devtools/mkfunding.o diff --git a/devtools/bolt11-cli.c b/devtools/bolt11-cli.c index 5553822c6738..cc11e9dbe08b 100644 --- a/devtools/bolt11-cli.c +++ b/devtools/bolt11-cli.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -108,7 +109,7 @@ static void encode(const tal_t *ctx, struct pubkey me; bool explicit_n = false; - b11->timestamp = time_now().ts.tv_sec; + b11->timestamp = clock_time().ts.tv_sec; b11->chain = chainparams_for_network("regtest"); b11->expiry = 3600; b11->min_final_cltv_expiry = DEFAULT_FINAL_CLTV_DELTA; diff --git a/devtools/gossipwith.c b/devtools/gossipwith.c index f506787cd4e3..316787e5127d 100644 --- a/devtools/gossipwith.c +++ b/devtools/gossipwith.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -214,7 +215,7 @@ static struct io_plan *handshake_success(struct io_conn *conn, msg = towire_gossip_timestamp_filter(NULL, &chainparams->genesis_blockhash, all_gossip ? 0 - : no_gossip ? 0xFFFFFFFF : time_now().ts.tv_sec, + : no_gossip ? 0xFFFFFFFF : clock_time().ts.tv_sec, 0xFFFFFFFF); sync_crypto_write(peer_fd, cs, take(msg)); } diff --git a/doc/schemas/listchainmoves.json b/doc/schemas/listchainmoves.json index 985105e93a55..eeec3e6b902e 100644 --- a/doc/schemas/listchainmoves.json +++ b/doc/schemas/listchainmoves.json @@ -197,5 +197,358 @@ ], "resources": [ "Main web site: " + ], + "examples": [ + { + "request": { + "id": "example:listchainmoves#1", + "method": "listchainmoves", + "params": {} + }, + "response": { + "chainmoves": [ + { + "created_index": 1, + "account_id": "wallet", + "credit_msat": 200000000000, + "debit_msat": 0, + "timestamp": 1758192762, + "primary_tag": "deposit", + "extra_tags": [], + "utxo": "994185cba7723715c0aa1d1859ce2781116776cea917035c90f8f04c9f4e095e:1", + "output_msat": 200000000000, + "blockheight": 104 + }, + { + "created_index": 2, + "account_id": "252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7", + "credit_msat": 0, + "debit_msat": 0, + "timestamp": 1758192777, + "primary_tag": "channel_open", + "extra_tags": [], + "utxo": "542906c8a9d90596592459a9484f4286a3200f6540599c83b43af2ac4166c6ca:1", + "peer_id": "nodeid010101010101010101010101010101010101010101010101010101010101", + "output_msat": 1000000000, + "blockheight": 109 + }, + { + "created_index": 3, + "account_id": "wallet", + "credit_msat": 2000000000, + "debit_msat": 0, + "timestamp": 1758192780, + "primary_tag": "deposit", + "extra_tags": [], + "utxo": "19e9e42f2f2097ea1dc18d7eb670bc53c90cbe31bb1daba8e94abf3c6b60d2dc:1", + "output_msat": 2000000000, + "blockheight": 110 + }, + { + "created_index": 4, + "account_id": "wallet", + "credit_msat": 0, + "debit_msat": 200000000000, + "timestamp": 1738530000, + "primary_tag": "withdrawal", + "extra_tags": [], + "utxo": "994185cba7723715c0aa1d1859ce2781116776cea917035c90f8f04c9f4e095e:1", + "spending_txid": "94418b652c9a0d79129552d317dcc37cb55afda1387257a22c7f16aa3981b7bc", + "output_msat": 200000000000, + "blockheight": 111 + }, + { + "created_index": 5, + "account_id": "wallet", + "credit_msat": 198995073000, + "debit_msat": 0, + "timestamp": 1738530000, + "primary_tag": "deposit", + "extra_tags": [], + "utxo": "94418b652c9a0d79129552d317dcc37cb55afda1387257a22c7f16aa3981b7bc:1", + "output_msat": 198995073000, + "blockheight": 111 + }, + { + "created_index": 6, + "account_id": "a397dd9b3e44afcb67f3f3ce1d649b74a8ade63e35505985e4cc1828634f69a2", + "credit_msat": 1000000000, + "debit_msat": 0, + "timestamp": 1738530000, + "primary_tag": "channel_open", + "extra_tags": [ + "opener" + ], + "utxo": "94418b652c9a0d79129552d317dcc37cb55afda1387257a22c7f16aa3981b7bc:0", + "peer_id": "nodeid030303030303030303030303030303030303030303030303030303030303", + "output_msat": 1000000000, + "blockheight": 111 + }, + { + "created_index": 7, + "account_id": "wallet", + "credit_msat": 2000000000, + "debit_msat": 0, + "timestamp": 1758192792, + "primary_tag": "deposit", + "extra_tags": [], + "utxo": "b6d0090efbeb347fa59f90b321d6906cdf86779c15477582979fa427249f71f5:1", + "output_msat": 2000000000, + "blockheight": 114 + }, + { + "created_index": 8, + "account_id": "wallet", + "credit_msat": 0, + "debit_msat": 198995073000, + "timestamp": 1758192795, + "primary_tag": "withdrawal", + "extra_tags": [], + "utxo": "94418b652c9a0d79129552d317dcc37cb55afda1387257a22c7f16aa3981b7bc:1", + "spending_txid": "32de3d1592062670eb8630875a28705cc1988b7f83f8c712bf9d39be2152efec", + "output_msat": 198995073000, + "blockheight": 115 + }, + { + "created_index": 9, + "account_id": "wallet", + "credit_msat": 197990453000, + "debit_msat": 0, + "timestamp": 1758192795, + "primary_tag": "deposit", + "extra_tags": [], + "utxo": "32de3d1592062670eb8630875a28705cc1988b7f83f8c712bf9d39be2152efec:0", + "output_msat": 197990453000, + "blockheight": 115 + }, + { + "created_index": 10, + "account_id": "f8fc83a432cbfb2fffe222cc06727fdd977b5dd10ebd6707158e799e6f522d9f", + "credit_msat": 1000000000, + "debit_msat": 0, + "timestamp": 1758192795, + "primary_tag": "channel_open", + "extra_tags": [ + "opener" + ], + "utxo": "32de3d1592062670eb8630875a28705cc1988b7f83f8c712bf9d39be2152efec:1", + "peer_id": "nodeid050505050505050505050505050505050505050505050505050505050505", + "output_msat": 1000000000, + "blockheight": 115 + }, + { + "created_index": 11, + "account_id": "wallet", + "credit_msat": 486914000, + "debit_msat": 0, + "timestamp": 1738520000, + "primary_tag": "deposit", + "extra_tags": [], + "utxo": "874b26d4c523a902fdc44b88ec000eb5c3fe8754c9d44190a140561e24e77781:0", + "output_msat": 486914000, + "blockheight": 121 + }, + { + "created_index": 12, + "account_id": "a397dd9b3e44afcb67f3f3ce1d649b74a8ade63e35505985e4cc1828634f69a2", + "credit_msat": 0, + "debit_msat": 489809898, + "timestamp": 1738520000, + "primary_tag": "channel_close", + "extra_tags": [], + "utxo": "94418b652c9a0d79129552d317dcc37cb55afda1387257a22c7f16aa3981b7bc:0", + "spending_txid": "txid010101010101010101010101010101010101010101010101010101010101", + "output_msat": 1000000000, + "output_count": 2, + "blockheight": 121 + }, + { + "created_index": 13, + "account_id": "external", + "credit_msat": 510190000, + "debit_msat": 0, + "timestamp": 1738520000, + "primary_tag": "to_them", + "extra_tags": [], + "utxo": "874b26d4c523a902fdc44b88ec000eb5c3fe8754c9d44190a140561e24e77781:1", + "originating_account": "channelid0230000230000230000230000230000230000230000230000230000", + "output_msat": 510190000, + "blockheight": 121 + }, + { + "created_index": 14, + "account_id": "wallet", + "credit_msat": 2000000000, + "debit_msat": 0, + "timestamp": 1758192808, + "primary_tag": "deposit", + "extra_tags": [], + "utxo": "c9c9bec064382b6a6fb2a30d8923949b3c9f732465542b96e9ad1b5eebda4c7d:0", + "output_msat": 2000000000, + "blockheight": 122 + }, + { + "created_index": 15, + "account_id": "wallet", + "credit_msat": 0, + "debit_msat": 197990453000, + "timestamp": 1738500000, + "primary_tag": "withdrawal", + "extra_tags": [], + "utxo": "32de3d1592062670eb8630875a28705cc1988b7f83f8c712bf9d39be2152efec:0", + "spending_txid": "0137213d852e76d48f0270a78218d2f562ac0a8974f814cab66376537cfd1682", + "output_msat": 197990453000, + "blockheight": 123 + }, + { + "created_index": 16, + "account_id": "wallet", + "credit_msat": 196985833000, + "debit_msat": 0, + "timestamp": 1738500000, + "primary_tag": "deposit", + "extra_tags": [], + "utxo": "0137213d852e76d48f0270a78218d2f562ac0a8974f814cab66376537cfd1682:1", + "output_msat": 196985833000, + "blockheight": 123 + }, + { + "created_index": 17, + "account_id": "channelid0230200230200230200230200230200230200230200230200230200", + "credit_msat": 1000000000, + "debit_msat": 0, + "timestamp": 1738500000, + "primary_tag": "channel_open", + "extra_tags": [ + "opener" + ], + "utxo": "0137213d852e76d48f0270a78218d2f562ac0a8974f814cab66376537cfd1682:0", + "peer_id": "nodeid030303030303030303030303030303030303030303030303030303030303", + "output_msat": 1000000000, + "blockheight": 123 + } + ] + } + }, + { + "request": { + "id": "example:listchainmoves#2", + "method": "listchainmoves", + "params": { + "index": "created", + "start": 10 + } + }, + "response": { + "chainmoves": [ + { + "created_index": 10, + "account_id": "f8fc83a432cbfb2fffe222cc06727fdd977b5dd10ebd6707158e799e6f522d9f", + "credit_msat": 1000000000, + "debit_msat": 0, + "timestamp": 1758192795, + "primary_tag": "channel_open", + "extra_tags": [ + "opener" + ], + "utxo": "32de3d1592062670eb8630875a28705cc1988b7f83f8c712bf9d39be2152efec:1", + "peer_id": "nodeid050505050505050505050505050505050505050505050505050505050505", + "output_msat": 1000000000, + "blockheight": 115 + }, + { + "created_index": 11, + "account_id": "wallet", + "credit_msat": 486914000, + "debit_msat": 0, + "timestamp": 1738520000, + "primary_tag": "deposit", + "extra_tags": [], + "utxo": "874b26d4c523a902fdc44b88ec000eb5c3fe8754c9d44190a140561e24e77781:0", + "output_msat": 486914000, + "blockheight": 121 + }, + { + "created_index": 12, + "account_id": "a397dd9b3e44afcb67f3f3ce1d649b74a8ade63e35505985e4cc1828634f69a2", + "credit_msat": 0, + "debit_msat": 489809898, + "timestamp": 1738520000, + "primary_tag": "channel_close", + "extra_tags": [], + "utxo": "94418b652c9a0d79129552d317dcc37cb55afda1387257a22c7f16aa3981b7bc:0", + "spending_txid": "txid010101010101010101010101010101010101010101010101010101010101", + "output_msat": 1000000000, + "output_count": 2, + "blockheight": 121 + }, + { + "created_index": 13, + "account_id": "external", + "credit_msat": 510190000, + "debit_msat": 0, + "timestamp": 1738520000, + "primary_tag": "to_them", + "extra_tags": [], + "utxo": "874b26d4c523a902fdc44b88ec000eb5c3fe8754c9d44190a140561e24e77781:1", + "originating_account": "channelid0230000230000230000230000230000230000230000230000230000", + "output_msat": 510190000, + "blockheight": 121 + }, + { + "created_index": 14, + "account_id": "wallet", + "credit_msat": 2000000000, + "debit_msat": 0, + "timestamp": 1758192808, + "primary_tag": "deposit", + "extra_tags": [], + "utxo": "c9c9bec064382b6a6fb2a30d8923949b3c9f732465542b96e9ad1b5eebda4c7d:0", + "output_msat": 2000000000, + "blockheight": 122 + }, + { + "created_index": 15, + "account_id": "wallet", + "credit_msat": 0, + "debit_msat": 197990453000, + "timestamp": 1738500000, + "primary_tag": "withdrawal", + "extra_tags": [], + "utxo": "32de3d1592062670eb8630875a28705cc1988b7f83f8c712bf9d39be2152efec:0", + "spending_txid": "0137213d852e76d48f0270a78218d2f562ac0a8974f814cab66376537cfd1682", + "output_msat": 197990453000, + "blockheight": 123 + }, + { + "created_index": 16, + "account_id": "wallet", + "credit_msat": 196985833000, + "debit_msat": 0, + "timestamp": 1738500000, + "primary_tag": "deposit", + "extra_tags": [], + "utxo": "0137213d852e76d48f0270a78218d2f562ac0a8974f814cab66376537cfd1682:1", + "output_msat": 196985833000, + "blockheight": 123 + }, + { + "created_index": 17, + "account_id": "channelid0230200230200230200230200230200230200230200230200230200", + "credit_msat": 1000000000, + "debit_msat": 0, + "timestamp": 1738500000, + "primary_tag": "channel_open", + "extra_tags": [ + "opener" + ], + "utxo": "0137213d852e76d48f0270a78218d2f562ac0a8974f814cab66376537cfd1682:0", + "peer_id": "nodeid030303030303030303030303030303030303030303030303030303030303", + "output_msat": 1000000000, + "blockheight": 123 + } + ] + } + } ] } diff --git a/doc/schemas/listchannelmoves.json b/doc/schemas/listchannelmoves.json index d98a72b777a8..eba0f45a35db 100644 --- a/doc/schemas/listchannelmoves.json +++ b/doc/schemas/listchannelmoves.json @@ -145,5 +145,241 @@ ], "resources": [ "Main web site: " + ], + "examples": [ + { + "request": { + "id": "example:listchannelmoves#1", + "method": "listchannelmoves", + "params": {} + }, + "response": { + "channelmoves": [ + { + "created_index": 1, + "account_id": "252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7", + "credit_msat": 500000000, + "debit_msat": 0, + "timestamp": 1738520000, + "primary_tag": "invoice", + "payment_hash": "paymenthashdelpay10101010101010101010101010101010101010101010101", + "fees_msat": 0 + }, + { + "created_index": 2, + "account_id": "a397dd9b3e44afcb67f3f3ce1d649b74a8ade63e35505985e4cc1828634f69a2", + "credit_msat": 0, + "debit_msat": 500000000, + "timestamp": 1738520000, + "primary_tag": "invoice", + "payment_hash": "8a46ab91013146df39e98ad7c89505fbb5419f110e928f7a393e8304f3057df7", + "part_id": 0, + "group_id": 1, + "fees_msat": 0 + }, + { + "created_index": 3, + "account_id": "f8fc83a432cbfb2fffe222cc06727fdd977b5dd10ebd6707158e799e6f522d9f", + "credit_msat": 0, + "debit_msat": 500000000, + "timestamp": 1758192801, + "primary_tag": "invoice", + "payment_hash": "88969daaf02214a1928e6eb62a237a8ee557f3da93b2c44f3901432c88f4334b", + "part_id": 0, + "group_id": 1, + "fees_msat": 0 + }, + { + "created_index": 4, + "account_id": "a397dd9b3e44afcb67f3f3ce1d649b74a8ade63e35505985e4cc1828634f69a2", + "credit_msat": 0, + "debit_msat": 10000, + "timestamp": 1758192801, + "primary_tag": "routed", + "payment_hash": "paymenthashinvl0310031003100310031003100310031003100310031003100", + "fees_msat": 1 + }, + { + "created_index": 5, + "account_id": "252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7", + "credit_msat": 10001, + "debit_msat": 0, + "timestamp": 1758192801, + "primary_tag": "routed", + "payment_hash": "paymenthashinvl0310031003100310031003100310031003100310031003100", + "fees_msat": 1 + }, + { + "created_index": 6, + "account_id": "a397dd9b3e44afcb67f3f3ce1d649b74a8ade63e35505985e4cc1828634f69a2", + "credit_msat": 0, + "debit_msat": 10000, + "timestamp": 1758192801, + "primary_tag": "routed", + "payment_hash": "paymenthashkey01k101k101k101k101k101k101k101k101k101k101k101k101", + "fees_msat": 1 + }, + { + "created_index": 7, + "account_id": "252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7", + "credit_msat": 10001, + "debit_msat": 0, + "timestamp": 1758192801, + "primary_tag": "routed", + "payment_hash": "paymenthashkey01k101k101k101k101k101k101k101k101k101k101k101k101", + "fees_msat": 1 + }, + { + "created_index": 8, + "account_id": "a397dd9b3e44afcb67f3f3ce1d649b74a8ade63e35505985e4cc1828634f69a2", + "credit_msat": 0, + "debit_msat": 10000101, + "timestamp": 1758192802, + "primary_tag": "routed", + "payment_hash": "paymenthashkey02k201k201k201k201k201k201k201k201k201k201k201k201", + "fees_msat": 101 + }, + { + "created_index": 9, + "account_id": "252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7", + "credit_msat": 10000202, + "debit_msat": 0, + "timestamp": 1758192802, + "primary_tag": "routed", + "payment_hash": "paymenthashkey02k201k201k201k201k201k201k201k201k201k201k201k201", + "fees_msat": 101 + }, + { + "created_index": 10, + "account_id": "a397dd9b3e44afcb67f3f3ce1d649b74a8ade63e35505985e4cc1828634f69a2", + "credit_msat": 0, + "debit_msat": 10000, + "timestamp": 1758192802, + "primary_tag": "routed", + "payment_hash": "paymenthashkey03k301k301k301k301k301k301k301k301k301k301k301k301", + "fees_msat": 1 + }, + { + "created_index": 11, + "account_id": "252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7", + "credit_msat": 10001, + "debit_msat": 0, + "timestamp": 1758192802, + "primary_tag": "routed", + "payment_hash": "paymenthashkey03k301k301k301k301k301k301k301k301k301k301k301k301", + "fees_msat": 1 + }, + { + "created_index": 12, + "account_id": "a397dd9b3e44afcb67f3f3ce1d649b74a8ade63e35505985e4cc1828634f69a2", + "credit_msat": 0, + "debit_msat": 50000, + "timestamp": 1758192802, + "primary_tag": "routed", + "payment_hash": "paymenthashinvl0320032003200320032003200320032003200320032003200", + "fees_msat": 1 + }, + { + "created_index": 13, + "account_id": "252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7", + "credit_msat": 50001, + "debit_msat": 0, + "timestamp": 1758192802, + "primary_tag": "routed", + "payment_hash": "paymenthashinvl0320032003200320032003200320032003200320032003200", + "fees_msat": 1 + }, + { + "created_index": 14, + "account_id": "a397dd9b3e44afcb67f3f3ce1d649b74a8ade63e35505985e4cc1828634f69a2", + "credit_msat": 0, + "debit_msat": 100000, + "timestamp": 1758192803, + "primary_tag": "invoice", + "payment_hash": "paymenthashinvl0330033003300330033003300330033003300330033003300", + "part_id": 0, + "group_id": 1, + "fees_msat": 0 + }, + { + "created_index": 15, + "account_id": "a397dd9b3e44afcb67f3f3ce1d649b74a8ade63e35505985e4cc1828634f69a2", + "credit_msat": 0, + "debit_msat": 10001, + "timestamp": 1758192803, + "primary_tag": "routed", + "payment_hash": "61b929204f4db4f38e0412b2bd4c3c03668dad3575fb05f4e15a2214046c2bff", + "fees_msat": 1 + }, + { + "created_index": 16, + "account_id": "252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7", + "credit_msat": 10002, + "debit_msat": 0, + "timestamp": 1758192803, + "primary_tag": "routed", + "payment_hash": "61b929204f4db4f38e0412b2bd4c3c03668dad3575fb05f4e15a2214046c2bff", + "fees_msat": 1 + }, + { + "created_index": 17, + "account_id": "252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7", + "credit_msat": 0, + "debit_msat": 1000000, + "timestamp": 1758192821, + "primary_tag": "invoice", + "payment_hash": "paymenthashsdinvsi10si10si10si10si10si10si10si10si10si10si10si10", + "part_id": 0, + "group_id": 1, + "fees_msat": 0 + }, + { + "created_index": 18, + "account_id": "252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7", + "credit_msat": 1000, + "debit_msat": 0, + "timestamp": 1758192821, + "primary_tag": "invoice", + "payment_hash": "paymenthashinvl0270027002700270027002700270027002700270027002700", + "fees_msat": 0 + } + ] + } + }, + { + "request": { + "id": "example:listchannelmoves#2", + "method": "listchannelmoves", + "params": { + "index": "created", + "start": 10, + "limit": 2 + } + }, + "response": { + "channelmoves": [ + { + "created_index": 10, + "account_id": "a397dd9b3e44afcb67f3f3ce1d649b74a8ade63e35505985e4cc1828634f69a2", + "credit_msat": 0, + "debit_msat": 10000, + "timestamp": 1758192802, + "primary_tag": "routed", + "payment_hash": "paymenthashkey03k301k301k301k301k301k301k301k301k301k301k301k301", + "fees_msat": 1 + }, + { + "created_index": 11, + "account_id": "252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7", + "credit_msat": 10001, + "debit_msat": 0, + "timestamp": 1758192802, + "primary_tag": "routed", + "payment_hash": "paymenthashkey03k301k301k301k301k301k301k301k301k301k301k301k301", + "fees_msat": 1 + } + ] + } + } ] } diff --git a/gossipd/Makefile b/gossipd/Makefile index c0732482d75f..76999cf93f67 100644 --- a/gossipd/Makefile +++ b/gossipd/Makefile @@ -35,6 +35,7 @@ GOSSIPD_COMMON_OBJS := \ common/bigsize.o \ common/bip32.o \ common/channel_id.o \ + common/clock_time.o \ common/cryptomsg.o \ common/daemon.o \ common/daemon_conn.o \ @@ -56,6 +57,7 @@ GOSSIPD_COMMON_OBJS := \ common/ping.o \ common/psbt_open.o \ common/pseudorand.o \ + common/randbytes.o \ common/random_select.o \ common/setup.o \ common/status.o \ diff --git a/gossipd/gossip_store.c b/gossipd/gossip_store.c index 906b6c10f22e..120b265b80f1 100644 --- a/gossipd/gossip_store.c +++ b/gossipd/gossip_store.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -204,7 +205,7 @@ static int gossip_store_compact(struct daemon *daemon, struct gossip_hdr hdr; u8 oldversion, version = GOSSIP_STORE_VER; struct stat st; - struct timeabs start = time_now(); + struct timemono start = time_mono(); const char *bad; *populated = false; @@ -351,7 +352,7 @@ static int gossip_store_compact(struct daemon *daemon, /* If we have any contents, and the file is less than 1 hour * old, say "seems good" */ - if (st.st_mtime > time_now().ts.tv_sec - 3600 && *total_len > 1) { + if (st.st_mtime > clock_time().ts.tv_sec - 3600 && *total_len > 1) { *populated = true; } @@ -370,7 +371,7 @@ static int gossip_store_compact(struct daemon *daemon, } status_debug("Store compact time: %"PRIu64" msec", - time_to_msec(time_between(time_now(), start))); + time_to_msec(timemono_between(time_mono(), start))); status_debug("gossip_store: Read %zu/%zu/%zu/%zu cannounce/cupdate/nannounce/delete from store in %"PRIu64" bytes, now %"PRIu64" bytes (populated=%s)", cannounces, cupdates, nannounces, deleted, old_len, *total_len, diff --git a/gossipd/gossipd.c b/gossipd/gossipd.c index 41807050806f..de420fd485a0 100644 --- a/gossipd/gossipd.c +++ b/gossipd/gossipd.c @@ -13,6 +13,7 @@ #include "config.h" #include #include +#include #include #include #include @@ -374,19 +375,11 @@ static void master_or_connectd_gone(struct daemon_conn *dc UNUSED) exit(2); } -struct timeabs gossip_time_now(const struct daemon *daemon) -{ - if (daemon->dev_gossip_time) - return *daemon->dev_gossip_time; - - return time_now(); -} - /* We don't check this when loading from the gossip_store: that would break * our canned tests, and usually old gossip is better than no gossip */ bool timestamp_reasonable(const struct daemon *daemon, u32 timestamp) { - u64 now = gossip_time_now(daemon).ts.tv_sec; + u64 now = clock_time().ts.tv_sec; /* More than one day ahead? */ if (timestamp > now + 24*60*60) @@ -400,27 +393,16 @@ bool timestamp_reasonable(const struct daemon *daemon, u32 timestamp) /*~ Parse init message from lightningd: starts the daemon properly. */ static void gossip_init(struct daemon *daemon, const u8 *msg) { - u32 *dev_gossip_time; - if (!fromwire_gossipd_init(daemon, msg, &chainparams, &daemon->our_features, &daemon->id, - &dev_gossip_time, &daemon->dev_fast_gossip, &daemon->dev_fast_gossip_prune, &daemon->autoconnect_seeker_peers)) { master_badmsg(WIRE_GOSSIPD_INIT, msg); } - if (dev_gossip_time) { - assert(daemon->developer); - daemon->dev_gossip_time = tal(daemon, struct timeabs); - daemon->dev_gossip_time->ts.tv_sec = *dev_gossip_time; - daemon->dev_gossip_time->ts.tv_nsec = 0; - tal_free(dev_gossip_time); - } - /* Gossmap manager starts up */ daemon->gm = gossmap_manage_new(daemon, daemon); @@ -479,7 +461,6 @@ static void dev_gossip_memleak(struct daemon *daemon, const u8 *msg) memleak_ptr(memtable, msg); /* Now delete daemon and those which it has pointers to. */ memleak_scan_obj(memtable, daemon); - memleak_scan_htable(memtable, &daemon->peers->raw); dev_seeker_memleak(memtable, daemon->seeker); gossmap_manage_memleak(memtable, daemon->gm); @@ -489,18 +470,6 @@ static void dev_gossip_memleak(struct daemon *daemon, const u8 *msg) found_leak))); } -static void dev_gossip_set_time(struct daemon *daemon, const u8 *msg) -{ - u32 time; - - if (!fromwire_gossipd_dev_set_time(msg, &time)) - master_badmsg(WIRE_GOSSIPD_DEV_SET_TIME, msg); - if (!daemon->dev_gossip_time) - daemon->dev_gossip_time = tal(daemon, struct timeabs); - daemon->dev_gossip_time->ts.tv_sec = time; - daemon->dev_gossip_time->ts.tv_nsec = 0; -} - /*~ lightningd tells us when about a gossip message directly, when told to by * the addgossip RPC call. That's usually used when a plugin gets an update * returned in an payment error. */ @@ -592,12 +561,6 @@ static struct io_plan *recv_req(struct io_conn *conn, goto done; } /* fall thru */ - case WIRE_GOSSIPD_DEV_SET_TIME: - if (daemon->developer) { - dev_gossip_set_time(daemon, msg); - goto done; - } - /* fall thru */ /* We send these, we don't receive them */ case WIRE_GOSSIPD_INIT_CUPDATE: @@ -631,9 +594,7 @@ int main(int argc, char *argv[]) daemon = tal(NULL, struct daemon); daemon->developer = developer; - daemon->dev_gossip_time = NULL; - daemon->peers = tal(daemon, struct peer_node_id_map); - peer_node_id_map_init(daemon->peers); + daemon->peers = new_htable(daemon, peer_node_id_map); daemon->deferred_txouts = tal_arr(daemon, struct short_channel_id, 0); daemon->current_blockheight = 0; /* i.e. unknown */ @@ -643,7 +604,7 @@ int main(int argc, char *argv[]) /* Note the use of time_mono() here. That's a monotonic clock, which * is really useful: it can only be used to measure relative events * (there's no correspondence to time-since-Ken-grew-a-beard or - * anything), but unlike time_now(), this will never jump backwards by + * anything), but unlike time_now, this will never jump backwards by * half a second and leave me wondering how my tests failed CI! */ timers_init(&daemon->timers, time_mono()); diff --git a/gossipd/gossipd.h b/gossipd/gossipd.h index 8318156348dc..6a347e61b251 100644 --- a/gossipd/gossipd.h +++ b/gossipd/gossipd.h @@ -65,9 +65,6 @@ struct daemon { /* Features lightningd told us to set. */ struct feature_set *our_features; - /* Override local time for gossip messages */ - struct timeabs *dev_gossip_time; - /* Speed up gossip. */ bool dev_fast_gossip; @@ -163,13 +160,6 @@ void tell_lightningd_peer_update(struct daemon *daemon, struct amount_msat htlc_minimum, struct amount_msat htlc_maximum); -/** - * Get the local time. - * - * This gets overridden in dev mode so we can use canned (stale) gossip. - */ -struct timeabs gossip_time_now(const struct daemon *daemon); - /** * Is this gossip timestamp reasonable? */ diff --git a/gossipd/gossipd_wire.csv b/gossipd/gossipd_wire.csv index d8bee4b298bb..10ba124da4a7 100644 --- a/gossipd/gossipd_wire.csv +++ b/gossipd/gossipd_wire.csv @@ -9,7 +9,6 @@ msgtype,gossipd_init,3000 msgdata,gossipd_init,chainparams,chainparams, msgdata,gossipd_init,our_features,feature_set, msgdata,gossipd_init,id,node_id, -msgdata,gossipd_init,dev_gossip_time,?u32, msgdata,gossipd_init,dev_fast_gossip,bool, msgdata,gossipd_init,dev_fast_gossip_prune,bool, msgdata,gossipd_init,autoconnect_seeker_peers,u32, @@ -27,10 +26,6 @@ msgdata,gossipd_init_nannounce,nannounce,u8,len msgtype,gossipd_init_reply,3100 -# In developer mode, we can mess with time. -msgtype,gossipd_dev_set_time,3001 -msgdata,gossipd_dev_set_time,dev_gossip_time,u32, - # Gossipd->master get this tx output please. msgtype,gossipd_get_txout,3018 msgdata,gossipd_get_txout,short_channel_id,short_channel_id, diff --git a/gossipd/gossmap_manage.c b/gossipd/gossmap_manage.c index 29b0a8db1d83..c75f8a19b94f 100644 --- a/gossipd/gossmap_manage.c +++ b/gossipd/gossmap_manage.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -356,7 +357,7 @@ static bool channel_already_dying(const struct chan_dying dying_channels[], /* Every half a week we look for dead channels (faster in dev) */ static void prune_network(struct gossmap_manage *gm) { - u64 now = gossip_time_now(gm->daemon).ts.tv_sec; + u64 now = clock_time().ts.tv_sec; /* Anything below this highwater mark ought to be pruned */ const s64 highwater = now - GOSSIP_PRUNE_INTERVAL(gm->daemon->dev_fast_gossip_prune); const struct gossmap_node *me; diff --git a/gossipd/seeker.c b/gossipd/seeker.c index 414aa3e73626..7a8a7e76f849 100644 --- a/gossipd/seeker.c +++ b/gossipd/seeker.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -245,7 +246,7 @@ static void enable_gossip_stream(struct seeker *seeker, struct peer *peer, start = 0; } else { /* Just in case they care */ - start = time_now().ts.tv_sec - GOSSIP_SEEKER_INTERVAL(seeker) * 10; + start = clock_time().ts.tv_sec - GOSSIP_SEEKER_INTERVAL(seeker) * 10; } status_peer_debug(&peer->id, "seeker: starting gossip (%s)", diff --git a/gossipd/test/Makefile b/gossipd/test/Makefile index 99cb7faafd3f..d87aa8a9a998 100644 --- a/gossipd/test/Makefile +++ b/gossipd/test/Makefile @@ -19,6 +19,7 @@ GOSSIPD_TEST_COMMON_OBJS := \ common/node_id.o \ common/lease_rates.o \ common/pseudorand.o \ + common/randbytes.o \ common/setup.o \ common/utils.o \ common/wireaddr.o \ diff --git a/gossipd/test/run-check_channel_announcement.c b/gossipd/test/run-check_channel_announcement.c index 6c743d4d9871..a55ca5dca6ab 100644 --- a/gossipd/test/run-check_channel_announcement.c +++ b/gossipd/test/run-check_channel_announcement.c @@ -33,8 +33,10 @@ In particular, we set feature bit 19. The spec says we should set feature bit 1 #include #include #include +#include #include #include +#include #include #include #include @@ -56,6 +58,12 @@ bool blinding_next_path_privkey(const struct privkey *e UNNEEDED, const struct sha256 *h UNNEEDED, struct privkey *next UNNEEDED) { fprintf(stderr, "blinding_next_path_privkey called!\n"); abort(); } +/* Generated stub for clock_time_overridden */ +bool clock_time_overridden(void) +{ fprintf(stderr, "clock_time_overridden called!\n"); abort(); } +/* Generated stub for clock_time_progresses_ */ +struct timeabs clock_time_progresses_(u64 *progress UNNEEDED) +{ fprintf(stderr, "clock_time_progresses_ called!\n"); abort(); } /* Generated stub for fromwire_sciddir_or_pubkey */ void fromwire_sciddir_or_pubkey(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct sciddir_or_pubkey *sciddpk UNNEEDED) diff --git a/gossipd/test/run-extended-info.c b/gossipd/test/run-extended-info.c index 45e19884d049..5dfe23ae8813 100644 --- a/gossipd/test/run-extended-info.c +++ b/gossipd/test/run-extended-info.c @@ -4,9 +4,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -31,6 +33,12 @@ bool blinding_next_path_privkey(const struct privkey *e UNNEEDED, const struct sha256 *h UNNEEDED, struct privkey *next UNNEEDED) { fprintf(stderr, "blinding_next_path_privkey called!\n"); abort(); } +/* Generated stub for clock_time_overridden */ +bool clock_time_overridden(void) +{ fprintf(stderr, "clock_time_overridden called!\n"); abort(); } +/* Generated stub for clock_time_progresses_ */ +struct timeabs clock_time_progresses_(u64 *progress UNNEEDED) +{ fprintf(stderr, "clock_time_progresses_ called!\n"); abort(); } /* Generated stub for decode_channel_update_timestamps */ struct channel_update_timestamps *decode_channel_update_timestamps(const tal_t *ctx UNNEEDED, const struct tlv_reply_channel_range_tlvs_timestamps_tlv *timestamps_tlv UNNEEDED) diff --git a/gossipd/test/run-next_block_range.c b/gossipd/test/run-next_block_range.c index 49bd20f9eea7..a7178390152f 100644 --- a/gossipd/test/run-next_block_range.c +++ b/gossipd/test/run-next_block_range.c @@ -27,6 +27,15 @@ bool blinding_next_path_privkey(const struct privkey *e UNNEEDED, const struct sha256 *h UNNEEDED, struct privkey *next UNNEEDED) { fprintf(stderr, "blinding_next_path_privkey called!\n"); abort(); } +/* Generated stub for clock_time */ +struct timeabs clock_time(void) +{ fprintf(stderr, "clock_time called!\n"); abort(); } +/* Generated stub for clock_time_overridden */ +bool clock_time_overridden(void) +{ fprintf(stderr, "clock_time_overridden called!\n"); abort(); } +/* Generated stub for clock_time_progresses_ */ +struct timeabs clock_time_progresses_(u64 *progress UNNEEDED) +{ fprintf(stderr, "clock_time_progresses_ called!\n"); abort(); } /* Generated stub for daemon_conn_send */ void daemon_conn_send(struct daemon_conn *dc UNNEEDED, const u8 *msg UNNEEDED) { fprintf(stderr, "daemon_conn_send called!\n"); abort(); } diff --git a/gossipd/test/run-txout_failure.c b/gossipd/test/run-txout_failure.c index ebb740ea77f4..0985c5f49096 100644 --- a/gossipd/test/run-txout_failure.c +++ b/gossipd/test/run-txout_failure.c @@ -3,9 +3,11 @@ #include "../common/timeout.c" #include #include +#include #include #include #include +#include #include #include #include @@ -29,6 +31,12 @@ bool blinding_next_path_privkey(const struct privkey *e UNNEEDED, const struct sha256 *h UNNEEDED, struct privkey *next UNNEEDED) { fprintf(stderr, "blinding_next_path_privkey called!\n"); abort(); } +/* Generated stub for clock_time_overridden */ +bool clock_time_overridden(void) +{ fprintf(stderr, "clock_time_overridden called!\n"); abort(); } +/* Generated stub for clock_time_progresses_ */ +struct timeabs clock_time_progresses_(u64 *progress UNNEEDED) +{ fprintf(stderr, "clock_time_progresses_ called!\n"); abort(); } /* Generated stub for fromwire_sciddir_or_pubkey */ void fromwire_sciddir_or_pubkey(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct sciddir_or_pubkey *sciddpk UNNEEDED) diff --git a/hsmd/Makefile b/hsmd/Makefile index b4f51bef2ffd..fc3aa3826d00 100644 --- a/hsmd/Makefile +++ b/hsmd/Makefile @@ -31,6 +31,7 @@ HSMD_COMMON_OBJS := \ common/bolt12_id.o \ common/bolt12_merkle.o \ common/channel_id.o \ + common/clock_time.o \ common/daemon.o \ common/daemon_conn.o \ common/derive_basepoints.o \ @@ -46,6 +47,7 @@ HSMD_COMMON_OBJS := \ common/permute_tx.o \ common/psbt_open.o \ common/pseudorand.o \ + common/randbytes.o \ common/setup.o \ common/status.o \ common/status_wire.o \ diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index ff6d1e7b2c91..eaa8a5fc4f61 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -322,7 +323,7 @@ static void maybe_create_new_hsm(const struct secret *encryption_key, /*~ This is libsodium's cryptographic randomness routine: we assume * it's doing a good job. */ if (random_hsm) - randombytes_buf(&hsm_secret, sizeof(hsm_secret)); + randbytes(&hsm_secret, sizeof(hsm_secret)); /*~ If an encryption_key was provided, store an encrypted seed. */ if (encryption_key) diff --git a/lightningd/Makefile b/lightningd/Makefile index fbf1d10f47a1..250835584629 100644 --- a/lightningd/Makefile +++ b/lightningd/Makefile @@ -95,6 +95,7 @@ LIGHTNINGD_COMMON_OBJS := \ common/channel_config.o \ common/channel_id.o \ common/channel_type.o \ + common/clock_time.o \ common/coin_mvt.o \ common/configdir.o \ common/configvar.o \ @@ -139,6 +140,7 @@ LIGHTNINGD_COMMON_OBJS := \ common/psbt_open.o \ common/pseudorand.o \ common/plugin.o \ + common/randbytes.o \ common/random_select.o \ common/setup.o \ common/shutdown_scriptpubkey.o \ diff --git a/lightningd/bitcoind.c b/lightningd/bitcoind.c index 771ccf2f9f0a..879e2d87fe7c 100644 --- a/lightningd/bitcoind.c +++ b/lightningd/bitcoind.c @@ -703,7 +703,6 @@ struct filteredblock_call { struct filteredblock *result; struct filteredblock_outpoint **outpoints; size_t current_outpoint; - struct timeabs start_time; u32 height; }; @@ -858,7 +857,6 @@ void bitcoind_getfilteredblock_(const tal_t *ctx, call->arg = arg; call->height = height; assert(call->cb != NULL); - call->start_time = time_now(); call->result = NULL; call->current_outpoint = 0; diff --git a/lightningd/chaintopology.c b/lightningd/chaintopology.c index 59f004f732a7..5214b490ed0e 100644 --- a/lightningd/chaintopology.c +++ b/lightningd/chaintopology.c @@ -356,6 +356,37 @@ static void watch_for_utxo_reconfirmation(struct chain_topology *topo, } } +static enum watch_result tx_confirmed(struct lightningd *ld, + const struct bitcoin_txid *txid, + const struct bitcoin_tx *tx, + unsigned int depth, + void *unused) +{ + /* We don't actually need to do anything here: the fact that we were + * watching the tx made chaintopology.c update the transaction depth */ + if (depth != 0) + return DELETE_WATCH; + return KEEP_WATCHING; +} + +void watch_unconfirmed_txid(struct lightningd *ld, + struct chain_topology *topo, + const struct bitcoin_txid *txid) +{ + watch_txid(ld->wallet, topo, txid, tx_confirmed, NULL); +} + +static void watch_for_unconfirmed_txs(struct lightningd *ld, + struct chain_topology *topo) +{ + struct bitcoin_txid *txids; + + txids = wallet_transactions_by_height(tmpctx, ld->wallet, 0); + log_debug(ld->log, "Got %zu unconfirmed transactions", tal_count(txids)); + for (size_t i = 0; i < tal_count(txids); i++) + watch_unconfirmed_txid(ld, topo, &txids[i]); +} + /* Mutual recursion via timer. */ static void next_updatefee_timer(struct chain_topology *topo); @@ -1028,6 +1059,7 @@ static void remove_tip(struct chain_topology *topo) /* This may have unconfirmed txs: reconfirm as we add blocks. */ watch_for_utxo_reconfirmation(topo, topo->ld->wallet); + block_map_del(topo->block_map, b); /* These no longer exist, so gossipd drops any reference to them just @@ -1197,14 +1229,10 @@ struct chain_topology *new_topology(struct lightningd *ld, struct logger *log) struct chain_topology *topo = tal(ld, struct chain_topology); topo->ld = ld; - topo->block_map = tal(topo, struct block_map); - block_map_init(topo->block_map); - topo->outgoing_txs = tal(topo, struct outgoing_tx_map); - outgoing_tx_map_init(topo->outgoing_txs); - topo->txwatches = tal(topo, struct txwatch_hash); - txwatch_hash_init(topo->txwatches); - topo->txowatches = tal(topo, struct txowatch_hash); - txowatch_hash_init(topo->txowatches); + topo->block_map = new_htable(topo, block_map); + topo->outgoing_txs = new_htable(topo, outgoing_tx_map); + topo->txwatches = new_htable(topo, txwatch_hash); + topo->txowatches = new_htable(topo, txowatch_hash); topo->log = log; topo->bitcoind = new_bitcoind(topo, ld, log); topo->poll_seconds = 30; @@ -1478,6 +1506,11 @@ void setup_topology(struct chain_topology *topo) /* May have unconfirmed txs: reconfirm as we add blocks. */ watch_for_utxo_reconfirmation(topo, topo->ld->wallet); + + /* We usually watch txs because we have outputs coming to us, or they're + * related to a channel. But not if they're created by sendpsbt without any + * outputs to us. */ + watch_for_unconfirmed_txs(topo->ld, topo); db_commit_transaction(topo->ld->wallet->db); tal_free(local_ctx); diff --git a/lightningd/chaintopology.h b/lightningd/chaintopology.h index 4f80d21622a8..8a867b0e21f1 100644 --- a/lightningd/chaintopology.h +++ b/lightningd/chaintopology.h @@ -12,6 +12,7 @@ struct command; struct lightningd; struct peer; struct txwatch; +struct wallet; /* We keep the last three in case there are outliers (for min/max) */ #define FEE_HISTORY_NUM 3 @@ -280,4 +281,11 @@ void topology_add_sync_waiter_(const tal_t *ctx, /* In channel_control.c */ void notify_feerate_change(struct lightningd *ld); + +/* We want to update db when this txid is confirmed. We always do this + * if it's related to a channel or incoming funds, but sendpsbt without + * change would be otherwise untracked. */ +void watch_unconfirmed_txid(struct lightningd *ld, + struct chain_topology *topo, + const struct bitcoin_txid *txid); #endif /* LIGHTNING_LIGHTNINGD_CHAINTOPOLOGY_H */ diff --git a/lightningd/channel.c b/lightningd/channel.c index 354249a4c24c..9a84b799a388 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -1,9 +1,11 @@ #include "config.h" #include #include +#include #include #include #include +#include #include #include #include @@ -343,7 +345,6 @@ struct channel *new_unsaved_channel(struct peer *peer, channel->openchannel_signed_cmd = NULL; channel->state = DUALOPEND_OPEN_INIT; channel->owner = NULL; - channel->scb = NULL; channel->reestablished = false; memset(&channel->billboard, 0, sizeof(channel->billboard)); channel->billboard.transient = tal_fmt(channel, "%s", @@ -578,30 +579,6 @@ struct channel *new_channel(struct peer *peer, u64 dbid, channel->billboard.transient = tal_strdup(channel, transient_billboard); channel->channel_info = *channel_info; - /* If it's a unix domain socket connection, we don't save it */ - if (peer->addr.itype == ADDR_INTERNAL_WIREADDR) { - channel->scb = tal(channel, struct modern_scb_chan); - channel->scb->id = dbid; - /* More useful to have last_known_addr, if avail */ - if (peer->last_known_addr) - channel->scb->addr = *peer->last_known_addr; - channel->scb->addr = peer->addr.u.wireaddr.wireaddr; - channel->scb->node_id = peer->id; - channel->scb->funding = *funding; - channel->scb->cid = *cid; - channel->scb->funding_sats = funding_sats; - channel->scb->type = channel_type_dup(channel->scb, type); - - struct tlv_scb_tlvs *scb_tlvs = tlv_scb_tlvs_new(channel); - scb_tlvs->shachain = &channel->their_shachain.chain; - scb_tlvs->basepoints = &channel->channel_info.theirbase; - scb_tlvs->opener = &channel->opener; - scb_tlvs->remote_to_self_delay = &channel->channel_info.their_config.to_self_delay; - - channel->scb->tlvs = scb_tlvs; - } else - channel->scb = NULL; - if (!log) { channel->log = new_logger(channel, peer->ld->log_book, @@ -1034,7 +1011,7 @@ void channel_set_state(struct channel *channel, struct channel_state_change *change; change = new_channel_state_change(channel->state_changes, - time_now(), + clock_time(), old_state, state, reason, diff --git a/lightningd/channel.h b/lightningd/channel.h index af2f18a54b8a..94960601b434 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -294,7 +294,7 @@ struct channel { u32 feerate_base, feerate_ppm; /* But allow these feerates/htlcs up until this time. */ - struct timeabs old_feerate_timeout; + struct timemono old_feerate_timeout; u32 old_feerate_base, old_feerate_ppm; struct amount_msat old_htlc_minimum_msat, old_htlc_maximum_msat; @@ -343,10 +343,6 @@ struct channel { /* Lease commited max part per thousandth channel fee (ppm * 1000) */ u16 lease_chan_max_ppt; - /* `Channel-shell` of this channel - * (Minimum information required to backup this channel). */ - struct modern_scb_chan *scb; - /* Do we allow the peer to set any fee it wants? */ bool ignore_fee_limits; diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index a72f959837ae..d44e03323ba6 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -1134,7 +1134,8 @@ static void handle_peer_splice_locked(struct channel *channel, const u8 *msg) wallet_htlcsigs_confirm_inflight(channel->peer->ld->wallet, channel, &inflight->funding->outpoint); - update_channel_from_inflight(channel->peer->ld, channel, inflight, true); + /* Stop watching previous funding tx (could be, for announcement) */ + channel_unwatch_funding(channel->peer->ld, channel); /* Stash prev funding data so we can log it after scid is updated * (to get the blockheight) */ @@ -1142,6 +1143,8 @@ static void handle_peer_splice_locked(struct channel *channel, const u8 *msg) prev_funding_sats = channel->funding_sats; prev_funding_out = channel->funding; + update_channel_from_inflight(channel->peer->ld, channel, inflight, true); + channel->our_msat.millisatoshis += splice_amnt * 1000; /* Raw: splicing */ channel->msat_to_us_min.millisatoshis += splice_amnt * 1000; /* Raw: splicing */ channel->msat_to_us_max.millisatoshis += splice_amnt * 1000; /* Raw: splicing */ @@ -1824,6 +1827,9 @@ bool peer_start_channeld(struct channel *channel, if (inflight->splice_locked_memonly) continue; + if (!inflight->funding->splice_remote_funding) + continue; + infcopy = tal(inflights, struct inflight); infcopy->remote_funding = *inflight->funding->splice_remote_funding; diff --git a/lightningd/channel_gossip.c b/lightningd/channel_gossip.c index d4153b207ad4..04da4555eeda 100644 --- a/lightningd/channel_gossip.c +++ b/lightningd/channel_gossip.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -582,7 +583,7 @@ static void arm_refresh_timer(struct channel *channel) { struct lightningd *ld = channel->peer->ld; struct channel_gossip *cg = channel->channel_gossip; - struct timeabs now = time_now(), due; + struct timeabs now = clock_time(), due; u32 timestamp; if (!channel_update_details(cg->cupdate, ×tamp, NULL)) { @@ -1188,7 +1189,7 @@ void channel_gossip_init_done(struct lightningd *ld) static void channel_reestablished_stable(struct channel *channel) { channel->stable_conn_timer = NULL; - channel->last_stable_connection = time_now().ts.tv_sec; + channel->last_stable_connection = clock_time().ts.tv_sec; wallet_channel_save(channel->peer->ld->wallet, channel); } diff --git a/lightningd/coin_mvts.c b/lightningd/coin_mvts.c index cc206b62b1bb..f1195aff7e2a 100644 --- a/lightningd/coin_mvts.c +++ b/lightningd/coin_mvts.c @@ -1,6 +1,7 @@ #include "config.h" #include #include +#include #include #include #include @@ -12,7 +13,7 @@ struct channel_coin_mvt *new_channel_mvt_invoice_hin(const tal_t *ctx, const struct htlc_in *hin, const struct channel *channel) { - return new_channel_coin_mvt(ctx, channel, time_now().ts.tv_sec, + return new_channel_coin_mvt(ctx, channel, coinmvt_current_time(), &hin->payment_hash, NULL, NULL, COIN_CREDIT, hin->msat, mk_mvt_tags(MVT_INVOICE), @@ -32,7 +33,7 @@ struct channel_coin_mvt *new_channel_mvt_routed_hin(const tal_t *ctx, hin->payload->amt_to_forward)) return NULL; - return new_channel_coin_mvt(ctx, channel, time_now().ts.tv_sec, + return new_channel_coin_mvt(ctx, channel, coinmvt_current_time(), &hin->payment_hash, NULL, NULL, COIN_CREDIT, hin->msat, mk_mvt_tags(MVT_ROUTED), @@ -43,7 +44,7 @@ struct channel_coin_mvt *new_channel_mvt_invoice_hout(const tal_t *ctx, const struct htlc_out *hout, const struct channel *channel) { - return new_channel_coin_mvt(ctx, channel, time_now().ts.tv_sec, + return new_channel_coin_mvt(ctx, channel, coinmvt_current_time(), &hout->payment_hash, &hout->partid, &hout->groupid, @@ -56,7 +57,7 @@ struct channel_coin_mvt *new_channel_mvt_routed_hout(const tal_t *ctx, const struct htlc_out *hout, const struct channel *channel) { - return new_channel_coin_mvt(ctx, channel, time_now().ts.tv_sec, + return new_channel_coin_mvt(ctx, channel, coinmvt_current_time(), &hout->payment_hash, NULL, NULL, COIN_DEBIT, hout->msat, mk_mvt_tags(MVT_ROUTED), @@ -68,7 +69,7 @@ struct channel_coin_mvt *new_channel_mvt_penalty_adj(const tal_t *ctx, struct amount_msat amount, enum coin_mvt_dir direction) { - return new_channel_coin_mvt(ctx, channel, time_now().ts.tv_sec, + return new_channel_coin_mvt(ctx, channel, coinmvt_current_time(), NULL, NULL, NULL, direction, amount, mk_mvt_tags(MVT_PENALTY_ADJ), @@ -109,7 +110,7 @@ void send_account_balance_snapshot(struct lightningd *ld) struct peer_node_id_map_iter it; snap->blockheight = get_block_height(ld->topology); - snap->timestamp = time_now().ts.tv_sec; + snap->timestamp = coinmvt_current_time(); snap->node_id = &ld->our_nodeid; /* Add the 'wallet' account balance */ diff --git a/lightningd/dual_open_control.c b/lightningd/dual_open_control.c index 3ad5cfb1dbb7..185450d0459f 100644 --- a/lightningd/dual_open_control.c +++ b/lightningd/dual_open_control.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -33,6 +34,7 @@ #include #include #include +#include struct commit_rcvd { struct channel *channel; @@ -1336,7 +1338,7 @@ wallet_update_channel_commit(struct lightningd *ld, &channel->peer->id, &channel->cid, channel->scid, - time_now(), + clock_time(), DUALOPEND_OPEN_COMMIT_READY, DUALOPEND_OPEN_COMMITTED, REASON_REMOTE, @@ -1434,7 +1436,7 @@ wallet_commit_channel(struct lightningd *ld, &channel->peer->id, &channel->cid, channel->scid, - time_now(), + clock_time(), DUALOPEND_OPEN_INIT, DUALOPEND_OPEN_COMMIT_READY, REASON_REMOTE, @@ -1467,28 +1469,9 @@ wallet_commit_channel(struct lightningd *ld, &commitment_feerate); channel->min_possible_feerate = commitment_feerate; channel->max_possible_feerate = commitment_feerate; - if (channel->peer->addr.itype == ADDR_INTERNAL_WIREADDR) { - channel->scb = tal(channel, struct modern_scb_chan); - channel->scb->id = channel->dbid; - channel->scb->addr = channel->peer->addr.u.wireaddr.wireaddr; - channel->scb->node_id = channel->peer->id; - channel->scb->funding = *funding; - channel->scb->cid = channel->cid; - channel->scb->funding_sats = total_funding; - - struct tlv_scb_tlvs *scb_tlvs = tlv_scb_tlvs_new(channel); - scb_tlvs->shachain = &channel->their_shachain.chain; - scb_tlvs->basepoints = &channel_info->theirbase; - scb_tlvs->opener = &channel->opener; - scb_tlvs->remote_to_self_delay = &channel_info->their_config.to_self_delay; - - channel->scb->tlvs = scb_tlvs; - } else - channel->scb = NULL; tal_free(channel->type); channel->type = channel_type_dup(channel, type); - channel->scb->type = channel_type_dup(channel->scb, type); if (our_upfront_shutdown_script) channel->shutdown_scriptpubkey[LOCAL] @@ -4083,6 +4066,35 @@ static void dualopen_errmsg(struct channel *channel, err_for_them ? "sent" : "received", desc); } +/* This is a hack for CLN_DEV_ENTROPY_SEED. We cannot actually use + * the same seed for each dualopend, or they choose the same ids, and we + * clash when combining the PSBTs (this is phenomenally unlikey normally). + * So we set it (for the child) to an incrementing value. */ +static const char *dev_setup_dualopend_seed(const tal_t *ctx, struct lightningd *ld) +{ + static u64 seed_incr = 0; + char seedstr[STR_MAX_CHARS(u64)]; + const char *old_seed; + + if (!ld->developer) + return NULL; + + old_seed = getenv("CLN_DEV_ENTROPY_SEED"); + if (!old_seed) + return NULL; + + old_seed = tal_strdup(tmpctx, old_seed); + seed_incr++; + snprintf(seedstr, sizeof(seedstr), "%"PRIu64, atol(old_seed) + seed_incr); + setenv("CLN_DEV_ENTROPY_SEED", seedstr, 1); + return old_seed; +} + +static void dev_restore_seed(const char *old_seed) +{ + if (old_seed) + setenv("CLN_DEV_ENTROPY_SEED", old_seed, 1); +} bool peer_start_dualopend(struct peer *peer, struct peer_fd *peer_fd, @@ -4092,6 +4104,7 @@ bool peer_start_dualopend(struct peer *peer, u32 max_to_self_delay; struct amount_msat min_effective_htlc_capacity; const u8 *msg; + const char *dev_old_seed; hsmfd = hsm_get_client_fd(peer->ld, &peer->id, channel->unsaved_dbid, HSM_PERM_COMMITMENT_POINT @@ -4105,6 +4118,7 @@ bool peer_start_dualopend(struct peer *peer, return false; } + dev_old_seed = dev_setup_dualopend_seed(tmpctx, peer->ld); channel->owner = new_channel_subd(channel, peer->ld, "lightning_dualopend", @@ -4117,6 +4131,7 @@ bool peer_start_dualopend(struct peer *peer, channel_set_billboard, take(&peer_fd->fd), take(&hsmfd), NULL); + dev_restore_seed(dev_old_seed); if (!channel->owner) { channel_internal_error(channel, @@ -4170,6 +4185,7 @@ bool peer_restart_dualopend(struct peer *peer, int hsmfd; u32 *local_shutdown_script_wallet_index; u8 *msg; + const char *dev_old_seed; if (channel_state_uncommitted(channel->state)) return peer_start_dualopend(peer, peer_fd, channel); @@ -4189,6 +4205,7 @@ bool peer_restart_dualopend(struct peer *peer, return false; } + dev_old_seed = dev_setup_dualopend_seed(tmpctx, peer->ld); channel_set_owner(channel, new_channel_subd(channel, peer->ld, "lightning_dualopend", @@ -4201,6 +4218,8 @@ bool peer_restart_dualopend(struct peer *peer, channel_set_billboard, take(&peer_fd->fd), take(&hsmfd), NULL)); + dev_restore_seed(dev_old_seed); + if (!channel->owner) { log_broken(channel->log, "Could not subdaemon channel: %s", strerror(errno)); diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index 4e931a7844cf..8bc5f86d6d0d 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -202,7 +202,6 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) case WIRE_GOSSIPD_GET_TXOUT_REPLY: case WIRE_GOSSIPD_OUTPOINTS_SPENT: case WIRE_GOSSIPD_DEV_MEMLEAK: - case WIRE_GOSSIPD_DEV_SET_TIME: case WIRE_GOSSIPD_NEW_BLOCKHEIGHT: case WIRE_GOSSIPD_ADDGOSSIP: /* This is a reply, so never gets through to here. */ @@ -329,7 +328,6 @@ void gossip_init(struct lightningd *ld, int connectd_fd) chainparams, ld->our_features, &ld->our_nodeid, - ld->dev_gossip_time ? &ld->dev_gossip_time: NULL, ld->dev_fast_gossip, ld->dev_fast_gossip_prune, ld->autoconnect_seeker_peers); @@ -498,29 +496,3 @@ static const struct json_command dev_set_max_scids_encode_size = { .dev_only = true, }; AUTODATA(json_command, &dev_set_max_scids_encode_size); - -static struct command_result *json_dev_gossip_set_time(struct command *cmd, - const char *buffer, - const jsmntok_t *obj UNNEEDED, - const jsmntok_t *params) -{ - u8 *msg; - u32 *time; - - if (!param(cmd, buffer, params, - p_req("time", param_number, &time), - NULL)) - return command_param_failed(); - - msg = towire_gossipd_dev_set_time(NULL, *time); - subd_send_msg(cmd->ld->gossip, take(msg)); - - return command_success(cmd, json_stream_success(cmd)); -} - -static const struct json_command dev_gossip_set_time = { - "dev-gossip-set-time", - json_dev_gossip_set_time, - .dev_only = true, -}; -AUTODATA(json_command, &dev_gossip_set_time); diff --git a/lightningd/gossip_generation.c b/lightningd/gossip_generation.c index 22877c9c0596..b4dffe5ac97d 100644 --- a/lightningd/gossip_generation.c +++ b/lightningd/gossip_generation.c @@ -1,6 +1,7 @@ #include "config.h" #include #include +#include #include #include #include @@ -124,7 +125,7 @@ u8 *unsigned_channel_update(const tal_t *ctx, message_flags |= ROUTING_OPT_DONT_FORWARD; /* Make sure timestamp changes! */ - timestamp = time_now().ts.tv_sec; + timestamp = clock_time().ts.tv_sec; /* FIXME: @endothermicdev points out that our clock could be * wrong once, and now we'll keep producing future timestamps. * We could sanity check that old_timestamp is within 2 weeks and @@ -417,7 +418,7 @@ u8 *unsigned_node_announcement(const tal_t *ctx, { secp256k1_ecdsa_signature sig; const struct wireaddr *addrs; - u32 timestamp = time_now().ts.tv_sec; + u32 timestamp = clock_time().ts.tv_sec; addrs = gather_addresses(tmpctx, ld); /* Even if we're quick, don't duplicate timestamps! */ diff --git a/lightningd/htlc_end.c b/lightningd/htlc_end.c index 91d66b0c3357..77fe3074b5bb 100644 --- a/lightningd/htlc_end.c +++ b/lightningd/htlc_end.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -161,7 +162,7 @@ struct htlc_in *new_htlc_in(const tal_t *ctx, hin->we_filled = NULL; hin->payload = NULL; - hin->received_time = time_now(); + hin->received_time = clock_time(); return htlc_in_check(hin, "new_htlc_in"); } diff --git a/lightningd/invoice.c b/lightningd/invoice.c index 31362ab6c7ef..6060b6fe3a74 100644 --- a/lightningd/invoice.c +++ b/lightningd/invoice.c @@ -10,10 +10,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -26,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -1183,8 +1184,8 @@ static struct command_result *json_invoice(struct command *cmd, info->payment_preimage = *preimage; else /* Generate random secret preimage. */ - randombytes_buf(&info->payment_preimage, - sizeof(info->payment_preimage)); + randbytes(&info->payment_preimage, + sizeof(info->payment_preimage)); /* Generate preimage hash. */ sha256(&rhash, &info->payment_preimage, sizeof(info->payment_preimage)); /* Generate payment secret. */ @@ -1192,7 +1193,7 @@ static struct command_result *json_invoice(struct command *cmd, info->b11 = new_bolt11(info, msatoshi_val); info->b11->chain = chainparams; - info->b11->timestamp = time_now().ts.tv_sec; + info->b11->timestamp = clock_time().ts.tv_sec; info->b11->payment_hash = rhash; info->b11->receiver_id = cmd->ld->our_nodeid; info->b11->min_final_cltv_expiry = *cltv; @@ -1623,7 +1624,7 @@ static void add_stub_blindedpath(const tal_t *ctx, path = tal(NULL, struct blinded_path); sciddir_or_pubkey_from_pubkey(&path->first_node_id, &ld->our_pubkey); - randombytes_buf(&path_key, sizeof(path_key)); + randbytes(&path_key, sizeof(path_key)); if (!pubkey_from_privkey(&path_key, &path->first_path_key)) abort(); path->path = tal_arr(path, struct blinded_path_hop *, 1); diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index 1c3fb7e4d77a..41d4608f77f8 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -130,7 +130,6 @@ static struct lightningd *new_lightningd(const tal_t *ctx) ld->dev_disconnect_fd = -1; ld->dev_subdaemon_fail = false; ld->dev_allow_localhost = false; - ld->dev_gossip_time = 0; ld->dev_fast_gossip = false; ld->dev_fast_gossip_prune = false; ld->dev_throttle_gossip = false; @@ -190,42 +189,34 @@ static struct lightningd *new_lightningd(const tal_t *ctx) * list attached to the channel structure itself, or even left them in * the database rather than making an in-memory version. Obviously * I was in a premature optimization mood when I wrote this: */ - ld->htlcs_in = tal(ld, struct htlc_in_map); - htlc_in_map_init(ld->htlcs_in); + ld->htlcs_in = new_htable(ld, htlc_in_map); /*~ Note also: we didn't need to use an allocation here! We could * have simply made the `struct htlc_out_map` a member. But we * override the htable allocation routines to use tal(), and they * want a tal parent, so we always make our hash table a tallocated * object. */ - ld->htlcs_out = tal(ld, struct htlc_out_map); - htlc_out_map_init(ld->htlcs_out); + ld->htlcs_out = new_htable(ld, htlc_out_map); /*~ This is the hash table of peers: converted from a * linked-list as part of the 100k-peers project! */ - ld->peers = tal(ld, struct peer_node_id_map); - peer_node_id_map_init(ld->peers); + ld->peers = new_htable(ld, peer_node_id_map); /*~ And this was done at the same time, for db lookups at startup */ - ld->peers_by_dbid = tal(ld, struct peer_dbid_map); - peer_dbid_map_init(ld->peers_by_dbid); + ld->peers_by_dbid = new_htable(ld, peer_dbid_map); /*~ This speeds lookups for short_channel_ids to their channels. */ - ld->channels_by_scid = tal(ld, struct channel_scid_map); - channel_scid_map_init(ld->channels_by_scid); + ld->channels_by_scid = new_htable(ld, channel_scid_map); /*~ Coin movements in db are indexed by the channel dbid. */ - ld->channels_by_dbid = tal(ld, struct channel_dbid_map); - channel_dbid_map_init(ld->channels_by_dbid); + ld->channels_by_dbid = new_htable(ld, channel_dbid_map); /*~ For multi-part payments, we need to keep some incoming payments * in limbo until we get all the parts, or we time them out. */ - ld->htlc_sets = tal(ld, struct htlc_set_map); - htlc_set_map_init(ld->htlc_sets); + ld->htlc_sets = new_htable(ld, htlc_set_map); /*~ We keep a map of closed channels. Mainly so we can respond to peers * who talk to us about long-closed channels. */ - ld->closed_channels = tal(ld, struct closed_channel_map); - closed_channel_map_init(ld->closed_channels); + ld->closed_channels = new_htable(ld, closed_channel_map); /*~ We have a multi-entry log-book infrastructure: we define a 10MB log * book to hold all the entries (and trims as necessary), and multiple @@ -1190,8 +1181,6 @@ int main(int argc, char *argv[]) bool try_reexec; size_t num_channels; - trace_span_start("lightningd/startup", argv); - /*~ What happens in strange locales should stay there. */ setup_locale(); @@ -1215,6 +1204,10 @@ int main(int argc, char *argv[]) * backtraces when we crash (if supported on this platform). */ daemon_setup(argv[0], log_backtrace_print, log_backtrace_exit); + /*~ We enable trace as early as possible, but it uses support functions + * (particularly if we're avoid entropy) so do it after daemon_setup. */ + trace_span_start("lightningd/startup", argv); + /*~ There's always a battle between what a constructor like this * should do, and what should be added later by the caller. In * general, because we use valgrind heavily for testing, we prefer not diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h index ce8b62b017a6..6d8eac7197d1 100644 --- a/lightningd/lightningd.h +++ b/lightningd/lightningd.h @@ -306,9 +306,6 @@ struct lightningd { /* Allow and accept localhost node_announcement addresses */ bool dev_allow_localhost; - /* Timestamp to use for gossipd, iff non-zero */ - u32 dev_gossip_time; - /* Speedup gossip propagation, for testing. */ bool dev_fast_gossip; bool dev_fast_gossip_prune; diff --git a/lightningd/log.c b/lightningd/log.c index 9775e79f44b1..1827b202e97d 100644 --- a/lightningd/log.c +++ b/lightningd/log.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -400,7 +401,7 @@ struct log_book *new_log_book(struct lightningd *ld, size_t max_mem) log_book->prefix = tal_strdup(log_book, ""); list_head_init(&log_book->print_filters); list_head_init(&log_book->loggers); - log_book->init_time = time_now(); + log_book->init_time = clock_time(); log_book->ld = ld; log_book->cache = tal(log_book, struct node_id_map); node_id_map_init(log_book->cache); @@ -525,7 +526,7 @@ static struct log_entry *new_log_entry(struct logger *log, enum log_level level, tal_resize(&log->log_book->log, tal_count(log->log_book->log) * 2); l = &log->log_book->log[log->log_book->num_entries]; - l->time = time_now(); + l->time = clock_time(); l->level = level; l->skipped = 0; l->prefix = log_prefix_get(log->prefix); @@ -1014,7 +1015,7 @@ void log_backtrace_exit(void) int fd; char timebuf[sizeof("YYYYmmddHHMMSS")]; char logfile[sizeof("/tmp/lightning-crash.log.") + sizeof(timebuf)]; - struct timeabs time = time_now(); + struct timeabs time = clock_time(); strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%S", gmtime(&time.ts.tv_sec)); diff --git a/lightningd/memdump.c b/lightningd/memdump.c index b2f32a10636f..31d84b0e057f 100644 --- a/lightningd/memdump.c +++ b/lightningd/memdump.c @@ -194,19 +194,6 @@ static bool lightningd_check_leaks(struct command *cmd) memleak_ptr(memtable, cmd); memleak_ignore_children(memtable, cmd); - /* First delete known false positives. */ - memleak_scan_htable(memtable, &ld->topology->txwatches->raw); - memleak_scan_htable(memtable, &ld->topology->txowatches->raw); - memleak_scan_htable(memtable, &ld->topology->outgoing_txs->raw); - memleak_scan_htable(memtable, &ld->htlcs_in->raw); - memleak_scan_htable(memtable, &ld->htlcs_out->raw); - memleak_scan_htable(memtable, &ld->htlc_sets->raw); - memleak_scan_htable(memtable, &ld->peers->raw); - memleak_scan_htable(memtable, &ld->peers_by_dbid->raw); - memleak_scan_htable(memtable, &ld->channels_by_scid->raw); - memleak_scan_htable(memtable, &ld->closed_channels->raw); - wallet_memleak_scan(memtable, ld->wallet); - /* Now delete ld and those which it has pointers to. */ memleak_scan_obj(memtable, ld); diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index b82523ab1b38..4d2723a5d1db 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -49,13 +49,6 @@ static bool replay_tx_eq_txid(const struct replay_tx *rtx, HTABLE_DEFINE_NODUPS_TYPE(struct replay_tx, replay_tx_keyof, txid_hash, replay_tx_eq_txid, replay_tx_hash); -/* Helper for memleak detection */ -static void memleak_replay_tx_hash(struct htable *memtable, - struct replay_tx_hash *replay_tx_hash) -{ - memleak_scan_htable(memtable, &replay_tx_hash->raw); -} - /* We dump all the known preimages when onchaind starts up. */ static void onchaind_tell_fulfill(struct channel *channel) { @@ -1904,11 +1897,8 @@ void onchaind_replay_channels(struct lightningd *ld) channel_state_name(channel), blockheight); /* We're in replay mode */ - channel->onchaind_replay_watches = tal(channel, struct replay_tx_hash); + channel->onchaind_replay_watches = new_htable(channel, replay_tx_hash); channel->onchaind_replay_height = blockheight; - replay_tx_hash_init(channel->onchaind_replay_watches); - memleak_add_helper(channel->onchaind_replay_watches, - memleak_replay_tx_hash); onchaind_funding_spent(channel, tx, blockheight); onchaind_replay(channel); diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 7c12a0ffd551..c914e51dadbd 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -243,7 +244,7 @@ wallet_commit_channel(struct lightningd *ld, wallet_channel_insert(ld->wallet, channel); /* Notify that channel state changed (from non existant to existant) */ - timestamp = time_now(); + timestamp = clock_time(); notify_channel_state_changed(ld, &channel->peer->id, &channel->cid, channel->scid, /* NULL */ diff --git a/lightningd/options.c b/lightningd/options.c index d746c0476e71..4b1dc99dfb9d 100644 --- a/lightningd/options.c +++ b/lightningd/options.c @@ -807,10 +807,6 @@ static void dev_register_opts(struct lightningd *ld) opt_set_bool, &ld->dev_fast_gossip_prune, "Make gossip pruning 120 seconds"); - clnopt_witharg("--dev-gossip-time", OPT_DEV|OPT_SHOWINT, - opt_set_u32, opt_show_u32, - &ld->dev_gossip_time, - "UNIX time to override gossipd to use."); clnopt_witharg("--dev-force-privkey", OPT_DEV, opt_force_privkey, NULL, ld, "Force HSM to use this as node private key"); diff --git a/lightningd/pay.c b/lightningd/pay.c index 44931d700ea3..2a4e0c175e43 100644 --- a/lightningd/pay.c +++ b/lightningd/pay.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -1150,7 +1151,7 @@ send_payment_core(struct lightningd *ld, payment = wallet_add_payment(cmd, ld->wallet, - time_now().ts.tv_sec, + clock_time().ts.tv_sec, NULL, rhash, partid, @@ -1464,7 +1465,7 @@ static struct command_result *self_payment(struct lightningd *ld, payment = wallet_add_payment(tmpctx, ld->wallet, - time_now().ts.tv_sec, + clock_time().ts.tv_sec, NULL, rhash, partid, @@ -1794,7 +1795,7 @@ static void register_payment_and_waiter(struct command *cmd, { wallet_add_payment(cmd, cmd->ld->wallet, - time_now().ts.tv_sec, + clock_time().ts.tv_sec, NULL, payment_hash, partid, @@ -2021,7 +2022,7 @@ static struct command_result *json_injectpaymentonion(struct command *cmd, if (amount_msat_greater(*msat, next->htlc_maximum_msat) || amount_msat_less(*msat, next->htlc_minimum_msat)) { /* Are we in old-range grace-period? */ - if (!time_before(time_now(), next->old_feerate_timeout) + if (!timemono_before(time_mono(), next->old_feerate_timeout) || amount_msat_less(*msat, next->old_htlc_minimum_msat) || amount_msat_greater(*msat, next->old_htlc_maximum_msat)) { return command_fail(cmd, JSONRPC2_INVALID_PARAMS, diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 35b88089991f..b4f1c04f7df6 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -2351,6 +2351,14 @@ void channel_watch_wrong_funding(struct lightningd *ld, struct channel *channel) } } +/* We need to do this before we change channel funding (for splice), otherwise + * funding_depth_cb will fail the assertion that it's the current funding tx */ +void channel_unwatch_funding(struct lightningd *ld, struct channel *channel) +{ + tal_free(find_txwatch(ld->topology, + &channel->funding.txid, funding_depth_cb, channel)); +} + void channel_watch_funding(struct lightningd *ld, struct channel *channel) { log_debug(channel->log, "Watching for funding txid: %s", @@ -2449,15 +2457,35 @@ static void json_add_scb(struct command *cmd, struct json_stream *response, struct channel *c) { - u8 *scb = tal_arr(cmd, u8, 0); + u8 *scb_wire = tal_arr(cmd, u8, 0); + struct modern_scb_chan *scb; - /* Update shachain & basepoints in SCB. */ - c->scb->tlvs->shachain = &c->their_shachain.chain; - c->scb->tlvs->basepoints = &c->channel_info.theirbase; - towire_modern_scb_chan(&scb, c->scb); + /* Don't do scb for unix domain sockets. */ + if (c->peer->addr.itype != ADDR_INTERNAL_WIREADDR) + return; - json_add_hex_talarr(response, fieldname, - scb); + scb = tal(tmpctx, struct modern_scb_chan); + scb->id = c->dbid; + /* More useful to have last_known_addr, if avail */ + if (c->peer->last_known_addr) + scb->addr = *c->peer->last_known_addr; + else + scb->addr = c->peer->addr.u.wireaddr.wireaddr; + scb->node_id = c->peer->id; + scb->funding = c->funding; + scb->cid = c->cid; + scb->funding_sats = c->funding_sats; + scb->type = channel_type_dup(scb, c->type); + + scb->tlvs = tlv_scb_tlvs_new(scb); + scb->tlvs->shachain = &c->their_shachain.chain; + scb->tlvs->basepoints = &c->channel_info.theirbase; + scb->tlvs->opener = &c->opener; + scb->tlvs->remote_to_self_delay = &c->channel_info.their_config.to_self_delay; + + towire_modern_scb_chan(&scb_wire, scb); + + json_add_hex_talarr(response, fieldname, scb_wire); } /* This will return a SCB for all the channels currently loaded @@ -2482,9 +2510,6 @@ static struct command_result *json_staticbackup(struct command *cmd, peer = peer_node_id_map_next(cmd->ld->peers, &it)) { struct channel *channel; list_for_each(&peer->channels, channel, list){ - /* cppcheck-suppress uninitvar - false positive on channel */ - if (!channel->scb) - continue; json_add_scb(cmd, NULL, response, channel); } } @@ -3153,7 +3178,7 @@ static void set_channel_config(struct command *cmd, struct channel *channel, || (htlc_max && amount_msat_less(*htlc_max, channel->htlc_maximum_msat))) { channel->old_feerate_timeout - = timeabs_add(time_now(), time_from_sec(delaysecs)); + = timemono_add(time_mono(), time_from_sec(delaysecs)); channel->old_feerate_base = channel->feerate_base; channel->old_feerate_ppm = channel->feerate_ppm; channel->old_htlc_minimum_msat = channel->htlc_minimum_msat; diff --git a/lightningd/peer_control.h b/lightningd/peer_control.h index 2a28183fdace..a27dff9fbb11 100644 --- a/lightningd/peer_control.h +++ b/lightningd/peer_control.h @@ -131,6 +131,7 @@ void update_channel_from_inflight(struct lightningd *ld, const struct channel_inflight *inflight, bool is_splice); +void channel_unwatch_funding(struct lightningd *ld, struct channel *channel); void channel_watch_funding(struct lightningd *ld, struct channel *channel); /* If this channel has a "wrong funding" shutdown, watch that too. */ diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 27c3a4757674..e776bde0fc5d 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -856,7 +856,7 @@ static void forward_htlc(struct htlc_in *hin, * - If it creates a new `channel_update` with updated channel parameters: * - SHOULD keep accepting the previous channel parameters for 10 minutes */ - if (!time_before(time_now(), next->old_feerate_timeout) + if (!timemono_before(time_mono(), next->old_feerate_timeout) || !check_fwd_amount(hin, amt_to_forward, hin->msat, next->old_feerate_base, next->old_feerate_ppm)) { @@ -872,7 +872,7 @@ static void forward_htlc(struct htlc_in *hin, if (amount_msat_greater(amt_to_forward, next->htlc_maximum_msat) || amount_msat_less(amt_to_forward, next->htlc_minimum_msat)) { /* Are we in old-range grace-period? */ - if (!time_before(time_now(), next->old_feerate_timeout) + if (!timemono_before(time_mono(), next->old_feerate_timeout) || amount_msat_less(amt_to_forward, next->old_htlc_minimum_msat) || amount_msat_greater(amt_to_forward, next->old_htlc_maximum_msat)) { failmsg = towire_temporary_channel_failure(tmpctx, diff --git a/lightningd/plugin.c b/lightningd/plugin.c index 1dba9a94dd87..e1c8130d3233 100644 --- a/lightningd/plugin.c +++ b/lightningd/plugin.c @@ -2688,16 +2688,24 @@ static void dev_save_plugin_io(struct plugins *plugins, const char *buf, size_t len) { static size_t counter; + static u64 starttime; const char *file; int fd; if (!plugins->dev_save_io) return; + /* If we reexec, we still want unique names */ + if (!starttime) { + struct timemono start = time_mono(); + starttime = start.ts.tv_sec * 1000000 + start.ts.tv_nsec / 1000; + } + file = path_join(tmpctx, plugins->dev_save_io, - take(tal_fmt(NULL, "%s-%s-%u-%zu", + take(tal_fmt(NULL, "%s-%s-%u-%"PRIu64"-%zu", type, name, (unsigned int)getpid(), + starttime, counter++))); fd = open(file, O_CREAT|O_EXCL|O_WRONLY, 0600); if (fd < 0 || !write_all(fd, buf, len)) diff --git a/lightningd/runes.c b/lightningd/runes.c index 77be7a30a0ad..e3285b06100b 100644 --- a/lightningd/runes.c +++ b/lightningd/runes.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -946,7 +947,7 @@ static struct command_result *json_checkrune(struct command *cmd, cinfo.buf = buffer; cinfo.method = method; cinfo.params = methodparams; - cinfo.now = time_now(); + cinfo.now = clock_time(); strmap_init(&cinfo.cached_params); err = rune_is_ours(cmd->ld, ras->rune); diff --git a/lightningd/test/Makefile b/lightningd/test/Makefile index a9aa3c12852b..694d1a6b6ead 100644 --- a/lightningd/test/Makefile +++ b/lightningd/test/Makefile @@ -15,12 +15,14 @@ LIGHTNINGD_TEST_COMMON_OBJS := \ common/autodata.o \ common/base32.o \ common/bech32.o \ + common/clock_time.o \ common/daemon_conn.o \ common/htlc_state.o \ common/htlc_wire.o \ common/json_parse_simple.o \ common/key_derive.o \ common/pseudorand.o \ + common/randbytes.o \ common/random_select.o \ common/memleak.o \ common/msg_queue.o \ diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index fc7c642496ab..a89fd4e472d7 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -144,6 +144,10 @@ const char *channel_state_name(const struct channel *channel UNNEEDED) /* Generated stub for channel_state_str */ const char *channel_state_str(enum channel_state state UNNEEDED) { fprintf(stderr, "channel_state_str called!\n"); abort(); } +/* Generated stub for channel_type_dup */ +struct channel_type *channel_type_dup(const tal_t *ctx UNNEEDED, + const struct channel_type *t UNNEEDED) +{ fprintf(stderr, "channel_type_dup called!\n"); abort(); } /* Generated stub for channel_type_has */ bool channel_type_has(const struct channel_type *type UNNEEDED, int feature UNNEEDED) { fprintf(stderr, "channel_type_has called!\n"); abort(); } @@ -291,6 +295,16 @@ struct channel *find_channel_by_id(const struct peer *peer UNNEEDED, struct plugin *find_plugin_for_command(struct lightningd *ld UNNEEDED, const char *cmd_name UNNEEDED) { fprintf(stderr, "find_plugin_for_command called!\n"); abort(); } +/* Generated stub for find_txwatch_ */ +struct txwatch *find_txwatch_(struct chain_topology *topo UNNEEDED, + const struct bitcoin_txid *txid UNNEEDED, + enum watch_result (*cb)(struct lightningd *ld UNNEEDED, + const struct bitcoin_txid * UNNEEDED, + const struct bitcoin_tx * UNNEEDED, + unsigned int depth UNNEEDED, + void *arg) UNNEEDED, + void *arg UNNEEDED) +{ fprintf(stderr, "find_txwatch_ called!\n"); abort(); } /* Generated stub for fixup_htlcs_out */ void fixup_htlcs_out(struct lightningd *ld UNNEEDED) { fprintf(stderr, "fixup_htlcs_out called!\n"); abort(); } @@ -966,6 +980,9 @@ void subd_send_fd(struct subd *sd UNNEEDED, int fd UNNEEDED) /* Generated stub for subd_send_msg */ void subd_send_msg(struct subd *sd UNNEEDED, const u8 *msg_out UNNEEDED) { fprintf(stderr, "subd_send_msg called!\n"); abort(); } +/* Generated stub for tlv_scb_tlvs_new */ +struct tlv_scb_tlvs *tlv_scb_tlvs_new(const tal_t *ctx UNNEEDED) +{ fprintf(stderr, "tlv_scb_tlvs_new called!\n"); abort(); } /* Generated stub for towire_bigsize */ void towire_bigsize(u8 **pptr UNNEEDED, const bigsize_t val UNNEEDED) { fprintf(stderr, "towire_bigsize called!\n"); abort(); } diff --git a/onchaind/Makefile b/onchaind/Makefile index 8ef57d9ba6cd..fdccc7ee39dd 100644 --- a/onchaind/Makefile +++ b/onchaind/Makefile @@ -36,6 +36,7 @@ ONCHAIND_COMMON_OBJS := \ common/base32.o \ common/bigsize.o \ common/bip32.o \ + common/clock_time.o \ common/coin_mvt.o \ common/channel_id.o \ common/daemon.o \ @@ -56,6 +57,7 @@ ONCHAIND_COMMON_OBJS := \ common/psbt_keypath.o \ common/psbt_open.o \ common/pseudorand.o \ + common/randbytes.o \ common/setup.o \ common/status.o \ common/status_wire.o \ diff --git a/onchaind/test/Makefile b/onchaind/test/Makefile index 6777cb13905d..717b6d999083 100644 --- a/onchaind/test/Makefile +++ b/onchaind/test/Makefile @@ -15,6 +15,7 @@ ONCHAIND_TEST_COMMON_OBJS := \ common/features.o \ common/psbt_keypath.o \ common/pseudorand.o \ + common/randbytes.o \ common/setup.o \ common/utils.o @@ -24,6 +25,7 @@ $(ONCHAIND_TEST_PROGRAMS): $(ONCHAIND_TEST_COMMON_OBJS) $(BITCOIN_OBJS) onchaind/test/run-onchainstress: \ common/htlc_tx.o \ common/derive_basepoints.o \ + common/clock_time.o \ common/daemon.o \ common/htlc_wire.o \ common/initial_commit_tx.o \ diff --git a/onchaind/test/run-grind_feerate.c b/onchaind/test/run-grind_feerate.c index e413f100d043..c9b1d4dd5368 100644 --- a/onchaind/test/run-grind_feerate.c +++ b/onchaind/test/run-grind_feerate.c @@ -356,7 +356,7 @@ int main(int argc, char *argv[]) struct amount_sat fee; struct pubkey htlc_key; struct keyset *keys; - struct timeabs start, end; + struct timemono start, end; int iterations = 1000; u8 *spk = tal_arr(tmpctx, u8, 1); spk[0] = 0x00; @@ -388,15 +388,15 @@ int main(int argc, char *argv[]) max_possible_feerate = 250000; min_possible_feerate = max_possible_feerate + 1 - iterations; - start = time_now(); + start = time_mono(); if (!grind_htlc_tx_fee(&fee, tx, &sig, wscript, 663)) abort(); - end = time_now(); + end = time_mono(); assert(amount_sat_eq(fee, AMOUNT_SAT(165750))); printf("%u iterations in %"PRIu64" msec = %"PRIu64" nsec each\n", iterations, - time_to_msec(time_between(end, start)), - time_to_nsec(time_divide(time_between(end, start), iterations))); + time_to_msec(timemono_between(end, start)), + time_to_nsec(time_divide(timemono_between(end, start), iterations))); common_shutdown(); return 0; diff --git a/openingd/Makefile b/openingd/Makefile index 57dc84ee4177..e5a37438e1b0 100644 --- a/openingd/Makefile +++ b/openingd/Makefile @@ -41,6 +41,7 @@ OPENINGD_COMMON_OBJS := \ common/channel_config.o \ common/channel_id.o \ common/channel_type.o \ + common/clock_time.o \ common/cryptomsg.o \ common/daemon.o \ common/daemon_conn.o \ @@ -70,6 +71,7 @@ OPENINGD_COMMON_OBJS := \ common/psbt_internal.o \ common/psbt_open.o \ common/pseudorand.o \ + common/randbytes.o \ common/read_peer_msg.o \ common/setup.o \ common/shutdown_scriptpubkey.o \ diff --git a/plugins/Makefile b/plugins/Makefile index 6efb6c2310f1..d5c94e085aec 100644 --- a/plugins/Makefile +++ b/plugins/Makefile @@ -181,6 +181,7 @@ PLUGIN_COMMON_OBJS := \ common/bigsize.o \ common/bolt11.o \ common/channel_id.o \ + common/clock_time.o \ common/daemon.o \ common/deprecation.o \ common/features.o \ @@ -197,6 +198,7 @@ PLUGIN_COMMON_OBJS := \ common/plugin.o \ common/psbt_open.o \ common/pseudorand.o \ + common/randbytes.o \ common/random_select.o \ common/splice_script.o \ common/setup.o \ diff --git a/plugins/askrene/askrene.c b/plugins/askrene/askrene.c index 9664d2487d7f..de659b5d9b89 100644 --- a/plugins/askrene/askrene.c +++ b/plugins/askrene/askrene.c @@ -9,7 +9,7 @@ #include "config.h" #include #include -#include +#include #include #include #include @@ -1029,7 +1029,7 @@ static struct command_result *json_askrene_inform_channel(struct command *cmd, *amount = AMOUNT_MSAT(0); if (command_check_only(cmd)) return command_check_done(cmd); - c = layer_add_constraint(layer, scidd, time_now().ts.tv_sec, + c = layer_add_constraint(layer, scidd, clock_time().ts.tv_sec, NULL, amount); goto output; case INFORM_UNCONSTRAINED: @@ -1037,7 +1037,7 @@ static struct command_result *json_askrene_inform_channel(struct command *cmd, * that no reserves were used) */ if (command_check_only(cmd)) return command_check_done(cmd); - c = layer_add_constraint(layer, scidd, time_now().ts.tv_sec, + c = layer_add_constraint(layer, scidd, clock_time().ts.tv_sec, amount, NULL); goto output; case INFORM_SUCCEEDED: @@ -1290,13 +1290,6 @@ static const struct plugin_command commands[] = { }, }; -static void askrene_markmem(struct plugin *plugin, struct htable *memtable) -{ - struct askrene *askrene = get_askrene(plugin); - layer_memleak_mark(askrene, memtable); - reserve_memleak_mark(askrene, memtable); -} - static const char *init(struct command *init_cmd, const char *buf UNUSED, const jsmntok_t *config UNUSED) { @@ -1316,7 +1309,6 @@ static const char *init(struct command *init_cmd, "{id:%}", JSON_SCAN(json_to_node_id, &askrene->my_id)); plugin_set_data(plugin, askrene); - plugin_set_memleak_handler(plugin, askrene_markmem); load_layers(askrene, init_cmd); diff --git a/plugins/askrene/layer.c b/plugins/askrene/layer.c index 281e32a03c7b..4cbe657ac637 100644 --- a/plugins/askrene/layer.c +++ b/plugins/askrene/layer.c @@ -162,14 +162,10 @@ struct layer *new_temp_layer(const tal_t *ctx, struct askrene *askrene, const ch l->askrene = askrene; l->name = tal_strdup(l, name); l->persistent = false; - l->local_channels = tal(l, struct local_channel_hash); - local_channel_hash_init(l->local_channels); - l->local_updates = tal(l, struct local_update_hash); - local_update_hash_init(l->local_updates); - l->constraints = tal(l, struct constraint_hash); - constraint_hash_init(l->constraints); - l->biases = tal(l, struct bias_hash); - bias_hash_init(l->biases); + l->local_channels = new_htable(l, local_channel_hash); + l->local_updates = new_htable(l, local_update_hash); + l->constraints = new_htable(l, constraint_hash); + l->biases = new_htable(l, bias_hash); l->disabled_nodes = tal_arr(l, struct node_id, 0); return l; @@ -1162,14 +1158,3 @@ bool layer_disables_node(const struct layer *layer, } return false; } - -void layer_memleak_mark(struct askrene *askrene, struct htable *memtable) -{ - struct layer *l; - list_for_each(&askrene->layers, l, list) { - memleak_scan_htable(memtable, &l->constraints->raw); - memleak_scan_htable(memtable, &l->local_channels->raw); - memleak_scan_htable(memtable, &l->local_updates->raw); - memleak_scan_htable(memtable, &l->biases->raw); - } -} diff --git a/plugins/askrene/layer.h b/plugins/askrene/layer.h index e9b06fd5a4e6..b93f228ff05d 100644 --- a/plugins/askrene/layer.h +++ b/plugins/askrene/layer.h @@ -135,6 +135,4 @@ bool layer_disables_chan(const struct layer *layer, const struct short_channel_i /* For explain_failure: did this layer disable this node? */ bool layer_disables_node(const struct layer *layer, const struct node_id *node); -/* Scan for memleaks */ -void layer_memleak_mark(struct askrene *askrene, struct htable *memtable); #endif /* LIGHTNING_PLUGINS_ASKRENE_LAYER_H */ diff --git a/plugins/askrene/reserve.c b/plugins/askrene/reserve.c index abec9372dfc7..678ca248d667 100644 --- a/plugins/askrene/reserve.c +++ b/plugins/askrene/reserve.c @@ -36,9 +36,7 @@ HTABLE_DEFINE_DUPS_TYPE(struct reserve, reserve_scidd, hash_scidd, struct reserve_htable *new_reserve_htable(const tal_t *ctx) { - struct reserve_htable *reserved = tal(ctx, struct reserve_htable); - reserve_htable_init(reserved); - return reserved; + return new_htable(ctx, reserve_htable); } void reserve_add(struct reserve_htable *reserved, @@ -176,8 +174,3 @@ const char *fmt_reservations(const tal_t *ctx, } return ret; } - -void reserve_memleak_mark(struct askrene *askrene, struct htable *memtable) -{ - memleak_scan_htable(memtable, &askrene->reserved->raw); -} diff --git a/plugins/askrene/reserve.h b/plugins/askrene/reserve.h index 1c9e71eaaf60..868756ca0d9a 100644 --- a/plugins/askrene/reserve.h +++ b/plugins/askrene/reserve.h @@ -50,6 +50,4 @@ void json_add_reservations(struct json_stream *js, const struct reserve_htable *reserved, const char *fieldname); -/* Scan for memleaks */ -void reserve_memleak_mark(struct askrene *askrene, struct htable *memtable); #endif /* LIGHTNING_PLUGINS_ASKRENE_RESERVE_H */ diff --git a/plugins/autoclean.c b/plugins/autoclean.c index bfd358c988c6..65a49693fc55 100644 --- a/plugins/autoclean.c +++ b/plugins/autoclean.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -502,7 +503,7 @@ static struct command_result *list_done(struct command *cmd, const struct subsystem_ops *ops = get_subsystem_ops(subsystem); const jsmntok_t *t, *inv = json_get_member(buf, result, ops->arr_name); size_t i; - u64 now = time_now().ts.tv_sec; + u64 now = clock_time().ts.tv_sec; json_for_each_arr(i, t, inv) { struct per_variant *variant; diff --git a/plugins/bcli.c b/plugins/bcli.c index fdd5a7c6e228..af232da24eae 100644 --- a/plugins/bcli.c +++ b/plugins/bcli.c @@ -66,6 +66,9 @@ struct bitcoind { /* Override in case we're developer mode for testing*/ bool dev_no_fake_fees; + + /* Override initialblockdownload (using canned blocks sets this) */ + bool dev_ignore_ibd; }; static struct bitcoind *bitcoind; @@ -76,7 +79,7 @@ struct bitcoin_cli { int *exitstatus; pid_t pid; const char **args; - struct timeabs start; + struct timemono start; enum bitcoind_prio prio; char *output; size_t output_bytes; @@ -247,7 +250,7 @@ static void bcli_finished(struct io_conn *conn UNUSED, struct bitcoin_cli *bcli) int ret, status; struct command_result *res; enum bitcoind_prio prio = bcli->prio; - u64 msec = time_to_msec(time_between(time_now(), bcli->start)); + u64 msec = time_to_msec(timemono_between(time_mono(), bcli->start)); /* If it took over 10 seconds, that's rather strange. */ if (msec > 10000) @@ -318,7 +321,7 @@ static void next_bcli(enum bitcoind_prio prio) close(in); - bcli->start = time_now(); + bcli->start = time_mono(); bitcoind->num_requests[prio]++; @@ -458,6 +461,9 @@ static struct command_result *process_getblockchaininfo(struct bitcoin_cli *bcli if (err) return command_err_bcli_badjson(bcli, err); + if (bitcoind->dev_ignore_ibd) + ibd = false; + response = jsonrpc_stream_success(bcli->cmd); json_add_string(response, "chain", chain); json_add_u32(response, "headercount", headers); @@ -1157,6 +1163,7 @@ static struct bitcoind *new_bitcoind(const tal_t *ctx) although normal rpcclienttimeout default value is 900. */ bitcoind->rpcclienttimeout = 60; bitcoind->dev_no_fake_fees = false; + bitcoind->dev_ignore_ibd = false; return bitcoind; } @@ -1208,5 +1215,9 @@ int main(int argc, char *argv[]) "bool", "Suppress fee faking for regtest", bool_option, NULL, &bitcoind->dev_no_fake_fees), + plugin_option_dev("dev-ignore-ibd", + "bool", + "Never tell lightningd we're doing initial block download", + bool_option, NULL, &bitcoind->dev_ignore_ibd), NULL); } diff --git a/plugins/bkpr/bookkeeper.c b/plugins/bkpr/bookkeeper.c index 1312924de600..b84e876f48b5 100644 --- a/plugins/bkpr/bookkeeper.c +++ b/plugins/bkpr/bookkeeper.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff --git a/plugins/bkpr/incomestmt.c b/plugins/bkpr/incomestmt.c index fd3a7e452c08..f35a0e96daa4 100644 --- a/plugins/bkpr/incomestmt.c +++ b/plugins/bkpr/incomestmt.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -442,7 +443,7 @@ const char *csv_filename(const tal_t *ctx, const struct csv_fmt *fmt) { return tal_fmt(ctx, "cln_incomestmt_%s_%lu.csv", fmt->fmt_name, - (unsigned long)time_now().ts.tv_sec); + (unsigned long)clock_time().ts.tv_sec); } static void cointrack_header(FILE *csvf) diff --git a/plugins/bkpr/test/Makefile b/plugins/bkpr/test/Makefile index 80fed1875c0a..716190cae908 100644 --- a/plugins/bkpr/test/Makefile +++ b/plugins/bkpr/test/Makefile @@ -20,6 +20,7 @@ BOOKKEEPER_TEST_COMMON_OBJS := \ common/memleak.o \ common/node_id.o \ common/pseudorand.o \ + common/randbytes.o \ common/setup.o \ common/trace.o \ common/timeout.o \ diff --git a/plugins/bkpr/test/run-recorder.c b/plugins/bkpr/test/run-recorder.c index af8802e618bc..4aa188763cfe 100644 --- a/plugins/bkpr/test/run-recorder.c +++ b/plugins/bkpr/test/run-recorder.c @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -50,6 +51,12 @@ const char *chain_event_description(const struct bkpr *bkpr UNNEEDED, const char *channel_event_description(const struct bkpr *bkpr UNNEEDED, const struct channel_event *ce UNNEEDED) { fprintf(stderr, "channel_event_description called!\n"); abort(); } +/* Generated stub for clock_time_overridden */ +bool clock_time_overridden(void) +{ fprintf(stderr, "clock_time_overridden called!\n"); abort(); } +/* Generated stub for clock_time_progresses_ */ +struct timeabs clock_time_progresses_(u64 *progress UNNEEDED) +{ fprintf(stderr, "clock_time_progresses_ called!\n"); abort(); } /* Generated stub for command_fail_badparam */ struct command_result *command_fail_badparam(struct command *cmd UNNEEDED, const char *paramname UNNEEDED, diff --git a/plugins/bkpr/test/run-sql.c b/plugins/bkpr/test/run-sql.c index 8be5859adad7..dc3604d0f8f8 100644 --- a/plugins/bkpr/test/run-sql.c +++ b/plugins/bkpr/test/run-sql.c @@ -3,6 +3,7 @@ #include "plugins/bkpr/sql.c" #include "plugins/libplugin.c" +#include #include #include #include @@ -12,6 +13,12 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for clock_time_overridden */ +bool clock_time_overridden(void) +{ fprintf(stderr, "clock_time_overridden called!\n"); abort(); } +/* Generated stub for clock_time_progresses_ */ +struct timeabs clock_time_progresses_(u64 *progress UNNEEDED) +{ fprintf(stderr, "clock_time_progresses_ called!\n"); abort(); } /* Generated stub for daemon_developer_mode */ bool daemon_developer_mode(char *argv[]) { fprintf(stderr, "daemon_developer_mode called!\n"); abort(); } diff --git a/plugins/chanbackup.c b/plugins/chanbackup.c index 11091edd92c4..3e51b1436200 100644 --- a/plugins/chanbackup.c +++ b/plugins/chanbackup.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -140,7 +141,7 @@ static void write_scb(struct plugin *p, struct modern_scb_chan **scb_chan_arr) { const struct chanbackup *cb = chanbackup(p); - u32 timestamp = time_now().ts.tv_sec; + u32 timestamp = clock_time().ts.tv_sec; u8 *decrypted_scb = towire_static_chan_backup_with_tlvs(tmpctx, VERSION, @@ -1040,10 +1041,8 @@ static void setup_backup_map(struct command *init_cmd, const jsmntok_t *datastore, *t; size_t i, total = 0; - cb->backups = tal(cb, struct backup_map); - backup_map_init(cb->backups); - cb->peers = tal(cb, struct peer_map); - peer_map_init(cb->peers); + cb->backups = new_htable(cb, backup_map); + cb->peers = new_htable(cb, peer_map); json_out_start(params, NULL, '{'); json_out_start(params, "key", '['); @@ -1084,14 +1083,6 @@ static void setup_backup_map(struct command *init_cmd, "Loaded %zu stored backups for peers", total); } -static void chanbackup_mark_mem(struct plugin *plugin, - struct htable *memtable) -{ - const struct chanbackup *cb = chanbackup(plugin); - memleak_scan_htable(memtable, &cb->backups->raw); - memleak_scan_htable(memtable, &cb->peers->raw); -} - static const char *init(struct command *init_cmd, const char *buf UNUSED, const jsmntok_t *config UNUSED) @@ -1132,9 +1123,6 @@ static const char *init(struct command *init_cmd, unlink_noerr("scb.tmp"); maybe_create_new_scb(init_cmd->plugin, scb_chan); - - plugin_set_memleak_handler(init_cmd->plugin, - chanbackup_mark_mem); return NULL; } diff --git a/plugins/channel_hint.c b/plugins/channel_hint.c index 1db37791ea0a..7a14f3992a44 100644 --- a/plugins/channel_hint.c +++ b/plugins/channel_hint.c @@ -23,12 +23,6 @@ bool channel_hint_eq(const struct channel_hint *a, a->scid.dir == b->dir; } -static void memleak_help_channel_hint_map(struct htable *memtable, - struct channel_hint_map *channel_hints) -{ - memleak_scan_htable(memtable, &channel_hints->raw); -} - void channel_hint_to_json(const char *name, const struct channel_hint *hint, struct json_stream *dest) { @@ -211,9 +205,7 @@ struct channel_hint *channel_hint_from_json(const tal_t *ctx, struct channel_hint_set *channel_hint_set_new(const tal_t *ctx) { struct channel_hint_set *set = tal(ctx, struct channel_hint_set); - set->hints = tal(set, struct channel_hint_map); - channel_hint_map_init(set->hints); - memleak_add_helper(set->hints, memleak_help_channel_hint_map); + set->hints = new_htable(set, channel_hint_map); return set; } diff --git a/plugins/fetchinvoice.c b/plugins/fetchinvoice.c index c40889763d95..9b1e68e42cf6 100644 --- a/plugins/fetchinvoice.c +++ b/plugins/fetchinvoice.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -17,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -25,7 +27,6 @@ #include #include #include -#include static LIST_HEAD(sent_list); @@ -448,7 +449,7 @@ static struct blinded_path *make_reply_path(const tal_t *ctx, assert(tal_count(path) > 0); - randombytes_buf(reply_secret, sizeof(struct secret)); + randbytes(reply_secret, sizeof(struct secret)); if (sent->dev_reply_path) { ids = sent->dev_reply_path; @@ -732,7 +733,7 @@ static struct command_result *invreq_done(struct command *cmd, } if (base) { - u64 period_start, period_end, now = time_now().ts.tv_sec; + u64 period_start, period_end, now = clock_time().ts.tv_sec; offer_period_paywindow(sent->invreq->offer_recurrence, sent->invreq->offer_recurrence_paywindow, sent->invreq->offer_recurrence_base, @@ -859,7 +860,7 @@ struct command_result *json_fetchinvoice(struct command *cmd, * - MUST NOT respond to the offer. */ if (sent->offer->offer_absolute_expiry - && time_now().ts.tv_sec > *sent->offer->offer_absolute_expiry) + && clock_time().ts.tv_sec > *sent->offer->offer_absolute_expiry) return command_fail(cmd, OFFER_EXPIRED, "Offer expired"); /* BOLT #12: @@ -1016,8 +1017,8 @@ struct command_result *json_fetchinvoice(struct command *cmd, * bytes. */ invreq->invreq_metadata = tal_arr(invreq, u8, 16); - randombytes_buf(invreq->invreq_metadata, - tal_bytelen(invreq->invreq_metadata)); + randbytes(invreq->invreq_metadata, + tal_bytelen(invreq->invreq_metadata)); } } @@ -1397,7 +1398,7 @@ struct command_result *json_sendinvoice(struct command *cmd, * `invreq_chain`. */ sent->inv->invoice_created_at = tal(sent->inv, u64); - *sent->inv->invoice_created_at = time_now().ts.tv_sec; + *sent->inv->invoice_created_at = clock_time().ts.tv_sec; /* FIXME: Support blinded paths, in which case use fake nodeid */ @@ -1405,7 +1406,7 @@ struct command_result *json_sendinvoice(struct command *cmd, * - MUST set `invoice_payment_hash` to the SHA256 hash of the * `payment_preimage` that will be given in return for payment. */ - randombytes_buf(&sent->inv_preimage, sizeof(sent->inv_preimage)); + randbytes(&sent->inv_preimage, sizeof(sent->inv_preimage)); sent->inv->invoice_payment_hash = tal(sent->inv, struct sha256); sha256(sent->inv->invoice_payment_hash, &sent->inv_preimage, sizeof(sent->inv_preimage)); diff --git a/plugins/keysend.c b/plugins/keysend.c index 6104bf607ccd..58e42e4f0ced 100644 --- a/plugins/keysend.c +++ b/plugins/keysend.c @@ -4,13 +4,14 @@ #include #include #include +#include #include #include #include #include +#include #include #include -#include #define PREIMAGE_TLV_TYPE 5482373484 #define KEYSEND_FEATUREBIT 55 @@ -49,7 +50,7 @@ static struct keysend_data *keysend_init(struct payment *p) * and populate the preimage field in the keysend_data and the * payment_hash in the payment. */ d = tal(p, struct keysend_data); - randombytes_buf(&d->preimage, sizeof(d->preimage)); + randbytes(&d->preimage, sizeof(d->preimage)); ccan_sha256(&payment_hash, &d->preimage, sizeof(d->preimage)); p->payment_hash = tal_dup(p, struct sha256, &payment_hash); d->extra_tlvs = NULL; @@ -241,7 +242,7 @@ static struct command_result *json_keysend(struct command *cmd, const char *buf, p->invstring_used = true; p->why = "Initial attempt"; p->constraints.cltv_budget = *maxdelay; - p->deadline = timeabs_add(time_now(), time_from_sec(*retryfor)); + p->deadline = timemono_add(time_mono(), time_from_sec(*retryfor)); p->getroute->riskfactorppm = 10000000; if (node_id_eq(&my_id, p->route_destination)) { @@ -448,7 +449,8 @@ static struct command_result *htlc_accepted_call(struct command *cmd, bigsize_t s; struct keysend_in *ki; struct out_req *req; - struct timeabs now = time_now(); + /* Even with CLN_DEV_SET_TIME, we need this to change */ + struct timeabs now = clock_time_progresses(); const char *err; u64 *allowed; size_t err_off; diff --git a/plugins/libplugin-pay.c b/plugins/libplugin-pay.c index b296b87d7a97..5b7330af2ec3 100644 --- a/plugins/libplugin-pay.c +++ b/plugins/libplugin-pay.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -87,7 +88,7 @@ struct payment *payment_new(tal_t *ctx, struct command *cmd, p->modifiers = mods; p->cmd = cmd; p->finished = false; - p->start_time = time_now(); + p->start_time = clock_time(); p->result = NULL; p->why = NULL; p->getroute = tal(p, struct getroute_request); @@ -428,7 +429,7 @@ static void channel_hints_update(struct payment *p, /* Local channels must have an HTLC budget */ assert(!local || htlc_budget != NULL); - channel_hint_set_add(root->hints, time_now().ts.tv_sec, scidd, enabled, + channel_hint_set_add(root->hints, clock_time().ts.tv_sec, scidd, enabled, estimated_capacity, overall_capacity, htlc_budget); hint = channel_hint_set_find(root->hints, scidd); @@ -1637,7 +1638,7 @@ payment_waitsendpay_finished(struct command *cmd, assert(p->route != NULL); - p->end_time = time_now(); + p->end_time = clock_time(); p->result = tal_sendpay_result_from_json(p, buffer, toks); if (p->result == NULL) { @@ -2332,7 +2333,7 @@ void payment_set_step(struct payment *p, enum payment_step newstep) /* Any final state needs an end_time */ if (p->step >= PAYMENT_STEP_SPLIT) - p->end_time = time_now(); + p->end_time = clock_time(); } struct command_result *payment_continue(struct payment *p) @@ -2391,7 +2392,7 @@ struct command_result *payment_abort(struct payment *p, enum jsonrpc_errcode cod va_list ap; struct payment *root = payment_root(p); payment_set_step(p, PAYMENT_STEP_FAILED); - p->end_time = time_now(); + p->end_time = clock_time(); /* We can fail twice, it seems. */ tal_free(p->failreason); @@ -2418,7 +2419,7 @@ struct command_result *payment_abort(struct payment *p, enum jsonrpc_errcode cod struct command_result *payment_fail(struct payment *p, const char *fmt, ...) { va_list ap; - p->end_time = time_now(); + p->end_time = clock_time(); payment_set_step(p, PAYMENT_STEP_FAILED); /* We can fail twice, it seems. */ tal_free(p->failreason); @@ -2525,12 +2526,12 @@ static struct command_result *retry_step_cb(struct retry_mod_data *rd, { struct payment *subpayment, *root = payment_root(p); struct retry_mod_data *rdata = payment_mod_retry_get_data(p); - struct timeabs now = time_now(); + struct timemono now = time_mono(); if (p->step != PAYMENT_STEP_FAILED) return payment_continue(p); - if (time_after(now, p->deadline)) { + if (timemono_after(now, p->deadline)) { paymod_log( p, LOG_INFORM, "Payment deadline expired, not retrying (partial-)payment " @@ -2644,7 +2645,7 @@ local_channel_hints_listpeerchannels(struct command *cmd, * observations, and should re-enable some channels that would * otherwise start out as excluded and remain so until * forever. */ - channel_hint_set_update(payment_root(p)->hints, time_now()); + channel_hint_set_update(payment_root(p)->hints, clock_time()); p->mods = gossmods_from_listpeerchannels( p, p->local_id, buffer, toks, true, gossmod_add_localchan, NULL); diff --git a/plugins/libplugin-pay.h b/plugins/libplugin-pay.h index bc1ec51b5dc9..20b6fae6f355 100644 --- a/plugins/libplugin-pay.h +++ b/plugins/libplugin-pay.h @@ -206,7 +206,7 @@ struct payment { u32 start_block; struct timeabs start_time, end_time; - struct timeabs deadline; + struct timemono deadline; /* Constraints the state machine and modifiers needs to maintain. */ struct payment_constraints constraints; diff --git a/plugins/offers.c b/plugins/offers.c index 48ecff4f4fdb..d9659ccee15a 100644 --- a/plugins/offers.c +++ b/plugins/offers.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -1320,7 +1321,7 @@ static void json_add_rune(struct command *cmd, struct json_stream *js, const str u64 t = atol(alt->value); if (t) { - u64 diff, now = time_now().ts.tv_sec; + u64 diff, now = clock_time().ts.tv_sec; /* Need a non-const during construction */ char *v; diff --git a/plugins/offers_inv_hook.c b/plugins/offers_inv_hook.c index 07bc1a7ed6b6..01a4fe1a49e5 100644 --- a/plugins/offers_inv_hook.c +++ b/plugins/offers_inv_hook.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -312,7 +313,7 @@ struct command_result *handle_invoice(struct command *cmd, invexpiry = *inv->inv->invoice_created_at + *inv->inv->invoice_relative_expiry; else invexpiry = *inv->inv->invoice_created_at + BOLT12_DEFAULT_REL_EXPIRY; - if (time_now().ts.tv_sec > invexpiry) + if (clock_time().ts.tv_sec > invexpiry) return fail_inv(cmd, inv, "Expired invoice"); /* BOLT #12: diff --git a/plugins/offers_invreq_hook.c b/plugins/offers_invreq_hook.c index c8fe8d6e5ed4..7a51e4525b2f 100644 --- a/plugins/offers_invreq_hook.c +++ b/plugins/offers_invreq_hook.c @@ -8,12 +8,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -857,7 +859,7 @@ static struct command_result *listoffers_done(struct command *cmd, } if (ir->invreq->offer_absolute_expiry - && time_now().ts.tv_sec >= *ir->invreq->offer_absolute_expiry) { + && clock_time().ts.tv_sec >= *ir->invreq->offer_absolute_expiry) { /* FIXME: do deloffer to disable it */ return fail_invreq(cmd, ir, "Offer expired"); } @@ -955,13 +957,13 @@ static struct command_result *listoffers_done(struct command *cmd, * Midnight 1 January 1970, UTC when the invoice was created. */ ir->inv->invoice_created_at = tal(ir->inv, u64); - *ir->inv->invoice_created_at = time_now().ts.tv_sec; + *ir->inv->invoice_created_at = clock_time().ts.tv_sec; /* BOLT #12: * - MUST set `invoice_payment_hash` to the SHA256 hash of the * `payment_preimage` that will be given in return for payment. */ - randombytes_buf(&ir->preimage, sizeof(ir->preimage)); + randbytes(&ir->preimage, sizeof(ir->preimage)); ir->inv->invoice_payment_hash = tal(ir->inv, struct sha256); sha256(ir->inv->invoice_payment_hash, &ir->preimage, sizeof(ir->preimage)); diff --git a/plugins/offers_offer.c b/plugins/offers_offer.c index a50052cb13b1..82f9dd19aba3 100644 --- a/plugins/offers_offer.c +++ b/plugins/offers_offer.c @@ -10,9 +10,9 @@ #include #include #include +#include #include #include -#include static bool msat_or_any(const char *buffer, const jsmntok_t *tok, @@ -710,8 +710,8 @@ struct command_result *json_invoicerequest(struct command *cmd, * - MUST set `invreq_metadata` to an unpredictable series of bytes. */ invreq->invreq_metadata = tal_arr(invreq, u8, 16); - randombytes_buf(invreq->invreq_metadata, - tal_bytelen(invreq->invreq_metadata)); + randbytes(invreq->invreq_metadata, + tal_bytelen(invreq->invreq_metadata)); /* BOLT #12: * - otherwise (not responding to an offer): diff --git a/plugins/pay.c b/plugins/pay.c index 7deaf85bc518..087b33ccdb87 100644 --- a/plugins/pay.c +++ b/plugins/pay.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -150,7 +151,7 @@ static void paystatus_add_payment(struct json_stream *s, const struct payment *p json_add_string(s, "strategy", p->why); json_add_string(s, "start_time", timestr); json_add_u64(s, "age_in_seconds", - time_to_sec(time_between(time_now(), p->start_time))); + time_to_sec(time_between(clock_time(), p->start_time))); /* Any final state will have an end time. */ if (p->step >= PAYMENT_STEP_SPLIT) { @@ -1424,7 +1425,7 @@ static struct command_result *json_pay(struct command *cmd, p->payment_secret = NULL; } - if (time_now().ts.tv_sec > invexpiry) + if (clock_time().ts.tv_sec > invexpiry) return command_fail(cmd, PAY_INVOICE_EXPIRED, "Invoice expired"); if (invmsat) { @@ -1480,7 +1481,7 @@ static struct command_result *json_pay(struct command *cmd, p->why = "Initial attempt"; p->constraints.cltv_budget = *maxdelay; tal_free(maxdelay); - p->deadline = timeabs_add(time_now(), time_from_sec(*retryfor)); + p->deadline = timemono_add(time_mono(), time_from_sec(*retryfor)); tal_free(retryfor); p->getroute->riskfactorppm = *riskfactor_millionths; tal_free(riskfactor_millionths); @@ -1549,7 +1550,7 @@ static struct command_result *handle_channel_hint_update(struct command *cmd, fmt_amount_msat(tmpctx, hint->estimated_capacity), fmt_amount_msat(tmpctx, hint->capacity) ); - channel_hint_set_add(global_hints, time_now().ts.tv_sec, &hint->scid, + channel_hint_set_add(global_hints, clock_time().ts.tv_sec, &hint->scid, hint->enabled, &hint->estimated_capacity, hint->capacity, NULL); tal_free(hint); diff --git a/plugins/renepay/main.c b/plugins/renepay/main.c index 01b4d13be34c..18872c1936fe 100644 --- a/plugins/renepay/main.c +++ b/plugins/renepay/main.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -311,7 +312,7 @@ static struct command_result *json_renepay(struct command *cmd, const char *buf, /* === Is it expired? === */ - const u64 now_sec = time_now().ts.tv_sec; + const u64 now_sec = clock_time().ts.tv_sec; if (now_sec > invexpiry) return command_fail(cmd, PAY_INVOICE_EXPIRED, "Invoice expired"); diff --git a/plugins/renepay/mods.c b/plugins/renepay/mods.c index 34e505816538..30d6314a2e6c 100644 --- a/plugins/renepay/mods.c +++ b/plugins/renepay/mods.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -917,7 +918,7 @@ REGISTER_PAYMENT_MODIFIER(end, end_cb); static struct command_result *checktimeout_cb(struct payment *payment) { - if (time_after(time_now(), payment->payment_info.stop_time)) { + if (time_after(clock_time(), payment->payment_info.stop_time)) { return payment_fail(payment, PAY_STOPPED_RETRYING, "Timed out"); } return payment_continue(payment); @@ -1129,7 +1130,7 @@ REGISTER_PAYMENT_MODIFIER(pendingsendpays, pendingsendpays_cb); static struct command_result *knowledgerelax_cb(struct payment *payment) { - const u64 now_sec = time_now().ts.tv_sec; + const u64 now_sec = clock_time().ts.tv_sec; enum renepay_errorcode err = uncertainty_relax( pay_plugin->uncertainty, now_sec - pay_plugin->last_time); if (err) diff --git a/plugins/renepay/payment.c b/plugins/renepay/payment.c index 02566b01cdff..c732ecca0ae4 100644 --- a/plugins/renepay/payment.c +++ b/plugins/renepay/payment.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -96,7 +97,7 @@ bool payment_refresh(struct payment *p){ p->retry = false; p->waitresult_timer = tal_free(p->waitresult_timer); - pinfo->start_time = time_now(); + pinfo->start_time = clock_time(); pinfo->stop_time = timeabs_add(pinfo->start_time, time_from_sec(pinfo->retryfor)); diff --git a/plugins/renepay/test/run-bottleneck.c b/plugins/renepay/test/run-bottleneck.c index f22d45fbbf6e..5111892e5911 100644 --- a/plugins/renepay/test/run-bottleneck.c +++ b/plugins/renepay/test/run-bottleneck.c @@ -14,9 +14,10 @@ #include #include #include +#include +#include #include #include -#include /* AUTOGENERATED MOCKS START */ /* Generated stub for sciddir_or_pubkey_from_node_id */ @@ -225,7 +226,7 @@ int main(int argc, char *argv[]) pinfo.maxdelay = 100; pinfo.final_cltv = 5; - pinfo.start_time = time_now(); + pinfo.start_time = clock_time(); pinfo.stop_time = timeabs_add(pinfo.start_time, time_from_sec(10000)); pinfo.base_fee_penalty = 1e-5; @@ -235,7 +236,7 @@ int main(int argc, char *argv[]) pinfo.base_prob_success = 1.0; pinfo.use_shadow = false; - randombytes_buf(&preimage, sizeof(preimage)); + randbytes(&preimage, sizeof(preimage)); sha256(&pinfo.payment_hash, &preimage, sizeof(preimage)); // char hex_preimage[600], hex_sha256[600]; diff --git a/plugins/test/Makefile b/plugins/test/Makefile index 3b5712d5ac09..c7744825295e 100644 --- a/plugins/test/Makefile +++ b/plugins/test/Makefile @@ -10,7 +10,9 @@ ALL_TEST_PROGRAMS += $(PLUGIN_TEST_PROGRAMS) PLUGIN_TEST_COMMON_OBJS := \ common/amount.o \ common/autodata.o \ + common/clock_time.o \ common/pseudorand.o \ + common/randbytes.o \ common/setup.o \ common/utils.o diff --git a/plugins/test/run-funder_policy.c b/plugins/test/run-funder_policy.c index 8880b905999a..89e5840c5340 100644 --- a/plugins/test/run-funder_policy.c +++ b/plugins/test/run-funder_policy.c @@ -1,6 +1,7 @@ #include "config.h" #include "../funder_policy.c" #include +#include #include #include diff --git a/plugins/topology.c b/plugins/topology.c index 4c84d02b92c2..5447303efdc5 100644 --- a/plugins/topology.c +++ b/plugins/topology.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -462,6 +463,33 @@ static struct amount_msat peer_capacity(const struct gossmap *gossmap, return capacity; } +/* For deterministic results with bolt12/11 routes, we only return a + * single candidate: choose the one with most capacity */ +static size_t best_candidate(const struct gossmap *gossmap, + const struct gossmap_node *me) +{ + struct amount_msat best_cap = AMOUNT_MSAT(0); + size_t best_num = 0; + for (size_t i = 0; i < me->num_chans; i++) { + int dir; + struct gossmap_chan *ourchan; + struct amount_msat cap; + struct gossmap_node *peer; + + ourchan = gossmap_nth_chan(gossmap, me, i, &dir); + if (ourchan->cupdate_off[!dir] == 0) + continue; + + peer = gossmap_nth_node(gossmap, ourchan, !dir); + cap = peer_capacity(gossmap, me, peer, ourchan); + if (amount_msat_greater(cap, best_cap)) { + best_num = i; + best_cap = cap; + } + } + return best_num; +} + static struct command_result * listpeerchannels_listincoming_done(struct command *cmd, const char *method, @@ -473,6 +501,7 @@ listpeerchannels_listincoming_done(struct command *cmd, struct gossmap_node *me; struct gossmap *gossmap; struct gossmap_localmods *mods; + size_t deterministic_candidate = 0; /* Get local knowledge */ mods = gossmods_from_listpeerchannels(tmpctx, &local_id, @@ -490,6 +519,9 @@ listpeerchannels_listincoming_done(struct command *cmd, if (!me) goto done; + if (randbytes_overridden()) + deterministic_candidate = best_candidate(gossmap, me); + for (size_t i = 0; i < me->num_chans; i++) { struct node_id peer_id; int dir; @@ -502,6 +534,10 @@ listpeerchannels_listincoming_done(struct command *cmd, /* Entirely missing? Ignore. */ if (ourchan->cupdate_off[!dir] == 0) continue; + + if (randbytes_overridden() && i != deterministic_candidate) + continue; + /* We used to ignore if the peer said it was disabled, * but we have a report of LND telling us our unannounced * channel is disabled, so we still use them. */ diff --git a/plugins/xpay/xpay.c b/plugins/xpay/xpay.c index 16717ce3d045..078ee747c382 100644 --- a/plugins/xpay/xpay.c +++ b/plugins/xpay/xpay.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -1867,7 +1868,7 @@ static struct command_result *xpay_core(struct command *cmd, payment->requests = tal_arr(payment, struct out_req *, 0); payment->prior_results = tal_strdup(payment, ""); payment->deadline = timemono_add(time_mono(), time_from_sec(retryfor)); - payment->start_time = time_now(); + payment->start_time = clock_time(); payment->pay_compat = as_pay; payment->invstring = tal_strdup(payment, invstring); if (layers) @@ -1975,7 +1976,7 @@ static struct command_result *xpay_core(struct command *cmd, invexpiry = b11->timestamp + b11->expiry; } - now = time_now().ts.tv_sec; + now = clock_time().ts.tv_sec; if (now > invexpiry) return command_fail(cmd, PAY_INVOICE_EXPIRED, "Invoice expired %"PRIu64" seconds ago", @@ -2092,7 +2093,7 @@ static struct command_result *age_layer(struct command *timer_cmd, void *unused) plugin_broken_cb, NULL); json_add_string(req->js, "layer", "xpay"); - json_add_u64(req->js, "cutoff", time_now().ts.tv_sec - 3600); + json_add_u64(req->js, "cutoff", clock_time().ts.tv_sec - 3600); return send_outreq(req); } diff --git a/tests/autogenerate-rpc-examples.py b/tests/autogenerate-rpc-examples.py index bfd564288c4f..1036adbd7a55 100644 --- a/tests/autogenerate-rpc-examples.py +++ b/tests/autogenerate-rpc-examples.py @@ -972,6 +972,19 @@ def generate_bookkeeper_examples(l2, l3, c23_2_chan_id): raise +def generate_coinmvt_examples(l2): + """Generates listchannelmoves and listchainmoves rpc examples""" + try: + logger.info('listcoinmoves Start...') + update_example(node=l2, method='listchainmoves', params={}) + update_example(node=l2, method='listchainmoves', params={'index': 'created', 'start': 10}) + update_example(node=l2, method='listchannelmoves', params={}) + update_example(node=l2, method='listchannelmoves', params={'index': 'created', 'start': 10, 'limit': 2}) + except Exception as e: + logger.error(f'Error in generating coinmoves examples: {e}') + raise + + def generate_offers_renepay_examples(l1, l2, inv_l21, inv_l34): """Covers all offers and renepay related examples""" try: @@ -2096,6 +2109,7 @@ def list_missing_examples(): c23_2, c23res2, c34_2, inv_l11, inv_l21, inv_l22, inv_l31, inv_l32, inv_l34 = generate_transactions_examples(l1, l2, l3, l4, l5, c25, bitcoind) rune_l21 = generate_runes_examples(l1, l2, l3) generate_datastore_examples(l2) + generate_coinmvt_examples(l2) generate_bookkeeper_examples(l2, l3, c23res2['channel_id']) offer_l23, inv_req_l1_l22 = generate_offers_renepay_examples(l1, l2, inv_l21, inv_l34) generate_askrene_examples(l1, l2, l3, c12, c23_2) diff --git a/tests/fuzz/Makefile b/tests/fuzz/Makefile index 6b36b1e941a3..1561f2d25da4 100644 --- a/tests/fuzz/Makefile +++ b/tests/fuzz/Makefile @@ -32,6 +32,7 @@ FUZZ_COMMON_OBJS := \ common/configvar.o \ common/channel_id.o \ common/channel_type.o \ + common/clock_time.o \ common/cryptomsg.o \ common/daemon.o \ common/daemon_conn.o \ diff --git a/tests/fuzz/connectd_handshake.h b/tests/fuzz/connectd_handshake.h index 6412db8a95c8..da4be733585e 100644 --- a/tests/fuzz/connectd_handshake.h +++ b/tests/fuzz/connectd_handshake.h @@ -1,6 +1,6 @@ /* This header contains globals and helper functions used by all the * fuzz-connectd-handshake-act* fuzz targets. It also takes care of intercepting - * io_read(), io_write(), and randombytes_buf(), so that the actual fuzz targets + * io_read(), io_write(), and randbytes(), so that the actual fuzz targets * only need to implement the test_read() and test_write() interceptors and the * run() function. */ @@ -21,7 +21,7 @@ #include static void seeded_randombytes_buf(u8 *secret, size_t len); -#define randombytes_buf(secret, len) seeded_randombytes_buf((secret), (len)) +#define randbytes(secret, len) seeded_randombytes_buf((secret), (len)) struct handshake; diff --git a/tests/plugins/Makefile b/tests/plugins/Makefile index 826857db18a1..ed9f4ee0ab3d 100644 --- a/tests/plugins/Makefile +++ b/tests/plugins/Makefile @@ -44,6 +44,7 @@ tests/plugins/channeld_fakenet: \ common/channel_config.o \ common/channel_id.o \ common/channel_type.o \ + common/clock_time.o \ common/daemon.o \ common/daemon_conn.o \ common/derive_basepoints.o \ @@ -74,6 +75,7 @@ tests/plugins/channeld_fakenet: \ common/per_peer_state.o \ common/permute_tx.o \ common/pseudorand.o \ + common/randbytes.o \ common/setup.o \ common/sphinx.o \ common/status.o \ diff --git a/tests/test_misc.py b/tests/test_misc.py index 5832787aff20..afefce365472 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -3662,8 +3662,6 @@ def test_version_reexec(node_factory, bitcoind): # We use a file to tell our openingd wrapper where the real one is with open(os.path.join(l1.daemon.lightning_dir, TEST_NETWORK, "openingd-real"), 'w') as f: f.write(os.path.abspath('lightningd/lightning_openingd')) - # Internal restart doesn't work well with --dev-save-plugin-io - del l1.daemon.opts['dev-save-plugin-io'] l1.start() # This is a "version" message verfile = os.path.join(l1.daemon.lightning_dir, TEST_NETWORK, "openingd-version") @@ -4539,11 +4537,7 @@ def test_setconfig_changed(node_factory, bitcoind): @unittest.skipIf(os.getenv('TEST_DB_PROVIDER', 'sqlite3') != 'sqlite3', "deletes database, which is assumed sqlite3") def test_recover_command(node_factory, bitcoind): - l1 = node_factory.get_node(start=False) - # Internal restart doesn't work well with --dev-save-plugin-io - del l1.daemon.opts['dev-save-plugin-io'] - l1.start() - l2 = node_factory.get_node() + l1, l2 = node_factory.get_nodes(2) l1oldid = l1.info['id'] diff --git a/tests/test_splicing.py b/tests/test_splicing.py index 4974b91410af..a2b4c8f43f51 100644 --- a/tests/test_splicing.py +++ b/tests/test_splicing.py @@ -551,3 +551,31 @@ def test_route_by_old_scid(node_factory, bitcoind): wait_for(lambda: only_one(l1.rpc.listpeers()['peers'])['connected'] is True) l1.rpc.sendpay(route, inv2['payment_hash'], payment_secret=inv2['payment_secret']) l1.rpc.waitsendpay(inv2['payment_hash']) + + +@pytest.mark.openchannel('v1') +@pytest.mark.openchannel('v2') +def test_splice_unannounced(node_factory, bitcoind): + l1, l2 = node_factory.line_graph(2, fundamount=1000000, wait_for_announce=False, opts={'experimental-splicing': None}) + + chan_id = l1.get_channel_id(l2) + + # add extra sats to pay fee + funds_result = l1.rpc.fundpsbt("109000sat", "slow", 166, excess_as_change=True) + result = l1.rpc.splice_init(chan_id, 100000, funds_result['psbt']) + result = l1.rpc.splice_update(chan_id, result['psbt']) + assert(result['commitments_secured'] is False) + result = l1.rpc.splice_update(chan_id, result['psbt']) + assert(result['commitments_secured'] is True) + result = l1.rpc.signpsbt(result['psbt']) + result = l1.rpc.splice_signed(chan_id, result['signed_psbt']) + + l2.daemon.wait_for_log(r'CHANNELD_NORMAL to CHANNELD_AWAITING_SPLICE') + l1.daemon.wait_for_log(r'CHANNELD_NORMAL to CHANNELD_AWAITING_SPLICE') + + bitcoind.generate_block(1, wait_for_mempool=1) + + l2.daemon.wait_for_log(r'CHANNELD_AWAITING_SPLICE to CHANNELD_NORMAL') + l1.daemon.wait_for_log(r'CHANNELD_AWAITING_SPLICE to CHANNELD_NORMAL') + bitcoind.generate_block(1) + sync_blockheight(bitcoind, [l1, l2]) diff --git a/tests/test_wallet.py b/tests/test_wallet.py index 63ddba2f1abe..e00e3199cfac 100644 --- a/tests/test_wallet.py +++ b/tests/test_wallet.py @@ -1884,3 +1884,31 @@ def test_onchain_missing_no_p2tr_migrate(node_factory, bitcoind): # This can actually take a while for 100 blocks! l2.daemon.wait_for_log('Rescan finished! 1 outputs recovered') + + +@pytest.mark.parametrize("restart", [False, True]) +def test_sendpsbt_confirm(node_factory, bitcoind, restart): + """We should see our sendpsbt in wallet, and that it gets confirmed""" + l1, l2 = node_factory.get_nodes(2) + l1.fundwallet(100000) + + psbt = l1.rpc.fundpsbt(satoshi=10000, + feerate=7500, + startweight=42)['psbt'] + psbt = l2.rpc.addpsbtoutput(10000, psbt)['psbt'] + psbt = l1.rpc.signpsbt(psbt)['signed_psbt'] + sent = l1.rpc.sendpsbt(psbt) + + # Unconfirmed + lt = only_one([t for t in l1.rpc.listtransactions()['transactions'] if t['rawtx'] == sent['tx']]) + assert lt['blockheight'] == 0 + + if restart: + l1.restart() + + bitcoind.generate_block(1, wait_for_mempool=sent['txid']) + sync_blockheight(bitcoind, [l1]) + + # Should be confirmed now! + lt = only_one([t for t in l1.rpc.listtransactions()['transactions'] if t['rawtx'] == sent['tx']]) + assert lt['blockheight'] == bitcoind.rpc.getblockcount() diff --git a/tools/Makefile b/tools/Makefile index 6b92ebdd5555..3922ce0c8566 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -18,7 +18,7 @@ tools/headerversions: $(FORCE) tools/headerversions.o libccan.a tools/headerversions.o: ccan/config.h tools/check-bolt: tools/check-bolt.o $(TOOLS_COMMON_OBJS) -tools/hsmtool: tools/hsmtool.o $(TOOLS_COMMON_OBJS) $(BITCOIN_OBJS) common/amount.o common/autodata.o common/bech32.o common/bech32_util.o common/bigsize.o common/codex32.o common/configdir.o common/configvar.o common/derive_basepoints.o common/descriptor_checksum.o common/hsm_encryption.o common/key_derive.o common/node_id.o common/version.o wire/fromwire.o wire/towire.o +tools/hsmtool: tools/hsmtool.o $(TOOLS_COMMON_OBJS) $(BITCOIN_OBJS) common/amount.o common/autodata.o common/bech32.o common/bech32_util.o common/bigsize.o common/codex32.o common/configdir.o common/configvar.o common/derive_basepoints.o common/descriptor_checksum.o common/hsm_encryption.o common/key_derive.o common/node_id.o common/version.o common/memleak.o wire/fromwire.o wire/towire.o tools/lightning-hsmtool: tools/hsmtool cp $< $@ diff --git a/tools/bench-gossipd.sh b/tools/bench-gossipd.sh index 9b4ff5269b44..4bea1552ce22 100755 --- a/tools/bench-gossipd.sh +++ b/tools/bench-gossipd.sh @@ -78,7 +78,7 @@ if ! bitcoin-cli -regtest ping >/dev/null 2>&1; then while ! bitcoin-cli -regtest ping >/dev/null 2>&1; do sleep 1; done fi -LIGHTNINGD="./lightningd/lightningd --developer --network=regtest --dev-gossip-time=1550513768" +LIGHTNINGD="CLN_DEV_SET_TIME=1550513768 ./lightningd/lightningd --developer --network=regtest" LCLI1="./cli/lightning-cli --lightning-dir=$DIR -R" if [ -z "$DIR" ]; then diff --git a/tools/hsmtool.c b/tools/hsmtool.c index 7f2d30fb9d59..a6ba5435fcee 100644 --- a/tools/hsmtool.c +++ b/tools/hsmtool.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,11 @@ #define ERROR_LANG_NOT_SUPPORTED 6 #define ERROR_TERM 7 +void randbytes_(void *bytes, size_t num_bytes, u64 *offset) +{ + abort(); +} + static void show_usage(const char *progname) { printf("%s [arguments]\n", progname); diff --git a/wallet/db.c b/wallet/db.c index 6057952dd9c1..d15f1ee8dd17 100644 --- a/wallet/db.c +++ b/wallet/db.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -16,7 +17,6 @@ #include #include #include -#include #include #include #include diff --git a/wallet/invoices.c b/wallet/invoices.c index 1655c8f96f85..ddbff6515146 100644 --- a/wallet/invoices.c +++ b/wallet/invoices.c @@ -1,5 +1,6 @@ #include "config.h" #include +#include #include #include #include @@ -179,7 +180,7 @@ static u64 *expired_ids(const tal_t *ctx, static void trigger_expiration(struct invoices *invoices) { u64 *inv_dbids; - u64 now = time_now().ts.tv_sec; + u64 now = clock_time().ts.tv_sec; struct db_stmt *stmt; /* Free current expiration timer */ @@ -214,7 +215,7 @@ static void install_expiration_timer(struct invoices *invoices) struct db_stmt *stmt; struct timerel rel; struct timeabs expiry; - struct timeabs now = time_now(); + struct timeabs now = clock_time(); assert(!invoices->expiration_timer); @@ -275,7 +276,7 @@ bool invoices_create(struct invoices *invoices, { struct db_stmt *stmt; u64 expiry_time; - u64 now = time_now().ts.tv_sec; + u64 now = clock_time().ts.tv_sec; if (invoices_find_by_label(invoices, inv_dbid, label)) { if (taken(msat)) @@ -609,7 +610,7 @@ bool invoices_resolve(struct invoices *invoices, /* Assign a pay-index. */ pay_index = get_next_pay_index(invoices->wallet->db); - paid_timestamp = time_now().ts.tv_sec; + paid_timestamp = clock_time().ts.tv_sec; /* Update database. */ stmt = db_prepare_v2(invoices->wallet->db, SQL("UPDATE invoices" diff --git a/wallet/test/Makefile b/wallet/test/Makefile index c986342dfbcf..5d2e6e598bc5 100644 --- a/wallet/test/Makefile +++ b/wallet/test/Makefile @@ -12,6 +12,7 @@ WALLET_TEST_COMMON_OBJS := \ common/blockheight_states.o \ common/channel_id.o \ common/channel_type.o \ + common/clock_time.o \ common/derive_basepoints.o \ common/features.o \ common/htlc_state.o \ @@ -24,6 +25,7 @@ WALLET_TEST_COMMON_OBJS := \ common/key_derive.o \ common/psbt_keypath.o \ common/pseudorand.o \ + common/randbytes.o \ common/setup.o \ common/timeout.o \ common/trace.o \ diff --git a/wallet/test/run-db.c b/wallet/test/run-db.c index 106cd38026ae..86d6501463a3 100644 --- a/wallet/test/run-db.c +++ b/wallet/test/run-db.c @@ -170,10 +170,6 @@ struct invoices *invoices_new(const tal_t *ctx UNNEEDED, void logv(struct logger *logger UNNEEDED, enum log_level level UNNEEDED, const struct node_id *node_id UNNEEDED, bool call_notifier UNNEEDED, const char *fmt UNNEEDED, va_list ap UNNEEDED) { fprintf(stderr, "logv called!\n"); abort(); } -/* Generated stub for memleak_scan_outpointfilter */ -void memleak_scan_outpointfilter(struct htable *memtable UNNEEDED, - const struct outpointfilter *opf UNNEEDED) -{ fprintf(stderr, "memleak_scan_outpointfilter called!\n"); abort(); } /* Generated stub for mk_mvt_tags_ */ struct mvt_tags mk_mvt_tags_(enum mvt_tag tag UNNEEDED, ...) { fprintf(stderr, "mk_mvt_tags_ called!\n"); abort(); } diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index c1cd3b066f25..dce93f941d9d 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -264,6 +264,16 @@ void fatal(const char *fmt UNNEEDED, ...) /* Generated stub for fatal_vfmt */ void fatal_vfmt(const char *fmt UNNEEDED, va_list ap UNNEEDED) { fprintf(stderr, "fatal_vfmt called!\n"); abort(); } +/* Generated stub for find_txwatch_ */ +struct txwatch *find_txwatch_(struct chain_topology *topo UNNEEDED, + const struct bitcoin_txid *txid UNNEEDED, + enum watch_result (*cb)(struct lightningd *ld UNNEEDED, + const struct bitcoin_txid * UNNEEDED, + const struct bitcoin_tx * UNNEEDED, + unsigned int depth UNNEEDED, + void *arg) UNNEEDED, + void *arg UNNEEDED) +{ fprintf(stderr, "find_txwatch_ called!\n"); abort(); } /* Generated stub for force_peer_disconnect */ void force_peer_disconnect(struct lightningd *ld UNNEEDED, const struct peer *peer UNNEEDED, @@ -651,10 +661,6 @@ void lockin_complete(struct channel *channel UNNEEDED, void logv(struct logger *logger UNNEEDED, enum log_level level UNNEEDED, const struct node_id *node_id UNNEEDED, bool call_notifier UNNEEDED, const char *fmt UNNEEDED, va_list ap UNNEEDED) { fprintf(stderr, "logv called!\n"); abort(); } -/* Generated stub for memleak_scan_outpointfilter */ -void memleak_scan_outpointfilter(struct htable *memtable UNNEEDED, - const struct outpointfilter *opf UNNEEDED) -{ fprintf(stderr, "memleak_scan_outpointfilter called!\n"); abort(); } /* Generated stub for mk_mvt_tags_ */ struct mvt_tags mk_mvt_tags_(enum mvt_tag tag UNNEEDED, ...) { fprintf(stderr, "mk_mvt_tags_ called!\n"); abort(); } diff --git a/wallet/txfilter.c b/wallet/txfilter.c index 10ef774e41b0..0ce6f46a7a2c 100644 --- a/wallet/txfilter.c +++ b/wallet/txfilter.c @@ -128,12 +128,6 @@ void outpointfilter_remove(struct outpointfilter *of, struct outpointfilter *outpointfilter_new(tal_t *ctx) { struct outpointfilter *opf = tal(ctx, struct outpointfilter); - opf->set = tal(opf, struct outpointset); - outpointset_init(opf->set); + opf->set = new_htable(opf, outpointset); return opf; } - -void memleak_scan_outpointfilter(struct htable *memtable, const struct outpointfilter *opf) -{ - memleak_scan_htable(memtable, &opf->set->raw); -} diff --git a/wallet/txfilter.h b/wallet/txfilter.h index c9152bffd390..2e72b68e1b93 100644 --- a/wallet/txfilter.h +++ b/wallet/txfilter.h @@ -64,9 +64,6 @@ bool outpointfilter_matches(struct outpointfilter *of, void outpointfilter_remove(struct outpointfilter *of, const struct bitcoin_outpoint *outpoint); -void memleak_scan_outpointfilter(struct htable *memtable, - const struct outpointfilter *opf); - /* Useful for other callers */ size_t scriptpubkey_hash(const u8 *out); diff --git a/wallet/wallet.c b/wallet/wallet.c index ddc933d70ced..4a4e20e4923e 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1,14 +1,17 @@ #include "config.h" #include #include +#include #include #include #include #include #include +#include #include #include #include +#include #include #include #include @@ -181,8 +184,7 @@ static void our_addresses_add_for_index(struct wallet *w, u32 i) static void our_addresses_init(struct wallet *w) { w->our_addresses_maxindex = 0; - w->our_addresses = tal(w, struct wallet_address_htable); - wallet_address_htable_init(w->our_addresses); + w->our_addresses = new_htable(w, wallet_address_htable); our_addresses_add_for_index(w, w->our_addresses_maxindex); } @@ -459,7 +461,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; @@ -471,6 +489,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; } @@ -817,27 +839,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); @@ -4162,7 +4210,7 @@ void wallet_payment_set_status(struct wallet *wallet, u32 completed_at = 0; if (newstatus != PAYMENT_PENDING) - completed_at = time_now().ts.tv_sec; + completed_at = clock_time().ts.tv_sec; stmt = db_prepare_v2(wallet->db, SQL("UPDATE payments SET status=?, completed_at=?, updated_index=? " @@ -5165,9 +5213,16 @@ struct bitcoin_txid *wallet_transactions_by_height(const tal_t *ctx, struct db_stmt *stmt; struct bitcoin_txid *txids = tal_arr(ctx, struct bitcoin_txid, 0); int count = 0; - stmt = db_prepare_v2( - w->db, SQL("SELECT id FROM transactions WHERE blockheight=?")); - db_bind_int(stmt, blockheight); + + /* Note: blockheight=NULL is not the same as is NULL! */ + if (blockheight == 0) { + stmt = db_prepare_v2( + w->db, SQL("SELECT id FROM transactions WHERE blockheight IS NULL")); + } else { + stmt = db_prepare_v2( + w->db, SQL("SELECT id FROM transactions WHERE blockheight=?")); + db_bind_int(stmt, blockheight); + } db_query_prepared(stmt); while (db_step(stmt)) { @@ -5310,7 +5365,7 @@ void wallet_forwarded_payment_add(struct wallet *w, const struct htlc_in *in, if (state == FORWARD_SETTLED || state == FORWARD_FAILED) { resolved_time = tal(tmpctx, struct timeabs); - *resolved_time = time_now(); + *resolved_time = clock_time(); } else { resolved_time = NULL; } @@ -6884,13 +6939,6 @@ struct local_anchor_info *wallet_get_local_anchors(const tal_t *ctx, return anchors; } -void wallet_memleak_scan(struct htable *memtable, const struct wallet *w) -{ - memleak_scan_outpointfilter(memtable, w->utxoset_outpoints); - memleak_scan_outpointfilter(memtable, w->owned_outpoints); - memleak_scan_htable(memtable, &w->our_addresses->raw); -} - struct issued_address_type *wallet_list_addresses(const tal_t *ctx, struct wallet *wallet, u64 liststart, const u32 *listlimit) { diff --git a/wallet/wallet.h b/wallet/wallet.h index 584f17b03076..512cac1ac57e 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -1920,8 +1920,4 @@ void wallet_datastore_save_payment_description(struct db *db, const char *desc); void migrate_setup_coinmoves(struct lightningd *ld, struct db *db); -/** - * wallet_memleak_scan - Check for memleaks in wallet. - */ -void wallet_memleak_scan(struct htable *memtable, const struct wallet *w); #endif /* LIGHTNING_WALLET_WALLET_H */ diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c index 677db8bab66f..ab011b553b4c 100644 --- a/wallet/walletrpc.c +++ b/wallet/walletrpc.c @@ -953,7 +953,6 @@ static void maybe_notify_new_external_send(struct lightningd *ld, wallet_save_chain_mvt(ld, take(mvt)); } - static void sendpsbt_done(struct bitcoind *bitcoind UNUSED, bool success, const char *msg, struct sending_psbt *sending) @@ -985,10 +984,14 @@ static void sendpsbt_done(struct bitcoind *bitcoind UNUSED, } wallet_transaction_add(ld->wallet, sending->wtx, 0, 0); + wally_txid(sending->wtx, &txid); /* Extract the change output and add it to the DB */ - wallet_extract_owned_outputs(ld->wallet, sending->wtx, false, NULL); - wally_txid(sending->wtx, &txid); + if (wallet_extract_owned_outputs(ld->wallet, sending->wtx, false, NULL) == 0) { + /* If we're not watching it for selfish reasons (i.e. pure send to + * others), make sure we're watching it so we can update depth in db */ + watch_unconfirmed_txid(ld, ld->topology, &txid); + } for (size_t i = 0; i < sending->psbt->num_outputs; i++) maybe_notify_new_external_send(ld, &txid, i, sending->psbt); diff --git a/wire/test/Makefile b/wire/test/Makefile index 997a72dae737..785fa5054293 100644 --- a/wire/test/Makefile +++ b/wire/test/Makefile @@ -13,6 +13,7 @@ WIRE_TEST_COMMON_OBJS := \ common/autodata.o \ common/base32.o \ common/pseudorand.o \ + common/randbytes.o \ common/setup.o \ common/utils.o \ common/wireaddr.o diff --git a/wire/test/run-peer-wire.c b/wire/test/run-peer-wire.c index 894920440a88..f8b17c32e60b 100644 --- a/wire/test/run-peer-wire.c +++ b/wire/test/run-peer-wire.c @@ -12,6 +12,7 @@ #include #include +#include #include #include #include diff --git a/wire/test/run-tlvstream.c b/wire/test/run-tlvstream.c index 68420fb900ed..2cb0c8ceb567 100644 --- a/wire/test/run-tlvstream.c +++ b/wire/test/run-tlvstream.c @@ -9,6 +9,7 @@ static const char *reason; #include #include #include +#include #include #include