diff --git a/bitcoin/script.c b/bitcoin/script.c index 2422f612b0e0..30cc0897a73c 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -13,6 +14,18 @@ /* To push 0-75 bytes onto stack. */ #define OP_PUSHBYTES(val) (val) +size_t script_with_len_hash(const struct script_with_len *swl) +{ + return siphash24(siphash_seed(), swl->script, swl->len); +} + +bool script_with_len_eq(const struct script_with_len *a, + const struct script_with_len *b) +{ + return memeq(a->script, a->len, b->script, b->len); +} + + /* Bitcoin's OP_HASH160 is RIPEMD(SHA256()) */ static void hash160(struct ripemd160 *redeemhash, const void *mem, size_t len) { diff --git a/bitcoin/script.h b/bitcoin/script.h index 52be6626c592..0c37c6457032 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -12,6 +12,16 @@ struct ripemd160; struct rel_locktime; struct abs_locktime; +/* libwally uses pointer/size pairs */ +struct script_with_len { + const u8 *script; + size_t len; +}; + +size_t script_with_len_hash(const struct script_with_len *swl); +bool script_with_len_eq(const struct script_with_len *a, + const struct script_with_len *b); + /* tal_count() gives the length of the script. */ u8 *bitcoin_redeem_2of2(const tal_t *ctx, const struct pubkey *key1, diff --git a/bitcoin/tx.c b/bitcoin/tx.c index 4c1a63de6c0a..0d5d6e560a89 100644 --- a/bitcoin/tx.c +++ b/bitcoin/tx.c @@ -326,13 +326,12 @@ struct amount_asset bitcoin_tx_output_get_amount(const struct bitcoin_tx *tx, return wally_tx_output_get_amount(&tx->wtx->outputs[outnum]); } -void bitcoin_tx_output_get_amount_sat(const struct bitcoin_tx *tx, int outnum, - struct amount_sat *amount) +struct amount_sat bitcoin_tx_output_get_amount_sat(const struct bitcoin_tx *tx, int outnum) { struct amount_asset asset_amt; asset_amt = bitcoin_tx_output_get_amount(tx, outnum); assert(amount_asset_is_main(&asset_amt)); - *amount = amount_asset_to_sat(&asset_amt); + return amount_asset_to_sat(&asset_amt); } void bitcoin_tx_input_set_witness(struct bitcoin_tx *tx, int innum, diff --git a/bitcoin/tx.h b/bitcoin/tx.h index 4b7134e0f8c2..1e28130d8a97 100644 --- a/bitcoin/tx.h +++ b/bitcoin/tx.h @@ -176,8 +176,8 @@ u8 *bitcoin_tx_output_get_witscript(const tal_t *ctx, const struct bitcoin_tx *t * Internally we use a `wally_tx` to represent the transaction. The * satoshi amount isn't a struct amount_sat, so we need a conversion */ -void bitcoin_tx_output_get_amount_sat(const struct bitcoin_tx *tx, int outnum, - struct amount_sat *amount); +struct amount_sat bitcoin_tx_output_get_amount_sat(const struct bitcoin_tx *tx, int outnum); + /** * Helper to just get an amount_sat for the output amount. */ diff --git a/ccan/README b/ccan/README index e15812c17108..9f750bd2e7c9 100644 --- a/ccan/README +++ b/ccan/README @@ -1,3 +1,3 @@ CCAN imported from http://ccodearchive.net. -CCAN version: init-2608-gb35fabb6 +CCAN version: init-2610-gde698d55 diff --git a/ccan/ccan/htable/htable.c b/ccan/ccan/htable/htable.c index f631ffebf1f7..0b515b94bbf0 100644 --- a/ccan/ccan/htable/htable.c +++ b/ccan/ccan/htable/htable.c @@ -136,9 +136,21 @@ bool htable_copy_(struct htable *dst, const struct htable *src) *dst = *src; dst->table = htable; memcpy(dst->table, src->table, sizeof(size_t) << src->bits); + dst->locked = 0; return true; } +void htable_lock(struct htable *ht) +{ + ht->locked++; +} + +void htable_unlock(struct htable *ht) +{ + assert(ht->locked != 0); + ht->locked--; +} + static size_t hash_bucket(const struct htable *ht, size_t h) { return h & ((1 << ht->bits)-1); @@ -380,6 +392,7 @@ bool htable_add_(struct htable *ht, size_t hash, const void *p) /* Cannot insert NULL, or (void *)1. */ assert(p); assert(entry_is_valid((uintptr_t)p)); + assert(ht->locked == 0); /* Getting too full? */ if (ht->elems+1 + ht->deleted > ht_max(ht)) { diff --git a/ccan/ccan/htable/htable.h b/ccan/ccan/htable/htable.h index faaf541bd8ce..8d0e63f909b4 100644 --- a/ccan/ccan/htable/htable.h +++ b/ccan/ccan/htable/htable.h @@ -25,7 +25,7 @@ struct htable { size_t (*rehash)(const void *elem, void *priv); void *priv; unsigned int bits, perfect_bitnum; - size_t elems, deleted; + size_t elems, deleted, locked; /* These are the bits which are the same in all pointers. */ uintptr_t common_mask, common_bits; uintptr_t *table; @@ -49,7 +49,7 @@ struct htable { * static struct htable ht = HTABLE_INITIALIZER(ht, rehash, NULL); */ #define HTABLE_INITIALIZER(name, rehash, priv) \ - { rehash, priv, 0, 0, 0, 0, -1, 0, &name.common_bits } + { rehash, priv, 0, 0, 0, 0, 0, -1, 0, &name.common_bits } /** * htable_init - initialize an empty hash table. @@ -113,7 +113,7 @@ struct htable *htable_check(const struct htable *ht, const char *abortstr); * @dst: the hash table to overwrite * @src: the hash table to copy * - * Only fails on out-of-memory. + * Only fails on out-of-memory. Note that the copy is not locked (see htable_lock()). * * Equivalent to (but faster than): * if (!htable_init_sized(dst, src->rehash, src->priv, 1U << src->bits)) @@ -128,6 +128,24 @@ struct htable *htable_check(const struct htable *ht, const char *abortstr); #define htable_copy(dst, src) htable_copy_(dst, htable_debug(src, HTABLE_LOC)) bool htable_copy_(struct htable *dst, const struct htable *src); +/** + * htable_lock - prevent additions to the hash table. + * @ht: the hash table + * + * Causes an assertion on htable_add. This is useful to enforce restrictions + * during iteration. This function nests, so you can htable_lock() multiple + * times before calling htable_unlock() multiple times. + */ +void htable_lock(struct htable *ht); + +/** + * htable_unlock - allow additions to the hash table. + * @ht: the locked hash table + * + * See htable_lock(). + */ +void htable_unlock(struct htable *ht); + /** * htable_add - add a pointer into a hash table. * @ht: the htable @@ -136,6 +154,8 @@ bool htable_copy_(struct htable *dst, const struct htable *src); * * Also note that this can only fail due to allocation failure. Otherwise, it * returns true. + * + * Note that iteration is NOT safe over htable_add, as the table could be resized. */ #define htable_add(ht, hash, p) \ htable_add_(htable_debug(ht, HTABLE_LOC), hash, p) @@ -148,6 +168,7 @@ bool htable_add_(struct htable *ht, size_t hash, const void *p); * @p: the pointer * * Returns true if the pointer was found (and deleted). + * Note that iteration is safe over htable_del. */ #define htable_del(ht, hash, p) \ htable_del_(htable_debug(ht, HTABLE_LOC), hash, p) diff --git a/ccan/ccan/htable/htable_type.h b/ccan/ccan/htable/htable_type.h index 103d2ff17cb1..2f7fb789c56f 100644 --- a/ccan/ccan/htable/htable_type.h +++ b/ccan/ccan/htable/htable_type.h @@ -32,6 +32,10 @@ * Count entries: * size_t _count(const struct *ht); * + * Lock and unlock (to prevent adds): + * void _lock(struct *ht); + * void _unlock(struct *ht); + * * Add function only fails if we run out of memory: * bool _add(struct *ht, const *e); * @@ -87,6 +91,14 @@ { \ return htable_count(&ht->raw); \ } \ + static inline void name##_lock(struct name *ht) \ + { \ + htable_lock(&ht->raw); \ + } \ + static inline void name##_unlock(struct name *ht) \ + { \ + htable_unlock(&ht->raw); \ + } \ static inline UNNEEDED void name##_clear(struct name *ht) \ { \ htable_clear(&ht->raw); \ diff --git a/common/addr.c b/common/addr.c index e7ff17c3a486..27aeacefb403 100644 --- a/common/addr.c +++ b/common/addr.c @@ -7,31 +7,31 @@ char *encode_scriptpubkey_to_addr(const tal_t *ctx, const struct chainparams *chainparams, - const u8 *scriptpubkey) + const u8 *scriptpubkey, + size_t scriptpubkey_len) { char *out; - const size_t script_len = tal_bytelen(scriptpubkey); struct bitcoin_address pkh; struct ripemd160 sh; int witver; - if (is_p2pkh(scriptpubkey, script_len, &pkh)) + if (is_p2pkh(scriptpubkey, scriptpubkey_len, &pkh)) return bitcoin_to_base58(ctx, chainparams, &pkh); - if (is_p2sh(scriptpubkey, script_len, &sh)) + if (is_p2sh(scriptpubkey, scriptpubkey_len, &sh)) return p2sh_to_base58(ctx, chainparams, &sh); - if (is_p2tr(scriptpubkey, script_len, NULL)) + if (is_p2tr(scriptpubkey, scriptpubkey_len, NULL)) witver = 1; - else if (is_p2wpkh(scriptpubkey, script_len, NULL) - || is_p2wsh(scriptpubkey, script_len, NULL)) + else if (is_p2wpkh(scriptpubkey, scriptpubkey_len, NULL) + || is_p2wsh(scriptpubkey, scriptpubkey_len, NULL)) witver = 0; else { return NULL; } out = tal_arr(ctx, char, 73 + strlen(chainparams->onchain_hrp)); if (!segwit_addr_encode(out, chainparams->onchain_hrp, witver, - scriptpubkey + 2, script_len - 2)) + scriptpubkey + 2, scriptpubkey_len - 2)) return tal_free(out); return out; diff --git a/common/addr.h b/common/addr.h index 7ab70f50158a..e5056990c795 100644 --- a/common/addr.h +++ b/common/addr.h @@ -6,7 +6,8 @@ /* Given a scriptPubkey, return an encoded address for p2pkh/p2w{pkh,sh}/p2tr */ char *encode_scriptpubkey_to_addr(const tal_t *ctx, const struct chainparams *chainparams, - const u8 *scriptpubkey); + const u8 *scriptpubkey, + size_t scriptpubkey_len); bool decode_scriptpubkey_from_addr(const tal_t *ctx, const struct chainparams *chainparams, diff --git a/common/bolt11_json.c b/common/bolt11_json.c index bdc91c124b43..c1891c23e116 100644 --- a/common/bolt11_json.c +++ b/common/bolt11_json.c @@ -28,7 +28,7 @@ static void json_add_fallback(struct json_stream *response, json_add_string(response, "type", "P2TR"); } - addr = encode_scriptpubkey_to_addr(tmpctx, chain, fallback); + addr = encode_scriptpubkey_to_addr(tmpctx, chain, fallback, fallback_len); if (addr) json_add_string(response, "addr", addr); json_add_hex_talarr(response, "hex", fallback); diff --git a/common/test/run-amount.c b/common/test/run-amount.c index f76484ef3436..d0e5933e2f20 100644 --- a/common/test/run-amount.c +++ b/common/test/run-amount.c @@ -1,6 +1,6 @@ #include "config.h" #include "../amount.c" -#include +#include #include #include @@ -37,6 +37,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 siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed 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-base64.c b/common/test/run-base64.c index e71371c9873b..f4df43bdf6a3 100644 --- a/common/test/run-base64.c +++ b/common/test/run-base64.c @@ -1,9 +1,10 @@ #include "config.h" #include "../base64.c" #include +#include #include #include -#include +#include #include #include #include @@ -77,6 +78,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 siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed 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-bigsize.c b/common/test/run-bigsize.c index 1e167fd7c559..6ee860aa0a41 100644 --- a/common/test/run-bigsize.c +++ b/common/test/run-bigsize.c @@ -4,7 +4,6 @@ #include #include #include -#include #include static const char *reason; @@ -91,6 +90,9 @@ bool parse_amount_msat(struct amount_msat *msat UNNEEDED, const char *s UNNEEDED /* Generated stub for parse_amount_sat */ bool parse_amount_sat(struct amount_sat *sat UNNEEDED, const char *s UNNEEDED, size_t slen UNNEEDED) { fprintf(stderr, "parse_amount_sat called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed 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-blindedpath_enctlv.c b/common/test/run-blindedpath_enctlv.c index d2552ad4e727..cc67bb20661a 100644 --- a/common/test/run-blindedpath_enctlv.c +++ b/common/test/run-blindedpath_enctlv.c @@ -3,7 +3,6 @@ #include "../blinding.c" #include "../hmac.c" #include -#include #include #include @@ -63,6 +62,9 @@ void fromwire_node_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct n void fromwire_sciddir_or_pubkey(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct sciddir_or_pubkey *sciddpk UNNEEDED) { fprintf(stderr, "fromwire_sciddir_or_pubkey called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed called!\n"); abort(); } /* Generated stub for towire_amount_msat */ void towire_amount_msat(u8 **pptr UNNEEDED, const struct amount_msat msat UNNEEDED) { fprintf(stderr, "towire_amount_msat called!\n"); abort(); } diff --git a/common/test/run-blindedpath_onion.c b/common/test/run-blindedpath_onion.c index fc6d015cc4d2..f52fa65ed056 100644 --- a/common/test/run-blindedpath_onion.c +++ b/common/test/run-blindedpath_onion.c @@ -81,6 +81,9 @@ struct onionreply *new_onionreply(const tal_t *ctx UNNEEDED, const u8 *contents /* Generated stub for pubkey_from_node_id */ bool pubkey_from_node_id(struct pubkey *key UNNEEDED, const struct node_id *id UNNEEDED) { fprintf(stderr, "pubkey_from_node_id called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed called!\n"); abort(); } /* Generated stub for towire_amount_msat */ void towire_amount_msat(u8 **pptr UNNEEDED, const struct amount_msat msat UNNEEDED) { fprintf(stderr, "towire_amount_msat called!\n"); abort(); } diff --git a/common/test/run-bolt11.c b/common/test/run-bolt11.c index bd8c2c662db2..fe2b3e2cb5b9 100644 --- a/common/test/run-bolt11.c +++ b/common/test/run-bolt11.c @@ -9,11 +9,13 @@ #include "../wire/fromwire.c" #include "../wire/towire.c" #include -#include #include #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ static struct privkey privkey; diff --git a/common/test/run-bolt12-encode-test.c b/common/test/run-bolt12-encode-test.c index 5ca641f93012..911ce003c53b 100644 --- a/common/test/run-bolt12-encode-test.c +++ b/common/test/run-bolt12-encode-test.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -72,6 +71,9 @@ void sighash_from_merkle(const char *messagename UNNEEDED, const struct sha256 *merkle UNNEEDED, struct sha256 *sighash UNNEEDED) { fprintf(stderr, "sighash_from_merkle called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed called!\n"); abort(); } /* Generated stub for towire_amount_msat */ void towire_amount_msat(u8 **pptr UNNEEDED, const struct amount_msat msat UNNEEDED) { fprintf(stderr, "towire_amount_msat called!\n"); abort(); } diff --git a/common/test/run-bolt12-format-string-test.c b/common/test/run-bolt12-format-string-test.c index f2a5e1124f56..d517a60cf11d 100644 --- a/common/test/run-bolt12-format-string-test.c +++ b/common/test/run-bolt12-format-string-test.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include @@ -77,6 +76,9 @@ void sighash_from_merkle(const char *messagename UNNEEDED, const struct sha256 *merkle UNNEEDED, struct sha256 *sighash UNNEEDED) { fprintf(stderr, "sighash_from_merkle called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed called!\n"); abort(); } /* Generated stub for towire_blinded_path */ void towire_blinded_path(u8 **p UNNEEDED, const struct blinded_path *blinded_path UNNEEDED) { fprintf(stderr, "towire_blinded_path called!\n"); abort(); } diff --git a/common/test/run-bolt12-offer-decode.c b/common/test/run-bolt12-offer-decode.c index 329a13970ac4..5c2a73d5ea92 100644 --- a/common/test/run-bolt12-offer-decode.c +++ b/common/test/run-bolt12-offer-decode.c @@ -14,7 +14,6 @@ #include #include #include -#include #include /* AUTOGENERATED MOCKS START */ @@ -79,6 +78,9 @@ void sighash_from_merkle(const char *messagename UNNEEDED, const struct sha256 *merkle UNNEEDED, struct sha256 *sighash UNNEEDED) { fprintf(stderr, "sighash_from_merkle called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed 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-bolt12_decode.c b/common/test/run-bolt12_decode.c index e4473ada7b64..f27f8734d5fb 100644 --- a/common/test/run-bolt12_decode.c +++ b/common/test/run-bolt12_decode.c @@ -8,7 +8,6 @@ #include #include #include -#include #include /* AUTOGENERATED MOCKS START */ @@ -122,6 +121,9 @@ void sighash_from_merkle(const char *messagename UNNEEDED, const struct sha256 *merkle UNNEEDED, struct sha256 *sighash UNNEEDED) { fprintf(stderr, "sighash_from_merkle called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed 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-bolt12_merkle-json.c b/common/test/run-bolt12_merkle-json.c index fefac76cc2cd..b414fe753602 100644 --- a/common/test/run-bolt12_merkle-json.c +++ b/common/test/run-bolt12_merkle-json.c @@ -12,7 +12,6 @@ #include #include #include -#include #include /* AUTOGENERATED MOCKS START */ @@ -32,6 +31,9 @@ bool mvt_tag_parse(const char *buf UNNEEDED, size_t len UNNEEDED, enum mvt_tag * /* Generated stub for node_id_from_hexstr */ bool node_id_from_hexstr(const char *str UNNEEDED, size_t slen UNNEEDED, struct node_id *id UNNEEDED) { fprintf(stderr, "node_id_from_hexstr called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed 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-bolt12_merkle.c b/common/test/run-bolt12_merkle.c index 4d2f0bc6d639..abc546872950 100644 --- a/common/test/run-bolt12_merkle.c +++ b/common/test/run-bolt12_merkle.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include @@ -27,6 +26,9 @@ struct blinded_path *fromwire_blinded_path(const tal_t *ctx UNNEEDED, const u8 * bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed called!\n"); abort(); } /* Generated stub for towire_blinded_path */ void towire_blinded_path(u8 **p UNNEEDED, const struct blinded_path *blinded_path UNNEEDED) { fprintf(stderr, "towire_blinded_path called!\n"); abort(); } diff --git a/common/test/run-bolt12_period.c b/common/test/run-bolt12_period.c index 6b92f9cb63f0..4152f13111ef 100644 --- a/common/test/run-bolt12_period.c +++ b/common/test/run-bolt12_period.c @@ -5,7 +5,6 @@ #include #include #include -#include #include /* AUTOGENERATED MOCKS START */ @@ -124,6 +123,9 @@ void sighash_from_merkle(const char *messagename UNNEEDED, const struct sha256 *merkle UNNEEDED, struct sha256 *sighash UNNEEDED) { fprintf(stderr, "sighash_from_merkle called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed called!\n"); abort(); } /* Generated stub for to_bech32_charset */ char *to_bech32_charset(const tal_t *ctx UNNEEDED, const char *hrp UNNEEDED, const u8 *data UNNEEDED) diff --git a/common/test/run-channel_type.c b/common/test/run-channel_type.c index 2cac84ac8f41..495f695c07a8 100644 --- a/common/test/run-channel_type.c +++ b/common/test/run-channel_type.c @@ -2,7 +2,6 @@ #include "../channel_type.c" #include "../features.c" #include -#include #include #include #include @@ -77,6 +76,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 siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed 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-codex32.c b/common/test/run-codex32.c index 276bd02775b0..79aafbf5e26b 100644 --- a/common/test/run-codex32.c +++ b/common/test/run-codex32.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include @@ -91,6 +90,9 @@ bool parse_amount_msat(struct amount_msat *msat UNNEEDED, const char *s UNNEEDED /* Generated stub for parse_amount_sat */ bool parse_amount_sat(struct amount_sat *sat UNNEEDED, const char *s UNNEEDED, size_t slen UNNEEDED) { fprintf(stderr, "parse_amount_sat called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed 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-coin_mvt.c b/common/test/run-coin_mvt.c index 99651ccbb54e..b499bdf06d14 100644 --- a/common/test/run-coin_mvt.c +++ b/common/test/run-coin_mvt.c @@ -1,7 +1,6 @@ #include "config.h" #include "../coin_mvt.c" #include -#include #include #include @@ -91,6 +90,9 @@ void fromwire_u8_array(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, u8 *arr /* Generated stub for fromwire_wirestring */ char *fromwire_wirestring(const tal_t *ctx UNNEEDED, const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_wirestring called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed 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-cryptomsg.c b/common/test/run-cryptomsg.c index 0284f9da1f94..3c1c77db7223 100644 --- a/common/test/run-cryptomsg.c +++ b/common/test/run-cryptomsg.c @@ -1,6 +1,5 @@ #include "config.h" #include -#include #include #include #include @@ -74,6 +73,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 siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed 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-deprecation.c b/common/test/run-deprecation.c index fa1378c8648b..01d5552fb894 100644 --- a/common/test/run-deprecation.c +++ b/common/test/run-deprecation.c @@ -6,7 +6,7 @@ static const char *test_next_version; #include "../deprecation.c" #include -#include +#include #include #include #include @@ -78,6 +78,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 siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed 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-derive_basepoints.c b/common/test/run-derive_basepoints.c index cb896ad7795a..91193822d0af 100644 --- a/common/test/run-derive_basepoints.c +++ b/common/test/run-derive_basepoints.c @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include #include @@ -79,6 +79,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 siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed 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-features.c b/common/test/run-features.c index efbea7f9fbe6..37c0ddd6375b 100644 --- a/common/test/run-features.c +++ b/common/test/run-features.c @@ -3,7 +3,6 @@ #include "../memleak.c" #include #include -#include #include /* AUTOGENERATED MOCKS START */ @@ -76,6 +75,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 siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed 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-gossmap-fp16.c b/common/test/run-gossmap-fp16.c index 539b129b5293..2b08524c6188 100644 --- a/common/test/run-gossmap-fp16.c +++ b/common/test/run-gossmap-fp16.c @@ -1,6 +1,6 @@ #include "config.h" #include "../fp16.c" -#include +#include #include #include #include @@ -72,6 +72,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 siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed 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-htable.c b/common/test/run-htable.c index 75164ce204fe..267ad8c03f10 100644 --- a/common/test/run-htable.c +++ b/common/test/run-htable.c @@ -8,7 +8,6 @@ #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 c7c5ba226530..13d34952c50b 100644 --- a/common/test/run-ip_port_parsing.c +++ b/common/test/run-ip_port_parsing.c @@ -4,7 +4,7 @@ #include #include -#include +#include #include /* AUTOGENERATED MOCKS START */ @@ -77,6 +77,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 siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed 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-json.c b/common/test/run-json.c index 18130c236945..1fc42a2223ae 100644 --- a/common/test/run-json.c +++ b/common/test/run-json.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include diff --git a/common/test/run-json_filter.c b/common/test/run-json_filter.c index d682b82130b3..015ff359bfb5 100644 --- a/common/test/run-json_filter.c +++ b/common/test/run-json_filter.c @@ -6,7 +6,6 @@ #include "../json_stream.c" #include #include -#include #include #include @@ -149,6 +148,9 @@ int segwit_addr_decode( const char* addr ) { fprintf(stderr, "segwit_addr_decode called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed called!\n"); abort(); } /* Generated stub for to_canonical_invstr */ const char *to_canonical_invstr(const tal_t *ctx UNNEEDED, const char *invstring UNNEEDED) { fprintf(stderr, "to_canonical_invstr called!\n"); abort(); } diff --git a/common/test/run-json_remove.c b/common/test/run-json_remove.c index 8a15653ebfae..880e9f8d6d29 100644 --- a/common/test/run-json_remove.c +++ b/common/test/run-json_remove.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include @@ -181,6 +180,9 @@ int segwit_addr_decode( const char* addr ) { fprintf(stderr, "segwit_addr_decode called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed called!\n"); abort(); } /* Generated stub for to_canonical_invstr */ const char *to_canonical_invstr(const tal_t *ctx UNNEEDED, const char *invstring UNNEEDED) { fprintf(stderr, "to_canonical_invstr called!\n"); abort(); } diff --git a/common/test/run-json_scan.c b/common/test/run-json_scan.c index 877bce6be077..6519129a3fba 100644 --- a/common/test/run-json_scan.c +++ b/common/test/run-json_scan.c @@ -2,7 +2,6 @@ #include "../json_parse.c" #include "../json_parse_simple.c" #include -#include #include #include #include @@ -86,6 +85,9 @@ bool parse_amount_msat(struct amount_msat *msat UNNEEDED, const char *s UNNEEDED /* Generated stub for parse_amount_sat */ bool parse_amount_sat(struct amount_sat *sat UNNEEDED, const char *s UNNEEDED, size_t slen UNNEEDED) { fprintf(stderr, "parse_amount_sat called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed 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-json_stream-filter.c b/common/test/run-json_stream-filter.c index 6f6fe060f834..3f40141fb566 100644 --- a/common/test/run-json_stream-filter.c +++ b/common/test/run-json_stream-filter.c @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -111,6 +110,9 @@ const char *json_tok_full(const char *buffer UNNEEDED, const jsmntok_t *t UNNEED /* Generated stub for json_tok_full_len */ int json_tok_full_len(const jsmntok_t *t UNNEEDED) { fprintf(stderr, "json_tok_full_len called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed 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-jsonrpc_io.c b/common/test/run-jsonrpc_io.c index d0f75ff2fa89..007132a5bbe0 100644 --- a/common/test/run-jsonrpc_io.c +++ b/common/test/run-jsonrpc_io.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include @@ -92,6 +92,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 siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed 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-key_derive.c b/common/test/run-key_derive.c index 6b158f74413d..9dc6f4b33ec4 100644 --- a/common/test/run-key_derive.c +++ b/common/test/run-key_derive.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include @@ -77,6 +77,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 siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed 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-lease_rates.c b/common/test/run-lease_rates.c index f995eb88c2f6..5bf13c62d648 100644 --- a/common/test/run-lease_rates.c +++ b/common/test/run-lease_rates.c @@ -1,7 +1,6 @@ #include "config.h" #include "../amount.c" #include "../lease_rates.c" -#include #include #include @@ -41,6 +40,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 siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed 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-marginal_feerate.c b/common/test/run-marginal_feerate.c index 097852ceabc8..e0d0ebd4ab72 100644 --- a/common/test/run-marginal_feerate.c +++ b/common/test/run-marginal_feerate.c @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include #include "../fee_states.c" @@ -80,6 +80,9 @@ int htlc_state_flags(enum htlc_state state UNNEEDED) /* Generated stub for htlc_state_name */ const char *htlc_state_name(enum htlc_state s UNNEEDED) { fprintf(stderr, "htlc_state_name called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed 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-onion-message-test.c b/common/test/run-onion-message-test.c index 7dba2c5cc2c6..299a0c5e9dda 100644 --- a/common/test/run-onion-message-test.c +++ b/common/test/run-onion-message-test.c @@ -36,6 +36,9 @@ struct onionreply *new_onionreply(const tal_t *ctx UNNEEDED, const u8 *contents /* Generated stub for pubkey_from_node_id */ bool pubkey_from_node_id(struct pubkey *key UNNEEDED, const struct node_id *id UNNEEDED) { fprintf(stderr, "pubkey_from_node_id called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed called!\n"); abort(); } /* Generated stub for towire_channel_id */ void towire_channel_id(u8 **pptr UNNEEDED, const struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "towire_channel_id called!\n"); abort(); } diff --git a/common/test/run-onion-test-vector.c b/common/test/run-onion-test-vector.c index 842c96c5da47..12986ad54b64 100644 --- a/common/test/run-onion-test-vector.c +++ b/common/test/run-onion-test-vector.c @@ -100,6 +100,9 @@ bool parse_amount_sat(struct amount_sat *sat UNNEEDED, const char *s UNNEEDED, s /* Generated stub for pubkey_from_node_id */ bool pubkey_from_node_id(struct pubkey *key UNNEEDED, const struct node_id *id UNNEEDED) { fprintf(stderr, "pubkey_from_node_id called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed called!\n"); abort(); } /* Generated stub for tlv_field_offset */ size_t tlv_field_offset(const u8 *tlvstream UNNEEDED, size_t tlvlen UNNEEDED, u64 fieldtype UNNEEDED) { fprintf(stderr, "tlv_field_offset called!\n"); abort(); } diff --git a/common/test/run-param.c b/common/test/run-param.c index 3287eb27d9d4..5b7d2952b33d 100644 --- a/common/test/run-param.c +++ b/common/test/run-param.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include diff --git a/common/test/run-psbt_diff.c b/common/test/run-psbt_diff.c index 1c107851ac66..bb183588bb7f 100644 --- a/common/test/run-psbt_diff.c +++ b/common/test/run-psbt_diff.c @@ -1,5 +1,4 @@ #include "config.h" -#include #include #include #include "../amount.c" @@ -41,6 +40,9 @@ void fromwire_u8_array(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, u8 *arr /* Generated stub for pseudorand_u64_ */ uint64_t pseudorand_u64_(uint64_t *offset UNNEEDED) { fprintf(stderr, "pseudorand_u64_ called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed 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 b52921e1d9a9..7556fd2f93af 100644 --- a/common/test/run-route-infloop.c +++ b/common/test/run-route-infloop.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include diff --git a/common/test/run-route-specific.c b/common/test/run-route-specific.c index 74653e206822..09f20d8a131e 100644 --- a/common/test/run-route-specific.c +++ b/common/test/run-route-specific.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/common/test/run-route.c b/common/test/run-route.c index 50f3f3b9b07d..59cede009b9f 100644 --- a/common/test/run-route.c +++ b/common/test/run-route.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include diff --git a/common/test/run-route_blinding_onion_test.c b/common/test/run-route_blinding_onion_test.c index d3b26db4b65c..378087d89f4b 100644 --- a/common/test/run-route_blinding_onion_test.c +++ b/common/test/run-route_blinding_onion_test.c @@ -41,6 +41,9 @@ bool node_id_from_hexstr(const char *str UNNEEDED, size_t slen UNNEEDED, struct /* Generated stub for pubkey_from_node_id */ bool pubkey_from_node_id(struct pubkey *key UNNEEDED, const struct node_id *id UNNEEDED) { fprintf(stderr, "pubkey_from_node_id called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed called!\n"); abort(); } /* Generated stub for towire_sciddir_or_pubkey */ void towire_sciddir_or_pubkey(u8 **pptr UNNEEDED, const struct sciddir_or_pubkey *sciddpk UNNEEDED) diff --git a/common/test/run-route_blinding_test.c b/common/test/run-route_blinding_test.c index cbd30ad4712f..27c740a93880 100644 --- a/common/test/run-route_blinding_test.c +++ b/common/test/run-route_blinding_test.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -36,6 +35,9 @@ void fromwire_sciddir_or_pubkey(const u8 **cursor UNNEEDED, size_t *max UNNEEDED /* Generated stub for node_id_from_hexstr */ bool node_id_from_hexstr(const char *str UNNEEDED, size_t slen UNNEEDED, struct node_id *id UNNEEDED) { fprintf(stderr, "node_id_from_hexstr called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed called!\n"); abort(); } /* Generated stub for towire_channel_id */ void towire_channel_id(u8 **pptr UNNEEDED, const struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "towire_channel_id called!\n"); abort(); } diff --git a/common/test/run-shutdown_scriptpubkey.c b/common/test/run-shutdown_scriptpubkey.c index c98610d28277..0054836ff842 100644 --- a/common/test/run-shutdown_scriptpubkey.c +++ b/common/test/run-shutdown_scriptpubkey.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include @@ -45,6 +45,9 @@ struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u /* Generated stub for amount_tx_fee */ struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) { fprintf(stderr, "amount_tx_fee called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ /* Thanks ChatGPT! */ diff --git a/common/test/run-sphinx-xor_cipher_stream.c b/common/test/run-sphinx-xor_cipher_stream.c index 0e33ace54de4..9c3ab2f34532 100644 --- a/common/test/run-sphinx-xor_cipher_stream.c +++ b/common/test/run-sphinx-xor_cipher_stream.c @@ -1,5 +1,6 @@ #include "config.h" #include "../sphinx.c" +#include #include #include @@ -103,6 +104,9 @@ struct onionreply *new_onionreply(const tal_t *ctx UNNEEDED, const u8 *contents /* Generated stub for pubkey_from_node_id */ bool pubkey_from_node_id(struct pubkey *key UNNEEDED, const struct node_id *id UNNEEDED) { fprintf(stderr, "pubkey_from_node_id called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed called!\n"); abort(); } /* Generated stub for subkey_from_hmac */ void subkey_from_hmac(const char *prefix UNNEEDED, const struct secret *base UNNEEDED, diff --git a/common/test/run-sphinx.c b/common/test/run-sphinx.c index b44101f69e1e..e9b26d6ca467 100644 --- a/common/test/run-sphinx.c +++ b/common/test/run-sphinx.c @@ -89,6 +89,9 @@ bool fromwire_tlv(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, /* Generated stub for pubkey_from_node_id */ bool pubkey_from_node_id(struct pubkey *key UNNEEDED, const struct node_id *id UNNEEDED) { fprintf(stderr, "pubkey_from_node_id called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed called!\n"); abort(); } /* Generated stub for tlv_field_offset */ size_t tlv_field_offset(const u8 *tlvstream UNNEEDED, size_t tlvlen UNNEEDED, u64 fieldtype UNNEEDED) { fprintf(stderr, "tlv_field_offset called!\n"); abort(); } diff --git a/common/test/run-splice_script.c b/common/test/run-splice_script.c index 082f46ceab49..58157e026fb9 100644 --- a/common/test/run-splice_script.c +++ b/common/test/run-splice_script.c @@ -6,7 +6,6 @@ #include "../json_stream.c" #include "../json_parse_simple.c" #include -#include #include #include #include @@ -39,6 +38,9 @@ void command_log(struct command *cmd UNNEEDED, enum log_level level UNNEEDED, /* Generated stub for mvt_tag_parse */ bool mvt_tag_parse(const char *buf UNNEEDED, size_t len UNNEEDED, enum mvt_tag *tag UNNEEDED) { fprintf(stderr, "mvt_tag_parse called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ static void set_node_id(struct splice_script_chan *chan, const char *hexstr) diff --git a/common/test/run-tlv_span.c b/common/test/run-tlv_span.c index eb3ede4b6cb4..8a6156e66911 100644 --- a/common/test/run-tlv_span.c +++ b/common/test/run-tlv_span.c @@ -2,7 +2,6 @@ #include "../bolt12.c" #include "../bigsize.c" #include "../../wire/fromwire.c" -#include #include #include @@ -72,6 +71,9 @@ void sighash_from_merkle(const char *messagename UNNEEDED, const struct sha256 *merkle UNNEEDED, struct sha256 *sighash UNNEEDED) { fprintf(stderr, "sighash_from_merkle called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed called!\n"); abort(); } /* Generated stub for to_bech32_charset */ char *to_bech32_charset(const tal_t *ctx UNNEEDED, const char *hrp UNNEEDED, const u8 *data UNNEEDED) diff --git a/common/test/run-tlv_unknown.c b/common/test/run-tlv_unknown.c index 071b10432e1d..966f53b6cd8f 100644 --- a/common/test/run-tlv_unknown.c +++ b/common/test/run-tlv_unknown.c @@ -5,7 +5,6 @@ #include "../../wire/towire.c" #include "../bigsize.c" #include "../bolt12.c" -#include #include #include @@ -88,6 +87,9 @@ void sighash_from_merkle(const char *messagename UNNEEDED, const struct sha256 *merkle UNNEEDED, struct sha256 *sighash UNNEEDED) { fprintf(stderr, "sighash_from_merkle called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed called!\n"); abort(); } /* Generated stub for to_bech32_charset */ char *to_bech32_charset(const tal_t *ctx UNNEEDED, const char *hrp UNNEEDED, const u8 *data UNNEEDED) diff --git a/common/test/run-version.c b/common/test/run-version.c index 3b46f56e2289..4bed5a3f8ab5 100644 --- a/common/test/run-version.c +++ b/common/test/run-version.c @@ -1,11 +1,14 @@ #include "config.h" #include "../version.c" -#include +#include #include #include #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ int main(int argc, char *argv[]) diff --git a/common/test/run-wireaddr.c b/common/test/run-wireaddr.c index f5dd2ff92806..6e8ccda471a6 100644 --- a/common/test/run-wireaddr.c +++ b/common/test/run-wireaddr.c @@ -1,7 +1,7 @@ #include "config.h" #include #include -#include +#include #include #include @@ -59,6 +59,9 @@ u8 *b32_decode(const tal_t *ctx UNNEEDED, const char *str UNNEEDED, size_t len U /* Generated stub for b32_encode */ char *b32_encode(const tal_t *ctx UNNEEDED, const void *data UNNEEDED, size_t len UNNEEDED) { fprintf(stderr, "b32_encode called!\n"); abort(); } +/* Generated stub for siphash_seed */ +const struct siphash_seed *siphash_seed(void) +{ fprintf(stderr, "siphash_seed called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ int main(int argc, char *argv[]) diff --git a/lightningd/chaintopology.c b/lightningd/chaintopology.c index 6ab4c659706b..6e4c5569dc37 100644 --- a/lightningd/chaintopology.c +++ b/lightningd/chaintopology.c @@ -40,19 +40,17 @@ static bool we_broadcast(const struct chain_topology *topo, static void filter_block_txs(struct chain_topology *topo, struct block *b) { - struct txfilter *filter = topo->bitcoind->ld->owned_txfilter; - size_t i; - /* Now we see if any of those txs are interesting. */ const size_t num_txs = tal_count(b->full_txs); - for (i = 0; i < num_txs; i++) { + for (size_t i = 0; i < num_txs; i++) { struct bitcoin_tx *tx = b->full_txs[i]; struct bitcoin_txid txid; - size_t j; + const struct txlocator loc = { b->height, i }; bool is_coinbase = i == 0; + size_t *our_outnums; /* Tell them if it spends a txo we care about. */ - for (j = 0; j < tx->wtx->num_inputs; j++) { + for (size_t j = 0; j < tx->wtx->num_inputs; j++) { struct bitcoin_outpoint out; struct txowatch_hash_iter it; @@ -69,29 +67,31 @@ static void filter_block_txs(struct chain_topology *topo, struct block *b) } txid = b->txids[i]; - if (txfilter_match(filter, tx)) { - wallet_extract_owned_outputs(topo->bitcoind->ld->wallet, - tx->wtx, is_coinbase, &b->height); + our_outnums = tal_arr(tmpctx, size_t, 0); + if (wallet_extract_owned_outputs(topo->bitcoind->ld->wallet, + tx->wtx, is_coinbase, &b->height, &our_outnums)) { wallet_transaction_add(topo->ld->wallet, tx->wtx, b->height, i); - // invoice_check_onchain_payment(tx); - for (size_t k = 0; k < tx->wtx->num_outputs; k++) { + for (size_t k = 0; k < tal_count(our_outnums); k++) { const struct wally_tx_output *txout; - txout = &tx->wtx->outputs[k]; - if (txfilter_scriptpubkey_matches(filter, txout->script)) { - struct amount_sat amount; - struct bitcoin_outpoint outpoint; - outpoint.txid = txid; - outpoint.n = k; - bitcoin_tx_output_get_amount_sat(tx, k, &amount); - invoice_check_onchain_payment(topo->ld, txout->script, amount, &outpoint); - } + struct amount_sat amount; + struct bitcoin_outpoint outpoint; + + txout = &tx->wtx->outputs[our_outnums[k]]; + outpoint.txid = txid; + outpoint.n = our_outnums[k]; + amount = bitcoin_tx_output_get_amount_sat(tx, our_outnums[k]); + invoice_check_onchain_payment(topo->ld, txout->script, amount, &outpoint); } } /* We did spends first, in case that tells us to watch tx. */ - if (watching_txid(topo, &txid) || we_broadcast(topo, &txid)) { + + /* Make sure we preserve any transaction we are interested in */ + if (watch_check_tx_outputs(topo, &loc, tx, &txid) + || watching_txid(topo, &txid) + || we_broadcast(topo, &txid)) { wallet_transaction_add(topo->ld->wallet, tx->wtx, b->height, i); } @@ -847,6 +847,9 @@ static void updates_complete(struct chain_topology *topo) /* Tell lightningd about new block. */ notify_new_block(topo->bitcoind->ld); + /* Tell blockdepth watchers */ + watch_check_block_added(topo, topo->tip->height); + /* Tell watch code to re-evaluate all txs. */ watch_topology_changed(topo); @@ -1054,6 +1057,9 @@ 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); + /* Anyone watching for block removes */ + watch_check_block_removed(topo, b->height); + block_map_del(topo->block_map, b); /* These no longer exist, so gossipd drops any reference to them just @@ -1227,6 +1233,8 @@ struct chain_topology *new_topology(struct lightningd *ld, struct logger *log) topo->outgoing_txs = new_htable(topo, outgoing_tx_map); topo->txwatches = new_htable(topo, txwatch_hash); topo->txowatches = new_htable(topo, txowatch_hash); + topo->scriptpubkeywatches = new_htable(topo, scriptpubkeywatch_hash); + topo->blockdepthwatches = new_htable(topo, blockdepthwatch_hash); topo->log = log; topo->bitcoind = new_bitcoind(topo, ld, log); topo->poll_seconds = 30; diff --git a/lightningd/chaintopology.h b/lightningd/chaintopology.h index 8515cb5bdaf3..451113cd2e8f 100644 --- a/lightningd/chaintopology.h +++ b/lightningd/chaintopology.h @@ -9,6 +9,7 @@ struct command; struct lightningd; struct peer; struct txwatch; +struct scriptpubkeywatch; struct wallet; /* We keep the last three in case there are outliers (for min/max) */ @@ -139,6 +140,8 @@ struct chain_topology { /* Transactions/txos we are watching. */ struct txwatch_hash *txwatches; struct txowatch_hash *txowatches; + struct scriptpubkeywatch_hash *scriptpubkeywatches; + struct blockdepthwatch_hash *blockdepthwatches; /* The number of headers known to the bitcoin backend at startup. Not * updated after the initial check. */ diff --git a/lightningd/channel.c b/lightningd/channel.c index e92ff8d756f4..55c3ca58ed79 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -92,6 +92,9 @@ void delete_channel(struct channel *channel STEALS, struct peer *peer = channel->peer; struct lightningd *ld = peer->ld; + /* We no longer care about the funding transaction */ + channel_unwatch_funding(ld, channel); + if (channel->dbid != 0) { wallet_channel_close(ld->wallet, channel); /* Never open at all, not ours. */ @@ -201,6 +204,7 @@ new_inflight(struct channel *channel, inflight->funding_psbt = tal_steal(inflight, psbt); inflight->last_tx = NULL; inflight->tx_broadcast = false; + inflight->scid = NULL; /* Channel lease infos */ inflight->lease_blockheight_start = lease_blockheight_start; @@ -718,18 +722,6 @@ struct channel *new_channel(struct peer *peer, u64 dbid, /* Populate channel->channel_gossip */ channel_gossip_init(channel, take(peer_update)); - /* Make sure we see any spends using this key */ - if (!local_shutdown_scriptpubkey) { - if (anysegwit) { - txfilter_add_scriptpubkey(peer->ld->owned_txfilter, - take(p2tr_for_keyidx(NULL, peer->ld, - channel->final_key_idx))); - } else { - txfilter_add_scriptpubkey(peer->ld->owned_txfilter, - take(p2wpkh_for_keyidx(NULL, peer->ld, - channel->final_key_idx))); - } - } /* scid is NULL when opening a new channel so we don't * need to set error in that case as well */ if (channel->scid && is_stub_scid(*channel->scid)) diff --git a/lightningd/channel.h b/lightningd/channel.h index 9661e4b7d2dd..b96666e04822 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -53,6 +53,9 @@ struct channel_inflight { /* Channel context */ struct channel *channel; + /* SCID once we're mined, otherwise NULL */ + struct short_channel_id *scid; + /* Funding info */ const struct funding_info *funding; struct wally_psbt *funding_psbt; diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 627e43604cbc..338c1ffe5ea1 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -496,17 +496,16 @@ static void handle_tx_broadcast(struct send_splice_info *info) struct json_stream *response; struct bitcoin_txid txid; u8 *tx_bytes; - int num_utxos; tx_bytes = linearize_tx(tmpctx, info->final_tx); bitcoin_txid(info->final_tx, &txid); /* This might have spent UTXOs from our wallet */ - num_utxos = wallet_extract_owned_outputs(ld->wallet, - info->final_tx->wtx, false, - NULL); - if (num_utxos) + if (wallet_extract_owned_outputs(ld->wallet, + info->final_tx->wtx, false, + NULL, NULL)) { wallet_transaction_add(ld->wallet, info->final_tx->wtx, 0, 0); + } if (info->cc) { response = json_stream_success(info->cc->cmd); @@ -652,51 +651,27 @@ static void handle_splice_confirmed_signed(struct lightningd *ld, } static enum watch_result splice_depth_cb(struct lightningd *ld, - const struct bitcoin_txid *txid, - const struct bitcoin_tx *tx, unsigned int depth, - void *param) + struct channel_inflight *inflight) { - /* find_txwatch triggers a type warning on inflight, so we do this. */ - struct channel_inflight *inflight = param; - struct txlocator *loc; - struct short_channel_id scid; - - /* What scid is this giving us? */ - loc = wallet_transaction_locate(tmpctx, ld->wallet, txid); - if (!mk_short_channel_id(&scid, - loc->blkheight, loc->index, - inflight->funding->outpoint.n)) { - channel_fail_permanent(inflight->channel, - REASON_LOCAL, - "Invalid funding scid %u:%u:%u", - loc->blkheight, loc->index, - inflight->funding->outpoint.n); - return false; - } - /* Usually, we're here because we're awaiting a splice, but * we could also mutual shutdown, or that weird splice_locked_memonly * hack... */ if (inflight->channel->state != CHANNELD_AWAITING_SPLICE) { - log_info(inflight->channel->log, "Splice inflight event but not" - " in AWAITING_SPLICE, ending watch of txid %s", - fmt_bitcoin_txid(tmpctx, txid)); + log_debug(inflight->channel->log, "Splice inflight event but not" + " in AWAITING_SPLICE, ending watch of txid %s", + fmt_bitcoin_txid(tmpctx, &inflight->funding->outpoint.txid)); return DELETE_WATCH; } - /* Reorged out? OK, we're not committed yet. */ - if (depth == 0) { - return KEEP_WATCHING; - } - if (inflight->channel->owner) { - log_info(inflight->channel->log, "splice_depth_cb: sending funding depth scid: %s", - fmt_short_channel_id(tmpctx, scid)); + log_debug(inflight->channel->log, "splice_depth_cb: sending funding depth scid: %s", + fmt_short_channel_id(tmpctx, *inflight->scid)); subd_send_msg(inflight->channel->owner, take(towire_channeld_funding_depth( - NULL, &scid, - depth, true, txid))); + NULL, inflight->scid, + depth, true, + &inflight->funding->outpoint.txid))); } /* channeld will tell us when splice is locked in: we'll clean @@ -704,23 +679,61 @@ static enum watch_result splice_depth_cb(struct lightningd *ld, return KEEP_WATCHING; } +/* Reorged out? OK, we're not committed yet. */ +static enum watch_result splice_reorged_cb(struct lightningd *ld, struct channel_inflight *inflight) +{ + log_unusual(inflight->channel->log, "Splice inflight txid %s reorged out", + fmt_bitcoin_txid(tmpctx, &inflight->funding->outpoint.txid)); + inflight->scid = tal_free(inflight->scid); + return DELETE_WATCH; +} + +/* We see this tx output spend to the splice funding address. */ +static void splice_found(struct lightningd *ld, + const struct bitcoin_tx *tx, + u32 outnum, + const struct txlocator *loc, + struct channel_inflight *inflight) +{ + assert(!inflight->scid); + inflight->scid = tal(inflight, struct short_channel_id); + + if (!mk_short_channel_id(inflight->scid, + loc->blkheight, loc->index, + inflight->funding->outpoint.n)) { + inflight->scid = tal_free(inflight->scid); + channel_fail_permanent(inflight->channel, + REASON_LOCAL, + "Invalid funding scid %u:%u:%u", + loc->blkheight, loc->index, + inflight->funding->outpoint.n); + return; + } + + /* We will almost immediately get called, which is what we want! */ + watch_blockdepth(inflight, ld->topology, loc->blkheight, + splice_depth_cb, + splice_reorged_cb, + inflight); +} + void watch_splice_inflight(struct lightningd *ld, struct channel_inflight *inflight) { + const u8 *funding_wscript = bitcoin_redeem_2of2(tmpctx, + &inflight->channel->local_funding_pubkey, + inflight->funding->splice_remote_funding); + log_info(inflight->channel->log, "Watching splice inflight %s", fmt_bitcoin_txid(tmpctx, &inflight->funding->outpoint.txid)); - watch_txid(inflight, ld->topology, - &inflight->funding->outpoint.txid, - splice_depth_cb, inflight); -} -static struct txwatch *splice_inflight_txwatch(struct channel *channel, - struct channel_inflight *inflight) -{ - return find_txwatch(channel->peer->ld->topology, - &inflight->funding->outpoint.txid, - splice_depth_cb, channel); + watch_scriptpubkey(inflight, ld->topology, + take(scriptpubkey_p2wsh(NULL, funding_wscript)), + &inflight->funding->outpoint, + inflight->funding->total_funds, + splice_found, + inflight); } static void handle_splice_sending_sigs(struct lightningd *ld, @@ -767,16 +780,39 @@ static void handle_splice_sending_sigs(struct lightningd *ld, watch_splice_inflight(ld, inflight); } +static void scid_updated(struct channel *channel) +{ + if (channel->channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL) + tell_connectd_scid(channel->peer->ld, *channel->scid, &channel->peer->id); + + wallet_channel_save(channel->peer->ld->wallet, channel); +} + +/* You must call scid_updated after this! */ +static void change_scid(struct channel *channel, + struct short_channel_id scid) +{ + struct short_channel_id old_scid = *channel->scid; + + /* We freaked out if required when original was + * removed, so just update now */ + log_info(channel->log, "Short channel id changed from %s->%s", + fmt_short_channel_id(tmpctx, *channel->scid), + fmt_short_channel_id(tmpctx, scid)); + channel_set_scid(channel, &scid); + /* In case we broadcast it before (e.g. splice!) */ + channel_add_old_scid(channel, old_scid); + channel_gossip_scid_changed(channel); +} + bool depthcb_update_scid(struct channel *channel, - const struct bitcoin_txid *txid, - const struct bitcoin_outpoint *outpoint) + const struct bitcoin_outpoint *outpoint, + const struct txlocator *loc) { - struct txlocator *loc; struct lightningd *ld = channel->peer->ld; struct short_channel_id scid; /* What scid is this giving us? */ - loc = wallet_transaction_locate(tmpctx, ld->wallet, txid); if (!mk_short_channel_id(&scid, loc->blkheight, loc->index, outpoint->n)) { @@ -807,23 +843,10 @@ bool depthcb_update_scid(struct channel *channel, lockin_has_completed(channel, false); } else { - struct short_channel_id old_scid = *channel->scid; - - /* We freaked out if required when original was - * removed, so just update now */ - log_info(channel->log, "Short channel id changed from %s->%s", - fmt_short_channel_id(tmpctx, *channel->scid), - fmt_short_channel_id(tmpctx, scid)); - channel_set_scid(channel, &scid); - /* In case we broadcast it before (e.g. splice!) */ - channel_add_old_scid(channel, old_scid); - channel_gossip_scid_changed(channel); + change_scid(channel, scid); } - if (channel->channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL) - tell_connectd_scid(ld, *channel->scid, &channel->peer->id); - - wallet_channel_save(ld->wallet, channel); + scid_updated(channel); return true; } @@ -1106,7 +1129,6 @@ static void handle_peer_splice_locked(struct channel *channel, const u8 *msg) s64 splice_amnt; struct channel_inflight *inflight; struct bitcoin_txid locked_txid; - struct txwatch *txw; if (!fromwire_channeld_got_splice_locked(msg, &funding_sats, &splice_amnt, @@ -1126,9 +1148,6 @@ static void handle_peer_splice_locked(struct channel *channel, const u8 *msg) wallet_htlcsigs_confirm_inflight(channel->peer->ld->wallet, channel, &inflight->funding->outpoint); - /* 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) */ prev_our_msats = channel->our_msat; @@ -1151,8 +1170,8 @@ static void handle_peer_splice_locked(struct channel *channel, const u8 *msg) wallet_channel_clear_inflights(channel->peer->ld->wallet, channel); - depthcb_update_scid(channel, &locked_txid, - &inflight->funding->outpoint); + /* Update the scid and tell everyone */ + change_scid(channel, *inflight->locked_scid); /* That freed watchers in inflights: now watch funding tx */ channel_watch_funding(channel->peer->ld, channel); @@ -1176,13 +1195,6 @@ static void handle_peer_splice_locked(struct channel *channel, const u8 *msg) list_add_tail(&channel->inflights, &inflight->list); lockin_complete(channel, CHANNELD_AWAITING_SPLICE); - - /* Turn off tx watcher for the splice */ - txw = splice_inflight_txwatch(channel, inflight); - if (!txw) - log_unusual(channel->log, "Can't unwatch txid %s", - fmt_bitcoin_txid(tmpctx, &locked_txid)); - tal_free(txw); } /* We were informed by channeld that channel is ready (reached mindepth) */ diff --git a/lightningd/channel_control.h b/lightningd/channel_control.h index 9cc417de11b9..b5d78381641c 100644 --- a/lightningd/channel_control.h +++ b/lightningd/channel_control.h @@ -9,6 +9,7 @@ struct crypto_state; struct lightningd; struct peer_fd; struct peer; +struct txlocator; bool peer_start_channeld(struct channel *channel, struct peer_fd *peer_fd, @@ -54,8 +55,9 @@ void lockin_has_completed(struct channel *channel, bool record_push); void watch_splice_inflight(struct lightningd *ld, struct channel_inflight *inflight); -/* Update/set scid now this txid is mined. */ +/* Update/set scid now this outpoint is mined. */ bool depthcb_update_scid(struct channel *channel, - const struct bitcoin_txid *txid, - const struct bitcoin_outpoint *outpoint); + const struct bitcoin_outpoint *outpoint, + const struct txlocator *loc); + #endif /* LIGHTNING_LIGHTNINGD_CHANNEL_CONTROL_H */ diff --git a/lightningd/channel_gossip.c b/lightningd/channel_gossip.c index 01207818a5d5..c12aa5fdcae7 100644 --- a/lightningd/channel_gossip.c +++ b/lightningd/channel_gossip.c @@ -1063,6 +1063,8 @@ void channel_gossip_notify_new_block(struct lightningd *ld) struct channel *channel; struct peer_node_id_map_iter it; + /* No addition during iteration! */ + peer_node_id_map_lock(ld->peers); for (peer = peer_node_id_map_first(ld->peers, &it); peer; peer = peer_node_id_map_next(ld->peers, &it)) { @@ -1074,6 +1076,7 @@ void channel_gossip_notify_new_block(struct lightningd *ld) new_blockheight(ld, channel); } } + peer_node_id_map_unlock(ld->peers); } /* Gossipd told us about a channel update on one of our channels (on loading) */ diff --git a/lightningd/dual_open_control.c b/lightningd/dual_open_control.c index a605a528fe76..acbeb21e9228 100644 --- a/lightningd/dual_open_control.c +++ b/lightningd/dual_open_control.c @@ -1003,71 +1003,60 @@ static void dualopend_tell_depth(struct channel *channel, } static enum watch_result opening_depth_cb(struct lightningd *ld, - const struct bitcoin_txid *txid, - const struct bitcoin_tx *tx, unsigned int depth, struct channel_inflight *inflight) { - struct txlocator *loc; - struct short_channel_id scid; - /* Usually, we're here because we're awaiting a lockin, but * we could also mutual shutdown */ if (inflight->channel->state != DUALOPEND_AWAITING_LOCKIN) return DELETE_WATCH; - /* Reorged out? OK, we're not committed yet. */ - if (depth == 0) - return KEEP_WATCHING; - - /* FIXME: Don't do this until we're actually locked in! */ - loc = wallet_transaction_locate(tmpctx, ld->wallet, txid); - if (!mk_short_channel_id(&scid, - loc->blkheight, loc->index, - inflight->funding->outpoint.n)) { - channel_fail_permanent(inflight->channel, - REASON_LOCAL, - "Invalid funding scid %u:%u:%u", - loc->blkheight, loc->index, - inflight->funding->outpoint.n); - return DELETE_WATCH; - } - - if (!inflight->channel->scid) { - wallet_annotate_txout(ld->wallet, &inflight->funding->outpoint, - TX_CHANNEL_FUNDING, inflight->channel->dbid); - channel_set_scid(inflight->channel, &scid); - wallet_channel_save(ld->wallet, inflight->channel); - } else if (!short_channel_id_eq(*inflight->channel->scid, scid)) { - /* We freaked out if required when original was - * removed, so just update now */ - log_info(inflight->channel->log, "Short channel id changed from %s->%s", - fmt_short_channel_id(tmpctx, *inflight->channel->scid), - fmt_short_channel_id(tmpctx, scid)); - channel_set_scid(inflight->channel, &scid); - wallet_channel_save(ld->wallet, inflight->channel); - } - - /* Tell connectd it can forward onion messages via this scid (ok if redundant!) */ - if (inflight->channel->channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL) - tell_connectd_scid(ld, *inflight->channel->scid, - &inflight->channel->peer->id); - if (depth >= inflight->channel->minimum_depth) update_channel_from_inflight(ld, inflight->channel, inflight, false); - dualopend_tell_depth(inflight->channel, txid, depth); - + dualopend_tell_depth(inflight->channel, &inflight->funding->outpoint.txid, depth); return KEEP_WATCHING; } +static enum watch_result opening_reorged_cb(struct lightningd *ld, struct channel_inflight *inflight) +{ + /* Reorged out? OK, we're not committed yet. */ + log_info(inflight->channel->log, "Candidate funding tx was in a block, now reorged out"); + return DELETE_WATCH; +} + +static void dual_funding_found(struct lightningd *ld, + const struct bitcoin_tx *tx, + u32 outnum, + const struct txlocator *loc, + struct channel_inflight *inflight) +{ + /* Kill it if the channel funding isn't a valid scid */ + if (!depthcb_update_scid(inflight->channel, + &inflight->funding->outpoint, + loc)) + return; + + /* Otherwise, watch for block depth increases (we'll immediately expect one) */ + watch_blockdepth(inflight, ld->topology, loc->blkheight, + opening_depth_cb, + opening_reorged_cb, + inflight); +} + void watch_opening_inflight(struct lightningd *ld, struct channel_inflight *inflight) { - watch_txid(inflight, ld->topology, - &inflight->funding->outpoint.txid, - opening_depth_cb, inflight); + const u8 *funding_wscript = bitcoin_redeem_2of2(tmpctx, + &inflight->channel->local_funding_pubkey, + &inflight->channel->channel_info.remote_fundingkey); + watch_scriptpubkey(inflight, ld->topology, + take(scriptpubkey_p2wsh(NULL, funding_wscript)), + &inflight->funding->outpoint, + inflight->funding->total_funds, + dual_funding_found, + inflight); } static void @@ -1655,14 +1644,13 @@ static void handle_tx_broadcast(struct channel_send *cs) struct command *cmd = channel->openchannel_signed_cmd; struct json_stream *response; struct bitcoin_txid txid; - int num_utxos; /* This might have spent UTXOs from our wallet */ - num_utxos = wallet_extract_owned_outputs(ld->wallet, - /* FIXME: what txindex? */ - wtx, false, NULL); - if (num_utxos) + if (wallet_extract_owned_outputs(ld->wallet, + /* FIXME: what txindex? */ + wtx, false, NULL, NULL)) { wallet_transaction_add(ld->wallet, wtx, 0, 0); + } if (cmd) { response = json_stream_success(cmd); diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index f23fb7df0dd0..fd5a978e33a3 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -77,7 +77,6 @@ #include #include #include -#include #include static void destroy_alt_subdaemons(struct lightningd *ld); @@ -616,10 +615,11 @@ static void free_all_channels(struct lightningd *ld) * given a destructor (`destroy_peer`) which removes itself from the * hashtable. * - * Deletion from a hashtable is allowed, but it does mean we could - * skip entries in iteration. Hence we repeat until empty! + * Deletion from a hashtable during iteration is safe and consistent. + * Adding is forbidden, hence the lock() function which causes that to + * assert. */ -again: + peer_node_id_map_lock(ld->peers); for (p = peer_node_id_map_first(ld->peers, &it); p; p = peer_node_id_map_next(ld->peers, &it)) { @@ -644,8 +644,7 @@ static void free_all_channels(struct lightningd *ld) /* Removes itself from htable as we free it */ tal_free(p); } - if (peer_node_id_map_first(ld->peers, &it)) - goto again; + peer_node_id_map_unlock(ld->peers); /*~ Commit the transaction. Note that the db is actually * single-threaded, so commits never fail and we don't need @@ -665,44 +664,6 @@ static void shutdown_global_subdaemons(struct lightningd *ld) ld->hsm = subd_shutdown(ld->hsm, 10); } -/*~ Our wallet logic needs to know what outputs we might be interested in. We - * use BIP32 (a.k.a. "HD wallet") to generate keys from a single seed, so we - * keep the maximum-ever-used key index in the db, and add them all to the - * filter here. */ -static void init_txfilter(struct wallet *w, - const struct ext_key *bip32_base, - struct txfilter *filter) -{ - /*~ This is defined in libwally, so we didn't have to reimplement */ - struct ext_key ext; - /*~ Note the use of ccan/short_types u64 rather than uint64_t. - * Thank me later. */ - u64 bip32_max_index, bip86_max_index; - - bip32_max_index = db_get_intvar(w->db, "bip32_max_index", 0); - /*~ One of the C99 things I unequivocally approve: for-loop scope. */ - for (u64 i = 0; i <= bip32_max_index + w->keyscan_gap; i++) { - if (bip32_key_from_parent(bip32_base, i, BIP32_FLAG_KEY_PUBLIC, &ext) != WALLY_OK) { - abort(); - } - txfilter_add_derkey(filter, ext.pub_key); - } - - /* If BIP86 is enabled, also add BIP86-derived keys to the filter */ - if (w->ld->bip86_base) { - bip86_max_index = db_get_intvar(w->db, "bip86_max_index", 0); - for (u64 i = 0; i <= bip86_max_index + w->keyscan_gap; i++) { - struct pubkey pubkey; - bip86_pubkey(w->ld, &pubkey, i); - /* Add both P2TR and P2WPKH scripts since BIP86 keys can be used for both */ - u8 *p2tr_script = scriptpubkey_p2tr(tmpctx, &pubkey); - txfilter_add_scriptpubkey(filter, take(p2tr_script)); - u8 *p2wpkh_script = scriptpubkey_p2wpkh(tmpctx, &pubkey); - txfilter_add_scriptpubkey(filter, take(p2wpkh_script)); - } - } -} - /*~ The normal advice for daemons is to move into the root directory, so you * don't prevent unmounting whatever filesystem you happen to start in. * @@ -1317,9 +1278,6 @@ int main(int argc, char *argv[]) ld->wallet = wallet_new(ld, ld->timers); trace_span_end(ld); - /*~ We keep a filter of scriptpubkeys we're interested in. */ - ld->owned_txfilter = txfilter_new(ld); - /*~ This is the ccan/io central poll override from above. */ io_poll_override(io_poll_lightningd); @@ -1351,11 +1309,6 @@ int main(int argc, char *argv[]) if (!wallet_sanity_check(ld->wallet)) errx(EXITCODE_WALLET_DB_MISMATCH, "Wallet sanity check failed."); - /*~ Initialize the transaction filter with our pubkeys. */ - trace_span_start("init_txfilter", ld->wallet); - init_txfilter(ld->wallet, ld->bip32_base, ld->owned_txfilter); - trace_span_end(ld->wallet); - /*~ Finish our runes initialization (includes reading from db) */ runes_finish_init(ld->runes); diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h index 79613faadb9c..9edba38d09fa 100644 --- a/lightningd/lightningd.h +++ b/lightningd/lightningd.h @@ -257,9 +257,6 @@ struct lightningd { /* Maintained by invoices.c */ struct invoices *invoices; - /* Transaction filter matching what we're interested in */ - struct txfilter *owned_txfilter; - /* PID file */ char *pidfile; diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 8d7f99f4e226..2a0fa58307e5 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -386,11 +386,13 @@ static void convert_replay_txs(struct channel *channel) /* Set to NULL so these are queued as real watches */ watches = tal_steal(tmpctx, channel->onchaind_replay_watches); channel->onchaind_replay_watches = NULL; + replay_tx_hash_lock(watches); for (rtx = replay_tx_hash_first(watches, &rit); rtx; rtx = replay_tx_hash_next(watches, &rit)) { watch_tx_and_outputs(channel, rtx->tx); } + replay_tx_hash_unlock(watches); } static void replay_block(struct bitcoind *bitcoind, @@ -407,12 +409,14 @@ static void replay_block(struct bitcoind *bitcoind, return; /* Tell onchaind that all existing txs have reached a new depth */ + replay_tx_hash_lock(channel->onchaind_replay_watches); for (rtx = replay_tx_hash_first(channel->onchaind_replay_watches, &rit); rtx; rtx = replay_tx_hash_next(channel->onchaind_replay_watches, &rit)) { /* Note: if you're in this block, that's depth 1! */ onchain_tx_depth(channel, &rtx->txid, height - rtx->blockheight + 1); } + replay_tx_hash_unlock(channel->onchaind_replay_watches); /* See if we add any new txs which spend a watched one */ for (size_t i = 0; i < tal_count(blk->tx); i++) { diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index ae302630f071..9263ae6cee60 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -311,7 +311,8 @@ static void funding_started_success(struct funding_channel *fc) response = json_stream_success(cmd); out = encode_scriptpubkey_to_addr(cmd, chainparams, - fc->funding_scriptpubkey); + fc->funding_scriptpubkey, + tal_bytelen(fc->funding_scriptpubkey)); if (out) { json_add_string(response, "funding_address", out); json_add_hex_talarr(response, "scriptpubkey", diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index ab26bb75840c..965c40b3bef2 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -309,7 +309,7 @@ static struct bitcoin_tx *sign_and_send_last(const tal_t *ctx, tx = sign_last_tx(ctx, channel, last_tx, last_sig); bitcoin_txid(tx, &txid); wallet_transaction_add(ld->wallet, tx->wtx, 0, 0); - wallet_extract_owned_outputs(ld->wallet, tx->wtx, false, NULL); + wallet_extract_owned_outputs(ld->wallet, tx->wtx, false, NULL, NULL); /* Remember anchor information for commit_tx_boost */ adet = create_anchor_details(NULL, channel, tx); @@ -329,22 +329,18 @@ static enum watch_result funding_spent(struct channel *channel, const struct block *block); /* We coop-closed channel: if another inflight confirms, force close */ -static enum watch_result closed_inflight_depth_cb(struct lightningd *ld, - const struct bitcoin_txid *txid, - const struct bitcoin_tx *tx, - unsigned int depth, - struct channel_inflight *inflight) +static void closed_inflight_splice_found(struct lightningd *ld, + const struct bitcoin_tx *tx, + u32 outnum, + const struct txlocator *loc, + struct channel_inflight *inflight) { - if (depth == 0) - return KEEP_WATCHING; - /* This is now the main tx. */ update_channel_from_inflight(ld, inflight->channel, inflight, false); channel_fail_saw_onchain(inflight->channel, REASON_UNKNOWN, tx, "Inflight tx confirmed after mutual close"); - return DELETE_WATCH; } void drop_to_chain(struct lightningd *ld, struct channel *channel, @@ -452,9 +448,15 @@ void drop_to_chain(struct lightningd *ld, struct channel *channel, &channel->funding)) { continue; } - watch_txid(inflight, ld->topology, - &inflight->funding->outpoint.txid, - closed_inflight_depth_cb, inflight); + const u8 *funding_wscript = bitcoin_redeem_2of2(tmpctx, + &channel->local_funding_pubkey, + inflight->funding->splice_remote_funding); + watch_scriptpubkey(inflight, ld->topology, + take(scriptpubkey_p2wsh(NULL, funding_wscript)), + &inflight->funding->outpoint, + inflight->funding->total_funds, + closed_inflight_splice_found, + inflight); } } } @@ -1059,7 +1061,8 @@ static void NON_NULL_ARGS(1, 2, 4, 5) json_add_channel(struct command *cmd, if (channel->shutdown_scriptpubkey[LOCAL]) { char *addr = encode_scriptpubkey_to_addr(tmpctx, chainparams, - channel->shutdown_scriptpubkey[LOCAL]); + channel->shutdown_scriptpubkey[LOCAL], + tal_bytelen(channel->shutdown_scriptpubkey[LOCAL])); if (addr) json_add_string(response, "close_to_addr", addr); json_add_hex_talarr(response, "close_to", @@ -2268,83 +2271,80 @@ void update_channel_from_inflight(struct lightningd *ld, wallet_channel_save(ld->wallet, channel); } -static enum watch_result funding_depth_cb(struct lightningd *ld, - const struct bitcoin_txid *txid, - const struct bitcoin_tx *tx, - unsigned int depth, - struct channel *channel) +/* All reorg callback must return DELETE_WATCH; we make this so it's clear that we + * won't be called again. */ +static enum watch_result funding_reorged_cb(struct lightningd *ld, struct channel *channel) { - /* This is stub channel, we don't activate anything! */ - if (channel->scid && is_stub_scid(*channel->scid)) - return DELETE_WATCH; - - /* We only use this to watch the current funding tx */ - assert(bitcoin_txid_eq(txid, &channel->funding.txid)); - - channel->depth = depth; - - log_debug(channel->log, "Funding tx %s depth %u of %u", - fmt_bitcoin_txid(tmpctx, txid), - depth, channel->minimum_depth); + log_unusual(channel->log, "Funding txid %s REORG from depth %u (state %s)", + fmt_bitcoin_txid(tmpctx, &channel->funding.txid), + channel->depth, + channel_state_name(channel)); + channel->depth = 0; - /* Reorged out? */ - if (depth == 0) { + /* That's not entirely unexpected in early states */ + switch (channel->state) { + case DUALOPEND_AWAITING_LOCKIN: + case DUALOPEND_OPEN_INIT: + case DUALOPEND_OPEN_COMMIT_READY: + case DUALOPEND_OPEN_COMMITTED: + /* Shouldn't be here! */ + channel_internal_error(channel, + "Bad %s state: %s", + __func__, + channel_state_name(channel)); + return DELETE_WATCH; + case CHANNELD_AWAITING_LOCKIN: /* That's not entirely unexpected in early states */ - switch (channel->state) { - case DUALOPEND_AWAITING_LOCKIN: - case DUALOPEND_OPEN_INIT: - case DUALOPEND_OPEN_COMMIT_READY: - case DUALOPEND_OPEN_COMMITTED: - /* Shouldn't be here! */ - channel_internal_error(channel, - "Bad %s state: %s", - __func__, - channel_state_name(channel)); - return DELETE_WATCH; - case CHANNELD_AWAITING_LOCKIN: - /* That's not entirely unexpected in early states */ - log_debug(channel->log, "Funding tx %s reorganized out!", - fmt_bitcoin_txid(tmpctx, txid)); - channel_set_scid(channel, NULL); - return KEEP_WATCHING; + log_debug(channel->log, "Funding tx %s reorganized out!", + fmt_bitcoin_txid(tmpctx, &channel->funding.txid)); + channel_set_scid(channel, NULL); + return DELETE_WATCH; /* But it's often Bad News in later states */ - case CHANNELD_AWAITING_SPLICE: - case CHANNELD_NORMAL: - /* If we opened, or it's zero-conf, we trust them anyway. */ - if (channel->opener == LOCAL - || channel->minimum_depth == 0) { - const char *str; - - str = tal_fmt(tmpctx, - "Funding tx %s reorganized out, but %s...", - fmt_bitcoin_txid(tmpctx, txid), - channel->opener == LOCAL ? "we opened it" : "zeroconf anyway"); - - /* Log even if not connected! */ - if (!channel->owner) - log_info(channel->log, "%s", str); - channel_fail_transient(channel, true, "%s", str); - return KEEP_WATCHING; - } - /* fall thru */ - case AWAITING_UNILATERAL: - case CHANNELD_SHUTTING_DOWN: - case CLOSINGD_SIGEXCHANGE: - case CLOSINGD_COMPLETE: - case FUNDING_SPEND_SEEN: - case ONCHAIN: - case CLOSED: - break; + case CHANNELD_AWAITING_SPLICE: + case CHANNELD_NORMAL: + /* If we opened, or it's zero-conf, we trust them anyway. */ + if (channel->opener == LOCAL + || channel->minimum_depth == 0) { + const char *str; + + str = tal_fmt(tmpctx, + "Funding tx %s reorganized out, but %s...", + fmt_bitcoin_txid(tmpctx, &channel->funding.txid), + channel->opener == LOCAL ? "we opened it" : "zeroconf anyway"); + + /* Log even if not connected! */ + if (!channel->owner) + log_info(channel->log, "%s", str); + channel_fail_transient(channel, true, "%s", str); + return DELETE_WATCH; } - channel_internal_error(channel, - "Funding transaction has been reorged out in state %s!", - channel_state_name(channel)); - return KEEP_WATCHING; + /* fall thru */ + case AWAITING_UNILATERAL: + case CHANNELD_SHUTTING_DOWN: + case CLOSINGD_SIGEXCHANGE: + case CLOSINGD_COMPLETE: + case FUNDING_SPEND_SEEN: + case ONCHAIN: + case CLOSED: + break; } - if (!depthcb_update_scid(channel, txid, &channel->funding)) - return DELETE_WATCH; + channel_internal_error(channel, + "Funding transaction has been reorged out in state %s!", + channel_state_name(channel)); + return DELETE_WATCH; +} + +static enum watch_result funding_depth_cb(struct lightningd *ld, + unsigned int depth, + struct channel *channel) +{ + channel->depth = depth; + + log_debug(channel->log, "Funding tx %s depth %u of %u", + fmt_bitcoin_txid(tmpctx, &channel->funding.txid), + depth, channel->minimum_depth); switch (channel->state) { /* We should not be in the callback! */ @@ -2364,7 +2364,7 @@ static enum watch_result funding_depth_cb(struct lightningd *ld, /* If not awaiting lockin/announce, it doesn't care any more */ log_debug(channel->log, "Funding tx %s confirmed, but peer in state %s", - fmt_bitcoin_txid(tmpctx, txid), + fmt_bitcoin_txid(tmpctx, &channel->funding.txid), channel_state_name(channel)); return DELETE_WATCH; @@ -2378,7 +2378,7 @@ static enum watch_result funding_depth_cb(struct lightningd *ld, /* Fall thru */ case CHANNELD_NORMAL: case CHANNELD_AWAITING_SPLICE: - channeld_tell_depth(channel, txid, depth); + channeld_tell_depth(channel, &channel->funding.txid, depth); if (depth < ANNOUNCE_MIN_DEPTH || depth < channel->minimum_depth) return KEEP_WATCHING; @@ -2388,6 +2388,23 @@ static enum watch_result funding_depth_cb(struct lightningd *ld, abort(); } +/* We see this tx output spend to the funding address. */ +static void channel_funding_found(struct lightningd *ld, + const struct bitcoin_tx *tx, + u32 outnum, + const struct txlocator *loc, + struct channel *channel) +{ + /* Closes channel if it doesn't fit in an scid! */ + if (depthcb_update_scid(channel, &channel->funding, loc)) { + /* We will almost immediately get called, which is what we want! */ + watch_blockdepth(channel, ld->topology, loc->blkheight, + funding_depth_cb, + funding_reorged_cb, + channel); + } +} + static enum watch_result funding_spent(struct channel *channel, const struct bitcoin_tx *tx, size_t inputnum UNUSED, @@ -2431,21 +2448,26 @@ 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", - fmt_bitcoin_txid(tmpctx, &channel->funding.txid)); - watch_txid(channel, ld->topology, - &channel->funding.txid, funding_depth_cb, channel); + fmt_bitcoin_txid(tmpctx, &channel->funding.txid)); + + /* This is stub channel, we don't watch anything funding. */ + if (!channel->scid || !is_stub_scid(*channel->scid)) { + const u8 *funding_wscript = bitcoin_redeem_2of2(tmpctx, + &channel->local_funding_pubkey, + &channel->channel_info.remote_fundingkey); + watch_scriptpubkey(channel, ld->topology, + take(scriptpubkey_p2wsh(NULL, funding_wscript)), + &channel->funding, + channel->funding_sats, + channel_funding_found, + channel); + } + + /* We watch for closing of course. */ tal_free(channel->funding_spend_watch); channel->funding_spend_watch = watch_txo(channel, ld->topology, channel, &channel->funding, @@ -2453,6 +2475,25 @@ void channel_watch_funding(struct lightningd *ld, struct channel *channel) channel_watch_wrong_funding(ld, channel); } +void channel_unwatch_funding(struct lightningd *ld, struct channel *channel) +{ + const u8 *funding_wscript = bitcoin_redeem_2of2(tmpctx, + &channel->local_funding_pubkey, + &channel->channel_info.remote_fundingkey); + + /* This is stub channel, we don't watch anything! */ + if (channel->scid && is_stub_scid(*channel->scid)) + return; + + unwatch_scriptpubkey(channel, ld->topology, + scriptpubkey_p2wsh(tmpctx, funding_wscript), + &channel->funding, + channel->funding_sats, + channel_funding_found, + channel); + /* FIXME: unwatch txo and depth too? */ +} + static void json_add_peer(struct lightningd *ld, struct json_stream *response, struct peer *p, diff --git a/lightningd/peer_control.h b/lightningd/peer_control.h index 70016d6d568a..8d7ccaa8e507 100644 --- a/lightningd/peer_control.h +++ b/lightningd/peer_control.h @@ -134,8 +134,8 @@ 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); +void channel_unwatch_funding(struct lightningd *ld, struct channel *channel); /* If this channel has a "wrong funding" shutdown, watch that too. */ void channel_watch_wrong_funding(struct lightningd *ld, struct channel *channel); diff --git a/lightningd/test/run-find_my_abspath.c b/lightningd/test/run-find_my_abspath.c index 37ff3c1a13ff..3d227bd9974d 100644 --- a/lightningd/test/run-find_my_abspath.c +++ b/lightningd/test/run-find_my_abspath.c @@ -12,9 +12,6 @@ int unused_main(int argc, char *argv[]); /* Generated stub for begin_topology */ void begin_topology(struct chain_topology *topo UNNEEDED) { fprintf(stderr, "begin_topology called!\n"); abort(); } -/* Generated stub for bip86_pubkey */ -void bip86_pubkey(struct lightningd *ld UNNEEDED, struct pubkey *pubkey UNNEEDED, u32 index UNNEEDED) -{ fprintf(stderr, "bip86_pubkey called!\n"); abort(); } /* Generated stub for channel_gossip_notify_new_block */ void channel_gossip_notify_new_block(struct lightningd *ld UNNEEDED) { fprintf(stderr, "channel_gossip_notify_new_block called!\n"); abort(); } @@ -55,9 +52,6 @@ void db_begin_transaction_(struct db *db UNNEEDED, const char *location UNNEEDED /* Generated stub for db_commit_transaction */ void db_commit_transaction(struct db *db UNNEEDED) { fprintf(stderr, "db_commit_transaction called!\n"); abort(); } -/* Generated stub for db_get_intvar */ -s64 db_get_intvar(struct db *db UNNEEDED, const char *varname UNNEEDED, s64 defval UNNEEDED) -{ fprintf(stderr, "db_get_intvar called!\n"); abort(); } /* Generated stub for db_in_transaction */ bool db_in_transaction(struct db *db UNNEEDED) { fprintf(stderr, "db_in_transaction called!\n"); abort(); } @@ -213,16 +207,6 @@ void stop_topology(struct chain_topology *topo UNNEEDED) /* Generated stub for towire_hsmd_ecdh_req */ u8 *towire_hsmd_ecdh_req(const tal_t *ctx UNNEEDED, const struct pubkey *point UNNEEDED) { fprintf(stderr, "towire_hsmd_ecdh_req called!\n"); abort(); } -/* Generated stub for txfilter_add_derkey */ -void txfilter_add_derkey(struct txfilter *filter UNNEEDED, - const u8 derkey[PUBKEY_CMPR_LEN]) -{ fprintf(stderr, "txfilter_add_derkey called!\n"); abort(); } -/* Generated stub for txfilter_add_scriptpubkey */ -void txfilter_add_scriptpubkey(struct txfilter *filter UNNEEDED, const u8 *script TAKES UNNEEDED) -{ fprintf(stderr, "txfilter_add_scriptpubkey called!\n"); abort(); } -/* Generated stub for txfilter_new */ -struct txfilter *txfilter_new(const tal_t *ctx UNNEEDED) -{ fprintf(stderr, "txfilter_new called!\n"); abort(); } /* Generated stub for waitblockheight_notify_new_block */ void waitblockheight_notify_new_block(struct lightningd *ld UNNEEDED) { fprintf(stderr, "waitblockheight_notify_new_block called!\n"); abort(); } diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index 3d64242aa64a..907f629644c5 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -246,8 +246,8 @@ void delete_channel(struct channel *channel STEALS UNNEEDED, { fprintf(stderr, "delete_channel called!\n"); abort(); } /* Generated stub for depthcb_update_scid */ bool depthcb_update_scid(struct channel *channel UNNEEDED, - const struct bitcoin_txid *txid UNNEEDED, - const struct bitcoin_outpoint *outpoint UNNEEDED) + const struct bitcoin_outpoint *outpoint UNNEEDED, + const struct txlocator *loc UNNEEDED) { fprintf(stderr, "depthcb_update_scid called!\n"); abort(); } /* Generated stub for dev_disconnect_permanent */ bool dev_disconnect_permanent(struct lightningd *ld UNNEEDED) @@ -263,16 +263,6 @@ 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(); } @@ -668,6 +658,19 @@ u8 *towire_onchaind_dev_memleak(const tal_t *ctx UNNEEDED) /* Generated stub for towire_openingd_dev_memleak */ u8 *towire_openingd_dev_memleak(const tal_t *ctx UNNEEDED) { fprintf(stderr, "towire_openingd_dev_memleak called!\n"); abort(); } +/* Generated stub for unwatch_scriptpubkey_ */ +bool unwatch_scriptpubkey_(const tal_t *ctx UNNEEDED, + struct chain_topology *topo UNNEEDED, + const u8 *scriptpubkey TAKES UNNEEDED, + const struct bitcoin_outpoint *expected_outpoint UNNEEDED, + struct amount_sat expected_amount UNNEEDED, + void (*cb)(struct lightningd *ld UNNEEDED, + const struct bitcoin_tx *tx UNNEEDED, + u32 outnum UNNEEDED, + const struct txlocator *loc UNNEEDED, + void *) UNNEEDED, + void *arg UNNEEDED) +{ fprintf(stderr, "unwatch_scriptpubkey_ called!\n"); abort(); } /* Generated stub for wallet_channel_save */ void wallet_channel_save(struct wallet *w UNNEEDED, struct channel *chan UNNEEDED) { fprintf(stderr, "wallet_channel_save called!\n"); abort(); } @@ -675,9 +678,11 @@ void wallet_channel_save(struct wallet *w UNNEEDED, struct channel *chan UNNEEDE void wallet_delete_peer_if_unused(struct wallet *w UNNEEDED, u64 peer_dbid UNNEEDED) { fprintf(stderr, "wallet_delete_peer_if_unused called!\n"); abort(); } /* Generated stub for wallet_extract_owned_outputs */ -int wallet_extract_owned_outputs(struct wallet *w UNNEEDED, const struct wally_tx *tx UNNEEDED, - bool is_coinbase UNNEEDED, - const u32 *blockheight UNNEEDED) +bool wallet_extract_owned_outputs(struct wallet *w UNNEEDED, + const struct wally_tx *wtx UNNEEDED, + bool is_coinbase UNNEEDED, + const u32 *blockheight UNNEEDED, + size_t **outputs UNNEEDED) { fprintf(stderr, "wallet_extract_owned_outputs called!\n"); abort(); } /* Generated stub for wallet_htlcs_load_in_for_channel */ bool wallet_htlcs_load_in_for_channel(struct wallet *wallet UNNEEDED, @@ -725,10 +730,31 @@ void wallet_transaction_add(struct wallet *w UNNEEDED, const struct wally_tx *tx /* Generated stub for wallet_transaction_height */ u32 wallet_transaction_height(struct wallet *w UNNEEDED, const struct bitcoin_txid *txid UNNEEDED) { fprintf(stderr, "wallet_transaction_height called!\n"); abort(); } +/* Generated stub for watch_blockdepth_ */ +void watch_blockdepth_(const tal_t *ctx UNNEEDED, + struct chain_topology *topo UNNEEDED, + u32 blockheight UNNEEDED, + enum watch_result (*depthcb)(struct lightningd *ld UNNEEDED, u32 depth UNNEEDED, void *) UNNEEDED, + enum watch_result (*reorgcb)(struct lightningd *ld UNNEEDED, void *) UNNEEDED, + void *arg UNNEEDED) +{ fprintf(stderr, "watch_blockdepth_ called!\n"); abort(); } /* Generated stub for watch_opening_inflight */ void watch_opening_inflight(struct lightningd *ld UNNEEDED, struct channel_inflight *inflight UNNEEDED) { fprintf(stderr, "watch_opening_inflight called!\n"); abort(); } +/* Generated stub for watch_scriptpubkey_ */ +void watch_scriptpubkey_(const tal_t *ctx UNNEEDED, + struct chain_topology *topo UNNEEDED, + const u8 *scriptpubkey TAKES UNNEEDED, + const struct bitcoin_outpoint *expected_outpoint UNNEEDED, + struct amount_sat expected_amount UNNEEDED, + void (*cb)(struct lightningd *ld UNNEEDED, + const struct bitcoin_tx *tx UNNEEDED, + u32 outnum UNNEEDED, + const struct txlocator *loc UNNEEDED, + void *) UNNEEDED, + void *arg UNNEEDED) +{ fprintf(stderr, "watch_scriptpubkey_ called!\n"); abort(); } /* Generated stub for watch_splice_inflight */ void watch_splice_inflight(struct lightningd *ld UNNEEDED, struct channel_inflight *inflight UNNEEDED) diff --git a/lightningd/watch.c b/lightningd/watch.c index 67b2bb083a04..eada9fa06fec 100644 --- a/lightningd/watch.c +++ b/lightningd/watch.c @@ -31,6 +31,8 @@ */ #include "config.h" #include +#include +#include #include #include #include @@ -275,24 +277,24 @@ void watch_topology_changed(struct chain_topology *topo) { struct txwatch_hash_iter i; struct txwatch *w; - bool needs_rerun; - do { - /* Iterating a htable during deletes is safe, but might skip entries. */ - needs_rerun = false; - for (w = txwatch_hash_first(topo->txwatches, &i); - w; - w = txwatch_hash_next(topo->txwatches, &i)) { - u32 depth; - depth = get_tx_depth(topo, &w->txid); - if (depth) { - if (!w->tx) - w->tx = wallet_transaction_get(w, topo->ld->wallet, + /* Iterating a htable during deletes is safe and consistent. + * Adding is forbidden. */ + txwatch_hash_lock(topo->txwatches); + for (w = txwatch_hash_first(topo->txwatches, &i); + w; + w = txwatch_hash_next(topo->txwatches, &i)) { + u32 depth; + + depth = get_tx_depth(topo, &w->txid); + if (depth) { + if (!w->tx) + w->tx = wallet_transaction_get(w, topo->ld->wallet, &w->txid); - needs_rerun |= txw_fire(w, &w->txid, depth); - } + txw_fire(w, &w->txid, depth); } - } while (needs_rerun); + } + txwatch_hash_unlock(topo->txwatches); } void txwatch_inform(const struct chain_topology *topo, @@ -316,3 +318,243 @@ void txwatch_inform(const struct chain_topology *topo, if (taken(tx)) tal_free(tx); } + +struct scriptpubkeywatch { + struct script_with_len swl; + struct bitcoin_outpoint expected_outpoint; + struct amount_sat expected_amount; + void (*cb)(struct lightningd *ld, + const struct bitcoin_tx *tx, + u32 outnum, + const struct txlocator *loc, + void *); + void *arg; +}; + +const struct script_with_len *scriptpubkeywatch_keyof(const struct scriptpubkeywatch *w) +{ + return &w->swl; +} + +bool scriptpubkeywatch_eq(const struct scriptpubkeywatch *w, const struct script_with_len *swl) +{ + return script_with_len_eq(&w->swl, swl); +} + +static void destroy_scriptpubkeywatch(struct scriptpubkeywatch *w, struct chain_topology *topo) +{ + scriptpubkeywatch_hash_del(topo->scriptpubkeywatches, w); +} + +void watch_scriptpubkey_(const tal_t *ctx, + struct chain_topology *topo, + const u8 *scriptpubkey TAKES, + const struct bitcoin_outpoint *expected_outpoint, + struct amount_sat expected_amount, + void (*cb)(struct lightningd *ld, + const struct bitcoin_tx *tx, + u32 outnum, + const struct txlocator *loc, + void *), + void *arg) +{ + struct scriptpubkeywatch *w = tal(ctx, struct scriptpubkeywatch); + w->swl.script = tal_dup_talarr(w, u8, scriptpubkey); + w->swl.len = tal_bytelen(w->swl.script); + w->expected_outpoint = *expected_outpoint; + w->expected_amount = expected_amount; + w->cb = cb; + w->arg = arg; + scriptpubkeywatch_hash_add(topo->scriptpubkeywatches, w); + tal_add_destructor2(w, destroy_scriptpubkeywatch, topo); +} + +bool unwatch_scriptpubkey_(const tal_t *ctx, + struct chain_topology *topo, + const u8 *scriptpubkey TAKES, + const struct bitcoin_outpoint *expected_outpoint, + struct amount_sat expected_amount, + void (*cb)(struct lightningd *ld, + const struct bitcoin_tx *tx, + u32 outnum, + const struct txlocator *loc, + void *), + void *arg) +{ + struct scriptpubkeywatch_hash_iter it; + const struct script_with_len swl = { scriptpubkey, tal_bytelen(scriptpubkey) }; + + for (struct scriptpubkeywatch *w = scriptpubkeywatch_hash_getfirst(topo->scriptpubkeywatches, &swl, &it); + w; + w = scriptpubkeywatch_hash_getnext(topo->scriptpubkeywatches, &swl, &it)) { + if (!bitcoin_outpoint_eq(&w->expected_outpoint, expected_outpoint) + || !amount_sat_eq(w->expected_amount, expected_amount) + || w->cb != cb + || w->arg != arg) { + continue; + } + tal_free(w); + return true; + } + return false; +} + +bool watch_check_tx_outputs(const struct chain_topology *topo, + const struct txlocator *loc, + const struct bitcoin_tx *tx, + const struct bitcoin_txid *txid) +{ + bool tx_interesting = false; + + for (size_t outnum = 0; outnum < tx->wtx->num_outputs; outnum++) { + const struct wally_tx_output *txout = &tx->wtx->outputs[outnum]; + const struct script_with_len swl = { txout->script, txout->script_len }; + struct scriptpubkeywatch_hash_iter it; + bool output_matched = false, bad_txid = false, bad_amount = false, bad_outnum = false; + struct amount_asset outasset = bitcoin_tx_output_get_amount(tx, outnum); + + /* Ensure callbacks don't do an insert during iteration! */ + scriptpubkeywatch_hash_lock(topo->scriptpubkeywatches); + for (struct scriptpubkeywatch *w = scriptpubkeywatch_hash_getfirst(topo->scriptpubkeywatches, &swl, &it); + w; + w = scriptpubkeywatch_hash_getnext(topo->scriptpubkeywatches, &swl, &it)) { + if (!bitcoin_txid_eq(&w->expected_outpoint.txid, txid)) { + bad_txid = true; + continue; + } + if (outnum != w->expected_outpoint.n) { + bad_outnum = true; + continue; + } + if (!amount_asset_is_main(&outasset) + || !amount_sat_eq(amount_asset_to_sat(&outasset), w->expected_amount)) { + bad_amount = true; + continue; + } + + w->cb(topo->ld, tx, outnum, loc, w->arg); + output_matched = true; + tx_interesting = true; + } + scriptpubkeywatch_hash_unlock(topo->scriptpubkeywatches); + + /* Only complain about mismatch if we missed all of them. + * This helps diagnose mistakes like wrong txid, see + * https://github.com/ElementsProject/lightning/issues/8892 */ + if (!output_matched && (bad_txid || bad_amount || bad_outnum)) { + const char *addr = encode_scriptpubkey_to_addr(tmpctx, chainparams, + txout->script, txout->script_len); + if (!addr) + addr = tal_fmt(tmpctx, "Scriptpubkey %s", tal_hexstr(tmpctx, txout->script, txout->script_len)); + if (bad_txid) { + log_unusual(topo->ld->log, + "Unexpected spend to %s by unexpected txid %s:%zu", + addr, fmt_bitcoin_txid(tmpctx, txid), outnum); + } + if (bad_amount) { + log_unusual(topo->ld->log, + "Unexpected amount %s to %s by txid %s:%zu", + amount_asset_is_main(&outasset) + ? fmt_amount_sat(tmpctx, amount_asset_to_sat(&outasset)) + : "fee output", + addr, fmt_bitcoin_txid(tmpctx, txid), outnum); + } + if (bad_outnum) { + log_unusual(topo->ld->log, + "Unexpected output number %zu paying to %s in txid %s", + outnum, addr, fmt_bitcoin_txid(tmpctx, txid)); + } + } + } + + return tx_interesting; +} + +struct blockdepthwatch { + u32 height; + enum watch_result (*depthcb)(struct lightningd *ld, + u32 depth, + void *); + enum watch_result (*reorgcb)(struct lightningd *ld, + void *); + void *arg; +}; + +u32 blockdepthwatch_keyof(const struct blockdepthwatch *w) +{ + return w->height; +} + +size_t u32_hash(u32 val) +{ + return siphash24(siphash_seed(), &val, sizeof(val)); +} + +bool blockdepthwatch_eq(const struct blockdepthwatch *w, u32 height) +{ + return w->height == height; +} + +static void destroy_blockdepthwatch(struct blockdepthwatch *w, struct chain_topology *topo) +{ + blockdepthwatch_hash_del(topo->blockdepthwatches, w); +} + +void watch_blockdepth_(const tal_t *ctx, + struct chain_topology *topo, + u32 blockheight, + enum watch_result (*depthcb)(struct lightningd *ld, u32 depth, void *), + enum watch_result (*reorgcb)(struct lightningd *ld, void *), + void *arg) +{ + struct blockdepthwatch *w = tal(ctx, struct blockdepthwatch); + w->height = blockheight; + w->depthcb = depthcb; + w->reorgcb = reorgcb; + w->arg = arg; + blockdepthwatch_hash_add(topo->blockdepthwatches, w); + tal_add_destructor2(w, destroy_blockdepthwatch, topo); +} + +void watch_check_block_added(const struct chain_topology *topo, u32 blockheight) +{ + struct blockdepthwatch_hash_iter it; + + /* With ccan/htable, deleting during iteration is safe: adding isn't! */ + blockdepthwatch_hash_lock(topo->blockdepthwatches); + for (struct blockdepthwatch *w = blockdepthwatch_hash_first(topo->blockdepthwatches, &it); + w; + w = blockdepthwatch_hash_next(topo->blockdepthwatches, &it)) { + /* You are not supposed to watch future blocks! */ + assert(blockheight >= w->height); + + u32 depth = blockheight - w->height + 1; + enum watch_result r = w->depthcb(topo->ld, depth, w->arg); + + switch (r) { + case DELETE_WATCH: + tal_free(w); + continue; + case KEEP_WATCHING: + continue; + } + fatal("blockdepthwatch depth callback %p returned %i", w->depthcb, r); + } + blockdepthwatch_hash_unlock(topo->blockdepthwatches); +} + +void watch_check_block_removed(const struct chain_topology *topo, u32 blockheight) +{ + struct blockdepthwatch_hash_iter it; + + /* With ccan/htable, deleting during iteration is safe. */ + blockdepthwatch_hash_lock(topo->blockdepthwatches); + for (struct blockdepthwatch *w = blockdepthwatch_hash_getfirst(topo->blockdepthwatches, blockheight, &it); + w; + w = blockdepthwatch_hash_getnext(topo->blockdepthwatches, blockheight, &it)) { + enum watch_result r = w->reorgcb(topo->ld, w->arg); + assert(r == DELETE_WATCH); + tal_free(w); + } + blockdepthwatch_hash_unlock(topo->blockdepthwatches); +} diff --git a/lightningd/watch.h b/lightningd/watch.h index 596da3a31497..bd371ef691ce 100644 --- a/lightningd/watch.h +++ b/lightningd/watch.h @@ -1,6 +1,7 @@ #ifndef LIGHTNING_LIGHTNINGD_WATCH_H #define LIGHTNING_LIGHTNINGD_WATCH_H #include "config.h" +#include #include #include @@ -8,8 +9,11 @@ struct block; struct channel; struct chain_topology; struct lightningd; +struct txlocator; struct txowatch; struct txwatch; +struct scriptpubkeywatch; +struct blockdepthwatch; enum watch_result { DELETE_WATCH = -1, @@ -29,6 +33,16 @@ bool txwatch_eq(const struct txwatch *w, const struct bitcoin_txid *txid); HTABLE_DEFINE_DUPS_TYPE(struct txwatch, txwatch_keyof, txid_hash, txwatch_eq, txwatch_hash); +const struct script_with_len *scriptpubkeywatch_keyof(const struct scriptpubkeywatch *w); +bool scriptpubkeywatch_eq(const struct scriptpubkeywatch *w, const struct script_with_len *swl); +HTABLE_DEFINE_DUPS_TYPE(struct scriptpubkeywatch, scriptpubkeywatch_keyof, script_with_len_hash, scriptpubkeywatch_eq, + scriptpubkeywatch_hash); + +u32 blockdepthwatch_keyof(const struct blockdepthwatch *w); +size_t u32_hash(u32); +bool blockdepthwatch_eq(const struct blockdepthwatch *w, u32 height); +HTABLE_DEFINE_DUPS_TYPE(struct blockdepthwatch, blockdepthwatch_keyof, u32_hash, blockdepthwatch_eq, + blockdepthwatch_hash); struct txwatch *watch_txid_(const tal_t *ctx, struct chain_topology *topo, @@ -93,5 +107,83 @@ void txwatch_inform(const struct chain_topology *topo, const struct bitcoin_txid *txid, struct bitcoin_tx *tx TAKES); +/* Watch for specific spends to this scriptpubkey */ +void watch_scriptpubkey_(const tal_t *ctx, + struct chain_topology *topo, + const u8 *scriptpubkey TAKES, + const struct bitcoin_outpoint *expected_outpoint, + struct amount_sat expected_amount, + void (*cb)(struct lightningd *ld, + const struct bitcoin_tx *tx, + u32 outnum, + const struct txlocator *loc, + void *), + void *arg); + +#define watch_scriptpubkey(ctx, topo, scriptpubkey, expected_outpoint, expected_amount, cb, arg) \ + watch_scriptpubkey_((ctx), (topo), (scriptpubkey), \ + (expected_outpoint), (expected_amount), \ + typesafe_cb_preargs(void, void *, \ + (cb), (arg), \ + struct lightningd *, \ + const struct bitcoin_tx *, \ + u32 outnum, \ + const struct txlocator *), \ + (arg)) + +bool unwatch_scriptpubkey_(const tal_t *ctx, + struct chain_topology *topo, + const u8 *scriptpubkey TAKES, + const struct bitcoin_outpoint *expected_outpoint, + struct amount_sat expected_amount, + void (*cb)(struct lightningd *ld, + const struct bitcoin_tx *tx, + u32 outnum, + const struct txlocator *loc, + void *), + void *arg); + +#define unwatch_scriptpubkey(ctx, topo, scriptpubkey, expected_outpoint, expected_amount, cb, arg) \ + unwatch_scriptpubkey_((ctx), (topo), (scriptpubkey), \ + (expected_outpoint), (expected_amount), \ + typesafe_cb_preargs(void, void *, \ + (cb), (arg), \ + struct lightningd *, \ + const struct bitcoin_tx *, \ + u32 outnum, \ + const struct txlocator *), \ + (arg)) + +/* Watch for this block getting deeper (or reorged out) */ +void watch_blockdepth_(const tal_t *ctx, + struct chain_topology *topo, + u32 blockheight, + enum watch_result (*depthcb)(struct lightningd *ld, u32 depth, void *), + enum watch_result (*reorgcb)(struct lightningd *ld, void *), + void *arg); + +#define watch_blockdepth(ctx, topo, blockheight, depthcb, reorgcb, arg) \ + watch_blockdepth_((ctx), (topo), (blockheight), \ + typesafe_cb_preargs(enum watch_result, void *, \ + (depthcb), (arg), \ + struct lightningd *, \ + u32), \ + typesafe_cb_preargs(enum watch_result, void *, \ + (reorgcb), (arg), \ + struct lightningd *), \ + (arg)) + +/* Call any scriptpubkey callbacks for this tx */ +bool watch_check_tx_outputs(const struct chain_topology *topo, + const struct txlocator *loc, + const struct bitcoin_tx *tx, + const struct bitcoin_txid *txid); + +/* Call anyone watching for block height increases. */ +void watch_check_block_added(const struct chain_topology *topo, u32 blockheight); + +/* Call anyone watching for block removals. */ +void watch_check_block_removed(const struct chain_topology *topo, u32 blockheight); + void watch_topology_changed(struct chain_topology *topo); #endif /* LIGHTNING_LIGHTNINGD_WATCH_H */ diff --git a/openingd/dualopend.c b/openingd/dualopend.c index 2b3ff44bf8e2..b0393ec8b42a 100644 --- a/openingd/dualopend.c +++ b/openingd/dualopend.c @@ -1871,8 +1871,7 @@ static bool run_tx_interactive(struct state *state, if (is_elements(chainparams)) { struct amount_asset asset; - bitcoin_tx_output_get_amount_sat(tx, outpoint.n, - &amt); + amt = bitcoin_tx_output_get_amount_sat(tx, outpoint.n); /* FIXME: persist asset tags */ asset = amount_sat_to_asset(&amt, diff --git a/plugins/spender/splice.c b/plugins/spender/splice.c index 35098c0c7f31..4b27197f38a6 100644 --- a/plugins/spender/splice.c +++ b/plugins/spender/splice.c @@ -1107,7 +1107,8 @@ static struct command_result *execute_splice(struct command *cmd, /* Reencode scriptpubkey to addr for verification */ bitcoin_address = encode_scriptpubkey_to_addr(tmpctx, chainparams, - scriptpubkey); + scriptpubkey, + tal_bytelen(scriptpubkey)); if (!bitcoin_address) return do_fail(cmd, splice_cmd, JSONRPC2_INVALID_PARAMS, diff --git a/tests/fuzz/fuzz-addr.c b/tests/fuzz/fuzz-addr.c index a833bc298300..3b456b89b656 100644 --- a/tests/fuzz/fuzz-addr.c +++ b/tests/fuzz/fuzz-addr.c @@ -1,6 +1,7 @@ #include "config.h" #include +#include #include #include #include @@ -16,13 +17,11 @@ void init(int *argc, char ***argv) void run(const uint8_t *data, size_t size) { - uint8_t *script_pubkey = tal_dup_arr(tmpctx, uint8_t, data, size, 0); - - char *addr = encode_scriptpubkey_to_addr(tmpctx, chainparams, script_pubkey); + char *addr = encode_scriptpubkey_to_addr(tmpctx, chainparams, data, size); if (addr) { uint8_t *decoded_script_pubkey; assert(decode_scriptpubkey_from_addr(tmpctx, chainparams, addr, &decoded_script_pubkey)); - assert(tal_arr_eq(script_pubkey, decoded_script_pubkey)); + assert(memeq(data, size, decoded_script_pubkey, tal_bytelen(decoded_script_pubkey))); } clean_tmpctx(); diff --git a/tests/fuzz/fuzz-full_channel.c b/tests/fuzz/fuzz-full_channel.c index c907f4533704..977b7367b697 100644 --- a/tests/fuzz/fuzz-full_channel.c +++ b/tests/fuzz/fuzz-full_channel.c @@ -14,15 +14,6 @@ #include #include -/* MOCKS START */ -const struct siphash_seed *siphash_seed(void) -{ - struct siphash_seed *siphashseed = tal(tmpctx, struct siphash_seed); - memset(siphashseed, 1, sizeof(*siphashseed)); - return siphashseed; -} -/* MOCKS END */ - #define MAX_SATS ((u64)WALLY_SATOSHI_PER_BTC * WALLY_BTC_MAX) #define MAX_MSATS (MAX_SATS * 1000) #define MAX_HTLCS 1000000 @@ -243,6 +234,7 @@ void init(int *argc, char ***argv) chainparams = chainparams_for_network("bitcoin"); int devnull = open("/dev/null", O_WRONLY); status_setup_sync(devnull); + fuzz_allow_siphash_seed = true; } struct pending_htlc { diff --git a/tests/fuzz/fuzz-handle_onion_message.c b/tests/fuzz/fuzz-handle_onion_message.c index d4a902d8e959..0e96d0323f87 100644 --- a/tests/fuzz/fuzz-handle_onion_message.c +++ b/tests/fuzz/fuzz-handle_onion_message.c @@ -16,7 +16,6 @@ static int lightningd_fd; static struct privkey priv; -static struct siphash_seed siphashseed; jmp_buf fuzz_env; /* MOCKS START */ @@ -27,9 +26,6 @@ u8 *towire_warningfmt(const tal_t *ctx UNNEEDED, const struct channel_id *channel UNNEEDED, const char *fmt UNNEEDED, ...) { longjmp(fuzz_env, 1); } - -const struct siphash_seed *siphash_seed(void) -{ return &siphashseed; } /* MOCKS END */ void ecdh(const struct pubkey *point, struct secret *ss) @@ -68,9 +64,9 @@ void init(int *argc, char ***argv) lightningd_fd = open("/dev/null", O_WRONLY); status_setup_sync(lightningd_fd); chainparams = chainparams_for_network("bitcoin"); + fuzz_allow_siphash_seed = true; memset(&priv, 'b', sizeof(priv)); - memset(&siphashseed, 1, sizeof(siphashseed)); } void run(const uint8_t *data, size_t size) diff --git a/tests/fuzz/libfuzz.c b/tests/fuzz/libfuzz.c index 8f8dc43e2c19..5d6f27afff72 100644 --- a/tests/fuzz/libfuzz.c +++ b/tests/fuzz/libfuzz.c @@ -22,6 +22,20 @@ int LLVMFuzzerInitialize(int *argc, char ***argv); /* Provide a non-random pseudo-random function to speed fuzzing. */ static isaac64_ctx isaac64; +/* Most tests should not be calling this */ +bool fuzz_allow_siphash_seed = false; + +/* Define this so we don't try to link against common/pseudorand.o! */ +const struct siphash_seed *siphash_seed(void) +{ + if (!fuzz_allow_siphash_seed) + abort(); + + struct siphash_seed *siphashseed = tal(tmpctx, struct siphash_seed); + memset(siphashseed, 1, sizeof(*siphashseed)); + return siphashseed; +} + uint64_t pseudorand_(uint64_t max, uint64_t *offset) { assert(max); diff --git a/tests/fuzz/libfuzz.h b/tests/fuzz/libfuzz.h index 332caa3e8340..00547e83c8d7 100644 --- a/tests/fuzz/libfuzz.h +++ b/tests/fuzz/libfuzz.h @@ -12,6 +12,9 @@ * environment. */ void init(int *argc, char ***argv); +/* Set if you want siphash_seed() to work */ +extern bool fuzz_allow_siphash_seed; + /* The actual target called multiple times with mutated data. */ void run(const uint8_t *data, size_t size); diff --git a/tests/test_misc.py b/tests/test_misc.py index faac4c7a3752..b36634f87e51 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -1453,7 +1453,7 @@ def test_funding_reorg_private(node_factory, bitcoind): # l2 was running, sees last stale block being removed l2.daemon.wait_for_logs([r'Removing stale block {}'.format(106), - r'Got depth change .->{} for .* REORG'.format(0)]) + r'Funding txid .* REORG from depth 2']) # New one should replace old. wait_for(lambda: l2.is_local_channel_active('108x1x0')) diff --git a/wallet/reservation.c b/wallet/reservation.c index b31870a66007..a340cd8803e7 100644 --- a/wallet/reservation.c +++ b/wallet/reservation.c @@ -386,7 +386,6 @@ static struct command_result *finish_psbt(struct command *cmd, "Failed to generate change address." " Keys generation failure"); } - txfilter_add_scriptpubkey(cmd->ld->owned_txfilter, b32script); change_outnum = psbt->num_outputs; psbt_append_output(psbt, b32script, change); @@ -725,7 +724,6 @@ static struct command_result *json_addpsbtoutput(struct command *cmd, "Failed to generate change address." " Keys generation failure"); } - txfilter_add_scriptpubkey(cmd->ld->owned_txfilter, b32script); } outnum = psbt->num_outputs; diff --git a/wallet/test/run-chain_moves_duplicate-detect.c b/wallet/test/run-chain_moves_duplicate-detect.c index 428768d27e38..491ccc1da265 100644 --- a/wallet/test/run-chain_moves_duplicate-detect.c +++ b/wallet/test/run-chain_moves_duplicate-detect.c @@ -355,9 +355,6 @@ u8 *towire_hsmd_get_channel_basepoints(const tal_t *ctx UNNEEDED, const struct n /* Generated stub for towire_hsmd_get_output_scriptpubkey */ u8 *towire_hsmd_get_output_scriptpubkey(const tal_t *ctx UNNEEDED, u64 channel_id UNNEEDED, const struct node_id *peer_id UNNEEDED, const struct pubkey *commitment_point UNNEEDED) { fprintf(stderr, "towire_hsmd_get_output_scriptpubkey called!\n"); abort(); } -/* Generated stub for txfilter_add_scriptpubkey */ -void txfilter_add_scriptpubkey(struct txfilter *filter UNNEEDED, const u8 *script TAKES UNNEEDED) -{ fprintf(stderr, "txfilter_add_scriptpubkey called!\n"); abort(); } /* Generated stub for wait_index_increment */ u64 wait_index_increment(struct lightningd *ld UNNEEDED, struct db *db UNNEEDED, diff --git a/wallet/test/run-db.c b/wallet/test/run-db.c index c1b4cb1bdaf5..3ac23b20f636 100644 --- a/wallet/test/run-db.c +++ b/wallet/test/run-db.c @@ -368,9 +368,6 @@ u8 *towire_hsmd_get_channel_basepoints(const tal_t *ctx UNNEEDED, const struct n /* Generated stub for towire_hsmd_get_output_scriptpubkey */ u8 *towire_hsmd_get_output_scriptpubkey(const tal_t *ctx UNNEEDED, u64 channel_id UNNEEDED, const struct node_id *peer_id UNNEEDED, const struct pubkey *commitment_point UNNEEDED) { fprintf(stderr, "towire_hsmd_get_output_scriptpubkey called!\n"); abort(); } -/* Generated stub for txfilter_add_scriptpubkey */ -void txfilter_add_scriptpubkey(struct txfilter *filter UNNEEDED, const u8 *script TAKES UNNEEDED) -{ fprintf(stderr, "txfilter_add_scriptpubkey called!\n"); abort(); } /* Generated stub for wait_index_increment */ u64 wait_index_increment(struct lightningd *ld UNNEEDED, struct db *db UNNEEDED, diff --git a/wallet/test/run-migrate_remove_chain_moves_duplicates.c b/wallet/test/run-migrate_remove_chain_moves_duplicates.c index 2bb792e2ade5..d2f25f8f6cdf 100644 --- a/wallet/test/run-migrate_remove_chain_moves_duplicates.c +++ b/wallet/test/run-migrate_remove_chain_moves_duplicates.c @@ -404,9 +404,6 @@ u8 *towire_hsmd_get_channel_basepoints(const tal_t *ctx UNNEEDED, const struct n /* Generated stub for towire_hsmd_get_output_scriptpubkey */ u8 *towire_hsmd_get_output_scriptpubkey(const tal_t *ctx UNNEEDED, u64 channel_id UNNEEDED, const struct node_id *peer_id UNNEEDED, const struct pubkey *commitment_point UNNEEDED) { fprintf(stderr, "towire_hsmd_get_output_scriptpubkey called!\n"); abort(); } -/* Generated stub for txfilter_add_scriptpubkey */ -void txfilter_add_scriptpubkey(struct txfilter *filter UNNEEDED, const u8 *script TAKES UNNEEDED) -{ fprintf(stderr, "txfilter_add_scriptpubkey called!\n"); abort(); } /* Generated stub for wait_index_increment */ u64 wait_index_increment(struct lightningd *ld UNNEEDED, struct db *db UNNEEDED, diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 339a21867e82..ed2849bb13a0 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -244,8 +244,8 @@ u8 *create_channel_announcement(const tal_t *ctx UNNEEDED, { fprintf(stderr, "create_channel_announcement called!\n"); abort(); } /* Generated stub for depthcb_update_scid */ bool depthcb_update_scid(struct channel *channel UNNEEDED, - const struct bitcoin_txid *txid UNNEEDED, - const struct bitcoin_outpoint *outpoint UNNEEDED) + const struct bitcoin_outpoint *outpoint UNNEEDED, + const struct txlocator *loc UNNEEDED) { fprintf(stderr, "depthcb_update_scid called!\n"); abort(); } /* Generated stub for dev_disconnect_permanent */ bool dev_disconnect_permanent(struct lightningd *ld UNNEEDED) @@ -256,16 +256,6 @@ 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, @@ -766,10 +756,44 @@ u8 *unsigned_node_announcement(const tal_t *ctx UNNEEDED, struct lightningd *ld UNNEEDED, const u8 *prev UNNEEDED) { fprintf(stderr, "unsigned_node_announcement called!\n"); abort(); } +/* Generated stub for unwatch_scriptpubkey_ */ +bool unwatch_scriptpubkey_(const tal_t *ctx UNNEEDED, + struct chain_topology *topo UNNEEDED, + const u8 *scriptpubkey TAKES UNNEEDED, + const struct bitcoin_outpoint *expected_outpoint UNNEEDED, + struct amount_sat expected_amount UNNEEDED, + void (*cb)(struct lightningd *ld UNNEEDED, + const struct bitcoin_tx *tx UNNEEDED, + u32 outnum UNNEEDED, + const struct txlocator *loc UNNEEDED, + void *) UNNEEDED, + void *arg UNNEEDED) +{ fprintf(stderr, "unwatch_scriptpubkey_ called!\n"); abort(); } +/* Generated stub for watch_blockdepth_ */ +void watch_blockdepth_(const tal_t *ctx UNNEEDED, + struct chain_topology *topo UNNEEDED, + u32 blockheight UNNEEDED, + enum watch_result (*depthcb)(struct lightningd *ld UNNEEDED, u32 depth UNNEEDED, void *) UNNEEDED, + enum watch_result (*reorgcb)(struct lightningd *ld UNNEEDED, void *) UNNEEDED, + void *arg UNNEEDED) +{ fprintf(stderr, "watch_blockdepth_ called!\n"); abort(); } /* Generated stub for watch_opening_inflight */ void watch_opening_inflight(struct lightningd *ld UNNEEDED, struct channel_inflight *inflight UNNEEDED) { fprintf(stderr, "watch_opening_inflight called!\n"); abort(); } +/* Generated stub for watch_scriptpubkey_ */ +void watch_scriptpubkey_(const tal_t *ctx UNNEEDED, + struct chain_topology *topo UNNEEDED, + const u8 *scriptpubkey TAKES UNNEEDED, + const struct bitcoin_outpoint *expected_outpoint UNNEEDED, + struct amount_sat expected_amount UNNEEDED, + void (*cb)(struct lightningd *ld UNNEEDED, + const struct bitcoin_tx *tx UNNEEDED, + u32 outnum UNNEEDED, + const struct txlocator *loc UNNEEDED, + void *) UNNEEDED, + void *arg UNNEEDED) +{ fprintf(stderr, "watch_scriptpubkey_ called!\n"); abort(); } /* Generated stub for watch_splice_inflight */ void watch_splice_inflight(struct lightningd *ld UNNEEDED, struct channel_inflight *inflight UNNEEDED) @@ -855,12 +879,6 @@ struct log_book *new_log_book(struct lightningd *ld UNNEEDED) return NULL; } -void txfilter_add_scriptpubkey(struct txfilter *filter UNNEEDED, const u8 *script TAKES) -{ - if (taken(script)) - tal_free(script); -} - /* Can actually be called by new_channel */ u32 get_block_height(const struct chain_topology *topo UNNEEDED) { diff --git a/wallet/txfilter.c b/wallet/txfilter.c index e3249acc30bc..f5255b472e84 100644 --- a/wallet/txfilter.c +++ b/wallet/txfilter.c @@ -5,31 +5,6 @@ #include #include -size_t scriptpubkey_hash(const u8 *out) -{ - struct siphash24_ctx ctx; - siphash24_init(&ctx, siphash_seed()); - siphash24_update(&ctx, out, tal_bytelen(out)); - return siphash24_done(&ctx); -} - -static const u8 *scriptpubkey_keyof(const u8 *out) -{ - return out; -} - -static bool scriptpubkey_eq(const u8 *a, const u8 *b) -{ - return tal_arr_eq(a, b); -} - -/* FIXME: Should we disallow dups here? */ -HTABLE_DEFINE_DUPS_TYPE(u8, scriptpubkey_keyof, scriptpubkey_hash, scriptpubkey_eq, scriptpubkeyset); - -struct txfilter { - struct scriptpubkeyset scriptpubkeyset; -}; - static size_t outpoint_hash(const struct bitcoin_outpoint *out) { struct siphash24_ctx ctx; @@ -51,52 +26,6 @@ struct outpointfilter { struct outpointset *set; }; -struct txfilter *txfilter_new(const tal_t *ctx) -{ - struct txfilter *filter = tal(ctx, struct txfilter); - scriptpubkeyset_init(&filter->scriptpubkeyset); - return filter; -} - -void txfilter_add_scriptpubkey(struct txfilter *filter, const u8 *script TAKES) -{ - scriptpubkeyset_add( - &filter->scriptpubkeyset, - notleak(tal_dup_talarr(filter, u8, script))); -} - -void txfilter_add_derkey(struct txfilter *filter, - const u8 derkey[PUBKEY_CMPR_LEN]) -{ - u8 *skp, *p2sh, *p2tr; - - skp = scriptpubkey_p2wpkh_derkey(tmpctx, derkey); - p2sh = scriptpubkey_p2sh(tmpctx, skp); - p2tr = scriptpubkey_p2tr_derkey(tmpctx, derkey); - - txfilter_add_scriptpubkey(filter, take(skp)); - txfilter_add_scriptpubkey(filter, take(p2sh)); - txfilter_add_scriptpubkey(filter, take(p2tr)); -} - - -bool txfilter_match(const struct txfilter *filter, const struct bitcoin_tx *tx) -{ - for (size_t i = 0; i < tx->wtx->num_outputs; i++) { - const struct wally_tx_output *txout = &tx->wtx->outputs[i]; - if (txfilter_scriptpubkey_matches(filter, txout->script)) - return true; - } - return false; -} - -bool txfilter_scriptpubkey_matches(const struct txfilter *filter, const u8 *scriptPubKey) -{ - if (!scriptPubKey) - return false; - return scriptpubkeyset_exists(&filter->scriptpubkeyset, scriptPubKey); -} - void outpointfilter_add(struct outpointfilter *of, const struct bitcoin_outpoint *outpoint) { diff --git a/wallet/txfilter.h b/wallet/txfilter.h index 2e72b68e1b93..768ca1579ac8 100644 --- a/wallet/txfilter.h +++ b/wallet/txfilter.h @@ -4,44 +4,11 @@ #include #include -struct txfilter; - /** * outpointfilter -- Simple filter that keeps track of outpoints */ struct outpointfilter; -/** - * txfilter_new -- Construct and initialize a new txfilter - */ -struct txfilter *txfilter_new(const tal_t *ctx); - -/** - * txfilter_add_derkey -- Add a scriptpubkeys matching the der key to the filter - * - * This ensures that we recognize the scriptpubkeys to our keys when - * filtering transactions. If any of the outputs matches the - * scriptpubkey then the transaction is marked as a match. Adds - * scriptpubkey for taproot, raw p2wpkh and p2wpkh wrapped in p2sh. - */ -void txfilter_add_derkey(struct txfilter *filter, - const u8 derkey[PUBKEY_CMPR_LEN]); - -/** - * txfilter_match -- Check whether the tx matches the filter - */ -bool txfilter_match(const struct txfilter *filter, const struct bitcoin_tx *tx); - -/** - * txfilter_matches -- Check whether the scriptpubkey matches the filter - */ -bool txfilter_scriptpubkey_matches(const struct txfilter *filter, const u8 *scriptPubKey); - -/** - * txfilter_add_scriptpubkey -- Add a serialized scriptpubkey to the filter - */ -void txfilter_add_scriptpubkey(struct txfilter *filter, const u8 *script TAKES); - /** * outpointfilter_new -- Create a new outpointfilter */ @@ -64,7 +31,4 @@ bool outpointfilter_matches(struct outpointfilter *of, void outpointfilter_remove(struct outpointfilter *of, const struct bitcoin_outpoint *outpoint); -/* Useful for other callers */ -size_t scriptpubkey_hash(const u8 *out); - #endif /* LIGHTNING_WALLET_TXFILTER_H */ diff --git a/wallet/wallet.c b/wallet/wallet.c index a8f4da06b61c..2b080247476e 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -68,12 +68,6 @@ static enum state_change state_change_in_db(enum state_change s) fatal("%s: %u is invalid", __func__, s); } -/* libwally uses pointer/size pairs */ -struct script_with_len { - const u8 *script; - size_t len; -}; - /* We keep a hash of these, for fast lookup */ struct wallet_address { u32 index; @@ -81,20 +75,15 @@ struct wallet_address { struct script_with_len swl; }; -static size_t script_with_len_hash(const struct script_with_len *swl) -{ - return siphash24(siphash_seed(), swl->script, swl->len); -} - static const struct script_with_len *wallet_address_keyof(const struct wallet_address *waddr) { return &waddr->swl; } static bool wallet_address_eq_scriptpubkey(const struct wallet_address *waddr, - const struct script_with_len *script) + const struct script_with_len *swl) { - return memeq(waddr->swl.script, waddr->swl.len, script->script, script->len); + return script_with_len_eq(&waddr->swl, swl); } HTABLE_DEFINE_NODUPS_TYPE(struct wallet_address, @@ -3354,10 +3343,6 @@ static void got_utxo(struct wallet *w, return; } - /* This is an unconfirmed change output, we should track it */ - if (utxo->utxotype != UTXO_P2SH_P2WPKH && !blockheight) - txfilter_add_scriptpubkey(w->ld->owned_txfilter, txout->script); - outpointfilter_add(w->owned_outpoints, &utxo->outpoint); wallet_annotate_txout(w, &utxo->outpoint, TX_WALLET_DEPOSIT, 0); @@ -3365,11 +3350,13 @@ static void got_utxo(struct wallet *w, *outpoint = utxo->outpoint; } -int wallet_extract_owned_outputs(struct wallet *w, const struct wally_tx *wtx, - bool is_coinbase, - const u32 *blockheight) +bool wallet_extract_owned_outputs(struct wallet *w, + const struct wally_tx *wtx, + bool is_coinbase, + const u32 *blockheight, + size_t **outputs) { - int num_utxos = 0; + bool matched = false; for (size_t i = 0; i < wtx->num_outputs; i++) { const struct wally_tx_output *txout = &wtx->outputs[i]; @@ -3384,9 +3371,11 @@ int wallet_extract_owned_outputs(struct wallet *w, const struct wally_tx *wtx, continue; got_utxo(w, keyindex, addrtype, wtx, i, is_coinbase, blockheight, NULL); - num_utxos++; + matched = true; + if (outputs) + tal_arr_expand(outputs, i); } - return num_utxos; + return matched; } void wallet_htlc_save_in(struct wallet *wallet, @@ -5274,34 +5263,6 @@ u32 wallet_transaction_height(struct wallet *w, const struct bitcoin_txid *txid) return blockheight; } -struct txlocator *wallet_transaction_locate(const tal_t *ctx, struct wallet *w, - const struct bitcoin_txid *txid) -{ - struct txlocator *loc; - struct db_stmt *stmt; - - stmt = db_prepare_v2( - w->db, SQL("SELECT blockheight, txindex FROM transactions WHERE id=?")); - db_bind_txid(stmt, txid); - db_query_prepared(stmt); - - if (!db_step(stmt)) { - tal_free(stmt); - return NULL; - } - - if (db_col_is_null(stmt, "blockheight")) { - db_col_ignore(stmt, "txindex"); - loc = NULL; - } else { - loc = tal(ctx, struct txlocator); - loc->blkheight = db_col_int(stmt, "blockheight"); - loc->index = db_col_int(stmt, "txindex"); - } - tal_free(stmt); - return loc; -} - struct bitcoin_txid *wallet_transactions_by_height(const tal_t *ctx, struct wallet *w, const u32 blockheight) diff --git a/wallet/wallet.h b/wallet/wallet.h index dcfc38782033..589b48889997 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -801,10 +801,18 @@ u32 wallet_blocks_contig_minheight(struct wallet *w); /** * wallet_extract_owned_outputs - given a tx, extract all of our outputs + * @w: wallet + * @is_coinbase: true if this is output 0 (can't spend for 100 blocks) + * @blockheight: non-NULL blockheight if known. + * @outputs: if non-NULL, output numbers of owned outputs are appended to it. + * + * Returns true if at least one output was to one of our addresses. */ -int wallet_extract_owned_outputs(struct wallet *w, const struct wally_tx *tx, - bool is_coinbase, - const u32 *blockheight); +bool wallet_extract_owned_outputs(struct wallet *w, + const struct wally_tx *wtx, + bool is_coinbase, + const u32 *blockheight, + size_t **outputs); /** * wallet_htlc_save_in - store an htlc_in in the database @@ -1272,13 +1280,6 @@ struct bitcoin_tx *wallet_transaction_get(const tal_t *ctx, struct wallet *w, */ u32 wallet_transaction_height(struct wallet *w, const struct bitcoin_txid *txid); -/** - * Locate a transaction in the blockchain, returns NULL if the transaction is - * not tracked or is not yet confirmed. - */ -struct txlocator *wallet_transaction_locate(const tal_t *ctx, struct wallet *w, - const struct bitcoin_txid *txid); - /** * Get transaction IDs for transactions that we are tracking. */ diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c index 4ea6b3b009cd..700367cc6dd8 100644 --- a/wallet/walletrpc.c +++ b/wallet/walletrpc.c @@ -108,8 +108,6 @@ static struct command_result *param_newaddr(struct command *cmd, bool WARN_UNUSED_RESULT newaddr_inner(struct command *cmd, struct pubkey *pubkey, enum addrtype addrtype) { s64 keyidx; - u8 *b32script; - u8 *p2tr_script; bool use_bip86_base = (cmd->ld->bip86_base != NULL); /* Get new index - wallet_get_newindex now handles both BIP32 and BIP86 */ @@ -124,17 +122,6 @@ bool WARN_UNUSED_RESULT newaddr_inner(struct command *cmd, struct pubkey *pubkey /* Legacy wallet - use BIP32 derivation */ bip32_pubkey(cmd->ld, pubkey, keyidx); } - - /* Generate scripts from pubkey (same logic for both wallet types) */ - b32script = scriptpubkey_p2wpkh(tmpctx, pubkey); - p2tr_script = scriptpubkey_p2tr(tmpctx, pubkey); - - /* Add scripts to filter based on requested address type */ - if (addrtype & ADDR_BECH32) - txfilter_add_scriptpubkey(cmd->ld->owned_txfilter, b32script); - if (addrtype & ADDR_P2TR) - txfilter_add_scriptpubkey(cmd->ld->owned_txfilter, p2tr_script); - return true; } @@ -226,7 +213,7 @@ static struct command_result *json_listaddresses(struct command *cmd, NULL)) return command_param_failed(); - addr = encode_scriptpubkey_to_addr(tmpctx, chainparams, scriptpubkey); + addr = encode_scriptpubkey_to_addr(tmpctx, chainparams, scriptpubkey, tal_bytelen(scriptpubkey)); if (*liststart == 0) { return command_fail(cmd, JSONRPC2_INVALID_PARAMS, @@ -391,7 +378,8 @@ static void json_add_utxo(struct json_stream *response, json_add_hex_talarr(response, "scriptpubkey", utxo->scriptPubkey); out = encode_scriptpubkey_to_addr(tmpctx, chainparams, - utxo->scriptPubkey); + utxo->scriptPubkey, + tal_bytelen(utxo->scriptPubkey)); if (!out) log_broken(wallet->log, "Could not encode utxo %s%s!", @@ -1027,7 +1015,7 @@ static void sendpsbt_done(struct bitcoind *bitcoind UNUSED, wally_txid(sending->wtx, &txid); /* Extract the change output and add it to the DB */ - if (wallet_extract_owned_outputs(ld->wallet, sending->wtx, false, NULL) == 0) { + if (!wallet_extract_owned_outputs(ld->wallet, sending->wtx, false, NULL, NULL)) { /* 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); @@ -1279,7 +1267,8 @@ json_signmessagewithkey(struct command *cmd, const char *buffer, /* FIXME: we already had the address from the input */ char *addr; - addr = encode_scriptpubkey_to_addr(tmpctx, chainparams, scriptpubkey); + addr = encode_scriptpubkey_to_addr(tmpctx, chainparams, scriptpubkey, + script_len); if (!is_p2wpkh(scriptpubkey, script_len, NULL)) { /* FIXME add support for BIP 322 */