diff --git a/common/base64.c b/common/base64.c index f7e7f7ef5a7b..75db1a4698f3 100644 --- a/common/base64.c +++ b/common/base64.c @@ -1,15 +1,16 @@ +#include "config.h" +#include +#include #include -#include -/* Decode/encode from/to base64, base64 helper functions. - * We import base64 from libsodium to generate tor V3 ED25519-V3 onions from blobs -*/ - -char *b64_encode(const tal_t *ctx, const u8 *data, size_t len) +/* Decode/encode from/to base64, base64 helper functions.*/ +char *b64_encode(const tal_t *ctx, const void *data, size_t len) { - char *str = tal_arr(ctx, char, sodium_base64_encoded_len(len, sodium_base64_VARIANT_ORIGINAL) + 1); + size_t slen = base64_encoded_length(len), enclen; + char *str = tal_arr(ctx, char, slen + 1); + enclen = base64_encode(str, slen, data, len); + assert(enclen == slen); - str = sodium_bin2base64(str, tal_count(str), data, - len, sodium_base64_VARIANT_ORIGINAL); + str[enclen] = '\0'; return str; } diff --git a/common/base64.h b/common/base64.h index dee4510cd37c..f963541dba17 100644 --- a/common/base64.h +++ b/common/base64.h @@ -4,6 +4,6 @@ #include #include -char *b64_encode(const tal_t *ctx, const u8 *data, size_t len); +char *b64_encode(const tal_t *ctx, const void *data, size_t len); #endif /* LIGHTNING_COMMON_BASE64_H */ diff --git a/common/json_helpers.c b/common/json_helpers.c index 65308d7ba37d..44efdffbd44c 100644 --- a/common/json_helpers.c +++ b/common/json_helpers.c @@ -273,7 +273,7 @@ void json_add_address(struct json_stream *response, const char *fieldname, json_add_string(response, "type", "ipv6"); json_add_string(response, "address", addrstr); json_add_num(response, "port", addr->port); - } else if (addr->type == ADDR_TYPE_TOR_V2) { + } else if (addr->type == ADDR_TYPE_TOR_V2_REMOVED) { json_add_string(response, "type", "torv2"); json_add_string(response, "address", fmt_wireaddr_without_port(tmpctx, addr)); json_add_num(response, "port", addr->port); diff --git a/common/test/run-base64.c b/common/test/run-base64.c new file mode 100644 index 000000000000..899e83b6b48e --- /dev/null +++ b/common/test/run-base64.c @@ -0,0 +1,134 @@ +#include "../base64.c" +#include +#include +#include +#include +#include +#include +#include +#include + +/* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_is_main */ +bool amount_asset_is_main(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); } +/* Generated stub for amount_asset_to_sat */ +struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_to_sat called!\n"); abort(); } +/* Generated stub for amount_sat */ +struct amount_sat amount_sat(u64 satoshis UNNEEDED) +{ fprintf(stderr, "amount_sat called!\n"); abort(); } +/* Generated stub for amount_sat_add */ + bool amount_sat_add(struct amount_sat *val UNNEEDED, + struct amount_sat a UNNEEDED, + struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_add called!\n"); abort(); } +/* Generated stub for amount_sat_eq */ +bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); } +/* Generated stub for amount_sat_greater_eq */ +bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_greater_eq called!\n"); abort(); } +/* Generated stub for amount_sat_sub */ + bool amount_sat_sub(struct amount_sat *val UNNEEDED, + struct amount_sat a UNNEEDED, + struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_sat_to_asset */ +struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u8 *asset UNNEEDED) +{ fprintf(stderr, "amount_sat_to_asset called!\n"); abort(); } +/* 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 fromwire */ +const u8 *fromwire(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, void *copy UNNEEDED, size_t n UNNEEDED) +{ fprintf(stderr, "fromwire called!\n"); abort(); } +/* Generated stub for fromwire_amount_sat */ +struct amount_sat fromwire_amount_sat(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_amount_sat called!\n"); abort(); } +/* Generated stub for fromwire_bool */ +bool fromwire_bool(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_bool called!\n"); abort(); } +/* Generated stub for fromwire_fail */ +void *fromwire_fail(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_fail called!\n"); abort(); } +/* Generated stub for fromwire_secp256k1_ecdsa_signature */ +void fromwire_secp256k1_ecdsa_signature(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, + secp256k1_ecdsa_signature *signature UNNEEDED) +{ fprintf(stderr, "fromwire_secp256k1_ecdsa_signature called!\n"); abort(); } +/* Generated stub for fromwire_sha256 */ +void fromwire_sha256(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct sha256 *sha256 UNNEEDED) +{ fprintf(stderr, "fromwire_sha256 called!\n"); abort(); } +/* Generated stub for fromwire_tal_arrn */ +u8 *fromwire_tal_arrn(const tal_t *ctx UNNEEDED, + const u8 **cursor UNNEEDED, size_t *max UNNEEDED, size_t num UNNEEDED) +{ fprintf(stderr, "fromwire_tal_arrn called!\n"); abort(); } +/* Generated stub for fromwire_u16 */ +u16 fromwire_u16(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_u16 called!\n"); abort(); } +/* Generated stub for fromwire_u32 */ +u32 fromwire_u32(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_u32 called!\n"); abort(); } +/* Generated stub for fromwire_u64 */ +u64 fromwire_u64(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_u64 called!\n"); abort(); } +/* Generated stub for fromwire_u8 */ +u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_u8 called!\n"); abort(); } +/* 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 towire */ +void towire(u8 **pptr UNNEEDED, const void *data UNNEEDED, size_t len UNNEEDED) +{ fprintf(stderr, "towire called!\n"); abort(); } +/* Generated stub for towire_amount_sat */ +void towire_amount_sat(u8 **pptr UNNEEDED, const struct amount_sat sat UNNEEDED) +{ fprintf(stderr, "towire_amount_sat called!\n"); abort(); } +/* Generated stub for towire_bool */ +void towire_bool(u8 **pptr UNNEEDED, bool v UNNEEDED) +{ fprintf(stderr, "towire_bool called!\n"); abort(); } +/* Generated stub for towire_secp256k1_ecdsa_signature */ +void towire_secp256k1_ecdsa_signature(u8 **pptr UNNEEDED, + const secp256k1_ecdsa_signature *signature UNNEEDED) +{ fprintf(stderr, "towire_secp256k1_ecdsa_signature called!\n"); abort(); } +/* Generated stub for towire_sha256 */ +void towire_sha256(u8 **pptr UNNEEDED, const struct sha256 *sha256 UNNEEDED) +{ fprintf(stderr, "towire_sha256 called!\n"); abort(); } +/* Generated stub for towire_u16 */ +void towire_u16(u8 **pptr UNNEEDED, u16 v UNNEEDED) +{ fprintf(stderr, "towire_u16 called!\n"); abort(); } +/* Generated stub for towire_u32 */ +void towire_u32(u8 **pptr UNNEEDED, u32 v UNNEEDED) +{ fprintf(stderr, "towire_u32 called!\n"); abort(); } +/* Generated stub for towire_u64 */ +void towire_u64(u8 **pptr UNNEEDED, u64 v UNNEEDED) +{ fprintf(stderr, "towire_u64 called!\n"); abort(); } +/* Generated stub for towire_u8 */ +void towire_u8(u8 **pptr UNNEEDED, u8 v UNNEEDED) +{ fprintf(stderr, "towire_u8 called!\n"); abort(); } +/* Generated stub for towire_u8_array */ +void towire_u8_array(u8 **pptr UNNEEDED, const u8 *arr UNNEEDED, size_t num UNNEEDED) +{ fprintf(stderr, "towire_u8_array called!\n"); abort(); } +/* AUTOGENERATED MOCKS END */ + +int main(int argc, char *argv[]) +{ + u8 data[1024]; + + common_setup(argv[0]); + + for (size_t i = 0; i < sizeof(data); i++) { + char *sodium, *ours, *ccan; + memset(data, i, i); + + ours = b64_encode(tmpctx, data, i); + ccan = tal_arr(tmpctx, char, base64_encoded_length(i) + 1); + ccan[base64_encode(ccan, base64_encoded_length(i), (char *)data, i)] = '\0'; + sodium = tal_arr(tmpctx, char, sodium_base64_encoded_len(i, sodium_base64_VARIANT_ORIGINAL) + 1); + sodium = sodium_bin2base64(sodium, tal_count(sodium), data, i, sodium_base64_VARIANT_ORIGINAL); + + assert(streq(ccan, sodium)); + assert(streq(ccan, ours)); + } + common_shutdown(); +} diff --git a/common/test/run-ip_port_parsing.c b/common/test/run-ip_port_parsing.c index ad9f73d77b04..68b1bdc55d42 100644 --- a/common/test/run-ip_port_parsing.c +++ b/common/test/run-ip_port_parsing.c @@ -182,19 +182,17 @@ int main(int argc, char *argv[]) assert(parse_wireaddr("4ruvswpqec5i2gogopxl4vm5bruzknbvbylov2awbo4rxiq4cimdldad.onion", &addr, 1, false, NULL)); assert(addr.port == 1); - assert(parse_wireaddr("odpzvneidqdf5hdq.onion:49150", &addr, 1, false, NULL)); - assert(addr.port == 49150); - - assert(parse_wireaddr("odpzvneidqdf5hdq.onion", &addr, 1, false, NULL)); - assert(addr.port == 1); + /* We don't accept torv2 any more */ + assert(!parse_wireaddr("odpzvneidqdf5hdq.onion:49150", &addr, 1, false, NULL)); + assert(!parse_wireaddr("odpzvneidqdf5hdq.onion", &addr, 1, false, NULL)); - // Don't accept legacy hidden services with deprecated APIs on + /* Neither allow_deprecated = true nor false will parse it now */ + assert(!parse_wireaddr_internal("odpzvneidqdf5hdq.onion", &addr_int, 1, + false, false, false, false, NULL)); assert(!parse_wireaddr_internal("odpzvneidqdf5hdq.onion", &addr_int, 1, - false, false, false, /* allow_deprecated = */ false, NULL)); - assert(parse_wireaddr_internal("odpzvneidqdf5hdq.onion", &addr_int, 1, - false, false, false, /* allow_deprecated = */ true, NULL)); + false, false, false, true, NULL)); - assert(tal_count(wireaddr_from_hostname(tmpctx, "odpzvneidqdf5hdq.onion", 1, NULL, NULL, NULL)) > 0); + assert(wireaddr_from_hostname(tmpctx, "odpzvneidqdf5hdq.onion", 1, NULL, NULL, NULL) == NULL); assert(wireaddr_from_hostname(tmpctx, "aaa.onion", 1, NULL, NULL, NULL) == NULL); common_shutdown(); diff --git a/common/test/run-wireaddr.c b/common/test/run-wireaddr.c index 3602ae2c7057..c6e19d8b752b 100644 --- a/common/test/run-wireaddr.c +++ b/common/test/run-wireaddr.c @@ -112,39 +112,6 @@ void towire_u8_array(u8 **pptr UNNEEDED, const u8 *arr UNNEEDED, size_t num UNNE { fprintf(stderr, "towire_u8_array called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ -static bool wireaddr_internal_eq(const struct wireaddr_internal *a, - const struct wireaddr_internal *b, - bool cmp_torservice_blob) -{ - if (a->itype != b->itype) - return false; - - switch (a->itype) { - case ADDR_INTERNAL_SOCKNAME: - return streq(a->u.sockname, b->u.sockname); - case ADDR_INTERNAL_ALLPROTO: - return a->u.port == b->u.port; - case ADDR_INTERNAL_AUTOTOR: - case ADDR_INTERNAL_STATICTOR: - if (!wireaddr_eq(&a->u.torservice.address, - &b->u.torservice.address)) - return false; - if (a->u.torservice.port != b->u.torservice.port) - return false; - if (!cmp_torservice_blob) - return true; - return memeq(a->u.torservice.blob, sizeof(a->u.torservice.blob), - b->u.torservice.blob, sizeof(b->u.torservice.blob)); - case ADDR_INTERNAL_FORPROXY: - if (!streq(a->u.unresolved.name, b->u.unresolved.name)) - return false; - return a->u.unresolved.port == b->u.unresolved.port; - case ADDR_INTERNAL_WIREADDR: - return wireaddr_eq(&a->u.wireaddr, &b->u.wireaddr); - } - abort(); -} - int main(int argc, char *argv[]) { const char *err; @@ -155,87 +122,98 @@ int main(int argc, char *argv[]) assert(parse_wireaddr_internal("127.0.0.1", &addr, DEFAULT_PORT, false, false, false, false, &err)); expect->itype = ADDR_INTERNAL_WIREADDR; assert(parse_wireaddr("127.0.0.1:9735", &expect->u.wireaddr, 0, NULL, &err)); - assert(wireaddr_internal_eq(&addr, expect, false)); + assert(wireaddr_internal_eq(&addr, expect)); /* IPv4 address with port. */ assert(parse_wireaddr_internal("127.0.0.1:1", &addr, DEFAULT_PORT, false, false, false, false, &err)); expect->itype = ADDR_INTERNAL_WIREADDR; assert(parse_wireaddr("127.0.0.1:1", &expect->u.wireaddr, 0, NULL, &err)); - assert(wireaddr_internal_eq(&addr, expect, false)); + assert(wireaddr_internal_eq(&addr, expect)); /* Simple IPv6 address. */ assert(parse_wireaddr_internal("::1", &addr, DEFAULT_PORT, false, false, false, false, &err)); expect->itype = ADDR_INTERNAL_WIREADDR; assert(parse_wireaddr("::1", &expect->u.wireaddr, DEFAULT_PORT, NULL, &err)); - assert(wireaddr_internal_eq(&addr, expect, false)); + assert(wireaddr_internal_eq(&addr, expect)); /* IPv6 address with port. */ assert(parse_wireaddr_internal("[::1]:1", &addr, DEFAULT_PORT, false, false, false, false, &err)); expect->itype = ADDR_INTERNAL_WIREADDR; assert(parse_wireaddr("::1", &expect->u.wireaddr, 1, NULL, &err)); - assert(wireaddr_internal_eq(&addr, expect, false)); + assert(wireaddr_internal_eq(&addr, expect)); /* autotor address */ assert(parse_wireaddr_internal("autotor:127.0.0.1", &addr, DEFAULT_PORT, false, false, false, false, &err)); expect->itype = ADDR_INTERNAL_AUTOTOR; expect->u.torservice.port = DEFAULT_PORT; assert(parse_wireaddr("127.0.0.1", &expect->u.torservice.address, 9051, NULL, &err)); - assert(wireaddr_internal_eq(&addr, expect, false)); + assert(wireaddr_internal_eq(&addr, expect)); /* autotor address with port */ assert(parse_wireaddr_internal("autotor:127.0.0.1:9055", &addr, DEFAULT_PORT, false, false, false, false, &err)); expect->itype = ADDR_INTERNAL_AUTOTOR; expect->u.torservice.port = DEFAULT_PORT; assert(parse_wireaddr("127.0.0.1", &expect->u.torservice.address, 9055, NULL, &err)); - assert(wireaddr_internal_eq(&addr, expect, false)); + assert(wireaddr_internal_eq(&addr, expect)); /* autotor address with torport */ assert(parse_wireaddr_internal("autotor:127.0.0.1/torport=9055", &addr, DEFAULT_PORT, false, false, false, false, &err)); expect->itype = ADDR_INTERNAL_AUTOTOR; expect->u.torservice.port = 9055; assert(parse_wireaddr("127.0.0.1", &expect->u.torservice.address, 9051, NULL, &err)); - assert(wireaddr_internal_eq(&addr, expect, false)); + assert(wireaddr_internal_eq(&addr, expect)); /* autotor address with port and torport */ assert(parse_wireaddr_internal("autotor:127.0.0.1:9055/torport=10055", &addr, DEFAULT_PORT, false, false, false, false, &err)); expect->itype = ADDR_INTERNAL_AUTOTOR; expect->u.torservice.port = 10055; assert(parse_wireaddr("127.0.0.1", &expect->u.torservice.address, 9055, NULL, &err)); - assert(wireaddr_internal_eq(&addr, expect, false)); + assert(wireaddr_internal_eq(&addr, expect)); /* statictor address */ assert(parse_wireaddr_internal("statictor:127.0.0.1", &addr, DEFAULT_PORT, false, false, false, false, &err)); expect->itype = ADDR_INTERNAL_STATICTOR; expect->u.torservice.port = DEFAULT_PORT; + memset(expect->u.torservice.blob, 0, sizeof(expect->u.torservice.blob)); + strcpy((char *)expect->u.torservice.blob, STATIC_TOR_MAGIC_STRING); assert(parse_wireaddr("127.0.0.1", &expect->u.torservice.address, 9051, NULL, &err)); - assert(wireaddr_internal_eq(&addr, expect, false)); + assert(wireaddr_internal_eq(&addr, expect)); /* statictor address with port */ assert(parse_wireaddr_internal("statictor:127.0.0.1:9055", &addr, DEFAULT_PORT, false, false, false, false, &err)); expect->itype = ADDR_INTERNAL_STATICTOR; expect->u.torservice.port = DEFAULT_PORT; assert(parse_wireaddr("127.0.0.1", &expect->u.torservice.address, 9055, NULL, &err)); - assert(wireaddr_internal_eq(&addr, expect, false)); + assert(wireaddr_internal_eq(&addr, expect)); /* statictor address with torport */ assert(parse_wireaddr_internal("statictor:127.0.0.1/torport=9055", &addr, DEFAULT_PORT, false, false, false, false, &err)); expect->itype = ADDR_INTERNAL_STATICTOR; expect->u.torservice.port = 9055; assert(parse_wireaddr("127.0.0.1", &expect->u.torservice.address, 9051, NULL, &err)); - assert(wireaddr_internal_eq(&addr, expect, false)); + assert(wireaddr_internal_eq(&addr, expect)); /* statictor address with port and torport */ assert(parse_wireaddr_internal("statictor:127.0.0.1:9055/torport=10055", &addr, DEFAULT_PORT, false, false, false, false, &err)); expect->itype = ADDR_INTERNAL_STATICTOR; expect->u.torservice.port = 10055; assert(parse_wireaddr("127.0.0.1", &expect->u.torservice.address, 9055, NULL, &err)); - assert(wireaddr_internal_eq(&addr, expect, false)); + assert(wireaddr_internal_eq(&addr, expect)); + + /* statictor address with port and torport and torblob */ + assert(parse_wireaddr_internal("statictor:127.0.0.1:9055/torport=10055/torblob=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", &addr, DEFAULT_PORT, false, false, false, false, &err)); + expect->itype = ADDR_INTERNAL_STATICTOR; + expect->u.torservice.port = 10055; + /* This is actually nul terminated */ + memset(expect->u.torservice.blob, 'x', sizeof(expect->u.torservice.blob)-1); + assert(parse_wireaddr("127.0.0.1", &expect->u.torservice.address, 9055, NULL, &err)); + assert(wireaddr_internal_eq(&addr, expect)); /* local socket path */ assert(parse_wireaddr_internal("/tmp/foo.sock", &addr, DEFAULT_PORT, false, false, false, false, &err)); expect->itype = ADDR_INTERNAL_SOCKNAME; strcpy(expect->u.sockname, "/tmp/foo.sock"); - assert(wireaddr_internal_eq(&addr, expect, false)); + assert(wireaddr_internal_eq(&addr, expect)); /* Unresolved */ assert(!parse_wireaddr_internal("ozlabs.org", &addr, DEFAULT_PORT, false, false, false, false, &err)); @@ -244,7 +222,7 @@ int main(int argc, char *argv[]) expect->itype = ADDR_INTERNAL_FORPROXY; strcpy(expect->u.unresolved.name, "ozlabs.org"); expect->u.unresolved.port = DEFAULT_PORT; - assert(wireaddr_internal_eq(&addr, expect, false)); + assert(wireaddr_internal_eq(&addr, expect)); /* Unresolved with port */ assert(!parse_wireaddr_internal("ozlabs.org:1234", &addr, DEFAULT_PORT, false, false, false, false, &err)); @@ -253,7 +231,7 @@ int main(int argc, char *argv[]) expect->itype = ADDR_INTERNAL_FORPROXY; strcpy(expect->u.unresolved.name, "ozlabs.org"); expect->u.unresolved.port = 1234; - assert(wireaddr_internal_eq(&addr, expect, false)); + assert(wireaddr_internal_eq(&addr, expect)); tal_free(expect); common_shutdown(); diff --git a/common/wireaddr.c b/common/wireaddr.c index 6851df8f80eb..6638f2e6e72d 100644 --- a/common/wireaddr.c +++ b/common/wireaddr.c @@ -31,7 +31,7 @@ bool fromwire_wireaddr(const u8 **cursor, size_t *max, struct wireaddr *addr) case ADDR_TYPE_IPV6: addr->addrlen = 16; break; - case ADDR_TYPE_TOR_V2: + case ADDR_TYPE_TOR_V2_REMOVED: addr->addrlen = TOR_V2_ADDRLEN; break; case ADDR_TYPE_TOR_V3: @@ -209,7 +209,7 @@ bool wireaddr_is_wildcard(const struct wireaddr *addr) case ADDR_TYPE_IPV6: case ADDR_TYPE_IPV4: return memeqzero(addr->addr, addr->addrlen); - case ADDR_TYPE_TOR_V2: + case ADDR_TYPE_TOR_V2_REMOVED: case ADDR_TYPE_TOR_V3: case ADDR_TYPE_WEBSOCKET: return false; @@ -255,7 +255,7 @@ char *fmt_wireaddr_without_port(const tal_t * ctx, const struct wireaddr *a) if (!inet_ntop(AF_INET6, a->addr, addrstr, INET6_ADDRSTRLEN)) return "Unprintable-ipv6-address"; return tal_fmt(ctx, "[%s]", addrstr); - case ADDR_TYPE_TOR_V2: + case ADDR_TYPE_TOR_V2_REMOVED: case ADDR_TYPE_TOR_V3: return tal_fmt(ctx, "%s.onion", b32_encode(tmpctx, a->addr, a->addrlen)); @@ -345,9 +345,7 @@ wireaddr_from_hostname(const tal_t *ctx, u8 *dec = b32_decode(tmpctx, hostname, strlen(hostname) - strlen(".onion")); tal_resize(&addrs, 1); - if (tal_count(dec) == TOR_V2_ADDRLEN) { - addrs[0].type = ADDR_TYPE_TOR_V2; - } else if (tal_count(dec) == TOR_V3_ADDRLEN) { + if (tal_count(dec) == TOR_V3_ADDRLEN) { addrs[0].type = ADDR_TYPE_TOR_V3; } else { if (err_msg) @@ -456,6 +454,37 @@ bool parse_wireaddr(const char *arg, struct wireaddr *addr, u16 defport, return res; } +bool wireaddr_internal_eq(const struct wireaddr_internal *a, + const struct wireaddr_internal *b) +{ + if (a->itype != b->itype) + return false; + + switch (a->itype) { + case ADDR_INTERNAL_SOCKNAME: + return streq(a->u.sockname, b->u.sockname); + case ADDR_INTERNAL_ALLPROTO: + return a->u.port == b->u.port; + case ADDR_INTERNAL_STATICTOR: + if (!memeq(a->u.torservice.blob, sizeof(a->u.torservice.blob), + b->u.torservice.blob, sizeof(b->u.torservice.blob))) + return false; + /* fall thru */ + case ADDR_INTERNAL_AUTOTOR: + if (!wireaddr_eq(&a->u.torservice.address, + &b->u.torservice.address)) + return false; + return a->u.torservice.port == b->u.torservice.port; + case ADDR_INTERNAL_FORPROXY: + if (!streq(a->u.unresolved.name, b->u.unresolved.name)) + return false; + return a->u.unresolved.port == b->u.unresolved.port; + case ADDR_INTERNAL_WIREADDR: + return wireaddr_eq(&a->u.wireaddr, &b->u.wireaddr); + } + abort(); +} + bool parse_wireaddr_internal(const char *arg, struct wireaddr_internal *addr, u16 port, bool wildcard_ok, bool dns_ok, bool unresolved_ok, bool allow_deprecated, @@ -491,21 +520,18 @@ bool parse_wireaddr_internal(const char *arg, struct wireaddr_internal *addr, char **parts = tal_strsplit(tmpctx, arg, "/", STR_EMPTY_OK); for (size_t i = 1; i < tal_count(parts)-1; i++) { - if (tal_strreg(tmpctx, parts[i], "torport")) { + if (strstarts(parts[i], "torport=")) { char *endp = NULL; - char **parts_2 = tal_strsplit(tmpctx, parts[i], "=", STR_EMPTY_OK); - if (tal_count(parts_2) == 3) { - addr->u.torservice.port = strtol((const char *)parts_2[1], &endp, 10); - if (addr->u.torservice.port <= 0 || *endp != '\0') { - if (err_msg) - *err_msg = "Bad :torport: number"; - return false; - } - } else { + addr->u.torservice.port = strtol(parts[i]+strlen("torport="), &endp, 10); + if (addr->u.torservice.port <= 0 || *endp != '\0') { if (err_msg) - *err_msg = "Bad :torport: format"; + *err_msg = "Bad :torport: number"; return false; } + } else { + if (err_msg) + *err_msg = tal_fmt(tmpctx, "unknown tor arg %s", parts[i]); + return false; } } @@ -522,47 +548,38 @@ bool parse_wireaddr_internal(const char *arg, struct wireaddr_internal *addr, bool use_magic_blob = true; addr->itype = ADDR_INTERNAL_STATICTOR; addr->u.torservice.port = DEFAULT_PORT; - memset(&(addr->u.torservice.blob[0]), 0, sizeof(addr->u.torservice.blob)); + memset(addr->u.torservice.blob, 0, sizeof(addr->u.torservice.blob)); /* Format is separated by slash. */ char **parts = tal_strsplit(tmpctx, arg, "/", STR_EMPTY_OK); for (size_t i = 1; i < tal_count(parts)-1; i++) { - if (tal_strreg(tmpctx, parts[i], "torport")) { + if (strstarts(parts[i], "torport=")) { char *endp = NULL; - char **parts_eq = tal_strsplit(tmpctx, parts[i], "=", STR_EMPTY_OK); - if (tal_count(parts_eq) == 3) { - addr->u.torservice.port = strtol((const char *)parts_eq[1], &endp, 10); - if (addr->u.torservice.port <= 0 || *endp != '\0') { - if (err_msg) - *err_msg = "Bad :torport: number"; - return false; - } - } else { + addr->u.torservice.port = strtol(parts[i]+strlen("torport="), &endp, 10); + if (addr->u.torservice.port <= 0 || *endp != '\0') { if (err_msg) - *err_msg = "Bad :torport: format"; + *err_msg = "Bad :torport: number"; return false; } - } - if (tal_strreg(tmpctx, parts[i], "torblob")) { - char **parts_eq = tal_strsplit(tmpctx, parts[i], "=", STR_EMPTY_OK); - if (tal_count(parts_eq) == 3) { - if (strlen((char *)parts_eq[1]) == 0) { - if (err_msg) - *err_msg = "Blob too short"; - return false; - } - strncpy((char *)&(addr->u.torservice.blob[0]), - (const char *)parts_eq[1], TOR_V3_BLOBLEN); - use_magic_blob = false; + } else if (strstarts(parts[i], "torblob=")) { + const char *blobdata = parts[i] + strlen("torblob="); + if (strlen(blobdata) > TOR_V3_BLOBLEN) { + if (err_msg) + *err_msg = "torblob too long"; + return false; } + strcpy(addr->u.torservice.blob, blobdata); + use_magic_blob = false; + } else { + if (err_msg) + *err_msg = tal_fmt(tmpctx, "unknown tor arg %s", parts[i]); + return false; } } if (use_magic_blob) { /* when statictor called just with the service address and or port generate the unique onion */ - strncpy((char *)&(addr->u.torservice.blob[0]), - tal_fmt(tmpctx, STATIC_TOR_MAGIC_STRING), - strlen(STATIC_TOR_MAGIC_STRING)); + strcpy(addr->u.torservice.blob, STATIC_TOR_MAGIC_STRING); } service_addr = tal_fmt(tmpctx, "%s", parts[0] + strlen("statictor:")); @@ -591,9 +608,9 @@ bool parse_wireaddr_internal(const char *arg, struct wireaddr_internal *addr, addr->itype = ADDR_INTERNAL_WIREADDR; if (parse_wireaddr(arg, &addr->u.wireaddr, port, dns_ok ? NULL : &needed_dns, err_msg)) { - if (!allow_deprecated && addr->u.wireaddr.type == ADDR_TYPE_TOR_V2) { + if (addr->u.wireaddr.type == ADDR_TYPE_TOR_V2_REMOVED) { if (err_msg) - *err_msg = "v2 Tor onion services are deprecated"; + *err_msg = "v2 Tor onion services not supported"; return false; } @@ -695,7 +712,7 @@ struct addrinfo *wireaddr_to_addrinfo(const tal_t *ctx, ai->ai_addrlen = sizeof(*sin6); ai->ai_addr = (struct sockaddr *)sin6; return ai; - case ADDR_TYPE_TOR_V2: + case ADDR_TYPE_TOR_V2_REMOVED: case ADDR_TYPE_TOR_V3: case ADDR_TYPE_WEBSOCKET: break; @@ -750,7 +767,7 @@ bool all_tor_addresses(const struct wireaddr_internal *wireaddr) case ADDR_TYPE_IPV4: case ADDR_TYPE_IPV6: return false; - case ADDR_TYPE_TOR_V2: + case ADDR_TYPE_TOR_V2_REMOVED: case ADDR_TYPE_TOR_V3: case ADDR_TYPE_WEBSOCKET: continue; diff --git a/common/wireaddr.h b/common/wireaddr.h index d7d894d23ca9..3f9cddc6249d 100644 --- a/common/wireaddr.h +++ b/common/wireaddr.h @@ -50,7 +50,7 @@ struct sockaddr_un; enum wire_addr_type { ADDR_TYPE_IPV4 = 1, ADDR_TYPE_IPV6 = 2, - ADDR_TYPE_TOR_V2 = 3, + ADDR_TYPE_TOR_V2_REMOVED = 3, ADDR_TYPE_TOR_V3 = 4, ADDR_TYPE_WEBSOCKET = 6, }; @@ -134,8 +134,8 @@ struct wireaddr_internal { struct wireaddr address; /* Tor port to use */ u16 port; - /* Blob to use to create tor service */ - u8 blob[TOR_V3_BLOBLEN + 1]; + /* Nul-terminated blob to use to create tor service */ + char blob[TOR_V3_BLOBLEN + 1]; } torservice; /* ADDR_INTERNAL_FORPROXY */ struct unresolved { @@ -146,6 +146,9 @@ struct wireaddr_internal { char sockname[sizeof(((struct sockaddr_un *)0)->sun_path)]; } u; }; + +bool wireaddr_internal_eq(const struct wireaddr_internal *a, + const struct wireaddr_internal *b); bool parse_wireaddr_internal(const char *arg, struct wireaddr_internal *addr, u16 port, bool wildcard_ok, bool dns_ok, bool unresolved_ok, bool allow_deprecated, diff --git a/connectd/connectd.c b/connectd/connectd.c index 68c767813aa4..1150f6ee7c5e 100644 --- a/connectd/connectd.c +++ b/connectd/connectd.c @@ -962,7 +962,9 @@ static void try_connect_one_addr(struct connecting *connect) break; case ADDR_INTERNAL_WIREADDR: switch (addr->u.wireaddr.type) { - case ADDR_TYPE_TOR_V2: + case ADDR_TYPE_TOR_V2_REMOVED: + af = -1; + break; case ADDR_TYPE_TOR_V3: use_proxy = true; break; @@ -1154,7 +1156,7 @@ static bool handle_wireaddr_listen(struct daemon *daemon, return false; /* Handle specially by callers. */ case ADDR_TYPE_WEBSOCKET: - case ADDR_TYPE_TOR_V2: + case ADDR_TYPE_TOR_V2_REMOVED: case ADDR_TYPE_TOR_V3: break; } @@ -1230,7 +1232,7 @@ static struct wireaddr_internal *setup_listeners(const tal_t *ctx, struct sockaddr_un addrun; int fd; struct wireaddr_internal *binding; - const u8 *blob = NULL; + const char *blob = NULL; struct secret random; struct pubkey pb; struct wireaddr *toraddr; @@ -1659,9 +1661,12 @@ static void add_gossip_addrs(struct wireaddr_internal **addrs, /* Wrap each one in a wireaddr_internal and add to addrs. */ for (size_t i = 0; i < tal_count(normal_addrs); i++) { + /* This is not supported, ignore. */ + if (normal_addrs[i].type == ADDR_TYPE_TOR_V2_REMOVED) + continue; + /* add TOR addresses in a second loop */ - if (normal_addrs[i].type == ADDR_TYPE_TOR_V2 || - normal_addrs[i].type == ADDR_TYPE_TOR_V3) + if (normal_addrs[i].type == ADDR_TYPE_TOR_V3) continue; if (wireaddr_int_equals_wireaddr(addrhint, &normal_addrs[i])) continue; @@ -1672,8 +1677,7 @@ static void add_gossip_addrs(struct wireaddr_internal **addrs, } /* so connectd prefers direct connections if possible. */ for (size_t i = 0; i < tal_count(normal_addrs); i++) { - if (normal_addrs[i].type != ADDR_TYPE_TOR_V2 && - normal_addrs[i].type != ADDR_TYPE_TOR_V3) + if (normal_addrs[i].type != ADDR_TYPE_TOR_V3) continue; if (wireaddr_int_equals_wireaddr(addrhint, &normal_addrs[i])) continue; diff --git a/connectd/netaddress.c b/connectd/netaddress.c index ce55cfa3939d..dff03e92d308 100644 --- a/connectd/netaddress.c +++ b/connectd/netaddress.c @@ -135,7 +135,7 @@ static bool IsRFC4843(const struct wireaddr *addr) static bool IsTor(const struct wireaddr *addr) { - return addr->type == ADDR_TYPE_TOR_V2 || addr->type == ADDR_TYPE_TOR_V3; + return addr->type == ADDR_TYPE_TOR_V3; } static bool IsLocal(const struct wireaddr *addr) @@ -256,7 +256,7 @@ bool guess_address(struct wireaddr *addr) memcpy(addr->addr, &sin6.sin6_addr, addr->addrlen); return ret; } - case ADDR_TYPE_TOR_V2: + case ADDR_TYPE_TOR_V2_REMOVED: case ADDR_TYPE_TOR_V3: case ADDR_TYPE_WEBSOCKET: status_broken("Cannot guess address type %u", addr->type); diff --git a/connectd/tor_autoservice.c b/connectd/tor_autoservice.c index 7ede2efb0f12..e471231f5324 100644 --- a/connectd/tor_autoservice.c +++ b/connectd/tor_autoservice.c @@ -146,7 +146,7 @@ static struct wireaddr *make_onion(const tal_t *ctx, static struct wireaddr *make_fixed_onion(const tal_t *ctx, struct rbuf *rbuf, - const struct wireaddr *local, const u8 *blob, u16 port) + const struct wireaddr *local, const char *blob, u16 port) { char *line; struct wireaddr *onion; @@ -323,7 +323,7 @@ struct wireaddr *tor_autoservice(const tal_t *ctx, struct wireaddr *tor_fixed_service(const tal_t *ctx, const struct wireaddr_internal *tor_serviceaddr, const char *tor_password, - const u8 *blob, + const char *blob, const struct wireaddr *bind, const u8 index) { diff --git a/connectd/tor_autoservice.h b/connectd/tor_autoservice.h index 6906a40be967..e88731ac9de4 100644 --- a/connectd/tor_autoservice.h +++ b/connectd/tor_autoservice.h @@ -15,7 +15,7 @@ struct wireaddr *tor_autoservice(const tal_t *ctx, struct wireaddr *tor_fixed_service(const tal_t *ctx, const struct wireaddr_internal *tor_serviceaddr, const char *tor_password, - const u8 *blob, + const char *blob, const struct wireaddr *bind, const u8 index); diff --git a/contrib/pyln-client/pyln/client/lightning.py b/contrib/pyln-client/pyln/client/lightning.py index 5ca8c2117624..f80006e91eaa 100644 --- a/contrib/pyln-client/pyln/client/lightning.py +++ b/contrib/pyln-client/pyln/client/lightning.py @@ -2,7 +2,6 @@ import logging import os import socket -import warnings from contextlib import contextmanager from decimal import Decimal from json import JSONEncoder @@ -757,34 +756,16 @@ def fundchannel_cancel(self, node_id): } return self.call("fundchannel_cancel", payload) - def _deprecated_fundchannel_complete(self, node_id, funding_txid, funding_txout): - warnings.warn("fundchannel_complete: funding_txid & funding_txout replaced by psbt: expect removal" - " in Mid-2021", - DeprecationWarning) - + def fundchannel_complete(self, node_id, psbt): + """ + Complete channel establishment with {id}, using {psbt}. + """ payload = { "id": node_id, - "txid": funding_txid, - "txout": funding_txout, + "psbt": psbt, } return self.call("fundchannel_complete", payload) - def fundchannel_complete(self, node_id, *args, **kwargs): - """ - Complete channel establishment with {id}, using {psbt}. - """ - if 'txid' in kwargs or len(args) == 2: - return self._deprecated_fundchannel_complete(node_id, *args, **kwargs) - - def _fundchannel_complete(node_id, psbt): - payload = { - "id": node_id, - "psbt": psbt, - } - return self.call("fundchannel_complete", payload) - - return _fundchannel_complete(node_id, *args, **kwargs) - def getinfo(self): """ Show information about this node. diff --git a/contrib/pyln-testing/pyln/testing/utils.py b/contrib/pyln-testing/pyln/testing/utils.py index f986e4ffcdae..dfc2fd666017 100644 --- a/contrib/pyln-testing/pyln/testing/utils.py +++ b/contrib/pyln-testing/pyln/testing/utils.py @@ -675,6 +675,7 @@ def __init__(self, node_id, lightning_dir, bitcoind, executor, valgrind, may_fai self.daemon.opts["dev-debugger"] = os.getenv("DEBUG_SUBD") if valgrind: self.daemon.env["LIGHTNINGD_DEV_NO_BACKTRACE"] = "1" + self.daemon.opts["dev-no-plugin-checksum"] = None else: # Under valgrind, scanning can access uninitialized mem. self.daemon.env["LIGHTNINGD_DEV_MEMLEAK"] = "1" diff --git a/devtools/gossipwith.c b/devtools/gossipwith.c index 2bd0a4778305..97287103d36b 100644 --- a/devtools/gossipwith.c +++ b/devtools/gossipwith.c @@ -317,7 +317,7 @@ int main(int argc, char *argv[]) case ADDR_INTERNAL_WIREADDR: switch (addr.u.wireaddr.type) { - case ADDR_TYPE_TOR_V2: + case ADDR_TYPE_TOR_V2_REMOVED: case ADDR_TYPE_TOR_V3: opt_usage_exit_fail("Don't support proxy use"); break; diff --git a/doc/TOR.md b/doc/TOR.md index e81bf3c94ca7..781af0cd70cf 100644 --- a/doc/TOR.md +++ b/doc/TOR.md @@ -2,10 +2,7 @@ To use any Tor features with c-lightning you must have Tor installed and running. -Note that [Tor v2 onion services are deprecated since mid-2020](https://blog.torproject.org/v2-deprecation-timeline) -and that C-lightning deprecated their support since mid-2021. - -You can check your installed Tor version with `tor --version` or `sudo tor --version` +Note that we only support Tor v3: you can check your installed Tor version with `tor --version` or `sudo tor --version` If Tor is not installed you can install it on Debian based Linux systems (Ubuntu, Debian, etc) with the following command: @@ -38,6 +35,7 @@ To provide the node with a .onion address you can: * create a **persistent** address with a hidden service. + ### Quick Start On Linux It is easy to create a single persistent Tor address and not announce a public IP. @@ -179,37 +177,73 @@ on those. ### Detailed Discussion -#### Creation of an auto service for non-persistent .onion addresses +#### Three Ways to Create .onion Addresses for C-lightning + +You have have Tor create an onion address for you, and tell +c-lightning to use that, or you can have c-lightning tell Tor to +create the same onion address every time it starts up, or you can have +c-lightning tell Tor to create a new onion address every time. -To provide the node a non-persistent .onion address it -is necessary to access the Tor auto service. These types of addresses change -each time the Tor service is restarted. +#### Tor-Created .onion Address -*NOTE:If the node is required to be reachable only by **persistent** .onion addresses, this -part can be skipped and it is necessary to set up a hidden service with the steps -outlined in the next section.* +Having Tor create an onion address lets you run other services (e.g. +a web server) at that same address, and you just tell that address to +c-lightning and it doesn't have to talk to the Tor server at all. -To create and use the auto service follow these steps: +Put the following in your `/etc/tor/torrc` file: + +``` +HiddenServiceDir /var/lib/tor/lightningd-service_v3/ +HiddenServiceVersion 3 +HiddenServicePort 1234 127.0.0.1:9735 +``` -Edit the Tor config file `/etc/tor/torrc` +The hidden lightning service will be reachable at port 1234 (global port) +of the .onion address, which will be created at the restart of the +Tor service. Both types of addresses can coexist on the same node. -You can configure the service authenticated by cookie or by password: +Save the file and restart the Tor service. In linux: + +`/etc/init.d/tor restart` or `sudo systemctl start tor` depending +on the configuration of your system. + +You will find the newly created address (myaddress.onion) with: +``` +sudo cat /var/lib/tor/lightningd-service_v3/hostname +``` + +Now you need to tell c-lightning to advertize that onion hostname and +port, by placing `announce-addr=myaddress.onion` in your lightning +config. + +#### Letting C-lightning Control Tor + +To have c-lightning control your Tor addresses, you have to tell Tor +to accept control commands from c-lightning, either by using a cookie, +or a password. ##### Service authenticated by cookie + +This tells Tor to create a cookie file each time: lightningd will have +to be in the same group as tor (e.g. debian-tor): you can look at +`/run/tor/control.authcookie` to check the group name. + Add the following lines in the `/etc/tor/torrc` file: -```` +``` ControlPort 9051 CookieAuthentication 1 CookieAuthFileGroupReadable 1 -```` +``` + +Save the file and restart the Tor service. ##### Service authenticated by password -Alternatively, you can set the authentication -to the service with a password by following these steps: +This tells Tor to allow password access: you also need to tell lightningd +what the password is. -1. Create a hash of your password with +Create a hash of your password with ``` tor --hash-password yourpassword ``` @@ -218,126 +252,62 @@ This returns a line like `16:533E3963988E038560A8C4EE6BBEE8DB106B38F9C8A7F81FE38D2A3B1F` -2. put these lines in the `/etc/tor/torrc` file: +Put these lines in the `/etc/tor/torrc` file: ``` ControlPort 9051 HashedControlPassword 16:533E3963988E038560A8C4EE6BBEE8DB106B38F9C8A7F81FE38D2A3B1F -```` - -Save the file and restart the Tor service. In linux: +``` -`/etc/init.d/tor restart` or `sudo systemctl start tor` depending -on the configuration of your system. +Save the file and restart the Tor service. -The auto service is used by adding `--addr=autotor:127.0.0.1:9051` if you -want the address to be public or `--bind-addr=autotor:127.0.0.1:9051` if you -don't want to publish it. +Put `tor-service-password=yourpassword` (not the hash) in your +lightning configuration file. -In the case where the auto service is authenticated through a password, it will -be necessary to add the option `--tor-service-password=yourpassword` (not the hash). +##### C-Lightning Creating Persistent Hidden Addresses -The created non-persistent .onion address will be shown by the `lightning-cli getinfo` -command. The other nodes will be able to `connect` to this .onion address through the -9735 port. +This is usually better than transient addresses, as nodes won't have +to wait for gossip propagation to find out your new address each time +you restart. -#### Creation of a hidden service for a persistent .onion address +Once you've configured access to Tor as described above, you need +to add *two* lines in your lightningd config file: -To have a persistent .onion address other nodes can connect to, it -is necessary to set up a [Tor Hidden Service]. +1. A local address which lightningd can tell Tor to connect to when + connections come in, e.g. `bind-addr=127.0.0.1:9735`. +2. After that, a `addr=statictor:127.0.0.1:9051` to tell + c-lightning to set up and announce a Tor onion address (and tell + Tor to send connections to our real address, above). -*NOTE: In the case where only non-persistent addresses are required, -you don't have to create the hidden service and you can skip this part.* +You can use `bind-addr` if you want to set up the onion address and +not announce it to the world for some reason. -##### Automatic persistent .onion address +You may add more `addr` lines if you want to advertize other +addresses. -It is possible to generate persistent .onion addresses automatically. +There is an older method, called "autotor" instead of "statictor" +which creates a different Tor address on each restart, which is +usually not very helpful; you need to use `lightning-cli getinfo` to +see what address it is currently using, and other peers need to wait +for fresh gossip messages if you announce it, before they can connect. -Add the following lines in the `/etc/tor/torrc` file -(you might already have done this if for example you connected Bitcoin -over Tor): - -```` -ControlPort 9051 -CookieAuthentication 1 -CookieAuthFileGroupReadable 1 -```` - -Then you can use `--addr=statictor:127.0.0.1:9051` instead of -`--announce-addr=.onionAddressV3`. -By default V3 onion addresses are generated. - -Note that you have to specify a `--bind-addr` first before using -`--addr=statictor:`. -Generally `--bind-addr=127.0.0.1:9735` should work fine. - -You can also have multiple persistent .onion addresses -by adding `/torblob=BLOB`, where `BLOB` is 32 to 64 ***random*** -bytes of text. -Note that this blob will be used to derive the secret key behind -the .onion address and you should keep the blob secret otherwise -anyone who steals it can spoof your .onion address and block -incoming data to your node via this .onion address. -You can then specify multiple `statictor:` options with different -`BLOB`s. - -However, even if you have multiple persistent addresses, you can -only announce up to one onion service (v3). -This is a limitation of the BOLT spec. -It is still possible for other nodes to contact you by those -other hidden services. - -Finally, the default external port number for the autogenerated -persistent .onion address will be 9735, but you can change this by -adding `/torport=9999` to change the external port for the .onion -address. - -##### Explicit Control - -If you want to create a version 3 address, you must also add `HiddenServiceVersion 3` so -the whole section will be: - -```` -HiddenServiceDir /var/lib/tor/lightningd-service_v3/ -HiddenServiceVersion 3 -HiddenServicePort 1234 127.0.0.1:9735 -```` - -The hidden lightning service will be reachable at port 1234 (global port) -of the .onion address, which will be created at the restart of the -Tor service. Both types of addresses can coexist on the same node. - -Save the file and restart the Tor service. In linux: - -`/etc/init.d/tor restart` or `sudo systemctl start tor` depending -on the configuration of your system. - -You will find the newly created address with: -``` -sudo cat /var/lib/tor/lightningd-service_v3/hostname -``` - -Now you are able to create: - -* Persistent version 3 hidden services. - -Let's see how to use them. ### What do we support | Case # | IP Number | Hidden service |Incoming / Outgoing Tor | | ------- | ------------- | ------------------------- |------------------------- | 1 | Public | NO | Outgoing | -| 6 | Public | v3 | Incoming [1] | -| 7 | Not Announced | v3 | Incoming | -| 8 | Public | NO | Outcoing socks5 . | +| 2 | Public | FIXED BY TOR | Incoming [1] | +| 3 | Public | FIXED BY C-LIGHTNING | Incoming [1] | +| 4 | Not Announced | FIXED BY TOR | Incoming [1] | +| 5 | Not Announced | FIXED BY C-LIGHTNING | Incoming [1] | + NOTE: 1. In all the "Incoming" use case, the node can also make "Outgoing" Tor -connections (connect to a .onion address) by adding the -`--proxy=127.0.0.1:9050` option. +connections (connect to a .onion address) by adding the `proxy=127.0.0.1:9050` option. -#### Case #1 c-lightning has a public IP address and no Tor hidden service address, but can connect to an onion address via a Tor socks 5 proxy. +#### Case #1: Public IP address and no Tor address, but can connect to Tor addresses Without a .onion address, the node won't be reachable through Tor by other nodes but it will always be able to `connect` to a Tor enabled node @@ -345,7 +315,7 @@ nodes but it will always be able to `connect` to a Tor enabled node service socks5 proxy. When the Tor service starts it creates a socks5 proxy which is by default at the address 127.0.0.1:9050. -If the node is started with the option `--proxy=127.0.0.1:9050` the node +If the node is started with the option `proxy=127.0.0.1:9050` the node will be always able to connect to nodes with .onion address through the socks5 proxy. @@ -353,18 +323,22 @@ proxy. Tor capabilities.** If you want to `connect` to nodes ONLY via the Tor proxy, you have to add the -`--always-use-proxy=true` option. +`always-use-proxy=true` option (though if you only advertize Tor addresses, +we also assume you want to always use the proxy). -You can announce your public IP address through the usual method: +You can announce your public IP address through the usual method: if +your node is in an internal network: ``` ---bind-addr=internalIPAddress:port --announce-addr=externalIpAddress +bind-addr=internalIPAddress:port +announce-addr=externalIpAddress ``` -if the node is into an internal network + +or if it has a public IP address: + ``` ---addr=externalIpAddress +addr=externalIpAddress ``` -if the node is not inside an internal network. TIP: If you are unsure which of the two is suitable for you, find your internal and external address and see if they match. @@ -377,142 +351,82 @@ and your internal IP Address with: `ip route get 1 | awk '{print $NF;exit}'` If they match you can use the `--addr` command line option. -#### Case #2 c-lightning has a public IP address and a fixed Tor hidden service address that is persistent, so that external users can connect to this node. +#### Case #2: Public IP address, and a fixed Tor address in torrc -To have your external IP address and your .onion address announced, you use the -``` ---bind-addr=yourInternalIPAddress:port --announce-addr=yourexternalIPAddress:port --announce-addr=your.onionAddress:port` -``` -or -``` ---bind-addr=yourInternalIPAddress:port --announce-addr=yourexternalIPAddress:port --addr=statictor:127.0.0.1:9051` -``` -options. +Other nodes can connect to you entirely over Tor, and the Tor address +doesn't change every time you restart. -If you are not inside an internal network you can use -``` ---addr=yourIPAddress:port --announce-addr=your.onionAddress:port -``` -or -``` ---addr=yourIPAddress:port --addr=statictor:127.0.0.1:9051 -``` - -your.onionAddress is the one created with the Tor hidden service ([see above](#creation-of-an-hidden-service-for-a-persistent-onion-address)). -The port is the one indicated as the hidden service port. If the hidden service creation -line is `HiddenServicePort 1234 127.0.0.1:9735` the .onion address will be reachable at -the 1234 port (the global port). +You simply tell c-lightning to advertize both addresses (you can use +`sudo cat /var/lib/tor/lightningd-service_v3/hostname` to get your +Tor-assigned onion address). -For `statictor` the `127.0.0.1` is your computer, and `9051` is the -Tor Control Port you set up in the `/etc/tor/torrc` file. +If you have an internal IP address: -It will be possible to connect to this node with: -``` -lightning-cli connect nodeID .onionAddress globalPort ``` -through Tor where .onion address is in the form `xxxxxxxxxxxxxxxxxxxxxxxxxx.onion`, Or +bind-addr=yourInternalIPAddress:port +announce-addr=yourexternalIPAddress:port +announce-addr=your.onionAddress:port ``` -lightning-cli connect nodeID yourexternalIPAddress Port -``` -through Clearnet. - -#### Case #3 c-lightning has a public IP address and a non-persisten Tor service address -In this case other nodes can connect to you via Clearnet or Tor. - -To announce your IP address to the network, you add: +Or an external address: ``` ---bind-addr=internalAddress:port --announce-addr=yourExternalIPAddress +addr=yourIPAddress:port +announce-addr=your.onionAddress:port ``` -or `--addr=yourExternalIPAddress`if you are NOT on an internal network. - -To get your non-persistent Tor address, add -`--addr=autotor:127.0.0.1:9051` if you want to announce it or -`--bind-addr=autotor:127.0.0.1:9051` if you don't want to announce it. -If the auto service is protected by password ([see above](#service-authenticated-by-password)) it is necessary to -specify it with the option `--tor-service-password=yourpassword` (not the hash). +#### Case #3: Public IP address, and a fixed Tor address set by C-lightning -You will obtain the generated non persisten .onion address by reading the results of the -`lightning-cli getinfo` command. Other nodes will be able to connect to the -.onion address through the 9735 port. +Other nodes can connect to you entirely over Tor, and the Tor address +doesn't change every time you restart. -#### Case #4 c-lightning has no public IP address, but has a fixed Tor hidden service address that is persistent +See "Letting C-lightning Control Tor" for how to get c-lightning +talking to Tor. -Other nodes can connect to the announced .onion address created with the -hidden service ([see above](#creation-of-an-hidden-service-for-a-persistent-onion-address)). +If you have an internal IP address: -In this case In the `lightningd` command line you will specify: ``` ---bind-addr=yourInternalIPAddress:port --announce-addr=your.onionAddress:port +bind-addr=yourInternalIPAddress:port +announce-addr=yourexternalIPAddress:port +addr=statictor:127.0.0.1:9051 ``` -or `--addr=your.onionAddress:port` if you are NOT on an internal network. -#### Case #5 c-lightning has no public IP address, and has no fixed Tor hidden service address - -In this case it is difficult to track the node. -You specify just: +Or an external address: ``` ---bind-addr=yourInternalIPAddress:port --addr=autotor:127.0.0.1:9051 +addr=yourIPAddress:port +addr=statictor:127.0.0.1:9051 ``` -In the `lightningd` command line. -Other nodes will not be able to `connect` to you unless you communicate them how to reach you. -You will find your .onion address with the command `lightning-cli getinfo` and the other nodes will -be able to connect to it through the 9735 port. +#### Case #4: Unannounced IP address, and a fixed Tor address in torrc -#### Case #6 c-lightning has a public IP address and a fixed Tor v3 hidden service +Other nodes can only connect to you over Tor. -You will be reachable via Clearnet, via Tor to the .onion if it is communicated to the node that wants to -connect with our node. +You simply tell c-lightning to advertize the Tor address (you can use +`sudo cat /var/lib/tor/lightningd-service_v3/hostname` to get your +Tor-assigned onion address). -To make your external IP address public you add: -``` ---bind-addr=yourInternalAddress:port --announce-addr=yourexternalIPAddress:port`. ``` -If the node is not on an internal network the option will be: -`--addr=yourexternalIPAddress:port`. - -Once the .onion addresses have been created with the procedures [oulined above](#creation-of-an-hidden-service-for-a-persistent-onion-address), -the node is already reachable at the .onion address. - -To make your external hidden service public you add: -``` ---announce-addr=.onionAddressV3:port +announce-addr=your.onionAddress:port +proxy=127.0.0.1:9050 +always-use-proxy=true ``` -to the options to publish your IP number. -#### Case #7 c-lightning has no public IP address, a fixed Tor V3 service address +#### Case #4: Unannounced IP address, and a fixed Tor address set by C-lightning -The Persistent addresses can be created with the steps [outlined above](#creation-of-an-hidden-service-for-a-persistent-onion-address). +Other nodes can only connect to you over Tor. -To create your non-persistent Tor address, add -`--addr=autotor:127.0.0.1:9051` if you want to announce it or -`--bind-addr=autotor:127.0.0.1:9051` if you don't want to announce it. +See "Letting C-lightning Control Tor" for how to get c-lightning +talking to Tor. -Also you must specify `--tor-service-password=yourpassword` (not the hash) to access the -Tor service at 9051 If you have protected them with the password (no additional options if -they are protected with a cookie file. [See above](#creation-of-an-auto-service-for-non-persistent-onion-addresses)). - -To make your external onion service public you add: -``` ---bind-addr=yourInternalIPAddress:port --announce-addr=your.onionAddressV3:port -``` -#### Case #8 c-lightning has a public IP address and no Tor addresses - -The external address is communicated by the -``` ---bind-addr=internalIPAddress:port --announce-addr=yourexternalIPAddress:port` ``` -or `--addr=yourexternalIPAddress:port` if the node is not inside an internal network. - -The node can connect to any V4/6 ip address via a IPV4/6 socks 5 proxy by specifing -``` ---proxy=127.0.0.1:9050 --always-use-proxy=true +addr=statictor:127.0.0.1:9051 +proxy=127.0.0.1:9050 +always-use-proxy=true ``` ## References +The lightningd-config manual page covers the various address cases in detail. + [The Tor project](https://www.torproject.org/) [tor FAQ]: https://www.torproject.org/docs/faq.html.en#WhatIsTor diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index 1af81a79032b..b20520d4ae7a 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -114,6 +114,7 @@ static struct lightningd *new_lightningd(const tal_t *ctx) * same exact code users will be running. */ #if DEVELOPER ld->dev_debug_subprocess = NULL; + ld->dev_no_plugin_checksum = false; ld->dev_disconnect_fd = -1; ld->dev_subdaemon_fail = false; ld->dev_allow_localhost = false; diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h index 553f10a785b4..772de83923b3 100644 --- a/lightningd/lightningd.h +++ b/lightningd/lightningd.h @@ -207,6 +207,9 @@ struct lightningd { /* If we want to debug a subdaemon/plugin. */ const char *dev_debug_subprocess; + /* If we have --dev-no-plugin-checksum */ + bool dev_no_plugin_checksum; + /* If we have a --dev-disconnect file */ int dev_disconnect_fd; diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 3b5b6e61debb..4df90dc51abe 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -974,34 +974,12 @@ static struct command_result *json_fundchannel_complete(struct command *cmd, struct wally_psbt *funding_psbt; u32 *funding_txout_num = NULL; struct funding_channel *fc; - bool old_api; - - /* params is NULL for initial parameter desc generation! */ - if (params && deprecated_apis) { - /* We used to have a three-arg version. */ - if (params->type == JSMN_ARRAY) - old_api = (params->size == 3); - else - old_api = (json_get_member(buffer, params, "txid") - != NULL); - if (old_api) { - if (!param(cmd, buffer, params, - p_req("id", param_node_id, &id), - p_req("txid", param_txid, &funding_txid), - p_req("txout", param_number, &funding_txout_num), - NULL)) - return command_param_failed(); - } - } else - old_api = false; - - if (!old_api) { - if (!param(cmd, buffer, params, - p_req("id", param_node_id, &id), - p_req("psbt", param_psbt, &funding_psbt), - NULL)) - return command_param_failed(); - } + + if (!param(cmd, buffer, params, + p_req("id", param_node_id, &id), + p_req("psbt", param_psbt, &funding_psbt), + NULL)) + return command_param_failed(); peer = peer_by_id(cmd->ld, id); if (!peer) { @@ -1024,40 +1002,38 @@ static struct command_result *json_fundchannel_complete(struct command *cmd, fc = peer->uncommitted_channel->fc; - if (!old_api) { - /* Figure out the correct output, and perform sanity checks. */ - for (size_t i = 0; i < funding_psbt->tx->num_outputs; i++) { - if (memeq(funding_psbt->tx->outputs[i].script, - funding_psbt->tx->outputs[i].script_len, - fc->funding_scriptpubkey, - tal_bytelen(fc->funding_scriptpubkey))) { - if (funding_txout_num) - return command_fail(cmd, FUNDING_PSBT_INVALID, - "Two outputs to open channel"); - funding_txout_num = tal(cmd, u32); - *funding_txout_num = i; - } + /* Figure out the correct output, and perform sanity checks. */ + for (size_t i = 0; i < funding_psbt->tx->num_outputs; i++) { + if (memeq(funding_psbt->tx->outputs[i].script, + funding_psbt->tx->outputs[i].script_len, + fc->funding_scriptpubkey, + tal_bytelen(fc->funding_scriptpubkey))) { + if (funding_txout_num) + return command_fail(cmd, FUNDING_PSBT_INVALID, + "Two outputs to open channel"); + funding_txout_num = tal(cmd, u32); + *funding_txout_num = i; } - if (!funding_txout_num) - return command_fail(cmd, FUNDING_PSBT_INVALID, - "No output to open channel"); - - /* Can't really check amounts for elements. */ - if (!chainparams->is_elements - && !amount_sat_eq(amount_sat(funding_psbt->tx->outputs - [*funding_txout_num].satoshi), - fc->funding_sats)) - return command_fail(cmd, FUNDING_PSBT_INVALID, - "Output to open channel is %"PRIu64"sat," - " should be %s", - funding_psbt->tx->outputs - [*funding_txout_num].satoshi, - type_to_string(tmpctx, struct amount_sat, - &fc->funding_sats)); - - funding_txid = tal(cmd, struct bitcoin_txid); - psbt_txid(NULL, funding_psbt, funding_txid, NULL); } + if (!funding_txout_num) + return command_fail(cmd, FUNDING_PSBT_INVALID, + "No output to open channel"); + + /* Can't really check amounts for elements. */ + if (!chainparams->is_elements + && !amount_sat_eq(amount_sat(funding_psbt->tx->outputs + [*funding_txout_num].satoshi), + fc->funding_sats)) + return command_fail(cmd, FUNDING_PSBT_INVALID, + "Output to open channel is %"PRIu64"sat," + " should be %s", + funding_psbt->tx->outputs + [*funding_txout_num].satoshi, + type_to_string(tmpctx, struct amount_sat, + &fc->funding_sats)); + + funding_txid = tal(cmd, struct bitcoin_txid); + psbt_txid(NULL, funding_psbt, funding_txid, NULL); /* Fun fact: our wire protocol only allows 16 bits for outnum. * That is reflected in our encoding scheme for short_channel_id. */ diff --git a/lightningd/options.c b/lightningd/options.c index d8431c13c542..54dde2aa640d 100644 --- a/lightningd/options.c +++ b/lightningd/options.c @@ -198,6 +198,18 @@ static char *opt_add_addr_withtype(const char *arg, deprecated_apis, &err_msg)) { return tal_fmt(NULL, "Unable to parse address '%s': %s", arg, err_msg); } + + /* Sanity check for exact duplicates. */ + for (size_t i = 0; i < tal_count(ld->proposed_wireaddr); i++) { + /* Only compare announce vs announce and bind vs bind */ + if ((ld->proposed_listen_announce[i] & ala) == 0) + continue; + + if (wireaddr_internal_eq(&ld->proposed_wireaddr[i], &wi)) + return tal_fmt(NULL, "Duplicate %s address %s", + ala & ADDR_ANNOUNCE ? "announce" : "listen", + type_to_string(tmpctx, struct wireaddr_internal, &wi)); + } tal_arr_expand(&ld->proposed_wireaddr, wi); return NULL; @@ -205,7 +217,6 @@ static char *opt_add_addr_withtype(const char *arg, static char *opt_add_announce_addr(const char *arg, struct lightningd *ld) { - const struct wireaddr *wn; size_t n = tal_count(ld->proposed_wireaddr); char *err; @@ -226,24 +237,6 @@ static char *opt_add_announce_addr(const char *arg, struct lightningd *ld) return tal_fmt(NULL, "address '%s' is not announcable", arg); - /* gossipd will refuse to announce the second one, sure, but it's - * better to check and fail now if they've explicitly asked for it. */ - wn = &ld->proposed_wireaddr[n].u.wireaddr; - for (size_t i = 0; i < n; i++) { - const struct wireaddr *wi; - - if (ld->proposed_listen_announce[i] != ADDR_ANNOUNCE) - continue; - assert(ld->proposed_wireaddr[i].itype == ADDR_INTERNAL_WIREADDR); - wi = &ld->proposed_wireaddr[i].u.wireaddr; - - if (wn->type != wi->type) - continue; - return tal_fmt(NULL, "Cannot announce address %s;" - " already have %s which is the same type", - type_to_string(tmpctx, struct wireaddr, wn), - type_to_string(tmpctx, struct wireaddr, wi)); - } return NULL; } @@ -254,9 +247,8 @@ static char *opt_add_addr(const char *arg, struct lightningd *ld) /* handle in case you used the addr option with an .onion */ if (parse_wireaddr_internal(arg, &addr, 0, true, false, true, deprecated_apis, NULL)) { - if (addr.itype == ADDR_INTERNAL_WIREADDR && ( - addr.u.wireaddr.type == ADDR_TYPE_TOR_V2 || - addr.u.wireaddr.type == ADDR_TYPE_TOR_V3)) { + if (addr.itype == ADDR_INTERNAL_WIREADDR && + addr.u.wireaddr.type == ADDR_TYPE_TOR_V3) { log_unusual(ld->log, "You used `--addr=%s` option with an .onion address, please use" " `--announce-addr` ! You are lucky in this node live some wizards and" " fairies, we have done this for you and announce, Be as hidden as wished", @@ -302,9 +294,8 @@ static char *opt_add_bind_addr(const char *arg, struct lightningd *ld) /* handle in case you used the bind option with an .onion */ if (parse_wireaddr_internal(arg, &addr, 0, true, false, true, deprecated_apis, NULL)) { - if (addr.itype == ADDR_INTERNAL_WIREADDR && ( - addr.u.wireaddr.type == ADDR_TYPE_TOR_V2 || - addr.u.wireaddr.type == ADDR_TYPE_TOR_V3)) { + if (addr.itype == ADDR_INTERNAL_WIREADDR && + addr.u.wireaddr.type == ADDR_TYPE_TOR_V3) { log_unusual(ld->log, "You used `--bind-addr=%s` option with an .onion address," " You are lucky in this node live some wizards and" " fairies, we have done this for you and don't announce, Be as hidden as wished", @@ -593,6 +584,10 @@ static void dev_register_opts(struct lightningd *ld) opt_register_early_arg("--dev-debugger=", opt_subprocess_debug, NULL, ld, "Invoke gdb at start of "); + opt_register_early_noarg("--dev-no-plugin-checksum", opt_set_bool, + &ld->dev_no_plugin_checksum, + "Don't checksum plugins to detect changes"); + opt_register_noarg("--dev-no-reconnect", opt_set_invbool, &ld->reconnect, "Disable automatic reconnect-attempts by this node, but accept incoming"); diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index e06c262eac56..a71bc358e461 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -2464,52 +2464,7 @@ static void custommsg_payload_serialize(struct custommsg_payload *payload, struct json_stream *stream, struct plugin *plugin) { - /* Backward compat for broken custommsg: if we get a custommsg - * from an old c-lightning node, then we must identify and - * strip the prefix from the payload. If it's a new one, we - * need to add the frame for the `message` for backward - * compatibility. */ - size_t msglen = tal_bytelen(payload->msg), framedlen, unframedlen, max; - const u8 *unframed, *framed, *p = payload->msg; - u8 *tmp; - max = msglen; - - if (msglen >= 4 && fromwire_u16(&p, &max) == WIRE_CUSTOMMSG_OUT && - fromwire_u16(&p, &max) == msglen - 4 && deprecated_apis) { - /* This is from an old c-lightning implementation that - * erroneously sent the framed message over the - * connection. */ - unframed = payload->msg + 4; - unframedlen = msglen - 4; - framed = payload->msg; - framedlen = msglen; - } else { - /* This is from a new c-lightning, which correctly - * sent the raw custommsg without framing. We still - * need to reconstruct the wrong message since plugins - * may rely on it. */ - if (deprecated_apis) { - tmp = tal_arr(tmpctx, u8, 0); - towire_u16(&tmp, WIRE_CUSTOMMSG_OUT); - towire_u16(&tmp, msglen); - towire(&tmp, payload->msg, msglen); - framedlen = msglen + 4; - framed = tmp; - } - - unframed = payload->msg; - unframedlen = msglen; - } - - if (deprecated_apis) { - json_add_hex(stream, "message", framed, framedlen); - json_add_string( - stream, "warning", - "The `message` field is deprecated and has been replaced " - "with the payload` field which skips the internal type and " - "the length prefix. Please update to use that instead."); - } - json_add_hex(stream, "payload", unframed, unframedlen); + json_add_hex_talarr(stream, "payload", payload->msg); json_add_node_id(stream, "peer_id", &payload->peer_id); } diff --git a/lightningd/plugin.c b/lightningd/plugin.c index 39e6e480c939..ee3c2c967a78 100644 --- a/lightningd/plugin.c +++ b/lightningd/plugin.c @@ -209,9 +209,14 @@ static void destroy_plugin(struct plugin *p) } } -static u32 file_checksum(const char* path) +static u32 file_checksum(struct lightningd *ld, const char *path) { - char *content = grab_file(tmpctx, path); + char *content; + + if (IFDEV(ld->dev_no_plugin_checksum, false)) + return 0; + + content = grab_file(tmpctx, path); if (content == NULL) return 0; return crc32c(0, content, tal_count(content)); } @@ -231,7 +236,7 @@ struct plugin *plugin_register(struct plugins *plugins, const char* path TAKES, if (important) p_temp->important = true; /* stop and restart plugin on different checksum */ - chksum = file_checksum(path); + chksum = file_checksum(plugins->ld, path); if (p_temp->checksum != chksum && !p_temp->important) { plugin_kill(p_temp, LOG_INFORM, "Plugin changed, needs restart."); @@ -246,7 +251,7 @@ struct plugin *plugin_register(struct plugins *plugins, const char* path TAKES, p = tal(plugins, struct plugin); p->plugins = plugins; p->cmd = tal_strdup(p, path); - p->checksum = file_checksum(p->cmd); + p->checksum = file_checksum(plugins->ld, p->cmd); p->shortname = path_basename(p, p->cmd); p->start_cmd = start_cmd; diff --git a/tests/test_closing.py b/tests/test_closing.py index eab628020562..ea85d82ec878 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -3070,53 +3070,6 @@ def test_segwit_shutdown_script(node_factory, bitcoind, executor): l1.rpc.fundchannel(l2.info['id'], 10**6) -@pytest.mark.openchannel('v1') -def test_shutdown_alternate_txid(node_factory, bitcoind): - l1, l2 = node_factory.line_graph(2, fundchannel=False, - opts={'experimental-shutdown-wrong-funding': None, - 'allow-deprecated-apis': True}) - - amount = 1000000 - amount_msat = Millisatoshi(amount * 1000) - - # Let's make a classic fundchannel mistake (wrong txid!) - addr = l1.rpc.fundchannel_start(l2.info['id'], amount_msat)['funding_address'] - txid = bitcoind.rpc.sendtoaddress(addr, amount / 10**8) - - # Gotta figure out which output manually :( - tx = bitcoind.rpc.getrawtransaction(txid, 1) - for n, out in enumerate(tx['vout']): - if scriptpubkey_addr(out['scriptPubKey']) == addr: - txout = n - - bitcoind.generate_block(1, wait_for_mempool=1) - - # Wrong txid, wrong txout! - wrong_txid = txid[16:] + txid[:16] - wrong_txout = txout ^ 1 - l1.rpc.fundchannel_complete(l2.info['id'], wrong_txid, wrong_txout) - - wait_for(lambda: only_one(l2.rpc.listpeers()['peers'])['channels'] != []) - wait_for(lambda: only_one(l2.rpc.listpeers()['peers'])['channels'][0]['state'] == 'CHANNELD_AWAITING_LOCKIN') - - closeaddr = l1.rpc.newaddr()['bech32'] - - # Oops, try rescuing it! - l1.rpc.call('close', {'id': l2.info['id'], 'destination': closeaddr, 'wrong_funding': txid + ':' + str(txout)}) - - # Just make sure node has no funds. - assert l1.rpc.listfunds()['outputs'] == [] - - bitcoind.generate_block(100, wait_for_mempool=1) - sync_blockheight(bitcoind, [l1, l2]) - - # We will see our funds return. - assert len(l1.rpc.listfunds()['outputs']) == 1 - - wait_for(lambda: l2.rpc.listpeers()['peers'] == []) - wait_for(lambda: l1.rpc.listpeers()['peers'] == []) - - @unittest.skipIf(not EXPERIMENTAL_FEATURES, "Needs anchor_outputs") @pytest.mark.developer("needs to set dev-disconnect") def test_closing_higherfee(node_factory, bitcoind, executor): diff --git a/tests/test_gossip.py b/tests/test_gossip.py index b69531f8006f..648606faaf87 100644 --- a/tests/test_gossip.py +++ b/tests/test_gossip.py @@ -916,11 +916,12 @@ def test_gossip_addresses(node_factory, bitcoind): l1 = node_factory.get_node(options={ 'announce-addr': [ '[::]:3', + '[::]', '127.0.0.1:2', + '127.0.0.1', 'vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd.onion', - '3fyb44wdhnd2ghhl.onion:1234' + '4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad.onion:1234' ], - 'allow-deprecated-apis': True, }) l2 = node_factory.get_node() l1.rpc.connect(l2.info['id'], 'localhost', l2.port) @@ -933,9 +934,11 @@ def test_gossip_addresses(node_factory, bitcoind): nodes = l2.rpc.listnodes(l1.info['id'])['nodes'] assert len(nodes) == 1 and nodes[0]['addresses'] == [ {'type': 'ipv4', 'address': '127.0.0.1', 'port': 2}, + {'type': 'ipv4', 'address': '127.0.0.1', 'port': 9735}, {'type': 'ipv6', 'address': '::', 'port': 3}, - {'type': 'torv2', 'address': '3fyb44wdhnd2ghhl.onion', 'port': 1234}, - {'type': 'torv3', 'address': 'vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd.onion', 'port': 9735} + {'type': 'ipv6', 'address': '::', 'port': 9735}, + {'type': 'torv3', 'address': 'vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd.onion', 'port': 9735}, + {'type': 'torv3', 'address': '4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad.onion', 'port': 1234}, ] diff --git a/tests/test_pay.py b/tests/test_pay.py index e7a0145b6dc6..709978ae82ca 100644 --- a/tests/test_pay.py +++ b/tests/test_pay.py @@ -4499,7 +4499,7 @@ def test_fetchinvoice(node_factory, bitcoind): 'recurrence_label': 'test recurrence'}) # Check we can request invoice without a channel. - l4, l5 = node_factory.get_nodes(2, opts={'experimental-offers': None}) + l4 = node_factory.get_node(options={'experimental-offers': None}) l4.rpc.connect(l2.info['id'], 'localhost', l2.port) # ... even if we can't find ourselves. l4.rpc.call('fetchinvoice', {'offer': offer3['bolt12'], @@ -4510,10 +4510,6 @@ def test_fetchinvoice(node_factory, bitcoind): l4.rpc.connect(l3.info['id'], 'localhost', l3.port) l4.rpc.call('fetchinvoice', {'offer': offer1['bolt12']}) - # ... even if we are also in gossmap. - node_factory.join_nodes([l3, l5], wait_for_announce=True) - l4.rpc.call('fetchinvoice', {'offer': offer1['bolt12']}) - # Now, test amount in different currency! plugin = os.path.join(os.path.dirname(__file__), 'plugins/currencyUSDAUD5000.py') l3.rpc.plugin_start(plugin) diff --git a/tests/test_plugin.py b/tests/test_plugin.py index b590ba680cdb..c8eeff43486b 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -2520,6 +2520,9 @@ def init(options, configuration, plugin): # get a node that is not started so we can put a plugin in its lightning_dir n = node_factory.get_node(start=False) + if "dev-no-plugin-checksum" in n.daemon.opts: + del n.daemon.opts["dev-no-plugin-checksum"] + lndir = n.daemon.lightning_dir # write hello world plugin to lndir/plugins