From cc75a8450a554741ad73c751fc619dabed40b150 Mon Sep 17 00:00:00 2001 From: William Casarin Date: Fri, 22 Dec 2023 16:48:50 -0800 Subject: [PATCH] nostrdb: add supporting files for the bolt11 parser A lot of this was pulled from core-lightning. Not sure what is actually needed or not. Signed-off-by: William Casarin --- nostrdb/bech32.c | 217 -------- nostrdb/bech32.h | 142 ----- nostrdb/bolt11/alignof.h | 20 + nostrdb/bolt11/amount.c | 566 ++++++++++++++++++++ nostrdb/bolt11/amount.h | 203 +++++++ nostrdb/bolt11/array_size.h | 26 + nostrdb/bolt11/bech32_util.c | 127 +++++ nostrdb/bolt11/bech32_util.h | 28 + nostrdb/bolt11/bolt11.c | 676 +++++++++++++++++++++++ nostrdb/bolt11/bolt11.h | 104 ++++ nostrdb/bolt11/build_assert.h | 40 ++ nostrdb/bolt11/check_type.h | 64 +++ nostrdb/bolt11/container_of.h | 145 +++++ nostrdb/bolt11/cppmagic.h | 191 +++++++ nostrdb/bolt11/debug.h | 15 + nostrdb/bolt11/error.c | 34 ++ nostrdb/bolt11/error.h | 33 ++ nostrdb/bolt11/hash_u5.c | 48 ++ nostrdb/bolt11/hash_u5.h | 20 + nostrdb/bolt11/libnostrdb.a | Bin 0 -> 172632 bytes nostrdb/bolt11/likely.h | 115 ++++ nostrdb/bolt11/list.c | 43 ++ nostrdb/bolt11/list.h | 842 +++++++++++++++++++++++++++++ nostrdb/bolt11/mem.c | 128 +++++ nostrdb/bolt11/mem.h | 295 +++++++++++ nostrdb/bolt11/node_id.c | 64 +++ nostrdb/bolt11/node_id.h | 38 ++ nostrdb/bolt11/overflows.h | 43 ++ nostrdb/bolt11/short_types.h | 35 ++ nostrdb/bolt11/str.h | 228 ++++++++ nostrdb/bolt11/str_debug.h | 30 ++ nostrdb/bolt11/structeq.h | 46 ++ nostrdb/bolt11/take.c | 126 +++++ nostrdb/bolt11/take.h | 136 +++++ nostrdb/bolt11/tal.c | 972 ++++++++++++++++++++++++++++++++++ nostrdb/bolt11/tal.h | 553 +++++++++++++++++++ nostrdb/bolt11/talstr.c | 315 +++++++++++ nostrdb/bolt11/talstr.h | 225 ++++++++ nostrdb/bolt11/typesafe_cb.h | 134 +++++ nostrdb/bolt11/utf8.c | 199 +++++++ nostrdb/bolt11/utf8.h | 57 ++ nostrdb/compiler.h | 384 +++++++++++--- nostrdb/cursor.h | 4 +- nostrdb/nostr_bech32.c | 306 +++++++++++ nostrdb/nostr_bech32.h | 84 +++ nostrdb/nostrdb.c | 2 + 46 files changed, 7665 insertions(+), 438 deletions(-) delete mode 100644 nostrdb/bech32.c delete mode 100644 nostrdb/bech32.h create mode 100644 nostrdb/bolt11/alignof.h create mode 100644 nostrdb/bolt11/amount.c create mode 100644 nostrdb/bolt11/amount.h create mode 100644 nostrdb/bolt11/array_size.h create mode 100644 nostrdb/bolt11/bech32_util.c create mode 100644 nostrdb/bolt11/bech32_util.h create mode 100644 nostrdb/bolt11/bolt11.c create mode 100644 nostrdb/bolt11/bolt11.h create mode 100644 nostrdb/bolt11/build_assert.h create mode 100644 nostrdb/bolt11/check_type.h create mode 100644 nostrdb/bolt11/container_of.h create mode 100644 nostrdb/bolt11/cppmagic.h create mode 100644 nostrdb/bolt11/debug.h create mode 100644 nostrdb/bolt11/error.c create mode 100644 nostrdb/bolt11/error.h create mode 100644 nostrdb/bolt11/hash_u5.c create mode 100644 nostrdb/bolt11/hash_u5.h create mode 100644 nostrdb/bolt11/libnostrdb.a create mode 100644 nostrdb/bolt11/likely.h create mode 100644 nostrdb/bolt11/list.c create mode 100644 nostrdb/bolt11/list.h create mode 100644 nostrdb/bolt11/mem.c create mode 100644 nostrdb/bolt11/mem.h create mode 100644 nostrdb/bolt11/node_id.c create mode 100644 nostrdb/bolt11/node_id.h create mode 100644 nostrdb/bolt11/overflows.h create mode 100644 nostrdb/bolt11/short_types.h create mode 100644 nostrdb/bolt11/str.h create mode 100644 nostrdb/bolt11/str_debug.h create mode 100644 nostrdb/bolt11/structeq.h create mode 100644 nostrdb/bolt11/take.c create mode 100644 nostrdb/bolt11/take.h create mode 100644 nostrdb/bolt11/tal.c create mode 100644 nostrdb/bolt11/tal.h create mode 100644 nostrdb/bolt11/talstr.c create mode 100644 nostrdb/bolt11/talstr.h create mode 100644 nostrdb/bolt11/typesafe_cb.h create mode 100644 nostrdb/bolt11/utf8.c create mode 100644 nostrdb/bolt11/utf8.h create mode 100644 nostrdb/nostr_bech32.c create mode 100644 nostrdb/nostr_bech32.h diff --git a/nostrdb/bech32.c b/nostrdb/bech32.c deleted file mode 100644 index 3ec6a1fb..00000000 --- a/nostrdb/bech32.c +++ /dev/null @@ -1,217 +0,0 @@ -/* Stolen from https://github.com/sipa/bech32/blob/master/ref/c/segwit_addr.c, - * with only the two ' > 90' checks hoisted, and more internals exposed */ - -/* Copyright (c) 2017, 2021 Pieter Wuille - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "config.h" -#include -#include "bech32.h" -#include - -static uint32_t bech32_polymod_step(uint32_t pre) { - uint8_t b = pre >> 25; - return ((pre & 0x1FFFFFF) << 5) ^ - (-((b >> 0) & 1) & 0x3b6a57b2UL) ^ - (-((b >> 1) & 1) & 0x26508e6dUL) ^ - (-((b >> 2) & 1) & 0x1ea119faUL) ^ - (-((b >> 3) & 1) & 0x3d4233ddUL) ^ - (-((b >> 4) & 1) & 0x2a1462b3UL); -} - -static uint32_t bech32_final_constant(bech32_encoding enc) { - if (enc == BECH32_ENCODING_BECH32) return 1; - if (enc == BECH32_ENCODING_BECH32M) return 0x2bc830a3; - assert(0); -} - -const char bech32_charset[] = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"; - -const int8_t bech32_charset_rev[128] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 15, -1, 10, 17, 21, 20, 26, 30, 7, 5, -1, -1, -1, -1, -1, -1, - -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, - 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1, - -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, - 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1 -}; - -int bech32_encode(char *output, const char *hrp, const uint8_t *data, size_t data_len, size_t max_input_len, bech32_encoding enc) { - uint32_t chk = 1; - size_t i = 0; - while (hrp[i] != 0) { - int ch = hrp[i]; - if (ch < 33 || ch > 126) { - return 0; - } - - if (ch >= 'A' && ch <= 'Z') return 0; - chk = bech32_polymod_step(chk) ^ (ch >> 5); - ++i; - } - if (i + 7 + data_len > max_input_len) return 0; - chk = bech32_polymod_step(chk); - while (*hrp != 0) { - chk = bech32_polymod_step(chk) ^ (*hrp & 0x1f); - *(output++) = *(hrp++); - } - *(output++) = '1'; - for (i = 0; i < data_len; ++i) { - if (*data >> 5) return 0; - chk = bech32_polymod_step(chk) ^ (*data); - *(output++) = bech32_charset[*(data++)]; - } - for (i = 0; i < 6; ++i) { - chk = bech32_polymod_step(chk); - } - chk ^= bech32_final_constant(enc); - for (i = 0; i < 6; ++i) { - *(output++) = bech32_charset[(chk >> ((5 - i) * 5)) & 0x1f]; - } - *output = 0; - return 1; -} - -bech32_encoding bech32_decode_len(char* hrp, uint8_t *data, size_t *data_len, const char *input, size_t input_len) { - uint32_t chk = 1; - size_t i; - size_t hrp_len; - int have_lower = 0, have_upper = 0; - if (input_len < 8) { - return BECH32_ENCODING_NONE; - } - *data_len = 0; - while (*data_len < input_len && input[(input_len - 1) - *data_len] != '1') { - ++(*data_len); - } - hrp_len = input_len - (1 + *data_len); - if (1 + *data_len >= input_len || *data_len < 6) { - return BECH32_ENCODING_NONE; - } - *(data_len) -= 6; - for (i = 0; i < hrp_len; ++i) { - int ch = input[i]; - if (ch < 33 || ch > 126) { - return BECH32_ENCODING_NONE; - } - if (ch >= 'a' && ch <= 'z') { - have_lower = 1; - } else if (ch >= 'A' && ch <= 'Z') { - have_upper = 1; - ch = (ch - 'A') + 'a'; - } - hrp[i] = ch; - chk = bech32_polymod_step(chk) ^ (ch >> 5); - } - hrp[i] = 0; - chk = bech32_polymod_step(chk); - for (i = 0; i < hrp_len; ++i) { - chk = bech32_polymod_step(chk) ^ (input[i] & 0x1f); - } - ++i; - while (i < input_len) { - int v = (input[i] & 0x80) ? -1 : bech32_charset_rev[(int)input[i]]; - if (input[i] >= 'a' && input[i] <= 'z') have_lower = 1; - if (input[i] >= 'A' && input[i] <= 'Z') have_upper = 1; - if (v == -1) { - return BECH32_ENCODING_NONE; - } - chk = bech32_polymod_step(chk) ^ v; - if (i + 6 < input_len) { - data[i - (1 + hrp_len)] = v; - } - ++i; - } - if (have_lower && have_upper) { - return BECH32_ENCODING_NONE; - } - if (chk == bech32_final_constant(BECH32_ENCODING_BECH32)) { - return BECH32_ENCODING_BECH32; - } else if (chk == bech32_final_constant(BECH32_ENCODING_BECH32M)) { - return BECH32_ENCODING_BECH32M; - } else { - return BECH32_ENCODING_NONE; - } -} - -bech32_encoding bech32_decode(char* hrp, uint8_t *data, size_t *data_len, const char *input, size_t max_input_len) { - size_t len = strlen(input); - if (len > max_input_len) { - return BECH32_ENCODING_NONE; - } - return bech32_decode_len(hrp, data, data_len, input, len); -} - -int bech32_convert_bits(uint8_t* out, size_t* outlen, int outbits, const uint8_t* in, size_t inlen, int inbits, int pad) { - uint32_t val = 0; - int bits = 0; - uint32_t maxv = (((uint32_t)1) << outbits) - 1; - while (inlen--) { - val = (val << inbits) | *(in++); - bits += inbits; - while (bits >= outbits) { - bits -= outbits; - out[(*outlen)++] = (val >> bits) & maxv; - } - } - if (pad) { - if (bits) { - out[(*outlen)++] = (val << (outbits - bits)) & maxv; - } - } else if (((val << (outbits - bits)) & maxv) || bits >= inbits) { - return 0; - } - return 1; -} - -int segwit_addr_encode(char *output, const char *hrp, int witver, const uint8_t *witprog, size_t witprog_len) { - uint8_t data[65]; - size_t datalen = 0; - bech32_encoding enc = BECH32_ENCODING_BECH32; - if (witver > 16) return 0; - if (witver == 0 && witprog_len != 20 && witprog_len != 32) return 0; - if (witprog_len < 2 || witprog_len > 40) return 0; - if (witver > 0) enc = BECH32_ENCODING_BECH32M; - data[0] = witver; - bech32_convert_bits(data + 1, &datalen, 5, witprog, witprog_len, 8, 1); - ++datalen; - return bech32_encode(output, hrp, data, datalen, 90, enc); -} - -int segwit_addr_decode(int* witver, uint8_t* witdata, size_t* witdata_len, const char* hrp, const char* addr) { - uint8_t data[84]; - char hrp_actual[84]; - size_t data_len; - bech32_encoding enc = bech32_decode(hrp_actual, data, &data_len, addr, 90); - if (enc == BECH32_ENCODING_NONE) return 0; - if (data_len == 0 || data_len > 65) return 0; - if (strncmp(hrp, hrp_actual, 84) != 0) return 0; - if (data[0] > 16) return 0; - if (data[0] == 0 && enc != BECH32_ENCODING_BECH32) return 0; - if (data[0] > 0 && enc != BECH32_ENCODING_BECH32M) return 0; - *witdata_len = 0; - if (!bech32_convert_bits(witdata, witdata_len, 8, data + 1, data_len - 1, 5, 0)) return 0; - if (*witdata_len < 2 || *witdata_len > 40) return 0; - if (data[0] == 0 && *witdata_len != 20 && *witdata_len != 32) return 0; - *witver = data[0]; - return 1; -} diff --git a/nostrdb/bech32.h b/nostrdb/bech32.h deleted file mode 100644 index d782211c..00000000 --- a/nostrdb/bech32.h +++ /dev/null @@ -1,142 +0,0 @@ -/* Stolen from https://github.com/sipa/bech32/blob/master/ref/c/segwit_addr.h, - * with only the two ' > 90' checks hoisted */ - -/* Copyright (c) 2017, 2021 Pieter Wuille - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef LIGHTNING_COMMON_BECH32_H -#define LIGHTNING_COMMON_BECH32_H -#include "config.h" - -#include -#include - -/** Encode a SegWit address - * - * Out: output: Pointer to a buffer of size 73 + strlen(hrp) that will be - * updated to contain the null-terminated address. - * In: hrp: Pointer to the null-terminated human readable part to use - * (chain/network specific). - * ver: Version of the witness program (between 0 and 16 inclusive). - * prog: Data bytes for the witness program (between 2 and 40 bytes). - * prog_len: Number of data bytes in prog. - * Returns 1 if successful. - */ -int segwit_addr_encode( - char *output, - const char *hrp, - int ver, - const uint8_t *prog, - size_t prog_len -); - -/** Decode a SegWit address - * - * Out: ver: Pointer to an int that will be updated to contain the witness - * program version (between 0 and 16 inclusive). - * prog: Pointer to a buffer of size 40 that will be updated to - * contain the witness program bytes. - * prog_len: Pointer to a size_t that will be updated to contain the length - * of bytes in prog. - * hrp: Pointer to the null-terminated human readable part that is - * expected (chain/network specific). - * addr: Pointer to the null-terminated address. - * Returns 1 if successful. - */ -int segwit_addr_decode( - int* ver, - uint8_t* prog, - size_t* prog_len, - const char* hrp, - const char* addr -); - -/** Supported encodings. */ -typedef enum { - BECH32_ENCODING_NONE, - BECH32_ENCODING_BECH32, - BECH32_ENCODING_BECH32M -} bech32_encoding; - -/** Encode a Bech32 or Bech32m string - * - * Out: output: Pointer to a buffer of size strlen(hrp) + data_len + 8 that - * will be updated to contain the null-terminated Bech32 string. - * In: hrp : Pointer to the null-terminated human readable part. - * data : Pointer to an array of 5-bit values. - * data_len: Length of the data array. - * max_input_len: Maximum valid length of input (90 for segwit usage). - * enc: Which encoding to use (BECH32_ENCODING_BECH32{,M}). - * Returns 1 if successful. - */ -int bech32_encode( - char *output, - const char *hrp, - const uint8_t *data, - size_t data_len, - size_t max_input_len, - bech32_encoding enc -); - -/** Decode a Bech32 or Bech32m string - * - * Out: hrp: Pointer to a buffer of size strlen(input) - 6. Will be - * updated to contain the null-terminated human readable part. - * data: Pointer to a buffer of size strlen(input) - 8 that will - * hold the encoded 5-bit data values. - * data_len: Pointer to a size_t that will be updated to be the number - * of entries in data. - * In: input: Pointer to a null-terminated Bech32 string. - * max_input_len: Maximum valid length of input (90 for segwit usage). - * Returns BECH32_ENCODING_BECH32{,M} to indicate decoding was successful - * with the specified encoding standard. BECH32_ENCODING_NONE is returned if - * decoding failed. - */ -bech32_encoding bech32_decode( - char *hrp, - uint8_t *data, - size_t *data_len, - const char *input, - size_t max_input_len -); - -bech32_encoding bech32_decode_len( - char *hrp, - uint8_t *data, - size_t *data_len, - const char *input, - size_t input_len -); - -/* Helper from bech32: translates inbits-bit bytes to outbits-bit bytes. - * @outlen is incremented as bytes are added. - * @pad is true if we're to pad, otherwise truncate last byte if necessary - */ -int bech32_convert_bits(uint8_t* out, size_t* outlen, int outbits, - const uint8_t* in, size_t inlen, int inbits, - int pad); - -/* The charset, and reverse mapping */ -extern const char bech32_charset[32]; -extern const int8_t bech32_charset_rev[128]; - -#endif /* LIGHTNING_COMMON_BECH32_H */ - diff --git a/nostrdb/bolt11/alignof.h b/nostrdb/bolt11/alignof.h new file mode 100644 index 00000000..7cf7b5cc --- /dev/null +++ b/nostrdb/bolt11/alignof.h @@ -0,0 +1,20 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_ALIGNOF_H +#define CCAN_ALIGNOF_H +#include "../config.h" + +/** + * ALIGNOF - get the alignment of a type + * @t: the type to test + * + * This returns a safe alignment for the given type. + */ +#if HAVE_ALIGNOF +/* A GCC extension. */ +#define ALIGNOF(t) __alignof__(t) +#else +/* Alignment by measuring structure padding. */ +#define ALIGNOF(t) ((char *)(&((struct { char c; t _h; } *)0)->_h) - (char *)0) +#endif + +#endif /* CCAN_ALIGNOF_H */ diff --git a/nostrdb/bolt11/amount.c b/nostrdb/bolt11/amount.c new file mode 100644 index 00000000..a0f9ef57 --- /dev/null +++ b/nostrdb/bolt11/amount.c @@ -0,0 +1,566 @@ +#include "../config.h" +#include +#include "mem.h" +#include "talstr.h" +#include "amount.h" +#include "overflows.h" +#include + +bool amount_sat_to_msat(struct amount_msat *msat, + struct amount_sat sat) +{ + if (mul_overflows_u64(sat.satoshis, MSAT_PER_SAT)) + return false; + msat->millisatoshis = sat.satoshis * MSAT_PER_SAT; + return true; +} + +bool amount_msat_to_sat(struct amount_sat *sat, + struct amount_msat msat) +{ + if (msat.millisatoshis % MSAT_PER_SAT) + return false; + sat->satoshis = msat.millisatoshis / MSAT_PER_SAT; + return true; +} + + +/* You can always truncate millisatoshis->satoshis. */ +struct amount_sat amount_msat_to_sat_round_down(struct amount_msat msat) +{ + struct amount_sat sat; + + sat.satoshis = msat.millisatoshis / MSAT_PER_SAT; + return sat; +} + +/* Different formatting by amounts: btc, sat and msat */ +const char *fmt_amount_msat_btc(const tal_t *ctx, + struct amount_msat msat, + bool append_unit) +{ + if (msat.millisatoshis == 0) + return tal_fmt(ctx, append_unit ? "0btc" : "0"); + + return tal_fmt(ctx, "%"PRIu64".%011"PRIu64"%s", + msat.millisatoshis / MSAT_PER_BTC, + msat.millisatoshis % MSAT_PER_BTC, + append_unit ? "btc" : ""); +} + +const char *fmt_amount_msat(const tal_t *ctx, struct amount_msat msat) +{ + return tal_fmt(ctx, "%"PRIu64"msat", msat.millisatoshis); +} + +const char *fmt_amount_sat_btc(const tal_t *ctx, + struct amount_sat sat, + bool append_unit) +{ + if (sat.satoshis == 0) + return tal_fmt(ctx, append_unit ? "0btc" : "0"); + + return tal_fmt(ctx, "%"PRIu64".%08"PRIu64"%s", + sat.satoshis / SAT_PER_BTC, + sat.satoshis % SAT_PER_BTC, + append_unit ? "btc" : ""); +} + +const char *fmt_amount_sat(const tal_t *ctx, struct amount_sat sat) +{ + return tal_fmt(ctx, "%"PRIu64"sat", sat.satoshis); +} + +static bool breakup(const char *str, size_t slen, + /* Length of first numeric part. */ + size_t *whole_number_len, + /* Pointer to post-decimal part, or NULL */ + const char **post_decimal_ptr, + size_t *post_decimal_len, + /* Pointer to suffix, or NULL */ + const char **suffix_ptr, + size_t *suffix_len) +{ + size_t i; + + *whole_number_len = 0; + *post_decimal_len = 0; + *post_decimal_ptr = NULL; + *suffix_ptr = NULL; + *suffix_len = 0; + + for (i = 0;; i++) { + /* The string may be null-terminated. */ + if (i >= slen || str[i] == '\0') + return i != 0; + if (cisdigit(str[i])) + (*whole_number_len)++; + else + break; + } + + if (str[i] == '.') { + i++; + *post_decimal_ptr = str + i; + for (;; i++) { + /* True if > 0 decimals. */ + if (i >= slen || str[i] == '\0') + return str + i != *post_decimal_ptr; + if (cisdigit(str[i])) + (*post_decimal_len)++; + else + break; + } + } + + *suffix_ptr = str + i; + *suffix_len = slen - i; + return true; +} + +static bool from_number(u64 *res, const char *s, size_t len, int tens_factor) +{ + if (len == 0) + return false; + + *res = 0; + for (size_t i = 0; i < len; i++) { + if (mul_overflows_u64(*res, 10)) + return false; + *res *= 10; + assert(cisdigit(s[i])); + if (add_overflows_u64(*res, s[i] - '0')) + return false; + *res += s[i] - '0'; + } + while (tens_factor > 0) { + if (mul_overflows_u64(*res, 10)) + return false; + *res *= 10; + tens_factor--; + } + return true; +} + +static bool from_numbers(u64 *res, + const char *s1, size_t len1, int tens_factor, + const char *s2, size_t len2) +{ + u64 p1, p2; + if (len2 > tens_factor) + return false; + + if (!from_number(&p1, s1, len1, tens_factor) + || !from_number(&p2, s2, len2, tens_factor - (int)len2)) + return false; + + if (add_overflows_u64(p1, p2)) + return false; + + *res = p1 + p2; + return true; +} + +/* Valid strings: + * [0-9]+ => millisatoshi. + * [0-9]+msat => millisatoshi. + * [0-9]+sat => *1000 -> millisatoshi. + * [0-9]+.[0-9]{1,11}btc => millisatoshi. + */ +bool parse_amount_msat(struct amount_msat *msat, const char *s, size_t slen) +{ + size_t whole_number_len, post_decimal_len, suffix_len; + const char *post_decimal_ptr, *suffix_ptr; + + if (!breakup(s, slen, &whole_number_len, + &post_decimal_ptr, &post_decimal_len, + &suffix_ptr, &suffix_len)) + return false; + + if (!post_decimal_ptr && !suffix_ptr) + return from_number(&msat->millisatoshis, s, whole_number_len, 0); + if (!post_decimal_ptr && memstarts_str(suffix_ptr, suffix_len, "msat")) + return from_number(&msat->millisatoshis, s, whole_number_len, 0); + if (!post_decimal_ptr && memstarts_str(suffix_ptr, suffix_len, "sat")) + return from_number(&msat->millisatoshis, s, whole_number_len, 3); + if (memstarts_str(suffix_ptr, suffix_len, "btc")) { + if (post_decimal_len > 0) + return from_numbers(&msat->millisatoshis, + s, whole_number_len, 11, + post_decimal_ptr, post_decimal_len); + return from_number(&msat->millisatoshis, s, whole_number_len, 11); + } + + return false; +} + +/* Valid strings: + * [0-9]+ => satoshi. + * [0-9]+sat => satoshi. + * [0-9]+000msat => satoshi. + * 0msat => 0 satoshi + * [0-9]+.[0-9]{1,8}btc => satoshi. + */ +bool parse_amount_sat(struct amount_sat *sat, const char *s, size_t slen) +{ + size_t whole_number_len, post_decimal_len, suffix_len; + const char *post_decimal_ptr, *suffix_ptr; + + if (!breakup(s, slen, &whole_number_len, + &post_decimal_ptr, &post_decimal_len, + &suffix_ptr, &suffix_len)) + return false; + + if (!post_decimal_ptr && !suffix_ptr) + return from_number(&sat->satoshis, s, whole_number_len, 0); + if (!post_decimal_ptr && memstarts_str(suffix_ptr, suffix_len, "sat")) + return from_number(&sat->satoshis, s, whole_number_len, 0); + if (!post_decimal_ptr && memstarts_str(suffix_ptr, suffix_len, "msat")) { + if (!memends(s, whole_number_len, "000", strlen("000"))) { + if (memstarts_str(s, whole_number_len, "0")) + return from_number(&sat->satoshis, s, + whole_number_len, 0); + return false; + } + return from_number(&sat->satoshis, s, whole_number_len - 3, 0); + } + if (memstarts_str(suffix_ptr, suffix_len, "btc")) { + if (post_decimal_len > 0) + return from_numbers(&sat->satoshis, + s, whole_number_len, 8, + post_decimal_ptr, post_decimal_len); + return from_number(&sat->satoshis, s, whole_number_len, 8); + } + + return false; +} + +WARN_UNUSED_RESULT bool amount_msat_add(struct amount_msat *val, + struct amount_msat a, + struct amount_msat b) +{ + if (add_overflows_u64(a.millisatoshis, b.millisatoshis)) + return false; + + val->millisatoshis = a.millisatoshis + b.millisatoshis; + return true; +} + +WARN_UNUSED_RESULT bool amount_msat_sub(struct amount_msat *val, + struct amount_msat a, + struct amount_msat b) +{ + if (a.millisatoshis < b.millisatoshis) + return false; + + val->millisatoshis = a.millisatoshis - b.millisatoshis; + return true; +} + +WARN_UNUSED_RESULT bool amount_sat_add(struct amount_sat *val, + struct amount_sat a, + struct amount_sat b) +{ + if (add_overflows_u64(a.satoshis, b.satoshis)) + return false; + + val->satoshis = a.satoshis + b.satoshis; + return true; +} + +WARN_UNUSED_RESULT bool amount_sat_sub(struct amount_sat *val, + struct amount_sat a, + struct amount_sat b) +{ + if (a.satoshis < b.satoshis) + return false; + + val->satoshis = a.satoshis - b.satoshis; + return true; +} + +WARN_UNUSED_RESULT bool amount_msat_sub_sat(struct amount_msat *val, + struct amount_msat a, + struct amount_sat b) +{ + struct amount_msat msatb; + + if (!amount_sat_to_msat(&msatb, b)) + return false; + + return amount_msat_sub(val, a, msatb); +} + +WARN_UNUSED_RESULT bool amount_sat_sub_msat(struct amount_msat *val, + struct amount_sat a, + struct amount_msat b) +{ + struct amount_msat msata; + + if (!amount_sat_to_msat(&msata, a)) + return false; + + return amount_msat_sub(val, msata, b); +} + +WARN_UNUSED_RESULT bool amount_msat_add_sat(struct amount_msat *val, + struct amount_msat a, + struct amount_sat b) +{ + struct amount_msat msatb; + + if (!amount_sat_to_msat(&msatb, b)) + return false; + + return amount_msat_add(val, a, msatb); +} + +WARN_UNUSED_RESULT bool amount_msat_scale(struct amount_msat *val, + struct amount_msat msat, + double scale) +{ + double scaled = msat.millisatoshis * scale; + + /* If mantissa is < 64 bits, a naive "if (scaled > + * UINT64_MAX)" doesn't work. Stick to powers of 2. */ + if (scaled >= (double)((u64)1 << 63) * 2) + return false; + val->millisatoshis = scaled; + return true; +} + +WARN_UNUSED_RESULT bool amount_sat_scale(struct amount_sat *val, + struct amount_sat sat, + double scale) +{ + double scaled = sat.satoshis * scale; + + /* If mantissa is < 64 bits, a naive "if (scaled > + * UINT64_MAX)" doesn't work. Stick to powers of 2. */ + if (scaled >= (double)((u64)1 << 63) * 2) + return false; + val->satoshis = scaled; + return true; +} + +bool amount_sat_eq(struct amount_sat a, struct amount_sat b) +{ + return a.satoshis == b.satoshis; +} + +bool amount_sat_zero(struct amount_sat a) +{ + return a.satoshis == 0; +} + +bool amount_msat_zero(struct amount_msat a) +{ + return a.millisatoshis == 0; +} + +bool amount_msat_eq(struct amount_msat a, struct amount_msat b) +{ + return a.millisatoshis == b.millisatoshis; +} + +bool amount_sat_greater(struct amount_sat a, struct amount_sat b) +{ + return a.satoshis > b.satoshis; +} + +bool amount_msat_greater(struct amount_msat a, struct amount_msat b) +{ + return a.millisatoshis > b.millisatoshis; +} + +bool amount_sat_greater_eq(struct amount_sat a, struct amount_sat b) +{ + return a.satoshis >= b.satoshis; +} + +bool amount_msat_greater_eq(struct amount_msat a, struct amount_msat b) +{ + return a.millisatoshis >= b.millisatoshis; +} + +bool amount_sat_less(struct amount_sat a, struct amount_sat b) +{ + return a.satoshis < b.satoshis; +} + +bool amount_msat_less(struct amount_msat a, struct amount_msat b) +{ + return a.millisatoshis < b.millisatoshis; +} + +bool amount_sat_less_eq(struct amount_sat a, struct amount_sat b) +{ + return a.satoshis <= b.satoshis; +} + +bool amount_msat_less_eq(struct amount_msat a, struct amount_msat b) +{ + return a.millisatoshis <= b.millisatoshis; +} + +bool amount_msat_greater_sat(struct amount_msat msat, struct amount_sat sat) +{ + struct amount_msat msat_from_sat; + + if (!amount_sat_to_msat(&msat_from_sat, sat)) + return false; + return msat.millisatoshis > msat_from_sat.millisatoshis; +} + +bool amount_msat_greater_eq_sat(struct amount_msat msat, struct amount_sat sat) +{ + struct amount_msat msat_from_sat; + + if (!amount_sat_to_msat(&msat_from_sat, sat)) + return false; + return msat.millisatoshis >= msat_from_sat.millisatoshis; +} + +bool amount_msat_less_sat(struct amount_msat msat, struct amount_sat sat) +{ + struct amount_msat msat_from_sat; + + if (!amount_sat_to_msat(&msat_from_sat, sat)) + return false; + return msat.millisatoshis < msat_from_sat.millisatoshis; +} + +bool amount_msat_less_eq_sat(struct amount_msat msat, struct amount_sat sat) +{ + struct amount_msat msat_from_sat; + + if (!amount_sat_to_msat(&msat_from_sat, sat)) + return false; + return msat.millisatoshis <= msat_from_sat.millisatoshis; +} + +bool amount_msat_eq_sat(struct amount_msat msat, struct amount_sat sat) +{ + struct amount_msat msat_from_sat; + + if (!amount_sat_to_msat(&msat_from_sat, sat)) + return false; + + return msat.millisatoshis == msat_from_sat.millisatoshis; +} + +bool amount_msat_to_u32(struct amount_msat msat, u32 *millisatoshis) +{ + if (amount_msat_greater_eq(msat, AMOUNT_MSAT(0x100000000))) + return false; + *millisatoshis = (u32)msat.millisatoshis; + return true; +} + +struct amount_msat amount_msat(u64 millisatoshis) +{ + struct amount_msat msat; + + msat.millisatoshis = millisatoshis; + return msat; +} + +struct amount_sat amount_sat(u64 satoshis) +{ + struct amount_sat sat; + + sat.satoshis = satoshis; + return sat; +} + +double amount_msat_ratio(struct amount_msat a, struct amount_msat b) +{ + return (double)a.millisatoshis / b.millisatoshis; +} + +struct amount_msat amount_msat_div(struct amount_msat msat, u64 div) +{ + msat.millisatoshis /= div; + return msat; +} + +struct amount_sat amount_sat_div(struct amount_sat sat, u64 div) +{ + sat.satoshis /= div; + return sat; +} + +bool amount_msat_fee(struct amount_msat *fee, + struct amount_msat amt, + u32 fee_base_msat, + u32 fee_proportional_millionths) +{ + struct amount_msat fee_base, fee_prop; + + /* BOLT #7: + * + * - SHOULD accept HTLCs that pay a fee equal to or greater than: + * - fee_base_msat + ( amount_to_forward * fee_proportional_millionths / 1000000 ) + */ + fee_base.millisatoshis = fee_base_msat; + + if (mul_overflows_u64(amt.millisatoshis, fee_proportional_millionths)) + return false; + fee_prop.millisatoshis = amt.millisatoshis * fee_proportional_millionths + / 1000000; + + return amount_msat_add(fee, fee_base, fee_prop); +} + +bool amount_msat_add_fee(struct amount_msat *amt, + u32 fee_base_msat, + u32 fee_proportional_millionths) +{ + struct amount_msat fee; + + if (!amount_msat_fee(&fee, *amt, + fee_base_msat, fee_proportional_millionths)) + return false; + return amount_msat_add(amt, *amt, fee); +} + +struct amount_sat amount_tx_fee(u32 fee_per_kw, size_t weight) +{ + struct amount_sat fee; + + /* If this overflows, weight must be > 2^32, which is not a real tx */ + assert(!mul_overflows_u64(fee_per_kw, weight)); + fee.satoshis = (u64)fee_per_kw * weight / 1000; + + return fee; +} + +/* +struct amount_msat fromwire_amount_msat(const u8 **cursor, size_t *max) +{ + struct amount_msat msat; + + msat.millisatoshis = fromwire_u64(cursor, max); + return msat; +} + +struct amount_sat fromwire_amount_sat(const u8 **cursor, size_t *max) +{ + struct amount_sat sat; + + sat.satoshis = fromwire_u64(cursor, max); + return sat; +} + +void towire_amount_msat(u8 **pptr, const struct amount_msat msat) +{ + towire_u64(pptr, msat.millisatoshis); +} + +void towire_amount_sat(u8 **pptr, const struct amount_sat sat) +{ + towire_u64(pptr, sat.satoshis); +} + + +*/ diff --git a/nostrdb/bolt11/amount.h b/nostrdb/bolt11/amount.h new file mode 100644 index 00000000..4e6c11ed --- /dev/null +++ b/nostrdb/bolt11/amount.h @@ -0,0 +1,203 @@ +#ifndef LIGHTNING_COMMON_AMOUNT_H +#define LIGHTNING_COMMON_AMOUNT_H +#include "../config.h" +#include "short_types.h" +#include "tal.h" + +#define MSAT_PER_SAT ((u64)1000) +#define SAT_PER_BTC ((u64)100000000) +#define MSAT_PER_BTC (MSAT_PER_SAT * SAT_PER_BTC) + +/* Use these to wrap amounts, for typesafety. Please use ops where possible, + * rather than accessing the members directly. */ +struct amount_sat { + /* Amount in satoshis. */ + u64 satoshis; +}; + +struct amount_msat { + /* Amount in millisatoshis. */ + u64 millisatoshis; +}; + +struct amount_asset { + u64 value; + u8 asset[33]; /* 1 version byte + 32 byte asset_tag */ +}; + +/* For constants only: others must be built from primitives! */ +#if HAVE_BUILTIN_CONSTANT_P +#define AMOUNT_MUST_BE_CONST(c) BUILD_ASSERT_OR_ZERO(IS_COMPILE_CONSTANT(c)) +#else +#define AMOUNT_MUST_BE_CONST(c) 0 +#endif + +/* GCC 4.8.5 (Centos 7.6!) thinks struct casts are not constants, so we + * need to not use a cast for static initializations. */ +#define AMOUNT_MSAT_INIT(msat) \ + { .millisatoshis = (msat) } +#define AMOUNT_SAT_INIT(sat) \ + { .satoshis = (sat) } + +#define AMOUNT_MSAT(constant) \ + ((struct amount_msat){(constant) + AMOUNT_MUST_BE_CONST(constant)}) + +#define AMOUNT_SAT(constant) \ + ((struct amount_sat){(constant) + AMOUNT_MUST_BE_CONST(constant)}) + +/* We do sometimes need to import from raw types, eg. wally or wire fmt */ +struct amount_msat amount_msat(u64 millisatoshis); +struct amount_sat amount_sat(u64 satoshis); + +/* You may not always be able to convert satoshis->millisatoshis. */ + bool amount_sat_to_msat(struct amount_msat *msat, + struct amount_sat sat); + +/* You may not always be able to convert millisatoshis->satoshis without rounding. */ + bool amount_msat_to_sat(struct amount_sat *sat, + struct amount_msat msat); + +/* You can always truncate millisatoshis->satoshis. */ +struct amount_sat amount_msat_to_sat_round_down(struct amount_msat msat); + +/* Simple operations: val = a + b, val = a - b. */ + bool amount_msat_add(struct amount_msat *val, + struct amount_msat a, + struct amount_msat b); + bool amount_msat_sub(struct amount_msat *val, + struct amount_msat a, + struct amount_msat b); + bool amount_sat_add(struct amount_sat *val, + struct amount_sat a, + struct amount_sat b); + bool amount_sat_sub(struct amount_sat *val, + struct amount_sat a, + struct amount_sat b); + bool amount_msat_sub_sat(struct amount_msat *val, + struct amount_msat a, + struct amount_sat b); + bool amount_msat_add_sat(struct amount_msat *val, + struct amount_msat a, + struct amount_sat b); + bool amount_sat_sub_msat(struct amount_msat *val, + struct amount_sat a, + struct amount_msat b); + bool amount_msat_scale(struct amount_msat *val, + struct amount_msat msat, + double scale); + bool amount_sat_scale(struct amount_sat *val, + struct amount_sat sat, + double scale); + +struct amount_msat amount_msat_div(struct amount_msat msat, u64 div); +struct amount_sat amount_sat_div(struct amount_sat sat, u64 div); + +/* Is a == b? */ +bool amount_sat_eq(struct amount_sat a, struct amount_sat b); +bool amount_msat_eq(struct amount_msat a, struct amount_msat b); + +/* Is a zero? */ +bool amount_sat_zero(struct amount_sat a); +bool amount_msat_zero(struct amount_msat a); + +/* Is a > b? */ +bool amount_sat_greater(struct amount_sat a, struct amount_sat b); +bool amount_msat_greater(struct amount_msat a, struct amount_msat b); + +/* Is a >= b */ +bool amount_sat_greater_eq(struct amount_sat a, struct amount_sat b); +bool amount_msat_greater_eq(struct amount_msat a, struct amount_msat b); + +/* Is a < b? */ +bool amount_sat_less(struct amount_sat a, struct amount_sat b); +bool amount_msat_less(struct amount_msat a, struct amount_msat b); + +/* Is a <= b? */ +bool amount_sat_less_eq(struct amount_sat a, struct amount_sat b); +bool amount_msat_less_eq(struct amount_msat a, struct amount_msat b); + +/* Is msat > sat? */ +bool amount_msat_greater_sat(struct amount_msat msat, struct amount_sat sat); +/* Is msat >= sat? */ +bool amount_msat_greater_eq_sat(struct amount_msat msat, struct amount_sat sat); +/* Is msat < sat? */ +bool amount_msat_less_sat(struct amount_msat msat, struct amount_sat sat); +/* Is msat <= sat? */ +bool amount_msat_less_eq_sat(struct amount_msat msat, struct amount_sat sat); +/* Is msat == sat? */ +bool amount_msat_eq_sat(struct amount_msat msat, struct amount_sat sat); + +/* a / b */ +double amount_msat_ratio(struct amount_msat a, struct amount_msat b); + +/* Check whether this asset is actually the main / fee-paying asset of the + * current chain. */ +bool amount_asset_is_main(struct amount_asset *asset); + +/* Convert an amount_sat to an amount_asset */ +struct amount_asset amount_sat_to_asset(struct amount_sat *sat, const u8 *asset); + +/* amount_asset_extract_value -Prefix the amount_asset's value + * to have the 'explicit' marker. Returns NULL if the + * asset was originally blinded. + * FIXME: pass through blinded amounts */ +u8 *amount_asset_extract_value(const tal_t *ctx, struct amount_asset *asset); + +/* Convert from a generic asset to the fee-paying asset if possible. */ +struct amount_sat amount_asset_to_sat(struct amount_asset *asset); + +/* Returns true if msat fits in a u32 value. */ + bool amount_msat_to_u32(struct amount_msat msat, + u32 *millisatoshis); + +/* Common operation: what is the HTLC fee for given feerate? Can overflow! */ + bool amount_msat_fee(struct amount_msat *fee, + struct amount_msat amt, + u32 fee_base_msat, + u32 fee_proportional_millionths); + +/* Same, but add into amt. */ + bool amount_msat_add_fee(struct amount_msat *amt, + u32 fee_base_msat, + u32 fee_proportional_millionths); + +/* What is the fee for this tx weight? */ +struct amount_sat amount_tx_fee(u32 fee_per_kw, size_t weight); + +/* Different formatting by amounts: btc, sat and msat */ +/* => 1.23456789012btc (11 decimals!) */ +const char *fmt_amount_msat_btc(const tal_t *ctx, + struct amount_msat msat, + bool append_unit); +/* => 1234msat */ +const char *fmt_amount_msat(const tal_t *ctx, struct amount_msat msat); + +/* => 1.23456789btc (8 decimals!) */ +const char *fmt_amount_sat_btc(const tal_t *ctx, + struct amount_sat sat, + bool append_unit); +/* => 1234sat */ +const char *fmt_amount_sat(const tal_t *ctx, struct amount_sat sat); + +/* Valid strings: + * [0-9]+ => millisatoshi. + * [0-9]+msat => millisatoshi. + * [0-9]+sat => *1000 -> millisatopshi. + * [0-9]+.[0-9]{1,11}btc => millisatoshi. + */ +bool parse_amount_msat(struct amount_msat *msat, const char *s, size_t slen); + +/* Valid strings: + * [0-9]+ => satoshi. + * [0-9]+sat => satoshi. + * [0-9]+000msat => satoshi. + * [0-9]+.[0-9]{1,8}btc => satoshi. + */ +bool parse_amount_sat(struct amount_sat *sat, const char *s, size_t slen); + +/* Marshal/unmarshal functions */ +struct amount_msat fromwire_amount_msat(const u8 **cursor, size_t *max); +struct amount_sat fromwire_amount_sat(const u8 **cursor, size_t *max); +void towire_amount_msat(u8 **pptr, const struct amount_msat msat); +void towire_amount_sat(u8 **pptr, const struct amount_sat sat); +#endif /* LIGHTNING_COMMON_AMOUNT_H */ diff --git a/nostrdb/bolt11/array_size.h b/nostrdb/bolt11/array_size.h new file mode 100644 index 00000000..3f9494e8 --- /dev/null +++ b/nostrdb/bolt11/array_size.h @@ -0,0 +1,26 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_ARRAY_SIZE_H +#define CCAN_ARRAY_SIZE_H +#include "../config.h" +#include "build_assert.h" + +/** + * ARRAY_SIZE - get the number of elements in a visible array + * @arr: the array whose size you want. + * + * This does not work on pointers, or arrays declared as [], or + * function parameters. With correct compiler support, such usage + * will cause a build error (see build_assert). + */ +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + _array_size_chk(arr)) + +#if HAVE_BUILTIN_TYPES_COMPATIBLE_P && HAVE_TYPEOF +/* Two gcc extensions. + * &a[0] degrades to a pointer: a different type from an array */ +#define _array_size_chk(arr) \ + BUILD_ASSERT_OR_ZERO(!__builtin_types_compatible_p(typeof(arr), \ + typeof(&(arr)[0]))) +#else +#define _array_size_chk(arr) 0 +#endif +#endif /* CCAN_ALIGNOF_H */ diff --git a/nostrdb/bolt11/bech32_util.c b/nostrdb/bolt11/bech32_util.c new file mode 100644 index 00000000..3667c28e --- /dev/null +++ b/nostrdb/bolt11/bech32_util.c @@ -0,0 +1,127 @@ +#include "config.h" +#include "bech32.h" +#include "bech32_util.h" +#include "hash_u5.h" +#include "talstr.h" +#include "tal.h" +#include "short_types.h" +#include + +static u8 get_bit(const u8 *src, size_t bitoff) +{ + return ((src[bitoff / 8] >> (7 - (bitoff % 8))) & 1); +} + +void bech32_push_bits(u5 **data, const void *src, size_t nbits) +{ + size_t i, b; + size_t data_len = tal_count(*data); + + for (i = 0; i < nbits; i += b) { + tal_resize(data, data_len+1); + (*data)[data_len] = 0; + for (b = 0; b < 5; b++) { + (*data)[data_len] <<= 1; + /* If we need bits we don't have, zero */ + if (i+b < nbits) + (*data)[data_len] |= get_bit(src, i+b); + } + data_len++; + } +} + +static u8 get_u5_bit(const u5 *src, size_t bitoff) +{ + return ((src[bitoff / 5] >> (4 - (bitoff % 5))) & 1); +} + +void bech32_pull_bits(u8 **data, const u5 *src, size_t nbits) +{ + size_t i; + size_t data_len = tal_count(*data); + + /* We discard trailing bits. */ + for (i = 0; i + 8 <= nbits; i += 8) { + tal_resize(data, data_len+1); + (*data)[data_len] = 0; + for (size_t b = 0; b < 8; b++) { + (*data)[data_len] <<= 1; + (*data)[data_len] |= get_u5_bit(src, i+b); + } + data_len++; + } +} + +/* Returns a char, tracks case. */ +static int fixup_char(int c, bool *upper, bool *lower) +{ + if (c >= 'A' && c <= 'Z') { + *upper = true; + return c + ('a' - 'A'); + } else if (c >= 'a' && c <= 'z') { + *lower = true; + } + return c; +} + +bool from_bech32_charset(const tal_t *ctx, + const char *bech32, + size_t bech32_len, + char **hrp, u8 **data) +{ + u5 *u5data; + const char *sep; + bool upper = false, lower = false; + size_t datalen; + + sep = memchr(bech32, '1', bech32_len); + if (!sep) + return false; + + *hrp = tal_strndup(ctx, bech32, sep - bech32); + for (size_t i = 0; i < strlen(*hrp); i++) + (*hrp)[i] = fixup_char((*hrp)[i], &upper, &lower); + + datalen = bech32_len - (sep + 1 - bech32); + u5data = tal_arr(NULL, u5, datalen); + for (size_t i = 0; i < datalen; i++) { + int c = sep[1+i]; + if (c < 0 || c > 128) + goto fail; + c = fixup_char(c, &upper, &lower); + if (bech32_charset_rev[c] == -1) + goto fail; + u5data[i] = bech32_charset_rev[c]; + } + + /* Check case consistency */ + if (upper && lower) + goto fail; + + *data = tal_arr(ctx, u8, 0); + bech32_pull_bits(data, u5data, tal_bytelen(u5data) * 5); + tal_free(u5data); + return true; + +fail: + *hrp = tal_free(*hrp); + tal_free(u5data); + return false; +} + +char *to_bech32_charset(const tal_t *ctx, + const char *hrp, const u8 *data) +{ + u5 *u5data = tal_arr(NULL, u5, 0); + char *ret; + + bech32_push_bits(&u5data, data, tal_bytelen(data) * 8); + ret = tal_dup_arr(ctx, char, hrp, strlen(hrp), + 1 + tal_bytelen(u5data) + 1); + ret[strlen(hrp)] = '1'; + for (size_t i = 0; i < tal_bytelen(u5data); i++) + ret[strlen(hrp) + 1 + i] = bech32_charset[u5data[i]]; + ret[strlen(hrp) + 1 + tal_bytelen(u5data)] = '\0'; + tal_free(u5data); + return ret; +} diff --git a/nostrdb/bolt11/bech32_util.h b/nostrdb/bolt11/bech32_util.h new file mode 100644 index 00000000..20031ebc --- /dev/null +++ b/nostrdb/bolt11/bech32_util.h @@ -0,0 +1,28 @@ +#ifndef LIGHTNING_COMMON_BECH32_UTIL_H +#define LIGHTNING_COMMON_BECH32_UTIL_H +#include "../config.h" + +#include "tal.h" +#include "hash_u5.h" + +/** + * Push the bytes in src in 5 bit format onto the end of data. + */ +void bech32_push_bits(u5 **data, const void *src, size_t nbits); + +/** + * Push the bytes in src in 8 bit format onto the end of data. + */ +void bech32_pull_bits(u8 **data, const u5 *src, size_t nbits); + +/** + * Checksumless bech32 routines. + */ +bool from_bech32_charset(const tal_t *ctx, + const char *bech32, size_t bech32_len, + char **hrp, u8 **data); + +char *to_bech32_charset(const tal_t *ctx, + const char *hrp, const u8 *data); + +#endif /* LIGHTNING_COMMON_BECH32_UTIL_H */ diff --git a/nostrdb/bolt11/bolt11.c b/nostrdb/bolt11/bolt11.c new file mode 100644 index 00000000..343a4090 --- /dev/null +++ b/nostrdb/bolt11/bolt11.c @@ -0,0 +1,676 @@ +// +// bolt11.c +// damus +// +// Created by William Casarin on 2022-10-18. +// + +#include "bolt11.h" + +//#include "address.h" +//#include "script.h" +#include "bech32.h" +#include "utf8.h" +#include "../compiler.h" +#include "../endian.h" +#include "list.h" +#include "talstr.h" +#include "tal.h" +#include "node_id.h" +#include "bech32_util.h" +#include "bolt11.h" +#include "amount.h" +#include "array_size.h" +#include "structeq.h" + +//#include "features.h" +#include +#include +#include + +#define MSAT_PER_SAT ((u64)1000) +#define SAT_PER_BTC ((u64)100000000) +#define MSAT_PER_BTC (MSAT_PER_SAT * SAT_PER_BTC) + +struct multiplier { + const char letter; + /* We can't represent p postfix to msat, so we multiply this by 10 */ + u64 m10; +}; + +/* BOLT #11: + * + * The following `multiplier` letters are defined: + * + * * `m` (milli): multiply by 0.001 + * * `u` (micro): multiply by 0.000001 + * * `n` (nano): multiply by 0.000000001 + * * `p` (pico): multiply by 0.000000000001 + */ +static struct multiplier multipliers[] = { + { 'm', 10 * MSAT_PER_BTC / 1000 }, + { 'u', 10 * MSAT_PER_BTC / 1000000 }, + { 'n', 10 * MSAT_PER_BTC / 1000000000 }, + { 'p', 10 * MSAT_PER_BTC / 1000000000000ULL } +}; + +/* If pad is false, we discard any bits which don't fit in the last byte. + * Otherwise we add an extra byte */ +static bool pull_bits(struct hash_u5 *hu5, + u5 **data, size_t *data_len, void *dst, size_t nbits, + bool pad) +{ + size_t n5 = nbits / 5; + size_t len = 0; + + if (nbits % 5) + n5++; + + if (*data_len < n5) + return false; + if (!bech32_convert_bits(dst, &len, 8, *data, n5, 5, pad)) + return false; + if (hu5) + hash_u5(hu5, *data, n5); + *data += n5; + *data_len -= n5; + + return true; +} + +/* For pulling fields where we should have checked it will succeed already. */ +#ifndef NDEBUG +#define pull_bits_certain(hu5, data, data_len, dst, nbits, pad) \ + assert(pull_bits((hu5), (data), (data_len), (dst), (nbits), (pad))) +#else +#define pull_bits_certain pull_bits +#endif + +/* Helper for pulling a variable-length big-endian int. */ +static bool pull_uint(struct hash_u5 *hu5, + u5 **data, size_t *data_len, + u64 *val, size_t databits) +{ + be64 be_val; + + /* Too big. */ + if (databits > sizeof(be_val) * CHAR_BIT) + return false; + if (!pull_bits(hu5, data, data_len, &be_val, databits, true)) + return false; + *val = be64_to_cpu(be_val) >> (sizeof(be_val) * CHAR_BIT - databits); + return true; +} + +static size_t num_u8(size_t num_u5) +{ + return (num_u5 * 5 + 4) / 8; +} + +/* Frees bolt11, returns NULL. */ +static struct bolt11 *decode_fail(struct bolt11 *b11, char **fail, + const char *fmt, ...) + PRINTF_FMT(3,4); + +static struct bolt11 *decode_fail(struct bolt11 *b11, char **fail, + const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + *fail = tal_vfmt(tal_parent(b11), fmt, ap); + va_end(ap); + return tal_free(b11); +} + +/* + * These handle specific fields in the payment request; returning the problem + * if any, or NULL. + */ +static char *unknown_field(struct bolt11 *b11, + struct hash_u5 *hu5, + u5 **data, size_t *data_len, + u5 type, size_t length) +{ + struct bolt11_field *extra = tal(b11, struct bolt11_field); + u8 u8data[num_u8(length)]; + + extra->tag = type; + extra->data = tal_dup_arr(extra, u5, *data, length, 0); + list_add_tail(&b11->extra_fields, &extra->list); + + pull_bits_certain(hu5, data, data_len, u8data, length * 5, true); + return NULL; +} + +/* BOLT #11: + * + * `p` (1): `data_length` 52. 256-bit SHA256 payment_hash. Preimage of this + * provides proof of payment + */ +static void decode_p(struct bolt11 *b11, + struct hash_u5 *hu5, + u5 **data, size_t *data_len, + size_t data_length, bool *have_p) +{ + /* BOLT #11: + * + * A payer... SHOULD use the first `p` field that it did NOT + * skip as the payment hash. + */ + if (*have_p) { + unknown_field(b11, hu5, data, data_len, 'p', data_length); + return; + } + + /* BOLT #11: + * + * A reader... MUST skip over unknown fields, OR an `f` field + * with unknown `version`, OR `p`, `h`, `s` or `n` fields that do + * NOT have `data_length`s of 52, 52, 52 or 53, respectively. + */ + if (data_length != 52) { + unknown_field(b11, hu5, data, data_len, 'p', data_length); + return; + } + + pull_bits_certain(hu5, data, data_len, &b11->payment_hash, 256, false); + *have_p = true; +} + + +static char *utf8_str(const tal_t *ctx, const u8 *buf TAKES, size_t buflen) +{ + char *ret; + + if (!utf8_check(buf, buflen)) { + if (taken(buf)) + tal_free(buf); + return NULL; + } + + /* Add one for nul term */ + ret = tal_dup_arr(ctx, char, (const char *)buf, buflen, 1); + ret[buflen] = '\0'; + return ret; +} + + +/* BOLT #11: + * + * `d` (13): `data_length` variable. Short description of purpose of payment + * (UTF-8), e.g. '1 cup of coffee' or 'ナンセンス 1杯' + */ +static char *decode_d(struct bolt11 *b11, + struct hash_u5 *hu5, + u5 **data, size_t *data_len, + size_t data_length, bool *have_d) +{ + u8 *desc; + if (*have_d) + return unknown_field(b11, hu5, data, data_len, 'd', data_length); + + desc = tal_arr(NULL, u8, data_length * 5 / 8); + pull_bits_certain(hu5, data, data_len, desc, data_length*5, false); + + *have_d = true; + b11->description = utf8_str(b11, take(desc), tal_bytelen(desc)); + if (b11->description) + return NULL; + + return tal_fmt(b11, "d: invalid utf8"); +} + +/* BOLT #11: + * + * `h` (23): `data_length` 52. 256-bit description of purpose of payment + * (SHA256). This is used to commit to an associated description that is over + * 639 bytes, but the transport mechanism for the description in that case is + * transport specific and not defined here. + */ +static void decode_h(struct bolt11 *b11, + struct hash_u5 *hu5, + u5 **data, size_t *data_len, + size_t data_length, bool *have_h) +{ + if (*have_h) { + unknown_field(b11, hu5, data, data_len, 'h', data_length); + return; + } + + /* BOLT #11: + * + * A reader... MUST skip over unknown fields, OR an `f` field + * with unknown `version`, OR `p`, `h`, `s` or `n` fields that do + * NOT have `data_length`s of 52, 52, 52 or 53, respectively. */ + if (data_length != 52) { + unknown_field(b11, hu5, data, data_len, 'h', data_length); + return; + } + + b11->description_hash = tal(b11, struct sha256); + pull_bits_certain(hu5, data, data_len, b11->description_hash, 256, + false); + *have_h = true; +} + +/* BOLT #11: + * + * `x` (6): `data_length` variable. `expiry` time in seconds + * (big-endian). Default is 3600 (1 hour) if not specified. + */ +#define DEFAULT_X 3600 +static char *decode_x(struct bolt11 *b11, + struct hash_u5 *hu5, + u5 **data, size_t *data_len, + size_t data_length, bool *have_x) +{ + if (*have_x) + return unknown_field(b11, hu5, data, data_len, 'x', + data_length); + + /* FIXME: Put upper limit in bolt 11 */ + if (!pull_uint(hu5, data, data_len, &b11->expiry, data_length * 5)) + return tal_fmt(b11, "x: length %zu chars is excessive", + *data_len); + + *have_x = true; + return NULL; +} + +/* BOLT #11: + * + * `c` (24): `data_length` variable. `min_final_cltv_expiry` to use for the + * last HTLC in the route. Default is 18 if not specified. + */ +static char *decode_c(struct bolt11 *b11, + struct hash_u5 *hu5, + u5 **data, size_t *data_len, + size_t data_length, bool *have_c) +{ + u64 c; + if (*have_c) + return unknown_field(b11, hu5, data, data_len, 'c', + data_length); + + /* FIXME: Put upper limit in bolt 11 */ + if (!pull_uint(hu5, data, data_len, &c, data_length * 5)) + return tal_fmt(b11, "c: length %zu chars is excessive", + *data_len); + b11->min_final_cltv_expiry = (u32)c; + /* Can overflow, since c is 64 bits but value must be < 32 bits */ + if (b11->min_final_cltv_expiry != c) + return tal_fmt(b11, "c: %"PRIu64" is too large", c); + + *have_c = true; + return NULL; +} + +static char *decode_n(struct bolt11 *b11, + struct hash_u5 *hu5, + u5 **data, size_t *data_len, + size_t data_length, bool *have_n) +{ + if (*have_n) + return unknown_field(b11, hu5, data, data_len, 'n', + data_length); + + /* BOLT #11: + * + * A reader... MUST skip over unknown fields, OR an `f` field + * with unknown `version`, OR `p`, `h`, `s` or `n` fields that do + * NOT have `data_length`s of 52, 52, 52 or 53, respectively. */ + if (data_length != 53) + return unknown_field(b11, hu5, data, data_len, 'n', + data_length); + + pull_bits_certain(hu5, data, data_len, &b11->receiver_id.k, + data_length * 5, false); + /* + if (!node_id_valid(&b11->receiver_id)) + return tal_fmt(b11, "n: invalid pubkey %s", + node_id_to_hexstr(b11, &b11->receiver_id)); + */ + + *have_n = true; + return NULL; +} + +/* BOLT #11: + * + * `m` (27): `data_length` variable. Additional metadata to attach to + * the payment. Note that the size of this field is limited by the + * maximum hop payload size. Long metadata fields reduce the maximum + * route length. + */ +static char *decode_m(struct bolt11 *b11, + struct hash_u5 *hu5, + u5 **data, size_t *data_len, + size_t data_length, + bool *have_m) +{ + size_t mlen = (data_length * 5) / 8; + + if (*have_m) + return unknown_field(b11, hu5, data, data_len, 'm', + data_length); + + b11->metadata = tal_arr(b11, u8, mlen); + pull_bits_certain(hu5, data, data_len, b11->metadata, + data_length * 5, false); + + *have_m = true; + return NULL; +} + +struct bolt11 *new_bolt11(const tal_t *ctx) +{ + struct bolt11 *b11 = tal(ctx, struct bolt11); + + list_head_init(&b11->extra_fields); + b11->description = NULL; + b11->description_hash = NULL; + b11->fallbacks = NULL; + b11->msat = NULL; + b11->expiry = DEFAULT_X; + b11->features = tal_arr(b11, u8, 0); + /* BOLT #11: + * - if the `c` field (`min_final_cltv_expiry`) is not provided: + * - MUST use an expiry delta of at least 18 when making the payment + */ + b11->min_final_cltv_expiry = 18; + //b11->payment_secret = NULL; + b11->metadata = NULL; + + //if (msat) + //b11->msat = tal_dup(b11, struct amount_msat, msat); + return b11; +} + +/* Define sha256_eq. */ +//STRUCTEQ_DEF(sha256, 0, u); + +/* Extracts signature but does not check it. */ +struct bolt11 *bolt11_decode_nosig(const tal_t *ctx, const char *str, u5 **sig, char **fail) +{ + char *hrp, *amountstr, *prefix; + u5 *data; + size_t data_len; + struct bolt11 *b11 = new_bolt11(ctx); + struct hash_u5 hu5; + bool have_p = false, have_d = false, have_h = false, have_n = false, + have_x = false, have_c = false, have_m = false; + + /* BOLT #11: + * + * If a URI scheme is desired, the current recommendation is to either + * use 'lightning:' as a prefix before the BOLT-11 encoding + */ + if (strstarts(str, "lightning:") || strstarts(str, "LIGHTNING:")) + str += strlen("lightning:"); + + if (strlen(str) < 8) + return decode_fail(b11, fail, "Bad bech32 string"); + + hrp = tal_arr(b11, char, strlen(str) - 6); + data = tal_arr(b11, u5, strlen(str) - 8); + + if (bech32_decode(hrp, data, &data_len, str, (size_t)-1) + != BECH32_ENCODING_BECH32) + return decode_fail(b11, fail, "Bad bech32 string"); + + /* For signature checking at the end. */ + hash_u5_init(&hu5, hrp); + + /* BOLT #11: + * + * The human-readable part of a Lightning invoice consists of two sections: + * 1. `prefix`: `ln` + BIP-0173 currency prefix (e.g. `lnbc` for Bitcoin mainnet, + * `lntb` for Bitcoin testnet, `lntbs` for Bitcoin signet, and `lnbcrt` for Bitcoin regtest) + * 1. `amount`: optional number in that currency, followed by an optional + * `multiplier` letter. The unit encoded here is the 'social' convention of a payment unit -- in the case of Bitcoin the unit is 'bitcoin' NOT satoshis. + */ + prefix = tal_strndup(b11, hrp, strcspn(hrp, "0123456789")); + + /* BOLT #11: + * + * A reader...if it does NOT understand the `prefix`... MUST fail the payment. + */ + if (!strstarts(prefix, "ln")) + return decode_fail(b11, fail, + "Prefix '%s' does not start with ln", prefix); + + /* BOLT #11: + * + * - if the `amount` is empty: + * */ + amountstr = tal_strdup(b11, hrp + strlen(prefix)); + if (streq(amountstr, "")) { + /* BOLT #11: + * + * - SHOULD indicate to the payer that amount is unspecified. + */ + b11->msat = NULL; + } else { + u64 m10 = 10 * MSAT_PER_BTC; /* Pico satoshis in a Bitcoin */ + u64 amount; + char *end; + + /* Gather and trim multiplier */ + end = amountstr + strlen(amountstr)-1; + for (size_t i = 0; i < ARRAY_SIZE(multipliers); i++) { + if (*end == multipliers[i].letter) { + m10 = multipliers[i].m10; + *end = '\0'; + break; + } + } + + /* BOLT #11: + * + * if `amount` contains a non-digit OR is followed by + * anything except a `multiplier` (see table above)... MUST fail the + * payment. + **/ + amount = strtoull(amountstr, &end, 10); + if (amount == ULLONG_MAX && errno == ERANGE) + return decode_fail(b11, fail, + "Invalid amount '%s'", amountstr); + if (!*amountstr || *end) + return decode_fail(b11, fail, + "Invalid amount postfix '%s'", end); + + /* BOLT #11: + * + * if the `multiplier` is present... MUST multiply + * `amount` by the `multiplier` value to derive the + * amount required for payment. + */ + b11->msat = tal(b11, struct amount_msat); + /* BOLT #11: + * + * - if multiplier is `p` and the last decimal of `amount` is + * not 0: + * - MUST fail the payment. + */ + if (amount * m10 % 10 != 0) + return decode_fail(b11, fail, + "Invalid sub-millisatoshi amount" + " '%sp'", amountstr); + + *b11->msat = amount_msat(amount * m10 / 10); + } + + /* BOLT #11: + * + * The data part of a Lightning invoice consists of multiple sections: + * + * 1. `timestamp`: seconds-since-1970 (35 bits, big-endian) + * 1. zero or more tagged parts + * 1. `signature`: Bitcoin-style signature of above (520 bits) + */ + if (!pull_uint(&hu5, &data, &data_len, &b11->timestamp, 35)) + return decode_fail(b11, fail, "Can't get 35-bit timestamp"); + + while (data_len > 520 / 5) { + const char *problem = NULL; + u64 type, data_length; + + /* BOLT #11: + * + * Each Tagged Field is of the form: + * + * 1. `type` (5 bits) + * 1. `data_length` (10 bits, big-endian) + * 1. `data` (`data_length` x 5 bits) + */ + if (!pull_uint(&hu5, &data, &data_len, &type, 5) + || !pull_uint(&hu5, &data, &data_len, &data_length, 10)) + return decode_fail(b11, fail, + "Can't get tag and length"); + + /* Can't exceed total data remaining. */ + if (data_length > data_len) + return decode_fail(b11, fail, "%c: truncated", + bech32_charset[type]); + + switch (bech32_charset[type]) { + case 'p': + decode_p(b11, &hu5, &data, &data_len, data_length, + &have_p); + break; + + case 'd': + problem = decode_d(b11, &hu5, &data, &data_len, + data_length, &have_d); + break; + + case 'h': + decode_h(b11, &hu5, &data, &data_len, data_length, + &have_h); + break; + + case 'n': + problem = decode_n(b11, &hu5, &data, + &data_len, data_length, + &have_n); + break; + + case 'x': + problem = decode_x(b11, &hu5, &data, + &data_len, data_length, + &have_x); + break; + + case 'c': + problem = decode_c(b11, &hu5, &data, + &data_len, data_length, + &have_c); + break; + + /* + case 'f': + problem = decode_f(b11, &hu5, &data, + &data_len, data_length); + break; + case 'r': + problem = decode_r(b11, &hu5, &data, &data_len, + data_length); + break; + case '9': + problem = decode_9(b11, our_features, &hu5, + &data, &data_len, + data_length); + break; + case 's': + problem = decode_s(b11, &hu5, &data, &data_len, + data_length, &have_s); + break; + */ + case 'm': + problem = decode_m(b11, &hu5, &data, &data_len, + data_length, &have_m); + break; + default: + unknown_field(b11, &hu5, &data, &data_len, + bech32_charset[type], data_length); + } + if (problem) + return decode_fail(b11, fail, "%s", problem); + } + + if (!have_p) + return decode_fail(b11, fail, "No valid 'p' field found"); + + *sig = tal_dup_arr(ctx, u5, data, data_len, 0); + return b11; +} + +/* Decodes and checks signature; returns NULL on error. */ +struct bolt11 *bolt11_decode(const tal_t *ctx, const char *str, char **fail) +{ + u5 *sigdata; + size_t data_len; + u8 sig_and_recid[65]; + //secp256k1_ecdsa_recoverable_signature sig; + struct bolt11 *b11; + + b11 = bolt11_decode_nosig(ctx, str, &sigdata, fail); + if (!b11) + return NULL; + + /* BOLT #11: + * + * A writer...MUST set `signature` to a valid 512-bit + * secp256k1 signature of the SHA2 256-bit hash of the + * human-readable part, represented as UTF-8 bytes, + * concatenated with the data part (excluding the signature) + * with 0 bits appended to pad the data to the next byte + * boundary, with a trailing byte containing the recovery ID + * (0, 1, 2, or 3). + */ + data_len = tal_count(sigdata); + if (!pull_bits(NULL, &sigdata, &data_len, sig_and_recid, 520, false)) + return decode_fail(b11, fail, "signature truncated"); + + assert(data_len == 0); + + /* + if (!secp256k1_ecdsa_recoverable_signature_parse_compact + (secp256k1_ctx, &sig, sig_and_recid, sig_and_recid[64])) + return decode_fail(b11, fail, "signature invalid"); + + secp256k1_ecdsa_recoverable_signature_convert(secp256k1_ctx, + &b11->sig, &sig); + */ + + /* BOLT #11: + * + * A reader... MUST check that the `signature` is valid (see + * the `n` tagged field specified below). ... A reader... + * MUST use the `n` field to validate the signature instead of + * performing signature recovery. + */ + /* + if (!have_n) { + struct pubkey k; + if (!secp256k1_ecdsa_recover(secp256k1_ctx, + &k.pubkey, + &sig, + (const u8 *)&hash)) + return decode_fail(b11, fail, + "signature recovery failed"); + node_id_from_pubkey(&b11->receiver_id, &k); + } else { + struct pubkey k; + if (!pubkey_from_node_id(&k, &b11->receiver_id)) + abort(); + if (!secp256k1_ecdsa_verify(secp256k1_ctx, &b11->sig, + (const u8 *)&hash, + &k.pubkey)) + return decode_fail(b11, fail, "invalid signature"); + } + */ + + return b11; +} diff --git a/nostrdb/bolt11/bolt11.h b/nostrdb/bolt11/bolt11.h new file mode 100644 index 00000000..2831eb94 --- /dev/null +++ b/nostrdb/bolt11/bolt11.h @@ -0,0 +1,104 @@ +#ifndef LIGHTNING_COMMON_BOLT11_H +#define LIGHTNING_COMMON_BOLT11_H + +#include "short_types.h" +#include "hash_u5.h" +#include "list.h" +#include "node_id.h" +//#include + +/* We only have 10 bits for the field length, meaning < 640 bytes */ +#define BOLT11_FIELD_BYTE_LIMIT ((1 << 10) * 5 / 8) + +/* BOLT #11: + * * `c` (24): `data_length` variable. + * `min_final_cltv_expiry` to use for the last HTLC in the route. + * Default is 18 if not specified. + */ +#define DEFAULT_FINAL_CLTV_DELTA 18 + +struct feature_set; + +struct bolt11_field { + struct list_node list; + + char tag; + u5 *data; +}; + +/* BOLT #11: + * * `pubkey` (264 bits) + * * `short_channel_id` (64 bits) + * * `fee_base_msat` (32 bits, big-endian) + * * `fee_proportional_millionths` (32 bits, big-endian) + * * `cltv_expiry_delta` (16 bits, big-endian) + */ + +/* +struct route_info { + struct node_id pubkey; + u16 cltv_expiry_delta; + struct short_channel_id short_channel_id; + u32 fee_base_msat, fee_proportional_millionths; +}; + */ + +struct bolt11 { + const struct chainparams *chain; + u64 timestamp; + struct amount_msat *msat; /* NULL if not specified. */ + + struct sha256 payment_hash; + struct node_id receiver_id; + + /* description_hash valid if and only if description is NULL. */ + const char *description; + struct sha256 *description_hash; + + /* How many seconds to pay from @timestamp above. */ + u64 expiry; + + /* How many blocks final hop requires. */ + u32 min_final_cltv_expiry; + + /* If non-NULL, indicates fallback addresses to pay to. */ + const u8 **fallbacks; + + /* If non-NULL: array of route arrays */ + //struct route_info **routes; + + /* signature of sha256 of entire thing. */ + //secp256k1_ecdsa_signature sig; + + /* payment secret, if any. */ + //struct secret *payment_secret; + + /* Features bitmap, if any. */ + u8 *features; + + /* Optional metadata to send with payment. */ + u8 *metadata; + + struct list_head extra_fields; +}; + +/* Decodes and checks signature; returns NULL on error; description is + * (optional) out-of-band description of payment, for `h` field. + * fset is NULL to accept any features (usually not desirable!). + * + * if @must_be_chain is not NULL, fails unless it's this chain. + */ +struct bolt11 *bolt11_decode(const tal_t *ctx, const char *str, char **fail); + +/* Extracts signature but does not check it. */ +struct bolt11 *bolt11_decode_nosig(const tal_t *ctx, const char *str, u5 **sigdata, char **fail); + +/* Initialize an empty bolt11 struct with optional amount */ +struct bolt11 *new_bolt11(const tal_t *ctx); + +#if DEVELOPER +/* Flag for tests to suppress `min_final_cltv_expiry` field generation, to match test vectors */ +extern bool dev_bolt11_no_c_generation; +#endif + +#endif /* LIGHTNING_COMMON_BOLT11_H */ diff --git a/nostrdb/bolt11/build_assert.h b/nostrdb/bolt11/build_assert.h new file mode 100644 index 00000000..6df9dae7 --- /dev/null +++ b/nostrdb/bolt11/build_assert.h @@ -0,0 +1,40 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_BUILD_ASSERT_H +#define CCAN_BUILD_ASSERT_H + +/** + * BUILD_ASSERT - assert a build-time dependency. + * @cond: the compile-time condition which must be true. + * + * Your compile will fail if the condition isn't true, or can't be evaluated + * by the compiler. This can only be used within a function. + * + * Example: + * #include + * ... + * static char *foo_to_char(struct foo *foo) + * { + * // This code needs string to be at start of foo. + * BUILD_ASSERT(offsetof(struct foo, string) == 0); + * return (char *)foo; + * } + */ +#define BUILD_ASSERT(cond) \ + do { (void) sizeof(char [1 - 2*!(cond)]); } while(0) + +/** + * BUILD_ASSERT_OR_ZERO - assert a build-time dependency, as an expression. + * @cond: the compile-time condition which must be true. + * + * Your compile will fail if the condition isn't true, or can't be evaluated + * by the compiler. This can be used in an expression: its value is "0". + * + * Example: + * #define foo_to_char(foo) \ + * ((char *)(foo) \ + * + BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0)) + */ +#define BUILD_ASSERT_OR_ZERO(cond) \ + (sizeof(char [1 - 2*!(cond)]) - 1) + +#endif /* CCAN_BUILD_ASSERT_H */ diff --git a/nostrdb/bolt11/check_type.h b/nostrdb/bolt11/check_type.h new file mode 100644 index 00000000..0492b56b --- /dev/null +++ b/nostrdb/bolt11/check_type.h @@ -0,0 +1,64 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_CHECK_TYPE_H +#define CCAN_CHECK_TYPE_H +#include "../config.h" + +/** + * check_type - issue a warning or build failure if type is not correct. + * @expr: the expression whose type we should check (not evaluated). + * @type: the exact type we expect the expression to be. + * + * This macro is usually used within other macros to try to ensure that a macro + * argument is of the expected type. No type promotion of the expression is + * done: an unsigned int is not the same as an int! + * + * check_type() always evaluates to 0. + * + * If your compiler does not support typeof, then the best we can do is fail + * to compile if the sizes of the types are unequal (a less complete check). + * + * Example: + * // They should always pass a 64-bit value to _set_some_value! + * #define set_some_value(expr) \ + * _set_some_value((check_type((expr), uint64_t), (expr))) + */ + +/** + * check_types_match - issue a warning or build failure if types are not same. + * @expr1: the first expression (not evaluated). + * @expr2: the second expression (not evaluated). + * + * This macro is usually used within other macros to try to ensure that + * arguments are of identical types. No type promotion of the expressions is + * done: an unsigned int is not the same as an int! + * + * check_types_match() always evaluates to 0. + * + * If your compiler does not support typeof, then the best we can do is fail + * to compile if the sizes of the types are unequal (a less complete check). + * + * Example: + * // Do subtraction to get to enclosing type, but make sure that + * // pointer is of correct type for that member. + * #define container_of(mbr_ptr, encl_type, mbr) \ + * (check_types_match((mbr_ptr), &((encl_type *)0)->mbr), \ + * ((encl_type *) \ + * ((char *)(mbr_ptr) - offsetof(encl_type, mbr)))) + */ +#if HAVE_TYPEOF +#define check_type(expr, type) \ + ((typeof(expr) *)0 != (type *)0) + +#define check_types_match(expr1, expr2) \ + ((typeof(expr1) *)0 != (typeof(expr2) *)0) +#else +#include +/* Without typeof, we can only test the sizes. */ +#define check_type(expr, type) \ + BUILD_ASSERT_OR_ZERO(sizeof(expr) == sizeof(type)) + +#define check_types_match(expr1, expr2) \ + BUILD_ASSERT_OR_ZERO(sizeof(expr1) == sizeof(expr2)) +#endif /* HAVE_TYPEOF */ + +#endif /* CCAN_CHECK_TYPE_H */ diff --git a/nostrdb/bolt11/container_of.h b/nostrdb/bolt11/container_of.h new file mode 100644 index 00000000..b27d7f3d --- /dev/null +++ b/nostrdb/bolt11/container_of.h @@ -0,0 +1,145 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_CONTAINER_OF_H +#define CCAN_CONTAINER_OF_H +#include + +#include "../config.h" +#include "check_type.h" + +/** + * container_of - get pointer to enclosing structure + * @member_ptr: pointer to the structure member + * @containing_type: the type this member is within + * @member: the name of this member within the structure. + * + * Given a pointer to a member of a structure, this macro does pointer + * subtraction to return the pointer to the enclosing type. + * + * Example: + * struct foo { + * int fielda, fieldb; + * // ... + * }; + * struct info { + * int some_other_field; + * struct foo my_foo; + * }; + * + * static struct info *foo_to_info(struct foo *foo) + * { + * return container_of(foo, struct info, my_foo); + * } + */ +#define container_of(member_ptr, containing_type, member) \ + ((containing_type *) \ + ((char *)(member_ptr) \ + - container_off(containing_type, member)) \ + + check_types_match(*(member_ptr), ((containing_type *)0)->member)) + + +/** + * container_of_or_null - get pointer to enclosing structure, or NULL + * @member_ptr: pointer to the structure member + * @containing_type: the type this member is within + * @member: the name of this member within the structure. + * + * Given a pointer to a member of a structure, this macro does pointer + * subtraction to return the pointer to the enclosing type, unless it + * is given NULL, in which case it also returns NULL. + * + * Example: + * struct foo { + * int fielda, fieldb; + * // ... + * }; + * struct info { + * int some_other_field; + * struct foo my_foo; + * }; + * + * static struct info *foo_to_info_allowing_null(struct foo *foo) + * { + * return container_of_or_null(foo, struct info, my_foo); + * } + */ +static inline char *container_of_or_null_(void *member_ptr, size_t offset) +{ + return member_ptr ? (char *)member_ptr - offset : NULL; +} +#define container_of_or_null(member_ptr, containing_type, member) \ + ((containing_type *) \ + container_of_or_null_(member_ptr, \ + container_off(containing_type, member)) \ + + check_types_match(*(member_ptr), ((containing_type *)0)->member)) + +/** + * container_off - get offset to enclosing structure + * @containing_type: the type this member is within + * @member: the name of this member within the structure. + * + * Given a pointer to a member of a structure, this macro does + * typechecking and figures out the offset to the enclosing type. + * + * Example: + * struct foo { + * int fielda, fieldb; + * // ... + * }; + * struct info { + * int some_other_field; + * struct foo my_foo; + * }; + * + * static struct info *foo_to_info(struct foo *foo) + * { + * size_t off = container_off(struct info, my_foo); + * return (void *)((char *)foo - off); + * } + */ +#define container_off(containing_type, member) \ + offsetof(containing_type, member) + +/** + * container_of_var - get pointer to enclosing structure using a variable + * @member_ptr: pointer to the structure member + * @container_var: a pointer of same type as this member's container + * @member: the name of this member within the structure. + * + * Given a pointer to a member of a structure, this macro does pointer + * subtraction to return the pointer to the enclosing type. + * + * Example: + * static struct info *foo_to_i(struct foo *foo) + * { + * struct info *i = container_of_var(foo, i, my_foo); + * return i; + * } + */ +#if HAVE_TYPEOF +#define container_of_var(member_ptr, container_var, member) \ + container_of(member_ptr, typeof(*container_var), member) +#else +#define container_of_var(member_ptr, container_var, member) \ + ((void *)((char *)(member_ptr) - \ + container_off_var(container_var, member))) +#endif + +/** + * container_off_var - get offset of a field in enclosing structure + * @container_var: a pointer to a container structure + * @member: the name of a member within the structure. + * + * Given (any) pointer to a structure and a its member name, this + * macro does pointer subtraction to return offset of member in a + * structure memory layout. + * + */ +#if HAVE_TYPEOF +#define container_off_var(var, member) \ + container_off(typeof(*var), member) +#else +#define container_off_var(var, member) \ + ((const char *)&(var)->member - (const char *)(var)) +#endif + +#endif /* CCAN_CONTAINER_OF_H */ diff --git a/nostrdb/bolt11/cppmagic.h b/nostrdb/bolt11/cppmagic.h new file mode 100644 index 00000000..fa8d70e2 --- /dev/null +++ b/nostrdb/bolt11/cppmagic.h @@ -0,0 +1,191 @@ +/* MIT (BSD) license - see LICENSE file for details */ +#ifndef CCAN_CPPMAGIC_H +#define CCAN_CPPMAGIC_H + +/** + * CPPMAGIC_NOTHING - expands to nothing + */ +#define CPPMAGIC_NOTHING() + +/** + * CPPMAGIC_STRINGIFY - convert arguments to a string literal + */ +#define _CPPMAGIC_STRINGIFY(...) #__VA_ARGS__ +#define CPPMAGIC_STRINGIFY(...) _CPPMAGIC_STRINGIFY(__VA_ARGS__) + +/** + * CPPMAGIC_GLUE2 - glue arguments together + * + * CPPMAGIC_GLUE2(@a_, @b_) + * expands to the expansion of @a_ followed immediately + * (combining tokens) by the expansion of @b_ + */ +#define _CPPMAGIC_GLUE2(a_, b_) a_##b_ +#define CPPMAGIC_GLUE2(a_, b_) _CPPMAGIC_GLUE2(a_, b_) + +/** + * CPPMAGIC_1ST - return 1st argument + * + * CPPMAGIC_1ST(@a_, ...) + * expands to the expansion of @a_ + */ +#define CPPMAGIC_1ST(a_, ...) a_ + +/** + * CPPMAGIC_2ND - return 2nd argument + * + * CPPMAGIC_2ST(@a_, @b_, ...) + * expands to the expansion of @b_ + */ +#define CPPMAGIC_2ND(a_, b_, ...) b_ + +/** + * CPPMAGIC_ISZERO - is argument '0' + * + * CPPMAGIC_ISZERO(@a) + * expands to '1' if @a is '0', otherwise expands to '0'. + */ +#define _CPPMAGIC_ISPROBE(...) CPPMAGIC_2ND(__VA_ARGS__, 0) +#define _CPPMAGIC_PROBE() $, 1 +#define _CPPMAGIC_ISZERO_0 _CPPMAGIC_PROBE() +#define CPPMAGIC_ISZERO(a_) \ + _CPPMAGIC_ISPROBE(CPPMAGIC_GLUE2(_CPPMAGIC_ISZERO_, a_)) + +/** + * CPPMAGIC_NONZERO - is argument not '0' + * + * CPPMAGIC_NONZERO(@a) + * expands to '0' if @a is '0', otherwise expands to '1'. + */ +#define CPPMAGIC_NONZERO(a_) CPPMAGIC_ISZERO(CPPMAGIC_ISZERO(a_)) + +/** + * CPPMAGIC_NONEMPTY - does the macro have any arguments? + * + * CPPMAGIC_NONEMPTY() + * expands to '0' + * CPPMAGIC_NONEMPTY(@a) + * CPPMAGIC_NONEMPTY(@a, ...) + * expand to '1' + */ +#define _CPPMAGIC_EOA() 0 +#define CPPMAGIC_NONEMPTY(...) \ + CPPMAGIC_NONZERO(CPPMAGIC_1ST(_CPPMAGIC_EOA __VA_ARGS__)()) + +/** + * CPPMAGIC_ISEMPTY - does the macro have no arguments? + * + * CPPMAGIC_ISEMPTY() + * expands to '1' + * CPPMAGIC_ISEMPTY(@a) + * CPPMAGIC_ISEMPTY(@a, ...) + * expand to '0' + */ +#define CPPMAGIC_ISEMPTY(...) \ + CPPMAGIC_ISZERO(CPPMAGIC_NONEMPTY(__VA_ARGS__)) + +/* + * CPPMAGIC_IFELSE - preprocessor conditional + * + * CPPMAGIC_IFELSE(@cond)(@if)(@else) + * expands to @else if @cond is '0', otherwise expands to @if + */ +#define _CPPMAGIC_IF_0(...) _CPPMAGIC_IF_0_ELSE +#define _CPPMAGIC_IF_1(...) __VA_ARGS__ _CPPMAGIC_IF_1_ELSE +#define _CPPMAGIC_IF_0_ELSE(...) __VA_ARGS__ +#define _CPPMAGIC_IF_1_ELSE(...) +#define _CPPMAGIC_IFELSE(cond_) CPPMAGIC_GLUE2(_CPPMAGIC_IF_, cond_) +#define CPPMAGIC_IFELSE(cond_) \ + _CPPMAGIC_IFELSE(CPPMAGIC_NONZERO(cond_)) + +/** + * CPPMAGIC_EVAL - force multiple expansion passes + * + * Forces macros in the arguments to be expanded repeatedly (up to + * 1024 times) even when CPP would usually stop expanding. + */ +#define CPPMAGIC_EVAL1(...) __VA_ARGS__ +#define CPPMAGIC_EVAL2(...) \ + CPPMAGIC_EVAL1(CPPMAGIC_EVAL1(__VA_ARGS__)) +#define CPPMAGIC_EVAL4(...) \ + CPPMAGIC_EVAL2(CPPMAGIC_EVAL2(__VA_ARGS__)) +#define CPPMAGIC_EVAL8(...) \ + CPPMAGIC_EVAL4(CPPMAGIC_EVAL4(__VA_ARGS__)) +#define CPPMAGIC_EVAL16(...) \ + CPPMAGIC_EVAL8(CPPMAGIC_EVAL8(__VA_ARGS__)) +#define CPPMAGIC_EVAL32(...) \ + CPPMAGIC_EVAL16(CPPMAGIC_EVAL16(__VA_ARGS__)) +#define CPPMAGIC_EVAL64(...) \ + CPPMAGIC_EVAL32(CPPMAGIC_EVAL32(__VA_ARGS__)) +#define CPPMAGIC_EVAL128(...) \ + CPPMAGIC_EVAL64(CPPMAGIC_EVAL64(__VA_ARGS__)) +#define CPPMAGIC_EVAL256(...) \ + CPPMAGIC_EVAL128(CPPMAGIC_EVAL128(__VA_ARGS__)) +#define CPPMAGIC_EVAL512(...) \ + CPPMAGIC_EVAL256(CPPMAGIC_EVAL256(__VA_ARGS__)) +#define CPPMAGIC_EVAL1024(...) \ + CPPMAGIC_EVAL512(CPPMAGIC_EVAL512(__VA_ARGS__)) +#define CPPMAGIC_EVAL(...) CPPMAGIC_EVAL1024(__VA_ARGS__) + +/** + * CPPMAGIC_DEFER1, CPPMAGIC_DEFER2 - defer expansion + */ +#define CPPMAGIC_DEFER1(a_) a_ CPPMAGIC_NOTHING() +#define CPPMAGIC_DEFER2(a_) a_ CPPMAGIC_NOTHING CPPMAGIC_NOTHING()() + +/** + * CPPMAGIC_MAP - iterate another macro across arguments + * @m: name of a one argument macro + * + * CPPMAGIC_MAP(@m, @a1, @a2, ... @an) + * expands to the expansion of @m(@a1) , @m(@a2) , ... , @m(@an) + */ +#define _CPPMAGIC_MAP_() _CPPMAGIC_MAP +#define _CPPMAGIC_MAP(m_, a_, ...) \ + m_(a_) \ + CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \ + (, CPPMAGIC_DEFER2(_CPPMAGIC_MAP_)()(m_, __VA_ARGS__)) \ + () +#define CPPMAGIC_MAP(m_, ...) \ + CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \ + (CPPMAGIC_EVAL(_CPPMAGIC_MAP(m_, __VA_ARGS__))) \ + () + +/** + * CPPMAGIC_2MAP - iterate another macro across pairs of arguments + * @m: name of a two argument macro + * + * CPPMAGIC_2MAP(@m, @a1, @b1, @a2, @b2, ..., @an, @bn) + * expands to the expansion of + * @m(@a1, @b1) , @m(@a2, @b2) , ... , @m(@an, @bn) + */ +#define _CPPMAGIC_2MAP_() _CPPMAGIC_2MAP +#define _CPPMAGIC_2MAP(m_, a_, b_, ...) \ + m_(a_, b_) \ + CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \ + (, CPPMAGIC_DEFER2(_CPPMAGIC_2MAP_)()(m_, __VA_ARGS__)) \ + () +#define CPPMAGIC_2MAP(m_, ...) \ + CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \ + (CPPMAGIC_EVAL(_CPPMAGIC_2MAP(m_, __VA_ARGS__))) \ + () + +/** + * CPPMAGIC_JOIN - separate arguments with given delimiter + * @d: delimiter + * + * CPPMAGIC_JOIN(@d, @a1, @a2, ..., @an) + * expands to the expansion of @a1 @d @a2 @d ... @d @an + */ +#define _CPPMAGIC_JOIN_() _CPPMAGIC_JOIN +#define _CPPMAGIC_JOIN(d_, a_, ...) \ + a_ \ + CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \ + (d_ CPPMAGIC_DEFER2(_CPPMAGIC_JOIN_)()(d_, __VA_ARGS__)) \ + () +#define CPPMAGIC_JOIN(d_, ...) \ + CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \ + (CPPMAGIC_EVAL(_CPPMAGIC_JOIN(d_, __VA_ARGS__))) \ + () + +#endif /* CCAN_CPPMAGIC_H */ diff --git a/nostrdb/bolt11/debug.h b/nostrdb/bolt11/debug.h new file mode 100644 index 00000000..11a6344e --- /dev/null +++ b/nostrdb/bolt11/debug.h @@ -0,0 +1,15 @@ + +#ifndef PROTOVERSE_DEBUG_H +#define PROTOVERSE_DEBUG_H + +#include + +#define unusual(...) fprintf(stderr, "UNUSUAL: " __VA_ARGS__) + +#ifdef DEBUG +#define debug(...) printf(__VA_ARGS__) +#else +#define debug(...) +#endif + +#endif /* PROTOVERSE_DEBUG_H */ diff --git a/nostrdb/bolt11/error.c b/nostrdb/bolt11/error.c new file mode 100644 index 00000000..5f26a2b8 --- /dev/null +++ b/nostrdb/bolt11/error.c @@ -0,0 +1,34 @@ + +#include "error.h" + +#include +#include + +int note_error_(struct errors *errs_, struct cursor *p, const char *fmt, ...) +{ + static char buf[512]; + struct error err; + struct cursor *errs; + va_list ap; + + errs = &errs_->cur; + + if (errs_->enabled == 0) + return 0; + + va_start(ap, fmt); + vsprintf(buf, fmt, ap); + va_end(ap); + + err.msg = buf; + err.pos = p ? (int)(p->p - p->start) : 0; + + if (!cursor_push_error(errs, &err)) { + fprintf(stderr, "arena OOM when recording error, "); + fprintf(stderr, "errs->p at %ld, remaining %ld, strlen %ld\n", + errs->p - errs->start, errs->end - errs->p, strlen(buf)); + } + + return 0; +} + diff --git a/nostrdb/bolt11/error.h b/nostrdb/bolt11/error.h new file mode 100644 index 00000000..48a62996 --- /dev/null +++ b/nostrdb/bolt11/error.h @@ -0,0 +1,33 @@ + +#ifndef PROTOVERSE_ERROR_H +#define PROTOVERSE_ERROR_H + +#include "cursor.h" + +struct error { + int pos; + const char *msg; +}; + +struct errors { + struct cursor cur; + int enabled; +}; + +#define note_error(errs, p, fmt, ...) note_error_(errs, p, "%s: " fmt, __FUNCTION__, ##__VA_ARGS__) + +static inline int cursor_push_error(struct cursor *cur, struct error *err) +{ + return cursor_push_int(cur, err->pos) && + cursor_push_c_str(cur, err->msg); +} + +static inline int cursor_pull_error(struct cursor *cur, struct error *err) +{ + return cursor_pull_int(cur, &err->pos) && + cursor_pull_c_str(cur, &err->msg); +} + +int note_error_(struct errors *errs, struct cursor *p, const char *fmt, ...); + +#endif /* PROTOVERSE_ERROR_H */ diff --git a/nostrdb/bolt11/hash_u5.c b/nostrdb/bolt11/hash_u5.c new file mode 100644 index 00000000..737ec03f --- /dev/null +++ b/nostrdb/bolt11/hash_u5.c @@ -0,0 +1,48 @@ +#include "../config.h" +#include "../endian.h" +#include "hash_u5.h" +#include + +void hash_u5_init(struct hash_u5 *hu5, const char *hrp) +{ + hu5->buf = 0; + hu5->num_bits = 0; + sha256_init(&hu5->hash); + sha256_update(&hu5->hash, hrp, strlen(hrp)); +} + +void hash_u5(struct hash_u5 *hu5, const u8 *u5, size_t len) +{ + size_t bits = len * 5; + + while (bits) { + size_t n = 5; + + if (bits < n) + n = bits; + + hu5->buf <<= n; + hu5->buf |= (*u5 >> (5-n)); + bits -= n; + hu5->num_bits += n; + + if (n == 5) + u5++; + + if (hu5->num_bits >= 32) { + be32 be32 = cpu_to_be32((u32)(hu5->buf >> (hu5->num_bits-32))); + sha256_update(&hu5->hash, &be32, sizeof(be32)); + hu5->num_bits -= 32; + } + } +} + +void hash_u5_done(struct hash_u5 *hu5, struct sha256 *res) +{ + if (hu5->num_bits) { + be32 be32 = cpu_to_be32((u32)(hu5->buf << (32 - hu5->num_bits))); + + sha256_update(&hu5->hash, &be32, (hu5->num_bits + 7) / 8); + } + sha256_done(&hu5->hash, res); +} diff --git a/nostrdb/bolt11/hash_u5.h b/nostrdb/bolt11/hash_u5.h new file mode 100644 index 00000000..69f4b6f7 --- /dev/null +++ b/nostrdb/bolt11/hash_u5.h @@ -0,0 +1,20 @@ +/* bech32 (thus bolt11) deal in 5-bit values */ +#ifndef LIGHTNING_COMMON_HASH_U5_H +#define LIGHTNING_COMMON_HASH_U5_H +#include "../sha256.h" +#include "short_types.h" + +/* Type to annotate a 5 bit value. */ +typedef unsigned char u5; + +struct hash_u5 { + u64 buf; + unsigned int num_bits; + struct sha256_ctx hash; +}; + +void hash_u5_init(struct hash_u5 *hu5, const char *hrp); +void hash_u5(struct hash_u5 *hu5, const u5 *u5, size_t len); +void hash_u5_done(struct hash_u5 *hu5, struct sha256 *res); + +#endif /* LIGHTNING_COMMON_HASH_U5_H */ diff --git a/nostrdb/bolt11/libnostrdb.a b/nostrdb/bolt11/libnostrdb.a new file mode 100644 index 0000000000000000000000000000000000000000..32e2bc1c6cdf47cffe68364f05162e9af763283e GIT binary patch literal 172632 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 literal 0 HcmV?d00001 diff --git a/nostrdb/bolt11/likely.h b/nostrdb/bolt11/likely.h new file mode 100644 index 00000000..3a2f18e6 --- /dev/null +++ b/nostrdb/bolt11/likely.h @@ -0,0 +1,115 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_LIKELY_H +#define CCAN_LIKELY_H +#include "../config.h" +#include + +#ifndef CCAN_LIKELY_DEBUG +#if HAVE_BUILTIN_EXPECT +/** + * likely - indicate that a condition is likely to be true. + * @cond: the condition + * + * This uses a compiler extension where available to indicate a likely + * code path and optimize appropriately; it's also useful for readers + * to quickly identify exceptional paths through functions. The + * threshold for "likely" is usually considered to be between 90 and + * 99%; marginal cases should not be marked either way. + * + * See Also: + * unlikely(), likely_stats() + * + * Example: + * // Returns false if we overflow. + * static inline bool inc_int(unsigned int *val) + * { + * (*val)++; + * if (likely(*val)) + * return true; + * return false; + * } + */ +#define likely(cond) __builtin_expect(!!(cond), 1) + +/** + * unlikely - indicate that a condition is unlikely to be true. + * @cond: the condition + * + * This uses a compiler extension where available to indicate an unlikely + * code path and optimize appropriately; see likely() above. + * + * See Also: + * likely(), likely_stats(), COLD (compiler.h) + * + * Example: + * // Prints a warning if we overflow. + * static inline void inc_int(unsigned int *val) + * { + * (*val)++; + * if (unlikely(*val == 0)) + * fprintf(stderr, "Overflow!"); + * } + */ +#define unlikely(cond) __builtin_expect(!!(cond), 0) +#else +#ifndef likely +#define likely(cond) (!!(cond)) +#endif +#ifndef unlikely +#define unlikely(cond) (!!(cond)) +#endif +#endif +#else /* CCAN_LIKELY_DEBUG versions */ +#include + +#define likely(cond) \ + (_likely_trace(!!(cond), 1, stringify(cond), __FILE__, __LINE__)) +#define unlikely(cond) \ + (_likely_trace(!!(cond), 0, stringify(cond), __FILE__, __LINE__)) + +long _likely_trace(bool cond, bool expect, + const char *condstr, + const char *file, unsigned int line); +/** + * likely_stats - return description of abused likely()/unlikely() + * @min_hits: minimum number of hits + * @percent: maximum percentage correct + * + * When CCAN_LIKELY_DEBUG is defined, likely() and unlikely() trace their + * results: this causes a significant slowdown, but allows analysis of + * whether the branches are labelled correctly. + * + * This function returns a malloc'ed description of the least-correct + * usage of likely() or unlikely(). It ignores places which have been + * called less than @min_hits times, and those which were predicted + * correctly more than @percent of the time. It returns NULL when + * nothing meets those criteria. + * + * Note that this call is destructive; the returned offender is + * removed from the trace so that the next call to likely_stats() will + * return the next-worst likely()/unlikely() usage. + * + * Example: + * // Print every place hit more than twice which was wrong > 5%. + * static void report_stats(void) + * { + * #ifdef CCAN_LIKELY_DEBUG + * const char *bad; + * + * while ((bad = likely_stats(2, 95)) != NULL) { + * printf("Suspicious likely: %s", bad); + * free(bad); + * } + * #endif + * } + */ +char *likely_stats(unsigned int min_hits, unsigned int percent); + +/** + * likely_stats_reset - free up memory of likely()/unlikely() branches. + * + * This can also plug memory leaks. + */ +void likely_stats_reset(void); +#endif /* CCAN_LIKELY_DEBUG */ +#endif /* CCAN_LIKELY_H */ diff --git a/nostrdb/bolt11/list.c b/nostrdb/bolt11/list.c new file mode 100644 index 00000000..c9ee35c7 --- /dev/null +++ b/nostrdb/bolt11/list.c @@ -0,0 +1,43 @@ +/* Licensed under BSD-MIT - see LICENSE file for details */ +#include +#include +#include "list.h" + +static void *corrupt(const char *abortstr, + const struct list_node *head, + const struct list_node *node, + unsigned int count) +{ + if (abortstr) { + fprintf(stderr, + "%s: prev corrupt in node %p (%u) of %p\n", + abortstr, node, count, head); + abort(); + } + return NULL; +} + +struct list_node *list_check_node(const struct list_node *node, + const char *abortstr) +{ + const struct list_node *p, *n; + int count = 0; + + for (p = node, n = node->next; n != node; p = n, n = n->next) { + count++; + if (n->prev != p) + return corrupt(abortstr, node, n, count); + } + /* Check prev on head node. */ + if (node->prev != p) + return corrupt(abortstr, node, node, 0); + + return (struct list_node *)node; +} + +struct list_head *list_check(const struct list_head *h, const char *abortstr) +{ + if (!list_check_node(&h->n, abortstr)) + return NULL; + return (struct list_head *)h; +} diff --git a/nostrdb/bolt11/list.h b/nostrdb/bolt11/list.h new file mode 100644 index 00000000..4574e911 --- /dev/null +++ b/nostrdb/bolt11/list.h @@ -0,0 +1,842 @@ +/* Licensed under BSD-MIT - see LICENSE file for details */ +#ifndef CCAN_LIST_H +#define CCAN_LIST_H +//#define CCAN_LIST_DEBUG 1 +#include +#include +#include "str.h" +#include "container_of.h" +#include "check_type.h" + +/** + * struct list_node - an entry in a doubly-linked list + * @next: next entry (self if empty) + * @prev: previous entry (self if empty) + * + * This is used as an entry in a linked list. + * Example: + * struct child { + * const char *name; + * // Linked list of all us children. + * struct list_node list; + * }; + */ +struct list_node +{ + struct list_node *next, *prev; +}; + +/** + * struct list_head - the head of a doubly-linked list + * @h: the list_head (containing next and prev pointers) + * + * This is used as the head of a linked list. + * Example: + * struct parent { + * const char *name; + * struct list_head children; + * unsigned int num_children; + * }; + */ +struct list_head +{ + struct list_node n; +}; + +/** + * list_check - check head of a list for consistency + * @h: the list_head + * @abortstr: the location to print on aborting, or NULL. + * + * Because list_nodes have redundant information, consistency checking between + * the back and forward links can be done. This is useful as a debugging check. + * If @abortstr is non-NULL, that will be printed in a diagnostic if the list + * is inconsistent, and the function will abort. + * + * Returns the list head if the list is consistent, NULL if not (it + * can never return NULL if @abortstr is set). + * + * See also: list_check_node() + * + * Example: + * static void dump_parent(struct parent *p) + * { + * struct child *c; + * + * printf("%s (%u children):\n", p->name, p->num_children); + * list_check(&p->children, "bad child list"); + * list_for_each(&p->children, c, list) + * printf(" -> %s\n", c->name); + * } + */ +struct list_head *list_check(const struct list_head *h, const char *abortstr); + +/** + * list_check_node - check node of a list for consistency + * @n: the list_node + * @abortstr: the location to print on aborting, or NULL. + * + * Check consistency of the list node is in (it must be in one). + * + * See also: list_check() + * + * Example: + * static void dump_child(const struct child *c) + * { + * list_check_node(&c->list, "bad child list"); + * printf("%s\n", c->name); + * } + */ +struct list_node *list_check_node(const struct list_node *n, + const char *abortstr); + +#define LIST_LOC __FILE__ ":" stringify(__LINE__) +#ifdef CCAN_LIST_DEBUG +#define list_debug(h, loc) list_check((h), loc) +#define list_debug_node(n, loc) list_check_node((n), loc) +#else +#define list_debug(h, loc) ((void)loc, h) +#define list_debug_node(n, loc) ((void)loc, n) +#endif + +/** + * LIST_HEAD_INIT - initializer for an empty list_head + * @name: the name of the list. + * + * Explicit initializer for an empty list. + * + * See also: + * LIST_HEAD, list_head_init() + * + * Example: + * static struct list_head my_list = LIST_HEAD_INIT(my_list); + */ +#define LIST_HEAD_INIT(name) { { &(name).n, &(name).n } } + +/** + * LIST_HEAD - define and initialize an empty list_head + * @name: the name of the list. + * + * The LIST_HEAD macro defines a list_head and initializes it to an empty + * list. It can be prepended by "static" to define a static list_head. + * + * See also: + * LIST_HEAD_INIT, list_head_init() + * + * Example: + * static LIST_HEAD(my_global_list); + */ +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +/** + * list_head_init - initialize a list_head + * @h: the list_head to set to the empty list + * + * Example: + * ... + * struct parent *parent = malloc(sizeof(*parent)); + * + * list_head_init(&parent->children); + * parent->num_children = 0; + */ +static inline void list_head_init(struct list_head *h) +{ + h->n.next = h->n.prev = &h->n; +} + +/** + * list_node_init - initialize a list_node + * @n: the list_node to link to itself. + * + * You don't need to use this normally! But it lets you list_del(@n) + * safely. + */ +static inline void list_node_init(struct list_node *n) +{ + n->next = n->prev = n; +} + +/** + * list_add_after - add an entry after an existing node in a linked list + * @h: the list_head to add the node to (for debugging) + * @p: the existing list_node to add the node after + * @n: the new list_node to add to the list. + * + * The existing list_node must already be a member of the list. + * The new list_node does not need to be initialized; it will be overwritten. + * + * Example: + * struct child c1, c2, c3; + * LIST_HEAD(h); + * + * list_add_tail(&h, &c1.list); + * list_add_tail(&h, &c3.list); + * list_add_after(&h, &c1.list, &c2.list); + */ +#define list_add_after(h, p, n) list_add_after_(h, p, n, LIST_LOC) +static inline void list_add_after_(struct list_head *h, + struct list_node *p, + struct list_node *n, + const char *abortstr) +{ + n->next = p->next; + n->prev = p; + p->next->prev = n; + p->next = n; + (void)list_debug(h, abortstr); +} + +/** + * list_add - add an entry at the start of a linked list. + * @h: the list_head to add the node to + * @n: the list_node to add to the list. + * + * The list_node does not need to be initialized; it will be overwritten. + * Example: + * struct child *child = malloc(sizeof(*child)); + * + * child->name = "marvin"; + * list_add(&parent->children, &child->list); + * parent->num_children++; + */ +#define list_add(h, n) list_add_(h, n, LIST_LOC) +static inline void list_add_(struct list_head *h, + struct list_node *n, + const char *abortstr) +{ + list_add_after_(h, &h->n, n, abortstr); +} + +/** + * list_add_before - add an entry before an existing node in a linked list + * @h: the list_head to add the node to (for debugging) + * @p: the existing list_node to add the node before + * @n: the new list_node to add to the list. + * + * The existing list_node must already be a member of the list. + * The new list_node does not need to be initialized; it will be overwritten. + * + * Example: + * list_head_init(&h); + * list_add_tail(&h, &c1.list); + * list_add_tail(&h, &c3.list); + * list_add_before(&h, &c3.list, &c2.list); + */ +#define list_add_before(h, p, n) list_add_before_(h, p, n, LIST_LOC) +static inline void list_add_before_(struct list_head *h, + struct list_node *p, + struct list_node *n, + const char *abortstr) +{ + n->next = p; + n->prev = p->prev; + p->prev->next = n; + p->prev = n; + (void)list_debug(h, abortstr); +} + +/** + * list_add_tail - add an entry at the end of a linked list. + * @h: the list_head to add the node to + * @n: the list_node to add to the list. + * + * The list_node does not need to be initialized; it will be overwritten. + * Example: + * list_add_tail(&parent->children, &child->list); + * parent->num_children++; + */ +#define list_add_tail(h, n) list_add_tail_(h, n, LIST_LOC) +static inline void list_add_tail_(struct list_head *h, + struct list_node *n, + const char *abortstr) +{ + list_add_before_(h, &h->n, n, abortstr); +} + +/** + * list_empty - is a list empty? + * @h: the list_head + * + * If the list is empty, returns true. + * + * Example: + * assert(list_empty(&parent->children) == (parent->num_children == 0)); + */ +#define list_empty(h) list_empty_(h, LIST_LOC) +static inline bool list_empty_(const struct list_head *h, const char* abortstr) +{ + (void)list_debug(h, abortstr); + return h->n.next == &h->n; +} + +/** + * list_empty_nodebug - is a list empty (and don't perform debug checks)? + * @h: the list_head + * + * If the list is empty, returns true. + * This differs from list_empty() in that if CCAN_LIST_DEBUG is set it + * will NOT perform debug checks. Only use this function if you REALLY + * know what you're doing. + * + * Example: + * assert(list_empty_nodebug(&parent->children) == (parent->num_children == 0)); + */ +#ifndef CCAN_LIST_DEBUG +#define list_empty_nodebug(h) list_empty(h) +#else +static inline bool list_empty_nodebug(const struct list_head *h) +{ + return h->n.next == &h->n; +} +#endif + +/** + * list_empty_nocheck - is a list empty? + * @h: the list_head + * + * If the list is empty, returns true. This doesn't perform any + * debug check for list consistency, so it can be called without + * locks, racing with the list being modified. This is ok for + * checks where an incorrect result is not an issue (optimized + * bail out path for example). + */ +static inline bool list_empty_nocheck(const struct list_head *h) +{ + return h->n.next == &h->n; +} + +/** + * list_del - delete an entry from an (unknown) linked list. + * @n: the list_node to delete from the list. + * + * Note that this leaves @n in an undefined state; it can be added to + * another list, but not deleted again. + * + * See also: + * list_del_from(), list_del_init() + * + * Example: + * list_del(&child->list); + * parent->num_children--; + */ +#define list_del(n) list_del_(n, LIST_LOC) +static inline void list_del_(struct list_node *n, const char* abortstr) +{ + (void)list_debug_node(n, abortstr); + n->next->prev = n->prev; + n->prev->next = n->next; +#ifdef CCAN_LIST_DEBUG + /* Catch use-after-del. */ + n->next = n->prev = NULL; +#endif +} + +/** + * list_del_init - delete a node, and reset it so it can be deleted again. + * @n: the list_node to be deleted. + * + * list_del(@n) or list_del_init() again after this will be safe, + * which can be useful in some cases. + * + * See also: + * list_del_from(), list_del() + * + * Example: + * list_del_init(&child->list); + * parent->num_children--; + */ +#define list_del_init(n) list_del_init_(n, LIST_LOC) +static inline void list_del_init_(struct list_node *n, const char *abortstr) +{ + list_del_(n, abortstr); + list_node_init(n); +} + +/** + * list_del_from - delete an entry from a known linked list. + * @h: the list_head the node is in. + * @n: the list_node to delete from the list. + * + * This explicitly indicates which list a node is expected to be in, + * which is better documentation and can catch more bugs. + * + * See also: list_del() + * + * Example: + * list_del_from(&parent->children, &child->list); + * parent->num_children--; + */ +static inline void list_del_from(struct list_head *h, struct list_node *n) +{ +#ifdef CCAN_LIST_DEBUG + { + /* Thorough check: make sure it was in list! */ + struct list_node *i; + for (i = h->n.next; i != n; i = i->next) + assert(i != &h->n); + } +#endif /* CCAN_LIST_DEBUG */ + + /* Quick test that catches a surprising number of bugs. */ + assert(!list_empty(h)); + list_del(n); +} + +/** + * list_swap - swap out an entry from an (unknown) linked list for a new one. + * @o: the list_node to replace from the list. + * @n: the list_node to insert in place of the old one. + * + * Note that this leaves @o in an undefined state; it can be added to + * another list, but not deleted/swapped again. + * + * See also: + * list_del() + * + * Example: + * struct child x1, x2; + * LIST_HEAD(xh); + * + * list_add(&xh, &x1.list); + * list_swap(&x1.list, &x2.list); + */ +#define list_swap(o, n) list_swap_(o, n, LIST_LOC) +static inline void list_swap_(struct list_node *o, + struct list_node *n, + const char* abortstr) +{ + (void)list_debug_node(o, abortstr); + *n = *o; + n->next->prev = n; + n->prev->next = n; +#ifdef CCAN_LIST_DEBUG + /* Catch use-after-del. */ + o->next = o->prev = NULL; +#endif +} + +/** + * list_entry - convert a list_node back into the structure containing it. + * @n: the list_node + * @type: the type of the entry + * @member: the list_node member of the type + * + * Example: + * // First list entry is children.next; convert back to child. + * child = list_entry(parent->children.n.next, struct child, list); + * + * See Also: + * list_top(), list_for_each() + */ +#define list_entry(n, type, member) container_of(n, type, member) + +/** + * list_top - get the first entry in a list + * @h: the list_head + * @type: the type of the entry + * @member: the list_node member of the type + * + * If the list is empty, returns NULL. + * + * Example: + * struct child *first; + * first = list_top(&parent->children, struct child, list); + * if (!first) + * printf("Empty list!\n"); + */ +#define list_top(h, type, member) \ + ((type *)list_top_((h), list_off_(type, member))) + +static inline const void *list_top_(const struct list_head *h, size_t off) +{ + if (list_empty(h)) + return NULL; + return (const char *)h->n.next - off; +} + +/** + * list_pop - remove the first entry in a list + * @h: the list_head + * @type: the type of the entry + * @member: the list_node member of the type + * + * If the list is empty, returns NULL. + * + * Example: + * struct child *one; + * one = list_pop(&parent->children, struct child, list); + * if (!one) + * printf("Empty list!\n"); + */ +#define list_pop(h, type, member) \ + ((type *)list_pop_((h), list_off_(type, member))) + +static inline const void *list_pop_(const struct list_head *h, size_t off) +{ + struct list_node *n; + + if (list_empty(h)) + return NULL; + n = h->n.next; + list_del(n); + return (const char *)n - off; +} + +/** + * list_tail - get the last entry in a list + * @h: the list_head + * @type: the type of the entry + * @member: the list_node member of the type + * + * If the list is empty, returns NULL. + * + * Example: + * struct child *last; + * last = list_tail(&parent->children, struct child, list); + * if (!last) + * printf("Empty list!\n"); + */ +#define list_tail(h, type, member) \ + ((type *)list_tail_((h), list_off_(type, member))) + +static inline const void *list_tail_(const struct list_head *h, size_t off) +{ + if (list_empty(h)) + return NULL; + return (const char *)h->n.prev - off; +} + +/** + * list_for_each - iterate through a list. + * @h: the list_head (warning: evaluated multiple times!) + * @i: the structure containing the list_node + * @member: the list_node member of the structure + * + * This is a convenient wrapper to iterate @i over the entire list. It's + * a for loop, so you can break and continue as normal. + * + * Example: + * list_for_each(&parent->children, child, list) + * printf("Name: %s\n", child->name); + */ +#define list_for_each(h, i, member) \ + list_for_each_off(h, i, list_off_var_(i, member)) + +/** + * list_for_each_rev - iterate through a list backwards. + * @h: the list_head + * @i: the structure containing the list_node + * @member: the list_node member of the structure + * + * This is a convenient wrapper to iterate @i over the entire list. It's + * a for loop, so you can break and continue as normal. + * + * Example: + * list_for_each_rev(&parent->children, child, list) + * printf("Name: %s\n", child->name); + */ +#define list_for_each_rev(h, i, member) \ + list_for_each_rev_off(h, i, list_off_var_(i, member)) + +/** + * list_for_each_rev_safe - iterate through a list backwards, + * maybe during deletion + * @h: the list_head + * @i: the structure containing the list_node + * @nxt: the structure containing the list_node + * @member: the list_node member of the structure + * + * This is a convenient wrapper to iterate @i over the entire list backwards. + * It's a for loop, so you can break and continue as normal. The extra + * variable * @nxt is used to hold the next element, so you can delete @i + * from the list. + * + * Example: + * struct child *next; + * list_for_each_rev_safe(&parent->children, child, next, list) { + * printf("Name: %s\n", child->name); + * } + */ +#define list_for_each_rev_safe(h, i, nxt, member) \ + list_for_each_rev_safe_off(h, i, nxt, list_off_var_(i, member)) + +/** + * list_for_each_safe - iterate through a list, maybe during deletion + * @h: the list_head + * @i: the structure containing the list_node + * @nxt: the structure containing the list_node + * @member: the list_node member of the structure + * + * This is a convenient wrapper to iterate @i over the entire list. It's + * a for loop, so you can break and continue as normal. The extra variable + * @nxt is used to hold the next element, so you can delete @i from the list. + * + * Example: + * list_for_each_safe(&parent->children, child, next, list) { + * list_del(&child->list); + * parent->num_children--; + * } + */ +#define list_for_each_safe(h, i, nxt, member) \ + list_for_each_safe_off(h, i, nxt, list_off_var_(i, member)) + +/** + * list_next - get the next entry in a list + * @h: the list_head + * @i: a pointer to an entry in the list. + * @member: the list_node member of the structure + * + * If @i was the last entry in the list, returns NULL. + * + * Example: + * struct child *second; + * second = list_next(&parent->children, first, list); + * if (!second) + * printf("No second child!\n"); + */ +#define list_next(h, i, member) \ + ((list_typeof(i))list_entry_or_null(list_debug(h, \ + __FILE__ ":" stringify(__LINE__)), \ + (i)->member.next, \ + list_off_var_((i), member))) + +/** + * list_prev - get the previous entry in a list + * @h: the list_head + * @i: a pointer to an entry in the list. + * @member: the list_node member of the structure + * + * If @i was the first entry in the list, returns NULL. + * + * Example: + * first = list_prev(&parent->children, second, list); + * if (!first) + * printf("Can't go back to first child?!\n"); + */ +#define list_prev(h, i, member) \ + ((list_typeof(i))list_entry_or_null(list_debug(h, \ + __FILE__ ":" stringify(__LINE__)), \ + (i)->member.prev, \ + list_off_var_((i), member))) + +/** + * list_append_list - empty one list onto the end of another. + * @to: the list to append into + * @from: the list to empty. + * + * This takes the entire contents of @from and moves it to the end of + * @to. After this @from will be empty. + * + * Example: + * struct list_head adopter; + * + * list_append_list(&adopter, &parent->children); + * assert(list_empty(&parent->children)); + * parent->num_children = 0; + */ +#define list_append_list(t, f) list_append_list_(t, f, \ + __FILE__ ":" stringify(__LINE__)) +static inline void list_append_list_(struct list_head *to, + struct list_head *from, + const char *abortstr) +{ + struct list_node *from_tail = list_debug(from, abortstr)->n.prev; + struct list_node *to_tail = list_debug(to, abortstr)->n.prev; + + /* Sew in head and entire list. */ + to->n.prev = from_tail; + from_tail->next = &to->n; + to_tail->next = &from->n; + from->n.prev = to_tail; + + /* Now remove head. */ + list_del(&from->n); + list_head_init(from); +} + +/** + * list_prepend_list - empty one list into the start of another. + * @to: the list to prepend into + * @from: the list to empty. + * + * This takes the entire contents of @from and moves it to the start + * of @to. After this @from will be empty. + * + * Example: + * list_prepend_list(&adopter, &parent->children); + * assert(list_empty(&parent->children)); + * parent->num_children = 0; + */ +#define list_prepend_list(t, f) list_prepend_list_(t, f, LIST_LOC) +static inline void list_prepend_list_(struct list_head *to, + struct list_head *from, + const char *abortstr) +{ + struct list_node *from_tail = list_debug(from, abortstr)->n.prev; + struct list_node *to_head = list_debug(to, abortstr)->n.next; + + /* Sew in head and entire list. */ + to->n.next = &from->n; + from->n.prev = &to->n; + to_head->prev = from_tail; + from_tail->next = to_head; + + /* Now remove head. */ + list_del(&from->n); + list_head_init(from); +} + +/* internal macros, do not use directly */ +#define list_for_each_off_dir_(h, i, off, dir) \ + for (i = list_node_to_off_(list_debug(h, LIST_LOC)->n.dir, \ + (off)); \ + list_node_from_off_((void *)i, (off)) != &(h)->n; \ + i = list_node_to_off_(list_node_from_off_((void *)i, (off))->dir, \ + (off))) + +#define list_for_each_safe_off_dir_(h, i, nxt, off, dir) \ + for (i = list_node_to_off_(list_debug(h, LIST_LOC)->n.dir, \ + (off)), \ + nxt = list_node_to_off_(list_node_from_off_(i, (off))->dir, \ + (off)); \ + list_node_from_off_(i, (off)) != &(h)->n; \ + i = nxt, \ + nxt = list_node_to_off_(list_node_from_off_(i, (off))->dir, \ + (off))) + +/** + * list_for_each_off - iterate through a list of memory regions. + * @h: the list_head + * @i: the pointer to a memory region which contains list node data. + * @off: offset(relative to @i) at which list node data resides. + * + * This is a low-level wrapper to iterate @i over the entire list, used to + * implement all oher, more high-level, for-each constructs. It's a for loop, + * so you can break and continue as normal. + * + * WARNING! Being the low-level macro that it is, this wrapper doesn't know + * nor care about the type of @i. The only assumption made is that @i points + * to a chunk of memory that at some @offset, relative to @i, contains a + * properly filled `struct list_node' which in turn contains pointers to + * memory chunks and it's turtles all the way down. With all that in mind + * remember that given the wrong pointer/offset couple this macro will + * happily churn all you memory until SEGFAULT stops it, in other words + * caveat emptor. + * + * It is worth mentioning that one of legitimate use-cases for that wrapper + * is operation on opaque types with known offset for `struct list_node' + * member(preferably 0), because it allows you not to disclose the type of + * @i. + * + * Example: + * list_for_each_off(&parent->children, child, + * offsetof(struct child, list)) + * printf("Name: %s\n", child->name); + */ +#define list_for_each_off(h, i, off) \ + list_for_each_off_dir_((h),(i),(off),next) + +/** + * list_for_each_rev_off - iterate through a list of memory regions backwards + * @h: the list_head + * @i: the pointer to a memory region which contains list node data. + * @off: offset(relative to @i) at which list node data resides. + * + * See list_for_each_off for details + */ +#define list_for_each_rev_off(h, i, off) \ + list_for_each_off_dir_((h),(i),(off),prev) + +/** + * list_for_each_safe_off - iterate through a list of memory regions, maybe + * during deletion + * @h: the list_head + * @i: the pointer to a memory region which contains list node data. + * @nxt: the structure containing the list_node + * @off: offset(relative to @i) at which list node data resides. + * + * For details see `list_for_each_off' and `list_for_each_safe' + * descriptions. + * + * Example: + * list_for_each_safe_off(&parent->children, child, + * next, offsetof(struct child, list)) + * printf("Name: %s\n", child->name); + */ +#define list_for_each_safe_off(h, i, nxt, off) \ + list_for_each_safe_off_dir_((h),(i),(nxt),(off),next) + +/** + * list_for_each_rev_safe_off - iterate backwards through a list of + * memory regions, maybe during deletion + * @h: the list_head + * @i: the pointer to a memory region which contains list node data. + * @nxt: the structure containing the list_node + * @off: offset(relative to @i) at which list node data resides. + * + * For details see `list_for_each_rev_off' and `list_for_each_rev_safe' + * descriptions. + * + * Example: + * list_for_each_rev_safe_off(&parent->children, child, + * next, offsetof(struct child, list)) + * printf("Name: %s\n", child->name); + */ +#define list_for_each_rev_safe_off(h, i, nxt, off) \ + list_for_each_safe_off_dir_((h),(i),(nxt),(off),prev) + +/* Other -off variants. */ +#define list_entry_off(n, type, off) \ + ((type *)list_node_from_off_((n), (off))) + +#define list_head_off(h, type, off) \ + ((type *)list_head_off((h), (off))) + +#define list_tail_off(h, type, off) \ + ((type *)list_tail_((h), (off))) + +#define list_add_off(h, n, off) \ + list_add((h), list_node_from_off_((n), (off))) + +#define list_del_off(n, off) \ + list_del(list_node_from_off_((n), (off))) + +#define list_del_from_off(h, n, off) \ + list_del_from(h, list_node_from_off_((n), (off))) + +/* Offset helper functions so we only single-evaluate. */ +static inline void *list_node_to_off_(struct list_node *node, size_t off) +{ + return (void *)((char *)node - off); +} +static inline struct list_node *list_node_from_off_(void *ptr, size_t off) +{ + return (struct list_node *)((char *)ptr + off); +} + +/* Get the offset of the member, but make sure it's a list_node. */ +#define list_off_(type, member) \ + (container_off(type, member) + \ + check_type(((type *)0)->member, struct list_node)) + +#define list_off_var_(var, member) \ + (container_off_var(var, member) + \ + check_type(var->member, struct list_node)) + +#if HAVE_TYPEOF +#define list_typeof(var) typeof(var) +#else +#define list_typeof(var) void * +#endif + +/* Returns member, or NULL if at end of list. */ +static inline void *list_entry_or_null(const struct list_head *h, + const struct list_node *n, + size_t off) +{ + if (n == &h->n) + return NULL; + return (char *)n - off; +} +#endif /* CCAN_LIST_H */ diff --git a/nostrdb/bolt11/mem.c b/nostrdb/bolt11/mem.c new file mode 100644 index 00000000..150f0616 --- /dev/null +++ b/nostrdb/bolt11/mem.c @@ -0,0 +1,128 @@ +/* CC0 (Public domain) - see LICENSE file for details */ + +#include "config.h" + +#include +#include +#include "mem.h" + +#if !HAVE_MEMMEM +void *memmem(const void *haystack, size_t haystacklen, + const void *needle, size_t needlelen) +{ + const char *p; + + if (needlelen > haystacklen) + return NULL; + + p = haystack; + + for (p = haystack; + (p + needlelen) <= ((const char *)haystack + haystacklen); + p++) + if (memcmp(p, needle, needlelen) == 0) + return (void *)p; + + return NULL; +} +#endif + +#if !HAVE_MEMRCHR +void *memrchr(const void *s, int c, size_t n) +{ + unsigned char *p = (unsigned char *)s; + + while (n) { + if (p[n-1] == c) + return p + n - 1; + n--; + } + + return NULL; +} +#endif + +void *mempbrkm(const void *data_, size_t len, const void *accept_, size_t accept_len) +{ + const char *data = data_, *accept = accept_; + size_t i, j; + + for (i = 0; i < len; i++) + for (j = 0; j < accept_len; j++) + if (accept[j] == data[i]) + return (void *)&data[i]; + return NULL; +} + +void *memcchr(void const *data, int c, size_t data_len) +{ + char const *p = data; + size_t i; + + for (i = 0; i < data_len; i++) + if (p[i] != c) + return (void *)&p[i]; + + return NULL; +} + +#define MEMSWAP_TMP_SIZE 256 + +void memswap(void *a, void *b, size_t n) +{ + char *ap = a; + char *bp = b; + char tmp[MEMSWAP_TMP_SIZE]; + + assert(!memoverlaps(a, n, b, n)); + + while (n) { + size_t m = n > MEMSWAP_TMP_SIZE ? MEMSWAP_TMP_SIZE : n; + + memcpy(tmp, bp, m); + memcpy(bp, ap, m); + memcpy(ap, tmp, m); + + ap += m; + bp += m; + n -= m; + } +} + +bool memeqzero(const void *data, size_t length) +{ + const unsigned char *p = data; + size_t len; + + /* Check first 16 bytes manually */ + for (len = 0; len < 16; len++) { + if (!length) + return true; + if (*p) + return false; + p++; + length--; + } + + /* Now we know that's zero, memcmp with self. */ + return memcmp(data, p, length) == 0; +} + +void memtaint(void *data, size_t len) +{ + /* Using 16 bytes is a bit quicker than 4 */ + const unsigned tainter[] + = { 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef }; + char *p = data; + + while (len >= sizeof(tainter)) { + memcpy(p, tainter, sizeof(tainter)); + p += sizeof(tainter); + len -= sizeof(tainter); + } + memcpy(p, tainter, len); + +#if HAVE_VALGRIND_MEMCHECK_H + VALGRIND_MAKE_MEM_UNDEFINED(data, len); +#endif +} diff --git a/nostrdb/bolt11/mem.h b/nostrdb/bolt11/mem.h new file mode 100644 index 00000000..9b8d01a3 --- /dev/null +++ b/nostrdb/bolt11/mem.h @@ -0,0 +1,295 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_MEM_H +#define CCAN_MEM_H + +#include "../config.h" +#include "../compiler.h" + +#include +#include + +#if !HAVE_MEMMEM +PURE_FUNCTION +void *memmem(const void *haystack, size_t haystacklen, + const void *needle, size_t needlelen); +#endif + +#if !HAVE_MEMRCHR +PURE_FUNCTION +void *memrchr(const void *s, int c, size_t n); +#endif + +/** + * mempbrkm - locates the first occurrence in @data of any bytes in @accept + * @data: where we search + * @len: length of data in bytes + * @accept: array of bytes we search for + * @accept_len: # of bytes in accept + * + * Returns a pointer to the byte in @data that matches one of the bytes in + * @accept, or NULL if no such byte is found. + * + * Example: + * char otherbytes[] = "Hello \0world"; + * size_t otherbytes_len = sizeof(otherbytes) - 1; + * char *r = mempbrkm(otherbytes, otherbytes_len, "\0b", 2); + * if (r) { + * printf("Found %c\n", *r); + * } else { + * printf("Nada\n"); + * } + * + */ +PURE_FUNCTION +void *mempbrkm(const void *data, size_t len, const void *accept, size_t accept_len); + +/** + * mempbrk - locates the first occurrence in @data of any bytes in @accept + * @data: where we search + * @len: length of data in bytes + * @accept: NUL terminated string containing the bytes we search for + * + * Returns a pointer to the byte in @data that matches one of the bytes in + * @accept, or NULL if no such byte is found. + * + * Example: + * + * r = mempbrk(otherbytes, otherbytes_len, "abcde"); + * if (r) { + * printf("Found %c\n", *r); + * } else { + * printf("Nada\n"); + * } + */ +PURE_FUNCTION +static inline char *mempbrk(const void *data, size_t len, const char *accept) +{ + return mempbrkm(data, len, accept, strlen(accept)); +} + +/** + * memcchr - scan memory until a character does _not_ match + * @data: pointer to memory to scan + * @data_len: length of data + * @c: character to scan for + * + * The complement of memchr(). + * + * Returns a pointer to the first character which is _not_ @c. If all memory in + * @data is @c, returns NULL. + * + * Example: + * char somebytes[] = "HI By\0e"; + * size_t bytes_len = sizeof(somebytes) - 1; + * r = memcchr(somebytes, ' ', bytes_len); + * if (r) { + * printf("Found %c after trimming spaces\n", *r); + * } + */ +PURE_FUNCTION +void *memcchr(void const *data, int c, size_t data_len); + +/** + * memeq - Are two byte arrays equal? + * @a: first array + * @al: bytes in first array + * @b: second array + * @bl: bytes in second array + * + * Example: + * if (memeq(somebytes, bytes_len, otherbytes, otherbytes_len)) { + * printf("memory blocks are the same!\n"); + * } + */ +PURE_FUNCTION +static inline bool memeq(const void *a, size_t al, const void *b, size_t bl) +{ + return al == bl && !memcmp(a, b, bl); +} + +/** + * memstarts - determine if @data starts with @prefix + * @data: does this begin with @prefix? + * @data_len: bytes in @data + * @prefix: does @data begin with these bytes? + * @prefix_len: bytes in @prefix + * + * Returns true if @data starts with @prefix, otherwise return false. + * + * Example: + * if (memstarts(somebytes, bytes_len, otherbytes, otherbytes_len)) { + * printf("somebytes starts with otherbytes!\n"); + * } + */ +PURE_FUNCTION +static inline bool memstarts(void const *data, size_t data_len, + void const *prefix, size_t prefix_len) +{ + if (prefix_len > data_len) + return false; + return memeq(data, prefix_len, prefix, prefix_len); +} + +/** + * memeqstr - Is a byte array equal to a NUL terminated string? + * @data: byte array + * @length: length of @data in bytes + * @string: NUL terminated string + * + * The '\0' byte is ignored when checking if @bytes == @string. + * + * Example: + * if (memeqstr(somebytes, bytes_len, "foo")) { + * printf("somebytes == 'foo'!\n"); + * } + */ +PURE_FUNCTION +static inline bool memeqstr(const void *data, size_t length, const char *string) +{ + return memeq(data, length, string, strlen(string)); +} + +/** + * memeqzero - Is a byte array all zeroes? + * @data: byte array + * @length: length of @data in bytes + * + * Example: + * if (memeqzero(somebytes, bytes_len)) { + * printf("somebytes == 0!\n"); + * } + */ +PURE_FUNCTION +bool memeqzero(const void *data, size_t length); + +/** + * memstarts_str - Does this byte array start with a string prefix? + * @a: byte array + * @al: length in bytes + * @s: string prefix + * + * Example: + * if (memstarts_str(somebytes, bytes_len, "It")) { + * printf("somebytes starts with 'It'\n"); + * } + */ +PURE_FUNCTION +static inline bool memstarts_str(const void *a, size_t al, const char *s) +{ + return memstarts(a, al, s, strlen(s)); +} + +/** + * memends - Does this byte array end with a given byte-array suffix? + * @s: byte array + * @s_len: length in bytes + * @suffix: byte array suffix + * @suffix_len: length of suffix in bytes + * + * Returns true if @suffix appears as a substring at the end of @s, + * false otherwise. + */ +PURE_FUNCTION +static inline bool memends(const void *s, size_t s_len, const void *suffix, size_t suffix_len) +{ + return (s_len >= suffix_len) && (memcmp((const char *)s + s_len - suffix_len, + suffix, suffix_len) == 0); +} + +/** + * memends_str - Does this byte array end with a string suffix? + * @a: byte array + * @al: length in bytes + * @s: string suffix + * + * Example: + * if (memends_str(somebytes, bytes_len, "It")) { + * printf("somebytes ends with with 'It'\n"); + * } + */ +PURE_FUNCTION +static inline bool memends_str(const void *a, size_t al, const char *s) +{ + return memends(a, al, s, strlen(s)); +} + +/** + * memoverlaps - Do two memory ranges overlap? + * @a: pointer to first memory range + * @al: length of first memory range + * @b: pointer to second memory range + * @al: length of second memory range + */ +CONST_FUNCTION +static inline bool memoverlaps(const void *a_, size_t al, + const void *b_, size_t bl) +{ + const char *a = a_; + const char *b = b_; + + return (a < (b + bl)) && (b < (a + al)); +} + +/* + * memswap - Exchange two memory regions + * @a: first region + * @b: second region + * @n: length of the regions + * + * Undefined results if the two memory regions overlap. + */ +void memswap(void *a, void *b, size_t n); + +#if HAVE_VALGRIND_MEMCHECK_H +#include +static inline void *memcheck_(const void *data, size_t len) +{ + VALGRIND_CHECK_MEM_IS_DEFINED(data, len); + return (void *)data; +} +#else +static inline void *memcheck_(const void *data, size_t len) +{ + (void)len; + return (void *)data; +} +#endif + +#if HAVE_TYPEOF +/** + * memcheck - check that a memory region is initialized + * @data: start of region + * @len: length in bytes + * + * When running under valgrind, this causes an error to be printed + * if the entire region is not defined. Otherwise valgrind only + * reports an error when an undefined value is used for a branch, or + * written out. + * + * Example: + * // Search for space, but make sure it's all initialized. + * if (memchr(memcheck(somebytes, bytes_len), ' ', bytes_len)) { + * printf("space was found!\n"); + * } + */ +#define memcheck(data, len) ((__typeof__((data)+0))memcheck_((data), (len))) +#else +#define memcheck(data, len) memcheck_((data), (len)) +#endif + +/** + * memtaint - mark a memory region unused + * @data: start of region + * @len: length in bytes + * + * This writes an "0xdeadbeef" eyecatcher repeatedly to the memory. + * When running under valgrind, it also tells valgrind that the memory is + * uninitialized, triggering valgrind errors if it is used for branches + * or written out (or passed to memcheck!) in future. + * + * Example: + * // We'll reuse this buffer later, but be sure we don't access it. + * memtaint(somebytes, bytes_len); + */ +void memtaint(void *data, size_t len); +#endif /* CCAN_MEM_H */ diff --git a/nostrdb/bolt11/node_id.c b/nostrdb/bolt11/node_id.c new file mode 100644 index 00000000..6778ddca --- /dev/null +++ b/nostrdb/bolt11/node_id.c @@ -0,0 +1,64 @@ +#include "config.h" +#include +#include "array_size.h" +#include "mem.h" +#include "hex.h" +#include "talstr.h" +#include "node_id.h" + +/* Convert from pubkey to compressed pubkey. */ +/* +void node_id_from_pubkey(struct node_id *id, const struct pubkey *key) +{ + size_t outlen = ARRAY_SIZE(id->k); + if (!secp256k1_ec_pubkey_serialize(secp256k1_ctx, id->k, &outlen, + &key->pubkey, + SECP256K1_EC_COMPRESSED)) + abort(); +} + +WARN_UNUSED_RESULT +bool pubkey_from_node_id(struct pubkey *key, const struct node_id *id) +{ + return secp256k1_ec_pubkey_parse(secp256k1_ctx, &key->pubkey, + memcheck(id->k, sizeof(id->k)), + sizeof(id->k)); +} + +WARN_UNUSED_RESULT +bool point32_from_node_id(struct point32 *key, const struct node_id *id) +{ + struct pubkey k; + if (!pubkey_from_node_id(&k, id)) + return false; + return secp256k1_xonly_pubkey_from_pubkey(secp256k1_ctx, &key->pubkey, + NULL, &k.pubkey) == 1; +} +*/ + +char *tal_hexstr(const tal_t *ctx, const void *data, size_t len) +{ + char *str = tal_arr(ctx, char, hex_str_size(len)); + hex_encode(data, len, str, hex_str_size(len)); + return str; +} + + +/* Convert to hex string of SEC1 encoding */ +char *node_id_to_hexstr(const tal_t *ctx, const struct node_id *id) +{ + return tal_hexstr(ctx, id->k, sizeof(id->k)); +} + +/* Convert from hex string of SEC1 encoding */ + +bool node_id_from_hexstr(const char *str, size_t slen, struct node_id *id) +{ + return hex_decode(str, slen, id->k, sizeof(id->k)); + /* && node_id_valid(id);*/ +} + +int node_id_cmp(const struct node_id *a, const struct node_id *b) +{ + return memcmp(a->k, b->k, sizeof(a->k)); +} diff --git a/nostrdb/bolt11/node_id.h b/nostrdb/bolt11/node_id.h new file mode 100644 index 00000000..873e10b1 --- /dev/null +++ b/nostrdb/bolt11/node_id.h @@ -0,0 +1,38 @@ +/* Encapsulation for pubkeys used as node ids: more compact, more dangerous. */ +#ifndef LIGHTNING_COMMON_NODE_ID_H +#define LIGHTNING_COMMON_NODE_ID_H +#include "../config.h" +#include "short_types.h" +#include "tal.h" + +struct node_id { + u8 k[33]; +}; + +static inline bool node_id_eq(const struct node_id *a, + const struct node_id *b) +{ + return memcmp(a->k, b->k, sizeof(a->k)) == 0; +} + +/* Is this actually a valid pubkey? Relatively expensive. */ +//bool node_id_valid(const struct node_id *id); + +/* Convert to hex string of SEC1 encoding. */ +char *node_id_to_hexstr(const tal_t *ctx, const struct node_id *id); + +/* Convert from hex string of SEC1 encoding: checks validity! */ +bool node_id_from_hexstr(const char *str, size_t slen, struct node_id *id); + +/* Compare the keys `a` and `b`. Return <0 if `a`<`b`, 0 if equal and >0 otherwise */ +int node_id_cmp(const struct node_id *a, const struct node_id *b); + +/* If the two nodes[] are id1 and id2, which index would id1 be? */ +static inline int node_id_idx(const struct node_id *id1, + const struct node_id *id2) +{ + return node_id_cmp(id1, id2) > 0; +} + +/* marshal/unmarshal functions */ +#endif /* LIGHTNING_COMMON_NODE_ID_H */ diff --git a/nostrdb/bolt11/overflows.h b/nostrdb/bolt11/overflows.h new file mode 100644 index 00000000..dac460c0 --- /dev/null +++ b/nostrdb/bolt11/overflows.h @@ -0,0 +1,43 @@ +#ifndef LIGHTNING_COMMON_OVERFLOWS_H +#define LIGHTNING_COMMON_OVERFLOWS_H +#include "../config.h" +#include "short_types.h" + +static inline bool add_overflows_size_t(uint64_t a, uint64_t b) +{ + return (size_t)a != a || (size_t)b != b || (a + b) < (size_t)a; +} + +static inline bool add_overflows_u64(uint64_t a, uint64_t b) +{ + return (a + b) < a; +} + +static inline bool mul_overflows_u64(uint64_t a, uint64_t b) +{ + uint64_t ret; + + if (a == 0) + return false; + ret = a * b; + return (ret / a != b); +} + +static inline bool assign_overflow_u8(u8 *dst, uint64_t v) +{ + *dst = v; + return *dst == v; +} + +static inline bool assign_overflow_u16(u16 *dst, uint64_t v) +{ + *dst = v; + return *dst == v; +} + +static inline bool assign_overflow_u32(u32 *dst, uint64_t v) +{ + *dst = (u32)v; + return *dst == v; +} +#endif /* LIGHTNING_COMMON_OVERFLOWS_H */ diff --git a/nostrdb/bolt11/short_types.h b/nostrdb/bolt11/short_types.h new file mode 100644 index 00000000..175377e9 --- /dev/null +++ b/nostrdb/bolt11/short_types.h @@ -0,0 +1,35 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_SHORT_TYPES_H +#define CCAN_SHORT_TYPES_H +#include + +/** + * u64/s64/u32/s32/u16/s16/u8/s8 - short names for explicitly-sized types. + */ +typedef uint64_t u64; +typedef int64_t s64; +typedef uint32_t u32; +typedef int32_t s32; +typedef uint16_t u16; +typedef int16_t s16; +typedef uint8_t u8; +typedef int8_t s8; + +/* Whichever they include first, they get these definitions. */ +#ifdef CCAN_ENDIAN_H +/** + * be64/be32/be16 - 64/32/16 bit big-endian representation. + */ +typedef beint64_t be64; +typedef beint32_t be32; +typedef beint16_t be16; + +/** + * le64/le32/le16 - 64/32/16 bit little-endian representation. + */ +typedef leint64_t le64; +typedef leint32_t le32; +typedef leint16_t le16; +#endif + +#endif /* CCAN_SHORT_TYPES_H */ diff --git a/nostrdb/bolt11/str.h b/nostrdb/bolt11/str.h new file mode 100644 index 00000000..f391abdd --- /dev/null +++ b/nostrdb/bolt11/str.h @@ -0,0 +1,228 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_STR_H +#define CCAN_STR_H +#include "../config.h" +#include +#include +#include +#include + +/** + * streq - Are two strings equal? + * @a: first string + * @b: first string + * + * This macro is arguably more readable than "!strcmp(a, b)". + * + * Example: + * if (streq(somestring, "")) + * printf("String is empty!\n"); + */ +#define streq(a,b) (strcmp((a),(b)) == 0) + +/** + * strstarts - Does this string start with this prefix? + * @str: string to test + * @prefix: prefix to look for at start of str + * + * Example: + * if (strstarts(somestring, "foo")) + * printf("String %s begins with 'foo'!\n", somestring); + */ +#define strstarts(str,prefix) (strncmp((str),(prefix),strlen(prefix)) == 0) + +/** + * strends - Does this string end with this postfix? + * @str: string to test + * @postfix: postfix to look for at end of str + * + * Example: + * if (strends(somestring, "foo")) + * printf("String %s end with 'foo'!\n", somestring); + */ +static inline bool strends(const char *str, const char *postfix) +{ + if (strlen(str) < strlen(postfix)) + return false; + + return streq(str + strlen(str) - strlen(postfix), postfix); +} + +/** + * stringify - Turn expression into a string literal + * @expr: any C expression + * + * Example: + * #define PRINT_COND_IF_FALSE(cond) \ + * ((cond) || printf("%s is false!", stringify(cond))) + */ +#define stringify(expr) stringify_1(expr) +/* Double-indirection required to stringify expansions */ +#define stringify_1(expr) #expr + +/** + * strcount - Count number of (non-overlapping) occurrences of a substring. + * @haystack: a C string + * @needle: a substring + * + * Example: + * assert(strcount("aaa aaa", "a") == 6); + * assert(strcount("aaa aaa", "ab") == 0); + * assert(strcount("aaa aaa", "aa") == 2); + */ +size_t strcount(const char *haystack, const char *needle); + +/** + * STR_MAX_CHARS - Maximum possible size of numeric string for this type. + * @type_or_expr: a pointer or integer type or expression. + * + * This provides enough space for a nul-terminated string which represents the + * largest possible value for the type or expression. + * + * Note: The implementation adds extra space so hex values or negative + * values will fit (eg. sprintf(... "%p"). ) + * + * Example: + * char str[STR_MAX_CHARS(int)]; + * + * sprintf(str, "%i", 7); + */ +#define STR_MAX_CHARS(type_or_expr) \ + ((sizeof(type_or_expr) * CHAR_BIT + 8) / 9 * 3 + 2 \ + + STR_MAX_CHARS_TCHECK_(type_or_expr)) + +#if HAVE_TYPEOF +/* Only a simple type can have 0 assigned, so test that. */ +#define STR_MAX_CHARS_TCHECK_(type_or_expr) \ + (sizeof(({ typeof(type_or_expr) x = 0; x; }))*0) +#else +#define STR_MAX_CHARS_TCHECK_(type_or_expr) 0 +#endif + +/** + * cisalnum - isalnum() which takes a char (and doesn't accept EOF) + * @c: a character + * + * Surprisingly, the standard ctype.h isalnum() takes an int, which + * must have the value of EOF (-1) or an unsigned char. This variant + * takes a real char, and doesn't accept EOF. + */ +static inline bool cisalnum(char c) +{ + return isalnum((unsigned char)c); +} +static inline bool cisalpha(char c) +{ + return isalpha((unsigned char)c); +} +static inline bool cisascii(char c) +{ + return isascii((unsigned char)c); +} +#if HAVE_ISBLANK +static inline bool cisblank(char c) +{ + return isblank((unsigned char)c); +} +#endif +static inline bool ciscntrl(char c) +{ + return iscntrl((unsigned char)c); +} +static inline bool cisdigit(char c) +{ + return isdigit((unsigned char)c); +} +static inline bool cisgraph(char c) +{ + return isgraph((unsigned char)c); +} +static inline bool cislower(char c) +{ + return islower((unsigned char)c); +} +static inline bool cisprint(char c) +{ + return isprint((unsigned char)c); +} +static inline bool cispunct(char c) +{ + return ispunct((unsigned char)c); +} +static inline bool cisspace(char c) +{ + return isspace((unsigned char)c); +} +static inline bool cisupper(char c) +{ + return isupper((unsigned char)c); +} +static inline bool cisxdigit(char c) +{ + return isxdigit((unsigned char)c); +} + +#include "str_debug.h" + +/* These checks force things out of line, hence they are under DEBUG. */ +#ifdef CCAN_STR_DEBUG +#include + +/* These are commonly misused: they take -1 or an *unsigned* char value. */ +#undef isalnum +#undef isalpha +#undef isascii +#undef isblank +#undef iscntrl +#undef isdigit +#undef isgraph +#undef islower +#undef isprint +#undef ispunct +#undef isspace +#undef isupper +#undef isxdigit + +/* You can use a char if char is unsigned. */ +#if HAVE_BUILTIN_TYPES_COMPATIBLE_P && HAVE_TYPEOF +#define str_check_arg_(i) \ + ((i) + BUILD_ASSERT_OR_ZERO(!__builtin_types_compatible_p(typeof(i), \ + char) \ + || (char)255 > 0)) +#else +#define str_check_arg_(i) (i) +#endif + +#define isalnum(i) str_isalnum(str_check_arg_(i)) +#define isalpha(i) str_isalpha(str_check_arg_(i)) +#define isascii(i) str_isascii(str_check_arg_(i)) +#if HAVE_ISBLANK +#define isblank(i) str_isblank(str_check_arg_(i)) +#endif +#define iscntrl(i) str_iscntrl(str_check_arg_(i)) +#define isdigit(i) str_isdigit(str_check_arg_(i)) +#define isgraph(i) str_isgraph(str_check_arg_(i)) +#define islower(i) str_islower(str_check_arg_(i)) +#define isprint(i) str_isprint(str_check_arg_(i)) +#define ispunct(i) str_ispunct(str_check_arg_(i)) +#define isspace(i) str_isspace(str_check_arg_(i)) +#define isupper(i) str_isupper(str_check_arg_(i)) +#define isxdigit(i) str_isxdigit(str_check_arg_(i)) + +#if HAVE_TYPEOF +/* With GNU magic, we can make const-respecting standard string functions. */ +#undef strstr +#undef strchr +#undef strrchr + +/* + 0 is needed to decay array into pointer. */ +#define strstr(haystack, needle) \ + ((typeof((haystack) + 0))str_strstr((haystack), (needle))) +#define strchr(haystack, c) \ + ((typeof((haystack) + 0))str_strchr((haystack), (c))) +#define strrchr(haystack, c) \ + ((typeof((haystack) + 0))str_strrchr((haystack), (c))) +#endif +#endif /* CCAN_STR_DEBUG */ + +#endif /* CCAN_STR_H */ diff --git a/nostrdb/bolt11/str_debug.h b/nostrdb/bolt11/str_debug.h new file mode 100644 index 00000000..92c10c41 --- /dev/null +++ b/nostrdb/bolt11/str_debug.h @@ -0,0 +1,30 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_STR_DEBUG_H +#define CCAN_STR_DEBUG_H + +/* #define CCAN_STR_DEBUG 1 */ + +#ifdef CCAN_STR_DEBUG +/* Because we mug the real ones with macros, we need our own wrappers. */ +int str_isalnum(int i); +int str_isalpha(int i); +int str_isascii(int i); +#if HAVE_ISBLANK +int str_isblank(int i); +#endif +int str_iscntrl(int i); +int str_isdigit(int i); +int str_isgraph(int i); +int str_islower(int i); +int str_isprint(int i); +int str_ispunct(int i); +int str_isspace(int i); +int str_isupper(int i); +int str_isxdigit(int i); + +char *str_strstr(const char *haystack, const char *needle); +char *str_strchr(const char *s, int c); +char *str_strrchr(const char *s, int c); +#endif /* CCAN_STR_DEBUG */ + +#endif /* CCAN_STR_DEBUG_H */ diff --git a/nostrdb/bolt11/structeq.h b/nostrdb/bolt11/structeq.h new file mode 100644 index 00000000..bb701465 --- /dev/null +++ b/nostrdb/bolt11/structeq.h @@ -0,0 +1,46 @@ +/* MIT (BSD) license - see LICENSE file for details */ +#ifndef CCAN_STRUCTEQ_H +#define CCAN_STRUCTEQ_H +#include "build_assert.h" +#include "cppmagic.h" +#include +#include + +/** + * STRUCTEQ_DEF - define an ..._eq function to compare two structures. + * @sname: name of the structure, and function (_eq) to define. + * @padbytes: number of bytes of expected padding, or negative "max". + * @...: name of every member of the structure. + * + * This generates a single memcmp() call in the common case where the + * structure contains no padding. Since it can't tell the difference between + * padding and a missing member, @padbytes can be used to assert that + * there isn't any, or how many we expect. A negative number means + * "up to or equal to that amount of padding", as padding can be + * platform dependent. + */ +#define STRUCTEQ_DEF(sname, padbytes, ...) \ +static inline bool CPPMAGIC_GLUE2(sname, _eq)(const struct sname *_a, \ + const struct sname *_b) \ +{ \ + BUILD_ASSERT(((padbytes) < 0 && \ + CPPMAGIC_JOIN(+, CPPMAGIC_MAP(STRUCTEQ_MEMBER_SIZE_, \ + __VA_ARGS__)) \ + - (padbytes) >= sizeof(*_a)) \ + || CPPMAGIC_JOIN(+, CPPMAGIC_MAP(STRUCTEQ_MEMBER_SIZE_, \ + __VA_ARGS__)) \ + + (padbytes) == sizeof(*_a)); \ + if (CPPMAGIC_JOIN(+, CPPMAGIC_MAP(STRUCTEQ_MEMBER_SIZE_, __VA_ARGS__)) \ + == sizeof(*_a)) \ + return memcmp(_a, _b, sizeof(*_a)) == 0; \ + else \ + return CPPMAGIC_JOIN(&&, \ + CPPMAGIC_MAP(STRUCTEQ_MEMBER_CMP_, \ + __VA_ARGS__)); \ +} + +/* Helpers */ +#define STRUCTEQ_MEMBER_SIZE_(m) sizeof((_a)->m) +#define STRUCTEQ_MEMBER_CMP_(m) memcmp(&_a->m, &_b->m, sizeof(_a->m)) == 0 + +#endif /* CCAN_STRUCTEQ_H */ diff --git a/nostrdb/bolt11/take.c b/nostrdb/bolt11/take.c new file mode 100644 index 00000000..3b59db08 --- /dev/null +++ b/nostrdb/bolt11/take.c @@ -0,0 +1,126 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#include "take.h" +#include "likely.h" +#include +#include +#include + +static const void **takenarr; +static const char **labelarr; +static size_t max_taken, num_taken; +static size_t allocfail; +static void (*allocfailfn)(const void *p); + +void *take_(const void *p, const char *label) +{ + /* Overallocate: it's better than risking calloc returning NULL! */ + if (unlikely(label && !labelarr)) + labelarr = calloc(max_taken+1, sizeof(*labelarr)); + + if (unlikely(num_taken == max_taken)) { + const void **new; + + new = realloc(takenarr, sizeof(*takenarr) * (max_taken+1)); + if (unlikely(!new)) { + if (allocfailfn) { + allocfail++; + allocfailfn(p); + return NULL; + } + /* Otherwise we leak p. */ + return (void *)p; + } + takenarr = new; + /* Once labelarr is set, we maintain it. */ + if (labelarr) { + const char **labelarr_new; + labelarr_new = realloc(labelarr, + sizeof(*labelarr) * (max_taken+1)); + if (labelarr_new) { + labelarr = labelarr_new; + } else { + /* num_taken will be out of sync with the size of + * labelarr after realloc failure. + * Just pretend that we never had labelarr allocated. */ + free(labelarr); + labelarr = NULL; + } + } + max_taken++; + } + if (unlikely(labelarr)) + labelarr[num_taken] = label; + takenarr[num_taken++] = p; + + return (void *)p; +} + +static size_t find_taken(const void *p) +{ + size_t i; + + for (i = 0; i < num_taken; i++) { + if (takenarr[i] == p) + return i+1; + } + return 0; +} + +bool taken(const void *p) +{ + size_t i; + + if (!p && unlikely(allocfail)) { + allocfail--; + return true; + } + + i = find_taken(p); + if (!i) + return false; + + memmove(&takenarr[i-1], &takenarr[i], + (--num_taken - (i - 1))*sizeof(takenarr[0])); + return true; +} + +bool is_taken(const void *p) +{ + if (!p && unlikely(allocfail)) + return true; + + return find_taken(p) > 0; +} + +const char *taken_any(void) +{ + static char pointer_buf[32]; + + if (num_taken == 0) + return NULL; + + /* We're *allowed* to have some with labels, some without. */ + if (labelarr) { + size_t i; + for (i = 0; i < num_taken; i++) + if (labelarr[i]) + return labelarr[i]; + } + + sprintf(pointer_buf, "%p", takenarr[0]); + return pointer_buf; +} + +void take_cleanup(void) +{ + max_taken = num_taken = 0; + free(takenarr); + takenarr = NULL; + free(labelarr); + labelarr = NULL; +} + +void take_allocfail(void (*fn)(const void *p)) +{ + allocfailfn = fn; +} diff --git a/nostrdb/bolt11/take.h b/nostrdb/bolt11/take.h new file mode 100644 index 00000000..3de6f99d --- /dev/null +++ b/nostrdb/bolt11/take.h @@ -0,0 +1,136 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_TAKE_H +#define CCAN_TAKE_H +#include "../config.h" +#include +#include "str.h" + +#ifdef CCAN_TAKE_DEBUG +#define TAKE_LABEL(p) __FILE__ ":" stringify(__LINE__) ":" stringify(p) +#else +#define TAKE_LABEL(p) NULL +#endif + +/** + * TAKES - annotate a formal parameter as being take()-able + * + * This doesn't do anything, but useful for documentation. + * + * Example: + * void print_string(const char *str TAKES); + * + */ +#define TAKES + +/** + * take - record a pointer to be consumed by the function its handed to. + * @p: the pointer to mark, or NULL. + * + * This marks a pointer object to be freed by the called function, + * which is extremely useful for chaining functions. It works on + * NULL, for pass-through error handling. + */ +#define take(p) (take_typeof(p) take_((p), TAKE_LABEL(p))) + +/** + * taken - check (and un-take) a pointer was passed with take() + * @p: the pointer to check. + * + * A function which accepts take() arguments uses this to see if it + * should own the pointer; it will be removed from the take list, so + * this only returns true once. + * + * Example: + * // Silly routine to add 1 + * static int *add_one(const int *num TAKES) + * { + * int *ret; + * if (taken(num)) + * ret = (int *)num; + * else + * ret = malloc(sizeof(int)); + * if (ret) + * *ret = (*num) + 1; + * return ret; + * } + */ +bool taken(const void *p); + +/** + * is_taken - check if a pointer was passed with take() + * @p: the pointer to check. + * + * This is like the above, but doesn't remove it from the taken list. + * + * Example: + * // Silly routine to add 1: doesn't handle taken args! + * static int *add_one_notake(const int *num) + * { + * int *ret = malloc(sizeof(int)); + * assert(!is_taken(num)); + * if (ret) + * *ret = (*num) + 1; + * return ret; + * } + */ +bool is_taken(const void *p); + +/** + * taken_any - are there any taken pointers? + * + * Mainly useful for debugging take() leaks. With CCAN_TAKE_DEBUG, returns + * the label where the pointer was passed to take(), otherwise returns + * a static char buffer with the pointer value in it. NULL if none are taken. + * + * Example: + * static void cleanup(void) + * { + * assert(!taken_any()); + * } + */ +const char *taken_any(void); + +/** + * take_cleanup - remove all taken pointers from list. + * + * This is useful in atexit() handlers for valgrind-style leak detection. + * + * Example: + * static void cleanup2(void) + * { + * take_cleanup(); + * } + */ +void take_cleanup(void); + +/** + * take_allocfail - set function to call if we can't reallocated taken array. + * @fn: the function. + * + * If this is not set, then if the array reallocation fails, the + * pointer won't be marked taken(). If @fn returns, it is expected to + * free the pointer; we return NULL from take() and the function handles + * it like any allocation failure. + * + * Example: + * static void free_on_fail(const void *p) + * { + * free((void *)p); + * } + * + * static void init(void) + * { + * take_allocfail(free_on_fail); + * } + */ +void take_allocfail(void (*fn)(const void *p)); + +/* Private functions */ +#if HAVE_TYPEOF +#define take_typeof(ptr) (__typeof__(ptr)) +#else +#define take_typeof(ptr) +#endif + +void *take_(const void *p, const char *label); +#endif /* CCAN_TAKE_H */ diff --git a/nostrdb/bolt11/tal.c b/nostrdb/bolt11/tal.c new file mode 100644 index 00000000..516b4404 --- /dev/null +++ b/nostrdb/bolt11/tal.c @@ -0,0 +1,972 @@ +/* Licensed under BSD-MIT - see LICENSE file for details */ +#include "tal.h" +#include "../compiler.h" +#include "list.h" +#include "alignof.h" + +#include +#include +#include +#include +#include +#include +#include + +//#define TAL_DEBUG 1 + +#define NOTIFY_IS_DESTRUCTOR 512 +#define NOTIFY_EXTRA_ARG 1024 + +/* This makes our parent_child ptr stand out for to_tal_hdr checks */ +#define TAL_PTR_OBFUSTICATOR ((intptr_t)0x1984200820142016ULL) + +/* 32-bit type field, first byte 0 in either endianness. */ +enum prop_type { + CHILDREN = 0x00c1d500, + NAME = 0x00111100, + NOTIFIER = 0x00071f00, +}; + +struct tal_hdr { + struct list_node list; + struct prop_hdr *prop; + /* XOR with TAL_PTR_OBFUSTICATOR */ + intptr_t parent_child; + size_t bytelen; +}; + +struct prop_hdr { + enum prop_type type; + struct prop_hdr *next; +}; + +struct children { + struct prop_hdr hdr; /* CHILDREN */ + struct tal_hdr *parent; + struct list_head children; /* Head of siblings. */ +}; + +struct name { + struct prop_hdr hdr; /* NAME */ + char name[]; +}; + +struct notifier { + struct prop_hdr hdr; /* NOTIFIER */ + enum tal_notify_type types; + union notifier_cb { + void (*notifyfn)(tal_t *, enum tal_notify_type, void *); + void (*destroy)(tal_t *); /* If NOTIFY_IS_DESTRUCTOR set */ + void (*destroy2)(tal_t *, void *); /* If NOTIFY_EXTRA_ARG */ + } u; +}; + +/* Extra arg */ +struct notifier_extra_arg { + struct notifier n; + void *arg; +}; + +#define EXTRA_ARG(n) (((struct notifier_extra_arg *)(n))->arg) + +static struct { + struct tal_hdr hdr; + struct children c; +} null_parent = { { { &null_parent.hdr.list, &null_parent.hdr.list }, + &null_parent.c.hdr, TAL_PTR_OBFUSTICATOR, 0 }, + { { CHILDREN, NULL }, + &null_parent.hdr, + { { &null_parent.c.children.n, + &null_parent.c.children.n } } + } +}; + + +static void *(*allocfn)(size_t size) = malloc; +static void *(*resizefn)(void *, size_t size) = realloc; +static void (*freefn)(void *) = free; +static void (*errorfn)(const char *msg) = (void *)abort; +/* Count on non-destrutor notifiers; often stays zero. */ +static size_t notifiers = 0; + +static inline void COLD call_error(const char *msg) +{ + errorfn(msg); +} + +static bool get_destroying_bit(intptr_t parent_child) +{ + return parent_child & 1; +} + +static void set_destroying_bit(intptr_t *parent_child) +{ + *parent_child |= 1; +} + +static struct children *ignore_destroying_bit(intptr_t parent_child) +{ + return (void *)((parent_child ^ TAL_PTR_OBFUSTICATOR) & ~(intptr_t)1); +} + +/* This means valgrind can see leaks. */ +void tal_cleanup(void) +{ + struct tal_hdr *i; + + while ((i = list_top(&null_parent.c.children, struct tal_hdr, list))) { + list_del(&i->list); + memset(i, 0, sizeof(*i)); + } + + /* Cleanup any taken pointers. */ + take_cleanup(); +} + +/* We carefully start all real properties with a zero byte. */ +static bool is_literal(const struct prop_hdr *prop) +{ + return ((char *)prop)[0] != 0; +} + +#ifndef NDEBUG +static const void *bounds_start, *bounds_end; + +static void update_bounds(const void *new, size_t size) +{ + if (unlikely(!bounds_start)) { + bounds_start = new; + bounds_end = (char *)new + size; + } else if (new < bounds_start) + bounds_start = new; + else if ((char *)new + size > (char *)bounds_end) + bounds_end = (char *)new + size; +} + +static bool in_bounds(const void *p) +{ + return !p + || (p >= (void *)&null_parent && p <= (void *)(&null_parent + 1)) + || (p >= bounds_start && p <= bounds_end); +} +#else +static void update_bounds(const void *new, size_t size) +{ +} + +static bool in_bounds(const void *p) +{ + return true; +} +#endif + +static void check_bounds(const void *p) +{ + if (!in_bounds(p)) + call_error("Not a valid header"); +} + +static struct tal_hdr *to_tal_hdr(const void *ctx) +{ + struct tal_hdr *t; + + t = (struct tal_hdr *)((char *)ctx - sizeof(struct tal_hdr)); + check_bounds(t); + check_bounds(ignore_destroying_bit(t->parent_child)); + check_bounds(t->list.next); + check_bounds(t->list.prev); + if (t->prop && !is_literal(t->prop)) + check_bounds(t->prop); + return t; +} + +static struct tal_hdr *to_tal_hdr_or_null(const void *ctx) +{ + if (!ctx) + return &null_parent.hdr; + return to_tal_hdr(ctx); +} + +static void *from_tal_hdr(const struct tal_hdr *hdr) +{ + return (void *)(hdr + 1); +} + +static void *from_tal_hdr_or_null(const struct tal_hdr *hdr) +{ + if (hdr == &null_parent.hdr) + return NULL; + return from_tal_hdr(hdr); +} + +#ifdef TAL_DEBUG +static struct tal_hdr *debug_tal(struct tal_hdr *tal) +{ + tal_check(from_tal_hdr_or_null(tal), "TAL_DEBUG "); + return tal; +} +#else +static struct tal_hdr *debug_tal(struct tal_hdr *tal) +{ + return tal; +} +#endif + +static void notify(const struct tal_hdr *ctx, + enum tal_notify_type type, const void *info, + int saved_errno) +{ + const struct prop_hdr *p; + + for (p = ctx->prop; p; p = p->next) { + struct notifier *n; + + if (is_literal(p)) + break; + if (p->type != NOTIFIER) + continue; + n = (struct notifier *)p; + if (n->types & type) { + errno = saved_errno; + if (n->types & NOTIFY_IS_DESTRUCTOR) { + /* Blatt this notifier in case it tries to + * tal_del_destructor() from inside */ + union notifier_cb cb = n->u; + /* It's a union, so this NULLs destroy2 too! */ + n->u.destroy = NULL; + if (n->types & NOTIFY_EXTRA_ARG) + cb.destroy2(from_tal_hdr(ctx), + EXTRA_ARG(n)); + else + cb.destroy(from_tal_hdr(ctx)); + } else + n->u.notifyfn(from_tal_hdr_or_null(ctx), type, + (void *)info); + } + } +} + +static void *allocate(size_t size) +{ + void *ret = allocfn(size); + if (!ret) + call_error("allocation failed"); + else + update_bounds(ret, size); + return ret; +} + +static struct prop_hdr **find_property_ptr(const struct tal_hdr *t, + enum prop_type type) +{ + struct prop_hdr **p; + + for (p = (struct prop_hdr **)&t->prop; *p; p = &(*p)->next) { + if (is_literal(*p)) { + if (type == NAME) + return p; + break; + } + if ((*p)->type == type) + return p; + } + return NULL; +} + +static void *find_property(const struct tal_hdr *parent, enum prop_type type) +{ + struct prop_hdr **p = find_property_ptr(parent, type); + + if (p) + return *p; + return NULL; +} + +static void init_property(struct prop_hdr *hdr, + struct tal_hdr *parent, + enum prop_type type) +{ + hdr->type = type; + hdr->next = parent->prop; + parent->prop = hdr; +} + +static struct notifier *add_notifier_property(struct tal_hdr *t, + enum tal_notify_type types, + void (*fn)(void *, + enum tal_notify_type, + void *), + void *extra_arg) +{ + struct notifier *prop; + + if (types & NOTIFY_EXTRA_ARG) + prop = allocate(sizeof(struct notifier_extra_arg)); + else + prop = allocate(sizeof(struct notifier)); + + if (prop) { + init_property(&prop->hdr, t, NOTIFIER); + prop->types = types; + prop->u.notifyfn = fn; + if (types & NOTIFY_EXTRA_ARG) + EXTRA_ARG(prop) = extra_arg; + } + return prop; +} + +static enum tal_notify_type del_notifier_property(struct tal_hdr *t, + void (*fn)(tal_t *, + enum tal_notify_type, + void *), + bool match_extra_arg, + void *extra_arg) +{ + struct prop_hdr **p; + + for (p = (struct prop_hdr **)&t->prop; *p; p = &(*p)->next) { + struct notifier *n; + enum tal_notify_type types; + + if (is_literal(*p)) + break; + if ((*p)->type != NOTIFIER) + continue; + n = (struct notifier *)*p; + if (n->u.notifyfn != fn) + continue; + + types = n->types; + if ((types & NOTIFY_EXTRA_ARG) + && match_extra_arg + && extra_arg != EXTRA_ARG(n)) + continue; + + *p = (*p)->next; + freefn(n); + return types & ~(NOTIFY_IS_DESTRUCTOR|NOTIFY_EXTRA_ARG); + } + return 0; +} + +static struct name *add_name_property(struct tal_hdr *t, const char *name) +{ + struct name *prop; + + prop = allocate(sizeof(*prop) + strlen(name) + 1); + if (prop) { + init_property(&prop->hdr, t, NAME); + strcpy(prop->name, name); + } + return prop; +} + +static struct children *add_child_property(struct tal_hdr *parent, + struct tal_hdr *child UNNEEDED) +{ + struct children *prop = allocate(sizeof(*prop)); + if (prop) { + init_property(&prop->hdr, parent, CHILDREN); + prop->parent = parent; + list_head_init(&prop->children); + } + return prop; +} + +static bool add_child(struct tal_hdr *parent, struct tal_hdr *child) +{ + struct children *children = find_property(parent, CHILDREN); + + if (!children) { + children = add_child_property(parent, child); + if (!children) + return false; + } + list_add(&children->children, &child->list); + child->parent_child = (intptr_t)children ^ TAL_PTR_OBFUSTICATOR; + return true; +} + +static void del_tree(struct tal_hdr *t, const tal_t *orig, int saved_errno) +{ + struct prop_hdr **prop, *p, *next; + + assert(!taken(from_tal_hdr(t))); + + /* Already being destroyed? Don't loop. */ + if (unlikely(get_destroying_bit(t->parent_child))) + return; + + set_destroying_bit(&t->parent_child); + + /* Call free notifiers. */ + notify(t, TAL_NOTIFY_FREE, (tal_t *)orig, saved_errno); + + /* Now free children and groups. */ + prop = find_property_ptr(t, CHILDREN); + if (prop) { + struct tal_hdr *i; + struct children *c = (struct children *)*prop; + + while ((i = list_top(&c->children, struct tal_hdr, list))) { + list_del(&i->list); + del_tree(i, orig, saved_errno); + } + } + + /* Finally free our properties. */ + for (p = t->prop; p && !is_literal(p); p = next) { + next = p->next; + freefn(p); + } + freefn(t); +} + +void *tal_alloc_(const tal_t *ctx, size_t size, bool clear, const char *label) +{ + struct tal_hdr *child, *parent = debug_tal(to_tal_hdr_or_null(ctx)); + + child = allocate(sizeof(struct tal_hdr) + size); + if (!child) + return NULL; + if (clear) + memset(from_tal_hdr(child), 0, size); + child->prop = (void *)label; + child->bytelen = size; + + if (!add_child(parent, child)) { + freefn(child); + return NULL; + } + debug_tal(parent); + if (notifiers) + notify(parent, TAL_NOTIFY_ADD_CHILD, from_tal_hdr(child), 0); + return from_tal_hdr(debug_tal(child)); +} + +static bool adjust_size(size_t *size, size_t count) +{ + const size_t extra = sizeof(struct tal_hdr); + + /* Multiplication wrap */ + if (count && unlikely(*size * count / *size != count)) + goto overflow; + + *size *= count; + + /* Make sure we don't wrap adding header. */ + if (*size + extra < extra) + goto overflow; + return true; +overflow: + call_error("allocation size overflow"); + return false; +} + +void *tal_alloc_arr_(const tal_t *ctx, size_t size, size_t count, bool clear, + const char *label) +{ + if (!adjust_size(&size, count)) + return NULL; + + return tal_alloc_(ctx, size, clear, label); +} + +void *tal_free(const tal_t *ctx) +{ + if (ctx) { + struct tal_hdr *t; + int saved_errno = errno; + t = debug_tal(to_tal_hdr(ctx)); + if (unlikely(get_destroying_bit(t->parent_child))) + return NULL; + if (notifiers) + notify(ignore_destroying_bit(t->parent_child)->parent, + TAL_NOTIFY_DEL_CHILD, ctx, saved_errno); + list_del(&t->list); + del_tree(t, ctx, saved_errno); + errno = saved_errno; + } + return NULL; +} + +void *tal_steal_(const tal_t *new_parent, const tal_t *ctx) +{ + if (ctx) { + struct tal_hdr *newpar, *t, *old_parent; + + newpar = debug_tal(to_tal_hdr_or_null(new_parent)); + t = debug_tal(to_tal_hdr(ctx)); + + /* Unlink it from old parent. */ + list_del(&t->list); + old_parent = ignore_destroying_bit(t->parent_child)->parent; + + if (unlikely(!add_child(newpar, t))) { + /* We can always add to old parent, because it has a + * children property already. */ + if (!add_child(old_parent, t)) + abort(); + return NULL; + } + debug_tal(newpar); + if (notifiers) + notify(t, TAL_NOTIFY_STEAL, new_parent, 0); + } + return (void *)ctx; +} + +bool tal_add_destructor_(const tal_t *ctx, void (*destroy)(void *me)) +{ + tal_t *t = debug_tal(to_tal_hdr(ctx)); + return add_notifier_property(t, TAL_NOTIFY_FREE|NOTIFY_IS_DESTRUCTOR, + (void *)destroy, NULL); +} + +bool tal_add_destructor2_(const tal_t *ctx, void (*destroy)(void *me, void *arg), + void *arg) +{ + tal_t *t = debug_tal(to_tal_hdr(ctx)); + return add_notifier_property(t, TAL_NOTIFY_FREE|NOTIFY_IS_DESTRUCTOR + |NOTIFY_EXTRA_ARG, + (void *)destroy, arg); +} + +/* We could support notifiers with an extra arg, but we didn't add to API */ +bool tal_add_notifier_(const tal_t *ctx, enum tal_notify_type types, + void (*callback)(tal_t *, enum tal_notify_type, void *)) +{ + struct tal_hdr *t = debug_tal(to_tal_hdr_or_null(ctx)); + struct notifier *n; + + assert(types); + assert((types & ~(TAL_NOTIFY_FREE | TAL_NOTIFY_STEAL | TAL_NOTIFY_MOVE + | TAL_NOTIFY_RESIZE | TAL_NOTIFY_RENAME + | TAL_NOTIFY_ADD_CHILD | TAL_NOTIFY_DEL_CHILD + | TAL_NOTIFY_ADD_NOTIFIER + | TAL_NOTIFY_DEL_NOTIFIER)) == 0); + + /* Don't call notifier about itself: set types after! */ + n = add_notifier_property(t, 0, callback, NULL); + if (unlikely(!n)) + return false; + + if (notifiers) + notify(t, TAL_NOTIFY_ADD_NOTIFIER, callback, 0); + + n->types = types; + if (types != TAL_NOTIFY_FREE) + notifiers++; + return true; +} + +bool tal_del_notifier_(const tal_t *ctx, + void (*callback)(tal_t *, enum tal_notify_type, void *), + bool match_extra_arg, void *extra_arg) +{ + struct tal_hdr *t = debug_tal(to_tal_hdr_or_null(ctx)); + enum tal_notify_type types; + + types = del_notifier_property(t, callback, match_extra_arg, extra_arg); + if (types) { + notify(t, TAL_NOTIFY_DEL_NOTIFIER, callback, 0); + if (types != TAL_NOTIFY_FREE) + notifiers--; + return true; + } + return false; +} + +bool tal_del_destructor_(const tal_t *ctx, void (*destroy)(void *me)) +{ + return tal_del_notifier_(ctx, (void *)destroy, false, NULL); +} + +bool tal_del_destructor2_(const tal_t *ctx, void (*destroy)(void *me, void *arg), + void *arg) +{ + return tal_del_notifier_(ctx, (void *)destroy, true, arg); +} + +bool tal_set_name_(tal_t *ctx, const char *name, bool literal) +{ + struct tal_hdr *t = debug_tal(to_tal_hdr(ctx)); + struct prop_hdr **prop = find_property_ptr(t, NAME); + + /* Get rid of any old name */ + if (prop) { + struct name *name = (struct name *)*prop; + if (is_literal(&name->hdr)) + *prop = NULL; + else { + *prop = name->hdr.next; + freefn(name); + } + } + + if (literal && name[0]) { + struct prop_hdr **p; + + /* Append literal. */ + for (p = &t->prop; *p && !is_literal(*p); p = &(*p)->next); + *p = (struct prop_hdr *)name; + } else if (!add_name_property(t, name)) + return false; + + debug_tal(t); + if (notifiers) + notify(t, TAL_NOTIFY_RENAME, name, 0); + return true; +} + +const char *tal_name(const tal_t *t) +{ + struct name *n; + + n = find_property(debug_tal(to_tal_hdr(t)), NAME); + if (!n) + return NULL; + + if (is_literal(&n->hdr)) + return (const char *)n; + return n->name; +} + +size_t tal_bytelen(const tal_t *ptr) +{ + /* NULL -> null_parent which has bytelen 0 */ + struct tal_hdr *t = debug_tal(to_tal_hdr_or_null(ptr)); + + return t->bytelen; +} + +/* Start one past first child: make stopping natural in circ. list. */ +static struct tal_hdr *first_child(struct tal_hdr *parent) +{ + struct children *child; + + child = find_property(parent, CHILDREN); + if (!child) + return NULL; + + return list_top(&child->children, struct tal_hdr, list); +} + +tal_t *tal_first(const tal_t *root) +{ + struct tal_hdr *c, *t = debug_tal(to_tal_hdr_or_null(root)); + + c = first_child(t); + if (!c) + return NULL; + return from_tal_hdr(c); +} + +tal_t *tal_next(const tal_t *prev) +{ + struct tal_hdr *next, *prevhdr = debug_tal(to_tal_hdr(prev)); + struct list_head *head; + + head = &ignore_destroying_bit(prevhdr->parent_child)->children; + next = list_next(head, prevhdr, list); + if (!next) + return NULL; + return from_tal_hdr(next); +} + +tal_t *tal_parent(const tal_t *ctx) +{ + struct tal_hdr *t; + + if (!ctx) + return NULL; + + t = debug_tal(to_tal_hdr(ctx)); + if (ignore_destroying_bit(t->parent_child)->parent == &null_parent.hdr) + return NULL; + return from_tal_hdr(ignore_destroying_bit(t->parent_child)->parent); +} + +bool tal_resize_(tal_t **ctxp, size_t size, size_t count, bool clear) +{ + struct tal_hdr *old_t, *t; + struct children *child; + + old_t = debug_tal(to_tal_hdr(*ctxp)); + + if (!adjust_size(&size, count)) + return false; + + t = resizefn(old_t, sizeof(struct tal_hdr) + size); + if (!t) { + call_error("Reallocation failure"); + return false; + } + + /* Clear between old end and new end. */ + if (clear && size > t->bytelen) { + char *old_end = (char *)(t + 1) + t->bytelen; + memset(old_end, 0, size - t->bytelen); + } + + /* Update length. */ + t->bytelen = size; + update_bounds(t, sizeof(struct tal_hdr) + size); + + /* If it didn't move, we're done! */ + if (t != old_t) { + /* Fix up linked list pointers. */ + t->list.next->prev = t->list.prev->next = &t->list; + + /* Copy take() property. */ + if (taken(from_tal_hdr(old_t))) + take(from_tal_hdr(t)); + + /* Fix up child property's parent pointer. */ + child = find_property(t, CHILDREN); + if (child) { + assert(child->parent == old_t); + child->parent = t; + } + *ctxp = from_tal_hdr(debug_tal(t)); + if (notifiers) + notify(t, TAL_NOTIFY_MOVE, from_tal_hdr(old_t), 0); + } + if (notifiers) + notify(t, TAL_NOTIFY_RESIZE, (void *)size, 0); + + return true; +} + +bool tal_expand_(tal_t **ctxp, const void *src, size_t size, size_t count) +{ + size_t old_len; + bool ret = false; + + old_len = debug_tal(to_tal_hdr(*ctxp))->bytelen; + + /* Check for additive overflow */ + if (old_len + count * size < old_len) { + call_error("dup size overflow"); + goto out; + } + + /* Don't point src inside thing we're expanding! */ + assert(src < *ctxp + || (char *)src >= (char *)(*ctxp) + old_len); + + if (!tal_resize_(ctxp, size, old_len/size + count, false)) + goto out; + + memcpy((char *)*ctxp + old_len, src, count * size); + ret = true; + +out: + if (taken(src)) + tal_free(src); + return ret; +} + +void *tal_dup_(const tal_t *ctx, const void *p, size_t size, + size_t n, size_t extra, bool nullok, const char *label) +{ + void *ret; + size_t nbytes = size; + + if (nullok && p == NULL) { + /* take(NULL) works. */ + (void)taken(p); + return NULL; + } + + if (!adjust_size(&nbytes, n)) { + if (taken(p)) + tal_free(p); + return NULL; + } + + /* Beware addition overflow! */ + if (n + extra < n) { + call_error("dup size overflow"); + if (taken(p)) + tal_free(p); + return NULL; + } + + if (taken(p)) { + if (unlikely(!p)) + return NULL; + if (unlikely(!tal_resize_((void **)&p, size, n + extra, false))) + return tal_free(p); + if (unlikely(!tal_steal(ctx, p))) + return tal_free(p); + return (void *)p; + } + + ret = tal_alloc_arr_(ctx, size, n + extra, false, label); + if (ret) + memcpy(ret, p, nbytes); + return ret; +} + +void *tal_dup_talarr_(const tal_t *ctx, const tal_t *src TAKES, const char *label) +{ + return tal_dup_(ctx, src, 1, tal_bytelen(src), 0, true, label); +} + +void tal_set_backend(void *(*alloc_fn)(size_t size), + void *(*resize_fn)(void *, size_t size), + void (*free_fn)(void *), + void (*error_fn)(const char *msg)) +{ + if (alloc_fn) + allocfn = alloc_fn; + if (resize_fn) + resizefn = resize_fn; + if (free_fn) + freefn = free_fn; + if (error_fn) + errorfn = error_fn; +} + +#ifdef CCAN_TAL_DEBUG +static void dump_node(unsigned int indent, const struct tal_hdr *t) +{ + unsigned int i; + const struct prop_hdr *p; + + for (i = 0; i < indent; i++) + fprintf(stderr, " "); + fprintf(stderr, "%p len=%zu", t, t->bytelen); + for (p = t->prop; p; p = p->next) { + struct children *c; + struct name *n; + struct notifier *no; + if (is_literal(p)) { + fprintf(stderr, " \"%s\"", (const char *)p); + break; + } + switch (p->type) { + case CHILDREN: + c = (struct children *)p; + fprintf(stderr, " CHILDREN(%p):parent=%p,children={%p,%p}", + p, c->parent, + c->children.n.prev, c->children.n.next); + break; + case NAME: + n = (struct name *)p; + fprintf(stderr, " NAME(%p):%s", p, n->name); + break; + case NOTIFIER: + no = (struct notifier *)p; + fprintf(stderr, " NOTIFIER(%p):fn=%p", p, no->u.notifyfn); + break; + default: + fprintf(stderr, " **UNKNOWN(%p):%i**", p, p->type); + } + } + fprintf(stderr, "\n"); +} + +static void tal_dump_(unsigned int level, const struct tal_hdr *t) +{ + struct children *children; + + dump_node(level, t); + + children = find_property(t, CHILDREN); + if (children) { + struct tal_hdr *i; + + list_for_each(&children->children, i, list) + tal_dump_(level + 1, i); + } +} + +void tal_dump(void) +{ + tal_dump_(0, &null_parent.hdr); +} +#endif /* CCAN_TAL_DEBUG */ + +#ifndef NDEBUG +static bool check_err(struct tal_hdr *t, const char *errorstr, + const char *errmsg) +{ + if (errorstr) { + /* Try not to malloc: it may be corrupted. */ + char msg[strlen(errorstr) + 20 + strlen(errmsg) + 1]; + sprintf(msg, "%s:%p %s", errorstr, from_tal_hdr(t), errmsg); + call_error(msg); + } + return false; +} + +static bool check_node(struct children *parent_child, + struct tal_hdr *t, const char *errorstr) +{ + struct prop_hdr *p; + struct name *name = NULL; + struct children *children = NULL; + + if (!in_bounds(t)) + return check_err(t, errorstr, "invalid pointer"); + + if (ignore_destroying_bit(t->parent_child) != parent_child) + return check_err(t, errorstr, "incorrect parent"); + + for (p = t->prop; p; p = p->next) { + if (is_literal(p)) { + if (name) + return check_err(t, errorstr, + "has extra literal"); + break; + } + if (!in_bounds(p)) + return check_err(t, errorstr, + "has bad property pointer"); + + switch (p->type) { + case CHILDREN: + if (children) + return check_err(t, errorstr, + "has two child nodes"); + children = (struct children *)p; + break; + case NOTIFIER: + break; + case NAME: + if (name) + return check_err(t, errorstr, + "has two names"); + name = (struct name *)p; + break; + default: + return check_err(t, errorstr, "has unknown property"); + } + } + if (children) { + struct tal_hdr *i; + + if (!list_check(&children->children, errorstr)) + return false; + list_for_each(&children->children, i, list) { + if (!check_node(children, i, errorstr)) + return false; + } + } + return true; +} + +bool tal_check(const tal_t *ctx, const char *errorstr) +{ + struct tal_hdr *t = to_tal_hdr_or_null(ctx); + + return check_node(ignore_destroying_bit(t->parent_child), t, errorstr); +} +#else /* NDEBUG */ +bool tal_check(const tal_t *ctx, const char *errorstr) +{ + return true; +} +#endif diff --git a/nostrdb/bolt11/tal.h b/nostrdb/bolt11/tal.h new file mode 100644 index 00000000..8cd7670f --- /dev/null +++ b/nostrdb/bolt11/tal.h @@ -0,0 +1,553 @@ +/* Licensed under BSD-MIT - see LICENSE file for details */ +#ifndef CCAN_TAL_H +#define CCAN_TAL_H +#include "../config.h" +#include "../compiler.h" +#include "likely.h" +#include "typesafe_cb.h" +#include "str.h" +#include "take.h" + +#include +#include +#include + +/** + * tal_t - convenient alias for void to mark tal pointers. + * + * Since any pointer can be a tal-allocated pointer, it's often + * useful to use this typedef to mark them explicitly. + */ +typedef void tal_t; + +/** + * tal - basic allocator function + * @ctx: NULL, or tal allocated object to be parent. + * @type: the type to allocate. + * + * Allocates a specific type, with a given parent context. The name + * of the object is a string of the type, but if CCAN_TAL_DEBUG is + * defined it also contains the file and line which allocated it. + * + * tal_count() of the return will be 1. + * + * Example: + * int *p = tal(NULL, int); + * *p = 1; + */ +#define tal(ctx, type) \ + tal_label(ctx, type, TAL_LABEL(type, "")) + +/** + * talz - zeroing allocator function + * @ctx: NULL, or tal allocated object to be parent. + * @type: the type to allocate. + * + * Equivalent to tal() followed by memset() to zero. + * + * Example: + * p = talz(NULL, int); + * assert(*p == 0); + */ +#define talz(ctx, type) \ + talz_label(ctx, type, TAL_LABEL(type, "")) + +/** + * tal_free - free a tal-allocated pointer. + * @p: NULL, or tal allocated object to free. + * + * This calls the destructors for p (if any), then does the same for all its + * children (recursively) before finally freeing the memory. It returns + * NULL, for convenience. + * + * Note: errno is preserved by this call, and also saved and restored + * for any destructors or notifiers. + * + * Example: + * p = tal_free(p); + */ +void *tal_free(const tal_t *p); + +/** + * tal_arr - allocate an array of objects. + * @ctx: NULL, or tal allocated object to be parent. + * @type: the type to allocate. + * @count: the number to allocate. + * + * tal_count() of the returned pointer will be @count. + * + * Example: + * p = tal_arr(NULL, int, 2); + * p[0] = 0; + * p[1] = 1; + */ +#define tal_arr(ctx, type, count) \ + tal_arr_label(ctx, type, count, TAL_LABEL(type, "[]")) + +/** + * tal_arrz - allocate an array of zeroed objects. + * @ctx: NULL, or tal allocated object to be parent. + * @type: the type to allocate. + * @count: the number to allocate. + * + * Equivalent to tal_arr() followed by memset() to zero. + * + * Example: + * p = tal_arrz(NULL, int, 2); + * assert(p[0] == 0 && p[1] == 0); + */ +#define tal_arrz(ctx, type, count) \ + tal_arrz_label(ctx, type, count, TAL_LABEL(type, "[]")) + +/** + * tal_resize - enlarge or reduce a tal object. + * @p: A pointer to the tal allocated array to resize. + * @count: the number to allocate. + * + * This returns true on success (and may move *@p), or false on failure. + * On success, tal_count() of *@p will be @count. + * + * Note: if *p is take(), it will still be take() upon return, even if it + * has been moved. + * + * Example: + * tal_resize(&p, 100); + */ +#define tal_resize(p, count) \ + tal_resize_((void **)(p), sizeof**(p), (count), false) + +/** + * tal_resizez - enlarge or reduce a tal object; zero out extra. + * @p: A pointer to the tal allocated array to resize. + * @count: the number to allocate. + * + * This returns true on success (and may move *@p), or false on failure. + * + * Example: + * tal_resizez(&p, 200); + */ +#define tal_resizez(p, count) \ + tal_resize_((void **)(p), sizeof**(p), (count), true) + +/** + * tal_steal - change the parent of a tal-allocated pointer. + * @ctx: The new parent. + * @ptr: The tal allocated object to move, or NULL. + * + * This may need to perform an allocation, in which case it may fail; thus + * it can return NULL, otherwise returns @ptr. If @ptr is NULL, this function does + * nothing. + */ +#if HAVE_STATEMENT_EXPR +/* Weird macro avoids gcc's 'warning: value computed is not used'. */ +#define tal_steal(ctx, ptr) \ + ({ (tal_typeof(ptr) tal_steal_((ctx),(ptr))); }) +#else +#define tal_steal(ctx, ptr) \ + (tal_typeof(ptr) tal_steal_((ctx),(ptr))) +#endif + +/** + * tal_add_destructor - add a callback function when this context is destroyed. + * @ptr: The tal allocated object. + * @function: the function to call before it's freed. + * + * This is a more convenient form of tal_add_notifier(@ptr, + * TAL_NOTIFY_FREE, ...), in that the function prototype takes only @ptr. + * + * Note that this can only fail if your allocfn fails and your errorfn returns. + */ +#define tal_add_destructor(ptr, function) \ + tal_add_destructor_((ptr), typesafe_cb(void, void *, (function), (ptr))) + +/** + * tal_del_destructor - remove a destructor callback function. + * @ptr: The tal allocated object. + * @function: the function to call before it's freed. + * + * If @function has not been successfully added as a destructor, this returns + * false. Note that if we're inside the destructor call itself, this will + * return false. + */ +#define tal_del_destructor(ptr, function) \ + tal_del_destructor_((ptr), typesafe_cb(void, void *, (function), (ptr))) + +/** + * tal_add_destructor2 - add a 2-arg callback function when context is destroyed. + * @ptr: The tal allocated object. + * @function: the function to call before it's freed. + * @arg: the extra argument to the function. + * + * Sometimes an extra argument is required for a destructor; this + * saves the extra argument internally to avoid the caller having to + * do an extra allocation. + * + * Note that this can only fail if your allocfn fails and your errorfn returns. + */ +#define tal_add_destructor2(ptr, function, arg) \ + tal_add_destructor2_((ptr), \ + typesafe_cb_cast(void (*)(tal_t *, void *), \ + void (*)(__typeof__(ptr), \ + __typeof__(arg)), \ + (function)), \ + (arg)) + +/** + * tal_del_destructor - remove a destructor callback function. + * @ptr: The tal allocated object. + * @function: the function to call before it's freed. + * + * If @function has not been successfully added as a destructor, this returns + * false. Note that if we're inside the destructor call itself, this will + * return false. + */ +#define tal_del_destructor(ptr, function) \ + tal_del_destructor_((ptr), typesafe_cb(void, void *, (function), (ptr))) + +/** + * tal_del_destructor2 - remove 2-arg callback function. + * @ptr: The tal allocated object. + * @function: the function to call before it's freed. + * @arg: the extra argument to the function. + * + * If @function has not been successfully added as a destructor with + * @arg, this returns false. + */ +#define tal_del_destructor2(ptr, function, arg) \ + tal_del_destructor2_((ptr), \ + typesafe_cb_cast(void (*)(tal_t *, void *), \ + void (*)(__typeof__(ptr), \ + __typeof__(arg)), \ + (function)), \ + (arg)) +enum tal_notify_type { + TAL_NOTIFY_FREE = 1, + TAL_NOTIFY_STEAL = 2, + TAL_NOTIFY_MOVE = 4, + TAL_NOTIFY_RESIZE = 8, + TAL_NOTIFY_RENAME = 16, + TAL_NOTIFY_ADD_CHILD = 32, + TAL_NOTIFY_DEL_CHILD = 64, + TAL_NOTIFY_ADD_NOTIFIER = 128, + TAL_NOTIFY_DEL_NOTIFIER = 256 +}; + +/** + * tal_add_notifier - add a callback function when this context changes. + * @ptr: The tal allocated object, or NULL. + * @types: Bitwise OR of the types the callback is interested in. + * @callback: the function to call. + * + * Note that this can only fail if your allocfn fails and your errorfn + * returns. Also note that notifiers are not reliable in the case + * where an allocation fails, as they may be called before any + * allocation is actually done. + * + * TAL_NOTIFY_FREE is called when @ptr is freed, either directly or + * because an ancestor is freed: @info is the argument to tal_free(). + * It is exactly equivalent to a destructor, with more information. + * errno is set to the value it was at the call of tal_free(). + * + * TAL_NOTIFY_STEAL is called when @ptr's parent changes: @info is the + * new parent. + * + * TAL_NOTIFY_MOVE is called when @ptr is realloced (via tal_resize) + * and moved. In this case, @ptr arg here is the new memory, and + * @info is the old pointer. + * + * TAL_NOTIFY_RESIZE is called when @ptr is realloced via tal_resize: + * @info is the new size, in bytes. If the pointer has moved, + * TAL_NOTIFY_MOVE callbacks are called first. + * + * TAL_NOTIFY_ADD_CHILD/TAL_NOTIFY_DEL_CHILD are called when @ptr is + * the context for a tal() allocating call, or a direct child is + * tal_free()d: @info is the child. Note that TAL_NOTIFY_DEL_CHILD is + * not called when this context is tal_free()d: TAL_NOTIFY_FREE is + * considered sufficient for that case. + * + * TAL_NOTIFY_ADD_NOTIFIER/TAL_NOTIFIER_DEL_NOTIFIER are called when a + * notifier is added or removed (not for this notifier): @info is the + * callback. This is also called for tal_add_destructor and + * tal_del_destructor. + */ +#define tal_add_notifier(ptr, types, callback) \ + tal_add_notifier_((ptr), (types), \ + typesafe_cb_postargs(void, tal_t *, (callback), \ + (ptr), \ + enum tal_notify_type, void *)) + +/** + * tal_del_notifier - remove a notifier callback function. + * @ptr: The tal allocated object. + * @callback: the function to call. + */ +#define tal_del_notifier(ptr, callback) \ + tal_del_notifier_((ptr), \ + typesafe_cb_postargs(void, void *, (callback), \ + (ptr), \ + enum tal_notify_type, void *), \ + false, NULL) + +/** + * tal_set_name - attach a name to a tal pointer. + * @ptr: The tal allocated object. + * @name: The name to use. + * + * The name is copied, unless we're certain it's a string literal. + */ +#define tal_set_name(ptr, name) \ + tal_set_name_((ptr), (name), TAL_IS_LITERAL(name)) + +/** + * tal_name - get the name for a tal pointer. + * @ptr: The tal allocated object. + * + * Returns NULL if no name has been set. + */ +const char *tal_name(const tal_t *ptr); + +/** + * tal_count - get the count of objects in a tal object. + * @ptr: The tal allocated object (or NULL) + * + * Returns 0 if @ptr is NULL. Note that if the allocation was done as a + * different type to @ptr, the result may not match the @count argument + * (or implied 1) of that allocation! + */ +#define tal_count(p) (tal_bytelen(p) / sizeof(*p)) + +/** + * tal_bytelen - get the count of bytes in a tal object. + * @ptr: The tal allocated object (or NULL) + * + * Returns 0 if @ptr is NULL. + */ +size_t tal_bytelen(const tal_t *ptr); + +/** + * tal_first - get the first immediate tal object child. + * @root: The tal allocated object to start with, or NULL. + * + * Returns NULL if there are no children. + */ +tal_t *tal_first(const tal_t *root); + +/** + * tal_next - get the next immediate tal object child. + * @prev: The return value from tal_first or tal_next. + * + * Returns NULL if there are no more immediate children. This should be safe to + * call on an altering tree unless @prev is no longer valid. + */ +tal_t *tal_next(const tal_t *prev); + +/** + * tal_parent - get the parent of a tal object. + * @ctx: The tal allocated object. + * + * Returns the parent, which may be NULL. Returns NULL if @ctx is NULL. + */ +tal_t *tal_parent(const tal_t *ctx); + +/** + * tal_dup - duplicate an object. + * @ctx: The tal allocated object to be parent of the result (may be NULL). + * @type: the type (should match type of @p!) + * @p: the object to copy (or reparented if take()). Must not be NULL. + */ +#define tal_dup(ctx, type, p) \ + tal_dup_label(ctx, type, p, TAL_LABEL(type, ""), false) + +/** + * tal_dup_or_null - duplicate an object, or just pass NULL. + * @ctx: The tal allocated object to be parent of the result (may be NULL). + * @type: the type (should match type of @p!) + * @p: the object to copy (or reparented if take()) + * + * if @p is NULL, just return NULL, otherwise to tal_dup(). + */ +#define tal_dup_or_null(ctx, type, p) \ + tal_dup_label(ctx, type, p, TAL_LABEL(type, ""), true) + +/** + * tal_dup_arr - duplicate an array. + * @ctx: The tal allocated object to be parent of the result (may be NULL). + * @type: the type (should match type of @p!) + * @p: the array to copy (or resized & reparented if take()) + * @n: the number of sizeof(type) entries to copy. + * @extra: the number of extra sizeof(type) entries to allocate. + */ +#define tal_dup_arr(ctx, type, p, n, extra) \ + tal_dup_arr_label(ctx, type, p, n, extra, TAL_LABEL(type, "[]")) + + +/** + * tal_dup_arr - duplicate a tal array. + * @ctx: The tal allocated object to be parent of the result (may be NULL). + * @type: the type (should match type of @p!) + * @p: the tal array to copy (or resized & reparented if take()) + * + * The comon case of duplicating an entire tal array. + */ +#define tal_dup_talarr(ctx, type, p) \ + ((type *)tal_dup_talarr_((ctx), tal_typechk_(p, type *), \ + TAL_LABEL(type, "[]"))) +/* Lower-level interfaces, where you want to supply your own label string. */ +#define tal_label(ctx, type, label) \ + ((type *)tal_alloc_((ctx), sizeof(type), false, label)) +#define talz_label(ctx, type, label) \ + ((type *)tal_alloc_((ctx), sizeof(type), true, label)) +#define tal_arr_label(ctx, type, count, label) \ + ((type *)tal_alloc_arr_((ctx), sizeof(type), (count), false, label)) +#define tal_arrz_label(ctx, type, count, label) \ + ((type *)tal_alloc_arr_((ctx), sizeof(type), (count), true, label)) +#define tal_dup_label(ctx, type, p, label, nullok) \ + ((type *)tal_dup_((ctx), tal_typechk_(p, type *), \ + sizeof(type), 1, 0, nullok, \ + label)) +#define tal_dup_arr_label(ctx, type, p, n, extra, label) \ + ((type *)tal_dup_((ctx), tal_typechk_(p, type *), \ + sizeof(type), (n), (extra), false, \ + label)) + +/** + * tal_set_backend - set the allocation or error functions to use + * @alloc_fn: allocator or NULL (default is malloc) + * @resize_fn: re-allocator or NULL (default is realloc) + * @free_fn: free function or NULL (default is free) + * @error_fn: called on errors or NULL (default is abort) + * + * The defaults are set up so tal functions never return NULL, but you + * can override erorr_fn to change that. error_fn can return, and is + * called if alloc_fn or resize_fn fail. + * + * If any parameter is NULL, that function is unchanged. + */ +void tal_set_backend(void *(*alloc_fn)(size_t size), + void *(*resize_fn)(void *, size_t size), + void (*free_fn)(void *), + void (*error_fn)(const char *msg)); + +/** + * tal_expand - expand a tal array with contents. + * @a1p: a pointer to the tal array to expand. + * @a2: the second array (can be take()). + * @num2: the number of elements in the second array. + * + * Note that *@a1 and @a2 should be the same type. tal_count(@a1) will + * be increased by @num2. + * + * Example: + * int *arr1 = tal_arrz(NULL, int, 2); + * int arr2[2] = { 1, 3 }; + * + * tal_expand(&arr1, arr2, 2); + * assert(tal_count(arr1) == 4); + * assert(arr1[2] == 1); + * assert(arr1[3] == 3); + */ +#define tal_expand(a1p, a2, num2) \ + tal_expand_((void **)(a1p), (a2), sizeof**(a1p), \ + (num2) + 0*sizeof(*(a1p) == (a2))) + +/** + * tal_cleanup - remove pointers from NULL node + * + * Internally, tal keeps a list of nodes allocated from @ctx NULL; this + * prevents valgrind from noticing memory leaks. This re-initializes + * that list to empty. + * + * It also calls take_cleanup() for you. + */ +void tal_cleanup(void); + + +/** + * tal_check - sanity check a tal context and its children. + * @ctx: a tal context, or NULL. + * @errorstr: a string to prepend calls to error_fn, or NULL. + * + * This sanity-checks a tal tree (unless NDEBUG is defined, in which case + * it simply returns true). If errorstr is not null, error_fn is called + * when a problem is found, otherwise it is not. + * + * See also: + * tal_set_backend() + */ +bool tal_check(const tal_t *ctx, const char *errorstr); + +#ifdef CCAN_TAL_DEBUG +/** + * tal_dump - dump entire tal tree to stderr. + * + * This is a helper for debugging tal itself, which dumps all the tal internal + * state. + */ +void tal_dump(void); +#endif + +/* Internal support functions */ +#ifndef TAL_LABEL +#ifdef CCAN_TAL_NO_LABELS +#define TAL_LABEL(type, arr) NULL +#else +#ifdef CCAN_TAL_DEBUG +#define TAL_LABEL(type, arr) \ + __FILE__ ":" stringify(__LINE__) ":" stringify(type) arr +#else +#define TAL_LABEL(type, arr) stringify(type) arr +#endif /* CCAN_TAL_DEBUG */ +#endif +#endif + +#if HAVE_BUILTIN_CONSTANT_P +#define TAL_IS_LITERAL(str) __builtin_constant_p(str) +#else +#define TAL_IS_LITERAL(str) (sizeof(&*(str)) != sizeof(char *)) +#endif + +bool tal_set_name_(tal_t *ctx, const char *name, bool literal); + +#if HAVE_TYPEOF +#define tal_typeof(ptr) (__typeof__(ptr)) +#if HAVE_STATEMENT_EXPR +/* Careful: ptr can be const foo *, ptype is foo *. Also, ptr could + * be an array, eg "hello". */ +#define tal_typechk_(ptr, ptype) ({ __typeof__((ptr)+0) _p = (ptype)(ptr); _p; }) +#else +#define tal_typechk_(ptr, ptype) (ptr) +#endif +#else /* !HAVE_TYPEOF */ +#define tal_typeof(ptr) +#define tal_typechk_(ptr, ptype) (ptr) +#endif + +void *tal_alloc_(const tal_t *ctx, size_t bytes, bool clear, const char *label); +void *tal_alloc_arr_(const tal_t *ctx, size_t bytes, size_t count, bool clear, + const char *label); + +void *tal_dup_(const tal_t *ctx, const void *p TAKES, size_t size, + size_t n, size_t extra, bool nullok, const char *label); +void *tal_dup_talarr_(const tal_t *ctx, const tal_t *src TAKES, + const char *label); + +tal_t *tal_steal_(const tal_t *new_parent, const tal_t *t); + +bool tal_resize_(tal_t **ctxp, size_t size, size_t count, bool clear); +bool tal_expand_(tal_t **ctxp, const void *src TAKES, size_t size, size_t count); + +bool tal_add_destructor_(const tal_t *ctx, void (*destroy)(void *me)); +bool tal_add_destructor2_(const tal_t *ctx, void (*destroy)(void *me, void *arg), + void *arg); +bool tal_del_destructor_(const tal_t *ctx, void (*destroy)(void *me)); +bool tal_del_destructor2_(const tal_t *ctx, void (*destroy)(void *me, void *arg), + void *arg); + +bool tal_add_notifier_(const tal_t *ctx, enum tal_notify_type types, + void (*notify)(tal_t *ctx, enum tal_notify_type, + void *info)); +bool tal_del_notifier_(const tal_t *ctx, + void (*notify)(tal_t *ctx, enum tal_notify_type, + void *info), + bool match_extra_arg, void *arg); +#endif /* CCAN_TAL_H */ diff --git a/nostrdb/bolt11/talstr.c b/nostrdb/bolt11/talstr.c new file mode 100644 index 00000000..1fb66858 --- /dev/null +++ b/nostrdb/bolt11/talstr.c @@ -0,0 +1,315 @@ +/* Licensed under BSD-MIT - see LICENSE file for details */ +#include +#include +#include +#include +#include +#include "talstr.h" +#include +#include +#include +#include +#include +#include "str.h" + +char *tal_strdup_(const tal_t *ctx, const char *p, const char *label) +{ + /* We have to let through NULL for take(). */ + return tal_dup_arr_label(ctx, char, p, p ? strlen(p) + 1: 1, 0, label); +} + +char *tal_strndup_(const tal_t *ctx, const char *p, size_t n, const char *label) +{ + size_t len; + char *ret; + + /* We have to let through NULL for take(). */ + if (likely(p)) + len = strnlen(p, n); + else + len = n; + + ret = tal_dup_arr_label(ctx, char, p, len, 1, label); + if (ret) + ret[len] = '\0'; + return ret; +} + +char *tal_fmt_(const tal_t *ctx, const char *label, const char *fmt, ...) +{ + va_list ap; + char *ret; + + va_start(ap, fmt); + ret = tal_vfmt_(ctx, fmt, ap, label); + va_end(ap); + + return ret; +} + +static bool do_vfmt(char **buf, size_t off, const char *fmt, va_list ap) +{ + /* A decent guess to start. */ + size_t max = strlen(fmt) * 2 + 1; + bool ok; + + for (;;) { + va_list ap2; + int ret; + + if (!tal_resize(buf, off + max)) { + ok = false; + break; + } + + va_copy(ap2, ap); + ret = vsnprintf(*buf + off, max, fmt, ap2); + va_end(ap2); + + if (ret < max) { + ok = true; + /* Make sure tal_count() is correct! */ + tal_resize(buf, off + ret + 1); + break; + } + max *= 2; + } + + if (taken(fmt)) + tal_free(fmt); + return ok; +} + +char *tal_vfmt_(const tal_t *ctx, const char *fmt, va_list ap, const char *label) +{ + char *buf; + + if (!fmt && taken(fmt)) + return NULL; + + /* A decent guess to start. */ + buf = tal_arr_label(ctx, char, strlen(fmt) * 2, label); + if (!do_vfmt(&buf, 0, fmt, ap)) + buf = tal_free(buf); + return buf; +} + +bool tal_append_vfmt(char **baseptr, const char *fmt, va_list ap) +{ + if (!fmt && taken(fmt)) + return false; + + return do_vfmt(baseptr, strlen(*baseptr), fmt, ap); +} + +bool tal_append_fmt(char **baseptr, const char *fmt, ...) +{ + va_list ap; + bool ret; + + va_start(ap, fmt); + ret = tal_append_vfmt(baseptr, fmt, ap); + va_end(ap); + + return ret; +} + +char *tal_strcat_(const tal_t *ctx, const char *s1, const char *s2, + const char *label) +{ + size_t len1, len2; + char *ret; + + if (unlikely(!s2) && taken(s2)) { + if (taken(s1)) + tal_free(s1); + return NULL; + } + /* We have to let through NULL for take(). */ + len1 = s1 ? strlen(s1) : 0; + len2 = strlen(s2); + + ret = tal_dup_arr_label(ctx, char, s1, len1, len2 + 1, label); + if (likely(ret)) + memcpy(ret + len1, s2, len2 + 1); + + if (taken(s2)) + tal_free(s2); + return ret; +} + +char **tal_strsplit_(const tal_t *ctx, + const char *string, const char *delims, enum strsplit flags, + const char *label) +{ + char **parts, *str; + size_t max = 64, num = 0; + + parts = tal_arr(ctx, char *, max + 1); + if (unlikely(!parts)) { + if (taken(string)) + tal_free(string); + if (taken(delims)) + tal_free(delims); + return NULL; + } + str = tal_strdup(parts, string); + if (unlikely(!str)) + goto fail; + if (unlikely(!delims) && is_taken(delims)) + goto fail; + + if (flags == STR_NO_EMPTY) + str += strspn(str, delims); + + while (*str != '\0') { + size_t len = strcspn(str, delims), dlen; + + parts[num] = str; + dlen = strspn(str + len, delims); + parts[num][len] = '\0'; + if (flags == STR_EMPTY_OK && dlen) + dlen = 1; + str += len + dlen; + if (++num == max && !tal_resize(&parts, max*=2 + 1)) + goto fail; + } + parts[num] = NULL; + + /* Ensure that tal_count() is correct. */ + if (unlikely(!tal_resize(&parts, num+1))) + goto fail; + + if (taken(delims)) + tal_free(delims); + return parts; + +fail: + tal_free(parts); + if (taken(delims)) + tal_free(delims); + return NULL; +} + +char *tal_strjoin_(const tal_t *ctx, + char *strings[], const char *delim, enum strjoin flags, + const char *label) +{ + unsigned int i; + char *ret = NULL; + size_t totlen = 0, dlen; + + if (unlikely(!strings) && is_taken(strings)) + goto fail; + + if (unlikely(!delim) && is_taken(delim)) + goto fail; + + dlen = strlen(delim); + ret = tal_arr_label(ctx, char, dlen*2+1, label); + if (!ret) + goto fail; + + ret[0] = '\0'; + for (i = 0; strings[i]; i++) { + size_t len = strlen(strings[i]); + + if (flags == STR_NO_TRAIL && !strings[i+1]) + dlen = 0; + if (!tal_resize(&ret, totlen + len + dlen + 1)) + goto fail; + memcpy(ret + totlen, strings[i], len); + totlen += len; + memcpy(ret + totlen, delim, dlen); + totlen += dlen; + } + ret[totlen] = '\0'; + /* Make sure tal_count() is correct! */ + tal_resize(&ret, totlen+1); +out: + if (taken(strings)) + tal_free(strings); + if (taken(delim)) + tal_free(delim); + return ret; +fail: + ret = tal_free(ret); + goto out; +} + +static size_t count_open_braces(const char *string) +{ +#if 1 + size_t num = 0, esc = 0; + + while (*string) { + if (*string == '\\') + esc++; + else { + /* An odd number of \ means it's escaped. */ + if (*string == '(' && (esc & 1) == 0) + num++; + esc = 0; + } + string++; + } + return num; +#else + return strcount(string, "("); +#endif +} + +bool tal_strreg_(const tal_t *ctx, const char *string, const char *label, + const char *regex, ...) +{ + size_t nmatch = 1 + count_open_braces(regex); + regmatch_t matches[nmatch]; + regex_t r; + bool ret = false; + unsigned int i; + va_list ap; + + if (unlikely(!regex) && is_taken(regex)) + goto fail_no_re; + + if (regcomp(&r, regex, REG_EXTENDED) != 0) + goto fail_no_re; + + if (unlikely(!string) && is_taken(string)) + goto fail; + + if (regexec(&r, string, nmatch, matches, 0) != 0) + goto fail; + + ret = true; + va_start(ap, regex); + for (i = 1; i < nmatch; i++) { + char **arg = va_arg(ap, char **); + if (arg) { + /* eg. ([a-z])? can give "no match". */ + if (matches[i].rm_so == -1) + *arg = NULL; + else { + *arg = tal_strndup_(ctx, + string + matches[i].rm_so, + matches[i].rm_eo + - matches[i].rm_so, + label); + /* FIXME: If we fail, we set some and leak! */ + if (!*arg) { + ret = false; + break; + } + } + } + } + va_end(ap); +fail: + regfree(&r); +fail_no_re: + if (taken(regex)) + tal_free(regex); + if (taken(string)) + tal_free(string); + return ret; +} diff --git a/nostrdb/bolt11/talstr.h b/nostrdb/bolt11/talstr.h new file mode 100644 index 00000000..fbf53a86 --- /dev/null +++ b/nostrdb/bolt11/talstr.h @@ -0,0 +1,225 @@ +/* Licensed under BSD-MIT - see LICENSE file for details */ +#ifndef CCAN_STR_TAL_H +#define CCAN_STR_TAL_H +#ifdef TAL_USE_TALLOC +#include +#else +#include "tal.h" +#endif +#include +#include + +/** + * tal_strdup - duplicate a string + * @ctx: NULL, or tal allocated object to be parent. + * @p: the string to copy (can be take()). + * + * The returned string will have tal_count() == strlen() + 1. + */ +#define tal_strdup(ctx, p) tal_strdup_(ctx, p, TAL_LABEL(char, "[]")) +char *tal_strdup_(const tal_t *ctx, const char *p TAKES, const char *label); + +/** + * tal_strndup - duplicate a limited amount of a string. + * @ctx: NULL, or tal allocated object to be parent. + * @p: the string to copy (can be take()). + * @n: the maximum length to copy. + * + * Always gives a nul-terminated string, with strlen() <= @n. + * The returned string will have tal_count() == strlen() + 1. + */ +#define tal_strndup(ctx, p, n) tal_strndup_(ctx, p, n, TAL_LABEL(char, "[]")) +char *tal_strndup_(const tal_t *ctx, const char *p TAKES, size_t n, + const char *label); + +/** + * tal_fmt - allocate a formatted string + * @ctx: NULL, or tal allocated object to be parent. + * @fmt: the printf-style format (can be take()). + * + * The returned string will have tal_count() == strlen() + 1. + */ +#define tal_fmt(ctx, ...) \ + tal_fmt_(ctx, TAL_LABEL(char, "[]"), __VA_ARGS__) +char *tal_fmt_(const tal_t *ctx, const char *label, const char *fmt TAKES, + ...) PRINTF_FMT(3,4); + +/** + * tal_vfmt - allocate a formatted string (va_list version) + * @ctx: NULL, or tal allocated object to be parent. + * @fmt: the printf-style format (can be take()). + * @va: the va_list containing the format args. + * + * The returned string will have tal_count() == strlen() + 1. + */ +#define tal_vfmt(ctx, fmt, va) \ + tal_vfmt_(ctx, fmt, va, TAL_LABEL(char, "[]")) +char *tal_vfmt_(const tal_t *ctx, const char *fmt TAKES, va_list ap, + const char *label) + PRINTF_FMT(2,0); + +/** + * tal_append_fmt - append a formatted string to a talloc string. + * @baseptr: a pointer to the tal string to be appended to. + * @fmt: the printf-style format (can be take()). + * + * Returns false on allocation failure. + * Otherwise tal_count(*@baseptr) == strlen(*@baseptr) + 1. + */ +bool tal_append_fmt(char **baseptr, const char *fmt TAKES, ...) PRINTF_FMT(2,3); + +/** + * tal_append_vfmt - append a formatted string to a talloc string (va_list) + * @baseptr: a pointer to the tal string to be appended to. + * @fmt: the printf-style format (can be take()). + * @va: the va_list containing the format args. + * + * Returns false on allocation failure. + * Otherwise tal_count(*@baseptr) == strlen(*@baseptr) + 1. + */ +bool tal_append_vfmt(char **baseptr, const char *fmt TAKES, va_list ap); + +/** + * tal_strcat - join two strings together + * @ctx: NULL, or tal allocated object to be parent. + * @s1: the first string (can be take()). + * @s2: the second string (can be take()). + * + * The returned string will have tal_count() == strlen() + 1. + */ +#define tal_strcat(ctx, s1, s2) tal_strcat_(ctx, s1, s2, TAL_LABEL(char, "[]")) +char *tal_strcat_(const tal_t *ctx, const char *s1 TAKES, const char *s2 TAKES, + const char *label); + +enum strsplit { + STR_EMPTY_OK, + STR_NO_EMPTY +}; + +/** + * tal_strsplit - Split string into an array of substrings + * @ctx: the context to tal from (often NULL). + * @string: the string to split (can be take()). + * @delims: delimiters where lines should be split (can be take()). + * @flags: whether to include empty substrings. + * + * This function splits a single string into multiple strings. + * + * If @string is take(), the returned array will point into the + * mangled @string. + * + * Multiple delimiters result in empty substrings. By definition, no + * delimiters will appear in the substrings. + * + * The final char * in the array will be NULL, and tal_count() will + * return the number of elements plus 1 (for that NULL). + * + * Example: + * #include + * ... + * static unsigned int count_long_lines(const char *string) + * { + * char **lines; + * unsigned int i, long_lines = 0; + * + * // Can only fail on out-of-memory. + * lines = tal_strsplit(NULL, string, "\n", STR_NO_EMPTY); + * for (i = 0; lines[i] != NULL; i++) + * if (strlen(lines[i]) > 80) + * long_lines++; + * tal_free(lines); + * return long_lines; + * } + */ +#define tal_strsplit(ctx, string, delims, flag) \ + tal_strsplit_(ctx, string, delims, flag, TAL_LABEL(char *, "[]")) +char **tal_strsplit_(const tal_t *ctx, + const char *string TAKES, + const char *delims TAKES, + enum strsplit flag, + const char *label); + +enum strjoin { + STR_TRAIL, + STR_NO_TRAIL +}; + +/** + * tal_strjoin - Join an array of substrings into one long string + * @ctx: the context to tal from (often NULL). + * @strings: the NULL-terminated array of strings to join (can be take()) + * @delim: the delimiter to insert between the strings (can be take()) + * @flags: whether to add a delimieter to the end + * + * This function joins an array of strings into a single string. The + * return value is allocated using tal. Each string in @strings is + * followed by a copy of @delim. + * + * The returned string will have tal_count() == strlen() + 1. + * + * Example: + * // Append the string "--EOL" to each line. + * static char *append_to_all_lines(const char *string) + * { + * char **lines, *ret; + * + * lines = tal_strsplit(NULL, string, "\n", STR_EMPTY_OK); + * ret = tal_strjoin(NULL, lines, "-- EOL\n", STR_TRAIL); + * tal_free(lines); + * return ret; + * } + */ +#define tal_strjoin(ctx, strings, delim, flags) \ + tal_strjoin_(ctx, strings, delim, flags, TAL_LABEL(char, "[]")) +char *tal_strjoin_(const void *ctx, + char *strings[] TAKES, + const char *delim TAKES, + enum strjoin flags, + const char *label); + +/** + * tal_strreg - match/extract from a string via (extended) regular expressions. + * @ctx: the context to tal from (often NULL) + * @string: the string to try to match (can be take()) + * @regex: the regular expression to match (can be take()) + * ...: pointers to strings to allocate for subexpressions. + * + * Returns true if we matched, in which case any parenthesized + * expressions in @regex are allocated and placed in the char ** + * arguments following @regex. NULL arguments mean the match is not + * saved. The order of the strings is the order + * of opening braces in the expression: in the case of repeated + * expressions (eg "([a-z])*") the last one is saved, in the case of + * non-existent matches (eg "([a-z]*)?") the pointer is set to NULL. + * + * Allocation failures or malformed regular expressions return false. + * The allocated strings will have tal_count() == strlen() + 1. + * + * See Also: + * regcomp(3), regex(3). + * + * Example: + * // Given "My name is Rusty" outputs "Hello Rusty!\n" + * // Given "my first name is Rusty Russell" outputs "Hello Rusty Russell!\n" + * // Given "My name isnt Rusty Russell" outputs "Hello there!\n" + * int main(int argc, char *argv[]) + * { + * char *person, *input; + * + * (void)argc; + * // Join args and trim trailing space. + * input = tal_strjoin(NULL, argv+1, " ", STR_NO_TRAIL); + * if (tal_strreg(NULL, input, + * "[Mm]y (first )?name is ([A-Za-z ]+)", + * NULL, &person)) + * printf("Hello %s!\n", person); + * else + * printf("Hello there!\n"); + * return 0; + * } + */ +#define tal_strreg(ctx, string, ...) \ + tal_strreg_(ctx, string, TAL_LABEL(char, "[]"), __VA_ARGS__) +bool tal_strreg_(const void *ctx, const char *string TAKES, + const char *label, const char *regex, ...); +#endif /* CCAN_STR_TAL_H */ diff --git a/nostrdb/bolt11/typesafe_cb.h b/nostrdb/bolt11/typesafe_cb.h new file mode 100644 index 00000000..acf346dd --- /dev/null +++ b/nostrdb/bolt11/typesafe_cb.h @@ -0,0 +1,134 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_TYPESAFE_CB_H +#define CCAN_TYPESAFE_CB_H +#include "../config.h" + +#if HAVE_TYPEOF && HAVE_BUILTIN_CHOOSE_EXPR && HAVE_BUILTIN_TYPES_COMPATIBLE_P +/** + * typesafe_cb_cast - only cast an expression if it matches a given type + * @desttype: the type to cast to + * @oktype: the type we allow + * @expr: the expression to cast + * + * This macro is used to create functions which allow multiple types. + * The result of this macro is used somewhere that a @desttype type is + * expected: if @expr is exactly of type @oktype, then it will be + * cast to @desttype type, otherwise left alone. + * + * This macro can be used in static initializers. + * + * This is merely useful for warnings: if the compiler does not + * support the primitives required for typesafe_cb_cast(), it becomes an + * unconditional cast, and the @oktype argument is not used. In + * particular, this means that @oktype can be a type which uses the + * "typeof": it will not be evaluated if typeof is not supported. + * + * Example: + * // We can take either an unsigned long or a void *. + * void _set_some_value(void *val); + * #define set_some_value(e) \ + * _set_some_value(typesafe_cb_cast(void *, unsigned long, (e))) + */ +#define typesafe_cb_cast(desttype, oktype, expr) \ + __builtin_choose_expr( \ + __builtin_types_compatible_p(__typeof__(0?(expr):(expr)), \ + oktype), \ + (desttype)(expr), (expr)) +#else +#define typesafe_cb_cast(desttype, oktype, expr) ((desttype)(expr)) +#endif + +/** + * typesafe_cb_cast3 - only cast an expression if it matches given types + * @desttype: the type to cast to + * @ok1: the first type we allow + * @ok2: the second type we allow + * @ok3: the third type we allow + * @expr: the expression to cast + * + * This is a convenient wrapper for multiple typesafe_cb_cast() calls. + * You can chain them inside each other (ie. use typesafe_cb_cast() + * for expr) if you need more than 3 arguments. + * + * Example: + * // We can take either a long, unsigned long, void * or a const void *. + * void _set_some_value(void *val); + * #define set_some_value(expr) \ + * _set_some_value(typesafe_cb_cast3(void *,, \ + * long, unsigned long, const void *,\ + * (expr))) + */ +#define typesafe_cb_cast3(desttype, ok1, ok2, ok3, expr) \ + typesafe_cb_cast(desttype, ok1, \ + typesafe_cb_cast(desttype, ok2, \ + typesafe_cb_cast(desttype, ok3, \ + (expr)))) + +/** + * typesafe_cb - cast a callback function if it matches the arg + * @rtype: the return type of the callback function + * @atype: the (pointer) type which the callback function expects. + * @fn: the callback function to cast + * @arg: the (pointer) argument to hand to the callback function. + * + * If a callback function takes a single argument, this macro does + * appropriate casts to a function which takes a single atype argument if the + * callback provided matches the @arg. + * + * It is assumed that @arg is of pointer type: usually @arg is passed + * or assigned to a void * elsewhere anyway. + * + * Example: + * void _register_callback(void (*fn)(void *arg), void *arg); + * #define register_callback(fn, arg) \ + * _register_callback(typesafe_cb(void, (fn), void*, (arg)), (arg)) + */ +#define typesafe_cb(rtype, atype, fn, arg) \ + typesafe_cb_cast(rtype (*)(atype), \ + rtype (*)(__typeof__(arg)), \ + (fn)) + +/** + * typesafe_cb_preargs - cast a callback function if it matches the arg + * @rtype: the return type of the callback function + * @atype: the (pointer) type which the callback function expects. + * @fn: the callback function to cast + * @arg: the (pointer) argument to hand to the callback function. + * + * This is a version of typesafe_cb() for callbacks that take other arguments + * before the @arg. + * + * Example: + * void _register_callback(void (*fn)(int, void *arg), void *arg); + * #define register_callback(fn, arg) \ + * _register_callback(typesafe_cb_preargs(void, void *, \ + * (fn), (arg), int), \ + * (arg)) + */ +#define typesafe_cb_preargs(rtype, atype, fn, arg, ...) \ + typesafe_cb_cast(rtype (*)(__VA_ARGS__, atype), \ + rtype (*)(__VA_ARGS__, __typeof__(arg)), \ + (fn)) + +/** + * typesafe_cb_postargs - cast a callback function if it matches the arg + * @rtype: the return type of the callback function + * @atype: the (pointer) type which the callback function expects. + * @fn: the callback function to cast + * @arg: the (pointer) argument to hand to the callback function. + * + * This is a version of typesafe_cb() for callbacks that take other arguments + * after the @arg. + * + * Example: + * void _register_callback(void (*fn)(void *arg, int), void *arg); + * #define register_callback(fn, arg) \ + * _register_callback(typesafe_cb_postargs(void, (fn), void *, \ + * (arg), int), \ + * (arg)) + */ +#define typesafe_cb_postargs(rtype, atype, fn, arg, ...) \ + typesafe_cb_cast(rtype (*)(atype, __VA_ARGS__), \ + rtype (*)(__typeof__(arg), __VA_ARGS__), \ + (fn)) +#endif /* CCAN_CAST_IF_TYPE_H */ diff --git a/nostrdb/bolt11/utf8.c b/nostrdb/bolt11/utf8.c new file mode 100644 index 00000000..01a73686 --- /dev/null +++ b/nostrdb/bolt11/utf8.c @@ -0,0 +1,199 @@ +/* MIT (BSD) license - see LICENSE file for details - taken from ccan. thanks rusty! */ + +#include "utf8.h" +#include +#include + +/* I loved this table, so I stole it: */ +/* + * Copyright (c) 2017 Christian Hansen + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * UTF-8 Encoding Form + * + * U+0000..U+007F 0xxxxxxx <= 7 bits + * U+0080..U+07FF 110xxxxx 10xxxxxx <= 11 bits + * U+0800..U+FFFF 1110xxxx 10xxxxxx 10xxxxxx <= 16 bits + * U+10000..U+10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx <= 21 bits + * + * + * U+0000..U+007F 00..7F + * N C0..C1 80..BF 1100000x 10xxxxxx + * U+0080..U+07FF C2..DF 80..BF + * N E0 80..9F 80..BF 11100000 100xxxxx + * U+0800..U+0FFF E0 A0..BF 80..BF + * U+1000..U+CFFF E1..EC 80..BF 80..BF + * U+D000..U+D7FF ED 80..9F 80..BF + * S ED A0..BF 80..BF 11101101 101xxxxx + * U+E000..U+FFFF EE..EF 80..BF 80..BF + * N F0 80..8F 80..BF 80..BF 11110000 1000xxxx + * U+10000..U+3FFFF F0 90..BF 80..BF 80..BF + * U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF + * U+100000..U+10FFFF F4 80..8F 80..BF 80..BF 11110100 1000xxxx + * + * Legend: + * N = Non-shortest form + * S = Surrogates + */ +bool utf8_decode(struct utf8_state *utf8_state, char c) +{ + if (utf8_state->used_len == utf8_state->total_len) { + utf8_state->used_len = 1; + /* First character in sequence. */ + if (((unsigned char)c & 0x80) == 0) { + /* ASCII, easy. */ + if (c == 0) + goto bad_encoding; + utf8_state->total_len = 1; + utf8_state->c = c; + goto finished_decoding; + } else if (((unsigned char)c & 0xE0) == 0xC0) { + utf8_state->total_len = 2; + utf8_state->c = ((unsigned char)c & 0x1F); + return false; + } else if (((unsigned char)c & 0xF0) == 0xE0) { + utf8_state->total_len = 3; + utf8_state->c = ((unsigned char)c & 0x0F); + return false; + } else if (((unsigned char)c & 0xF8) == 0xF0) { + utf8_state->total_len = 4; + utf8_state->c = ((unsigned char)c & 0x07); + return false; + } + goto bad_encoding; + } + + if (((unsigned char)c & 0xC0) != 0x80) + goto bad_encoding; + + utf8_state->c <<= 6; + utf8_state->c |= ((unsigned char)c & 0x3F); + + utf8_state->used_len++; + if (utf8_state->used_len == utf8_state->total_len) + goto finished_decoding; + return false; + +finished_decoding: + if (utf8_state->c == 0 || utf8_state->c > 0x10FFFF) + errno = ERANGE; + /* The UTF-16 "surrogate range": illegal in UTF-8 */ + else if (utf8_state->total_len == 3 + && (utf8_state->c & 0xFFFFF800) == 0x0000D800) + errno = ERANGE; + else { + int min_bits; + switch (utf8_state->total_len) { + case 1: + min_bits = 0; + break; + case 2: + min_bits = 7; + break; + case 3: + min_bits = 11; + break; + case 4: + min_bits = 16; + break; + default: + abort(); + } + if ((utf8_state->c >> min_bits) == 0) + errno = EFBIG; + else + errno = 0; + } + return true; + +bad_encoding: + utf8_state->total_len = utf8_state->used_len; + errno = EINVAL; + return true; +} + +size_t utf8_encode(uint32_t point, char dest[UTF8_MAX_LEN]) +{ + if ((point >> 7) == 0) { + if (point == 0) { + errno = ERANGE; + return 0; + } + /* 0xxxxxxx */ + dest[0] = point; + return 1; + } + + if ((point >> 11) == 0) { + /* 110xxxxx 10xxxxxx */ + dest[1] = 0x80 | (point & 0x3F); + dest[0] = 0xC0 | (point >> 6); + return 2; + } + + if ((point >> 16) == 0) { + if (point >= 0xD800 && point <= 0xDFFF) { + errno = ERANGE; + return 0; + } + /* 1110xxxx 10xxxxxx 10xxxxxx */ + dest[2] = 0x80 | (point & 0x3F); + dest[1] = 0x80 | ((point >> 6) & 0x3F); + dest[0] = 0xE0 | (point >> 12); + return 3; + } + + if (point > 0x10FFFF) { + errno = ERANGE; + return 0; + } + + /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ + dest[3] = 0x80 | (point & 0x3F); + dest[2] = 0x80 | ((point >> 6) & 0x3F); + dest[1] = 0x80 | ((point >> 12) & 0x3F); + dest[0] = 0xF0 | (point >> 18); + return 4; +} + +/* Check for valid UTF-8 */ +bool utf8_check(const void *vbuf, size_t buflen) +{ + const unsigned char *buf = vbuf; + struct utf8_state utf8_state = UTF8_STATE_INIT; + bool need_more = false; + + for (size_t i = 0; i < buflen; i++) { + if (!utf8_decode(&utf8_state, buf[i])) { + need_more = true; + continue; + } + need_more = false; + if (errno != 0) + return false; + } + return !need_more; +} + diff --git a/nostrdb/bolt11/utf8.h b/nostrdb/bolt11/utf8.h new file mode 100644 index 00000000..1321568a --- /dev/null +++ b/nostrdb/bolt11/utf8.h @@ -0,0 +1,57 @@ +/* MIT (BSD) license - see LICENSE file for details */ +#ifndef CCAN_UTF8_H +#define CCAN_UTF8_H +#include +#include +#include + +/* Unicode is limited to 21 bits. */ +#define UTF8_MAX_LEN 4 + +struct utf8_state { + /* How many characters we are expecting as part of this Unicode point */ + uint16_t total_len; + /* How many characters we've already seen. */ + uint16_t used_len; + /* Compound character, aka Unicode point. */ + uint32_t c; +}; + +#define UTF8_STATE_INIT { 0, 0, 0 } + +static inline void utf8_state_init(struct utf8_state *utf8_state) +{ + memset(utf8_state, 0, sizeof(*utf8_state)); +} + +/** + * utf8_decode - continue UTF8 decoding with this character. + * @utf8_state - initialized UTF8 state. + * @c - the character. + * + * Returns false if it needs another character to give results. + * Otherwise returns true, @utf8_state can be reused without initializeation, + * and sets errno: + * 0: success + * EINVAL: bad encoding (including a NUL character). + * EFBIG: not a minimal encoding. + * ERANGE: encoding of invalid character. + * + * You can extract the character from @utf8_state->c; @utf8_state->used_len + * indicates how many characters have been consumed. + */ +bool utf8_decode(struct utf8_state *utf8_state, char c); + +/** + * utf8_encode - encode a point into UTF8. + * @point - Unicode point to include. + * @dest - buffer to fill. + * + * Returns 0 if point was invalid, otherwise bytes of dest used. + * Sets errno to ERANGE if point was invalid. + */ +size_t utf8_encode(uint32_t point, char dest[UTF8_MAX_LEN]); + +/* Check for valid UTF-8 */ +bool utf8_check(const void *vbuf, size_t buflen); +#endif /* CCAN_UTF8_H */ diff --git a/nostrdb/compiler.h b/nostrdb/compiler.h index deb0621e..a9b5aa70 100644 --- a/nostrdb/compiler.h +++ b/nostrdb/compiler.h @@ -1,85 +1,317 @@ - -#ifndef COMPILER_H -#define COMPILER_H - -#include -#include -#include +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_COMPILER_H +#define CCAN_COMPILER_H #include "config.h" -#if HAVE_UNALIGNED_ACCESS -#define alignment_ok(p, n) 1 +#ifndef COLD +#if HAVE_ATTRIBUTE_COLD +/** + * COLD - a function is unlikely to be called. + * + * Used to mark an unlikely code path and optimize appropriately. + * It is usually used on logging or error routines. + * + * Example: + * static void COLD moan(const char *reason) + * { + * fprintf(stderr, "Error: %s (%s)\n", reason, strerror(errno)); + * } + */ +#define COLD __attribute__((__cold__)) #else -#define alignment_ok(p, n) ((size_t)(p) % (n) == 0) +#define COLD +#endif #endif +#ifndef NORETURN +#if HAVE_ATTRIBUTE_NORETURN +/** + * NORETURN - a function does not return + * + * Used to mark a function which exits; useful for suppressing warnings. + * + * Example: + * static void NORETURN fail(const char *reason) + * { + * fprintf(stderr, "Error: %s (%s)\n", reason, strerror(errno)); + * exit(1); + * } + */ +#define NORETURN __attribute__((__noreturn__)) +#else +#define NORETURN +#endif +#endif + +#ifndef PRINTF_FMT +#if HAVE_ATTRIBUTE_PRINTF +/** + * PRINTF_FMT - a function takes printf-style arguments + * @nfmt: the 1-based number of the function's format argument. + * @narg: the 1-based number of the function's first variable argument. + * + * This allows the compiler to check your parameters as it does for printf(). + * + * Example: + * void PRINTF_FMT(2,3) my_printf(const char *prefix, const char *fmt, ...); + */ +#define PRINTF_FMT(nfmt, narg) \ + __attribute__((format(__printf__, nfmt, narg))) +#else +#define PRINTF_FMT(nfmt, narg) +#endif +#endif + +#ifndef CONST_FUNCTION +#if HAVE_ATTRIBUTE_CONST +/** + * CONST_FUNCTION - a function's return depends only on its argument + * + * This allows the compiler to assume that the function will return the exact + * same value for the exact same arguments. This implies that the function + * must not use global variables, or dereference pointer arguments. + */ +#define CONST_FUNCTION __attribute__((__const__)) +#else +#define CONST_FUNCTION +#endif + +#ifndef PURE_FUNCTION +#if HAVE_ATTRIBUTE_PURE +/** + * PURE_FUNCTION - a function is pure + * + * A pure function is one that has no side effects other than it's return value + * and uses no inputs other than it's arguments and global variables. + */ +#define PURE_FUNCTION __attribute__((__pure__)) +#else +#define PURE_FUNCTION +#endif +#endif +#endif + +#if HAVE_ATTRIBUTE_UNUSED +#ifndef UNNEEDED +/** + * UNNEEDED - a variable/function may not be needed + * + * This suppresses warnings about unused variables or functions, but tells + * the compiler that if it is unused it need not emit it into the source code. + * + * Example: + * // With some preprocessor options, this is unnecessary. + * static UNNEEDED int counter; + * + * // With some preprocessor options, this is unnecessary. + * static UNNEEDED void add_to_counter(int add) + * { + * counter += add; + * } + */ +#define UNNEEDED __attribute__((__unused__)) +#endif + +#ifndef NEEDED +#if HAVE_ATTRIBUTE_USED +/** + * NEEDED - a variable/function is needed + * + * This suppresses warnings about unused variables or functions, but tells + * the compiler that it must exist even if it (seems) unused. + * + * Example: + * // Even if this is unused, these are vital for debugging. + * static NEEDED int counter; + * static NEEDED void dump_counter(void) + * { + * printf("Counter is %i\n", counter); + * } + */ +#define NEEDED __attribute__((__used__)) +#else +/* Before used, unused functions and vars were always emitted. */ +#define NEEDED __attribute__((__unused__)) +#endif +#endif + +#ifndef UNUSED +/** + * UNUSED - a parameter is unused + * + * Some compilers (eg. gcc with -W or -Wunused) warn about unused + * function parameters. This suppresses such warnings and indicates + * to the reader that it's deliberate. + * + * Example: + * // This is used as a callback, so needs to have this prototype. + * static int some_callback(void *unused UNUSED) + * { + * return 0; + * } + */ #define UNUSED __attribute__((__unused__)) - -/** - * BUILD_ASSERT - assert a build-time dependency. - * @cond: the compile-time condition which must be true. - * - * Your compile will fail if the condition isn't true, or can't be evaluated - * by the compiler. This can only be used within a function. - * - * Example: - * #include - * ... - * static char *foo_to_char(struct foo *foo) - * { - * // This code needs string to be at start of foo. - * BUILD_ASSERT(offsetof(struct foo, string) == 0); - * return (char *)foo; - * } - */ -#define BUILD_ASSERT(cond) \ - do { (void) sizeof(char [1 - 2*!(cond)]); } while(0) - -/** - * BUILD_ASSERT_OR_ZERO - assert a build-time dependency, as an expression. - * @cond: the compile-time condition which must be true. - * - * Your compile will fail if the condition isn't true, or can't be evaluated - * by the compiler. This can be used in an expression: its value is "0". - * - * Example: - * #define foo_to_char(foo) \ - * ((char *)(foo) \ - * + BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0)) - */ -#define BUILD_ASSERT_OR_ZERO(cond) \ - (sizeof(char [1 - 2*!(cond)]) - 1) - -#define memclear(mem, size) memset(mem, 0, size) -#define memclear_2(m1, s1, m2, s2) { memclear(m1, s1); memclear(m2, s2); } -#define memclear_3(m1, s1, m2, s2, m3, s3) { memclear(m1, s1); memclear(m2, s2); memclear(m3, s3); } - -static inline void *memcheck_(const void *data, size_t len) -{ - (void)len; - return (void *)data; -} - -#if HAVE_TYPEOF -/** - * memcheck - check that a memory region is initialized - * @data: start of region - * @len: length in bytes - * - * When running under valgrind, this causes an error to be printed - * if the entire region is not defined. Otherwise valgrind only - * reports an error when an undefined value is used for a branch, or - * written out. - * - * Example: - * // Search for space, but make sure it's all initialized. - * if (memchr(memcheck(somebytes, bytes_len), ' ', bytes_len)) { - * printf("space was found!\n"); - * } - */ -#define memcheck(data, len) ((__typeof__((data)+0))memcheck_((data), (len))) +#endif #else -#define memcheck(data, len) memcheck_((data), (len)) +#ifndef UNNEEDED +#define UNNEEDED +#endif +#ifndef NEEDED +#define NEEDED +#endif +#ifndef UNUSED +#define UNUSED +#endif #endif -#endif /* COMPILER_H */ +#ifndef IS_COMPILE_CONSTANT +#if HAVE_BUILTIN_CONSTANT_P +/** + * IS_COMPILE_CONSTANT - does the compiler know the value of this expression? + * @expr: the expression to evaluate + * + * When an expression manipulation is complicated, it is usually better to + * implement it in a function. However, if the expression being manipulated is + * known at compile time, it is better to have the compiler see the entire + * expression so it can simply substitute the result. + * + * This can be done using the IS_COMPILE_CONSTANT() macro. + * + * Example: + * enum greek { ALPHA, BETA, GAMMA, DELTA, EPSILON }; + * + * // Out-of-line version. + * const char *greek_name(enum greek greek); + * + * // Inline version. + * static inline const char *_greek_name(enum greek greek) + * { + * switch (greek) { + * case ALPHA: return "alpha"; + * case BETA: return "beta"; + * case GAMMA: return "gamma"; + * case DELTA: return "delta"; + * case EPSILON: return "epsilon"; + * default: return "**INVALID**"; + * } + * } + * + * // Use inline if compiler knows answer. Otherwise call function + * // to avoid copies of the same code everywhere. + * #define greek_name(g) \ + * (IS_COMPILE_CONSTANT(greek) ? _greek_name(g) : greek_name(g)) + */ +#define IS_COMPILE_CONSTANT(expr) __builtin_constant_p(expr) +#else +/* If we don't know, assume it's not. */ +#define IS_COMPILE_CONSTANT(expr) 0 +#endif +#endif + +#ifndef WARN_UNUSED_RESULT +#if HAVE_WARN_UNUSED_RESULT +/** + * WARN_UNUSED_RESULT - warn if a function return value is unused. + * + * Used to mark a function where it is extremely unlikely that the caller + * can ignore the result, eg realloc(). + * + * Example: + * // buf param may be freed by this; need return value! + * static char *WARN_UNUSED_RESULT enlarge(char *buf, unsigned *size) + * { + * return realloc(buf, (*size) *= 2); + * } + */ +#define WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) +#else +#define WARN_UNUSED_RESULT +#endif +#endif + + +#if HAVE_ATTRIBUTE_DEPRECATED +/** + * WARN_DEPRECATED - warn that a function/type/variable is deprecated when used. + * + * Used to mark a function, type or variable should not be used. + * + * Example: + * WARN_DEPRECATED char *oldfunc(char *buf); + */ +#define WARN_DEPRECATED __attribute__((__deprecated__)) +#else +#define WARN_DEPRECATED +#endif + + +#if HAVE_ATTRIBUTE_NONNULL +/** + * NO_NULL_ARGS - specify that no arguments to this function can be NULL. + * + * The compiler will warn if any pointer args are NULL. + * + * Example: + * NO_NULL_ARGS char *my_copy(char *buf); + */ +#define NO_NULL_ARGS __attribute__((__nonnull__)) + +/** + * NON_NULL_ARGS - specify that some arguments to this function can't be NULL. + * @...: 1-based argument numbers for which args can't be NULL. + * + * The compiler will warn if any of the specified pointer args are NULL. + * + * Example: + * char *my_copy2(char *buf, char *maybenull) NON_NULL_ARGS(1); + */ +#define NON_NULL_ARGS(...) __attribute__((__nonnull__(__VA_ARGS__))) +#else +#define NO_NULL_ARGS +#define NON_NULL_ARGS(...) +#endif + +#if HAVE_ATTRIBUTE_RETURNS_NONNULL +/** + * RETURNS_NONNULL - specify that this function cannot return NULL. + * + * Mainly an optimization opportunity, but can also suppress warnings. + * + * Example: + * RETURNS_NONNULL char *my_copy(char *buf); + */ +#define RETURNS_NONNULL __attribute__((__returns_nonnull__)) +#else +#define RETURNS_NONNULL +#endif + +#if HAVE_ATTRIBUTE_SENTINEL +/** + * LAST_ARG_NULL - specify the last argument of a variadic function must be NULL. + * + * The compiler will warn if the last argument isn't NULL. + * + * Example: + * char *join_string(char *buf, ...) LAST_ARG_NULL; + */ +#define LAST_ARG_NULL __attribute__((__sentinel__)) +#else +#define LAST_ARG_NULL +#endif + +#if HAVE_BUILTIN_CPU_SUPPORTS +/** + * cpu_supports - test if current CPU supports the named feature. + * + * This takes a literal string, and currently only works on glibc platforms. + * + * Example: + * if (cpu_supports("mmx")) + * printf("MMX support engaged!\n"); + */ +#define cpu_supports(x) __builtin_cpu_supports(x) +#else +#define cpu_supports(x) 0 +#endif /* HAVE_BUILTIN_CPU_SUPPORTS */ + +#endif /* CCAN_COMPILER_H */ diff --git a/nostrdb/cursor.h b/nostrdb/cursor.h index 2be7f191..aff0b55f 100644 --- a/nostrdb/cursor.h +++ b/nostrdb/cursor.h @@ -3,15 +3,13 @@ #define JB55_CURSOR_H #include "typedefs.h" +#include "bolt11/likely.h" #include #include #include #include -#define unlikely(x) __builtin_expect((x),0) -#define likely(x) __builtin_expect((x),1) - struct cursor { unsigned char *start; unsigned char *p; diff --git a/nostrdb/nostr_bech32.c b/nostrdb/nostr_bech32.c new file mode 100644 index 00000000..9710fbe2 --- /dev/null +++ b/nostrdb/nostr_bech32.c @@ -0,0 +1,306 @@ +// +// nostr_bech32.c +// damus +// +// Created by William Casarin on 2023-04-09. +// + +#include "nostr_bech32.h" +#include +#include "cursor.h" +#include "bech32.h" + +#define MAX_TLVS 16 + +#define TLV_SPECIAL 0 +#define TLV_RELAY 1 +#define TLV_AUTHOR 2 +#define TLV_KIND 3 +#define TLV_KNOWN_TLVS 4 + +struct nostr_tlv { + u8 type; + u8 len; + const u8 *value; +}; + +struct nostr_tlvs { + struct nostr_tlv tlvs[MAX_TLVS]; + int num_tlvs; +}; + +static int parse_nostr_tlv(struct cursor *cur, struct nostr_tlv *tlv) { + // get the tlv tag + if (!pull_byte(cur, &tlv->type)) + return 0; + + // unknown, fail! + if (tlv->type >= TLV_KNOWN_TLVS) + return 0; + + // get the length + if (!pull_byte(cur, &tlv->len)) + return 0; + + // is the reported length greater then our buffer? if so fail + if (cur->p + tlv->len > cur->end) + return 0; + + tlv->value = cur->p; + cur->p += tlv->len; + + return 1; +} + +static int parse_nostr_tlvs(struct cursor *cur, struct nostr_tlvs *tlvs) { + int i; + tlvs->num_tlvs = 0; + + for (i = 0; i < MAX_TLVS; i++) { + if (parse_nostr_tlv(cur, &tlvs->tlvs[i])) { + tlvs->num_tlvs++; + } else { + break; + } + } + + if (tlvs->num_tlvs == 0) + return 0; + + return 1; +} + +static int find_tlv(struct nostr_tlvs *tlvs, u8 type, struct nostr_tlv **tlv) { + *tlv = NULL; + + for (int i = 0; i < tlvs->num_tlvs; i++) { + if (tlvs->tlvs[i].type == type) { + *tlv = &tlvs->tlvs[i]; + return 1; + } + } + + return 0; +} + +static int parse_nostr_bech32_type(const char *prefix, enum nostr_bech32_type *type) { + // Parse type + if (strcmp(prefix, "note") == 0) { + *type = NOSTR_BECH32_NOTE; + return 1; + } else if (strcmp(prefix, "npub") == 0) { + *type = NOSTR_BECH32_NPUB; + return 1; + } else if (strcmp(prefix, "nsec") == 0) { + *type = NOSTR_BECH32_NSEC; + return 1; + } else if (strcmp(prefix, "nprofile") == 0) { + *type = NOSTR_BECH32_NPROFILE; + return 1; + } else if (strcmp(prefix, "nevent") == 0) { + *type = NOSTR_BECH32_NEVENT; + return 1; + } else if (strcmp(prefix, "nrelay") == 0) { + *type = NOSTR_BECH32_NRELAY; + return 1; + } else if (strcmp(prefix, "naddr") == 0) { + *type = NOSTR_BECH32_NADDR; + return 1; + } + + return 0; +} + +static int parse_nostr_bech32_note(struct cursor *cur, struct bech32_note *note) { + return pull_bytes(cur, 32, ¬e->event_id); +} + +static int parse_nostr_bech32_npub(struct cursor *cur, struct bech32_npub *npub) { + return pull_bytes(cur, 32, &npub->pubkey); +} + +static int parse_nostr_bech32_nsec(struct cursor *cur, struct bech32_nsec *nsec) { + return pull_bytes(cur, 32, &nsec->nsec); +} + +static int tlvs_to_relays(struct nostr_tlvs *tlvs, struct relays *relays) { + struct nostr_tlv *tlv; + struct str_block *str; + + relays->num_relays = 0; + + for (int i = 0; i < tlvs->num_tlvs; i++) { + tlv = &tlvs->tlvs[i]; + if (tlv->type != TLV_RELAY) + continue; + + if (relays->num_relays + 1 > MAX_RELAYS) + break; + + str = &relays->relays[relays->num_relays++]; + str->start = (const char*)tlv->value; + str->end = (const char*)(tlv->value + tlv->len); + } + + return 1; +} + +static int parse_nostr_bech32_nevent(struct cursor *cur, struct bech32_nevent *nevent) { + struct nostr_tlvs tlvs; + struct nostr_tlv *tlv; + + if (!parse_nostr_tlvs(cur, &tlvs)) + return 0; + + if (!find_tlv(&tlvs, TLV_SPECIAL, &tlv)) + return 0; + + if (tlv->len != 32) + return 0; + + nevent->event_id = tlv->value; + + if (find_tlv(&tlvs, TLV_AUTHOR, &tlv)) { + nevent->pubkey = tlv->value; + } else { + nevent->pubkey = NULL; + } + + return tlvs_to_relays(&tlvs, &nevent->relays); +} + +static int parse_nostr_bech32_naddr(struct cursor *cur, struct bech32_naddr *naddr) { + struct nostr_tlvs tlvs; + struct nostr_tlv *tlv; + + if (!parse_nostr_tlvs(cur, &tlvs)) + return 0; + + if (!find_tlv(&tlvs, TLV_SPECIAL, &tlv)) + return 0; + + naddr->identifier.start = (const char*)tlv->value; + naddr->identifier.end = (const char*)tlv->value + tlv->len; + + if (!find_tlv(&tlvs, TLV_AUTHOR, &tlv)) + return 0; + + naddr->pubkey = tlv->value; + + return tlvs_to_relays(&tlvs, &naddr->relays); +} + +static int parse_nostr_bech32_nprofile(struct cursor *cur, struct bech32_nprofile *nprofile) { + struct nostr_tlvs tlvs; + struct nostr_tlv *tlv; + + if (!parse_nostr_tlvs(cur, &tlvs)) + return 0; + + if (!find_tlv(&tlvs, TLV_SPECIAL, &tlv)) + return 0; + + if (tlv->len != 32) + return 0; + + nprofile->pubkey = tlv->value; + + return tlvs_to_relays(&tlvs, &nprofile->relays); +} + +static int parse_nostr_bech32_nrelay(struct cursor *cur, struct bech32_nrelay *nrelay) { + struct nostr_tlvs tlvs; + struct nostr_tlv *tlv; + + if (!parse_nostr_tlvs(cur, &tlvs)) + return 0; + + if (!find_tlv(&tlvs, TLV_SPECIAL, &tlv)) + return 0; + + nrelay->relay.start = (const char*)tlv->value; + nrelay->relay.end = (const char*)tlv->value + tlv->len; + + return 1; +} + +int parse_nostr_bech32(struct cursor *cur, struct nostr_bech32 *obj) { + u8 *start, *end; + + start = cur->p; + + if (!consume_until_non_alphanumeric(cur, 1)) { + cur->p = start; + return 0; + } + + end = cur->p; + + size_t data_len; + size_t input_len = end - start; + if (input_len < 10 || input_len > 10000) { + return 0; + } + + obj->buffer = malloc(input_len * 2); + if (!obj->buffer) + return 0; + + u8 data[input_len]; + char prefix[input_len]; + + if (bech32_decode_len(prefix, data, &data_len, (const char*)start, input_len) == BECH32_ENCODING_NONE) { + cur->p = start; + return 0; + } + + obj->buflen = 0; + if (!bech32_convert_bits(obj->buffer, &obj->buflen, 8, data, data_len, 5, 0)) { + goto fail; + } + + if (!parse_nostr_bech32_type(prefix, &obj->type)) { + goto fail; + } + + struct cursor bcur; + make_cursor(obj->buffer, obj->buffer + obj->buflen, &bcur); + + switch (obj->type) { + case NOSTR_BECH32_NOTE: + if (!parse_nostr_bech32_note(&bcur, &obj->data.note)) + goto fail; + break; + case NOSTR_BECH32_NPUB: + if (!parse_nostr_bech32_npub(&bcur, &obj->data.npub)) + goto fail; + break; + case NOSTR_BECH32_NSEC: + if (!parse_nostr_bech32_nsec(&bcur, &obj->data.nsec)) + goto fail; + break; + case NOSTR_BECH32_NEVENT: + if (!parse_nostr_bech32_nevent(&bcur, &obj->data.nevent)) + goto fail; + break; + case NOSTR_BECH32_NADDR: + if (!parse_nostr_bech32_naddr(&bcur, &obj->data.naddr)) + goto fail; + break; + case NOSTR_BECH32_NPROFILE: + if (!parse_nostr_bech32_nprofile(&bcur, &obj->data.nprofile)) + goto fail; + break; + case NOSTR_BECH32_NRELAY: + if (!parse_nostr_bech32_nrelay(&bcur, &obj->data.nrelay)) + goto fail; + break; + } + + return 1; + +fail: + free(obj->buffer); + cur->p = start; + return 0; +} diff --git a/nostrdb/nostr_bech32.h b/nostrdb/nostr_bech32.h new file mode 100644 index 00000000..23a381d9 --- /dev/null +++ b/nostrdb/nostr_bech32.h @@ -0,0 +1,84 @@ +// +// nostr_bech32.h +// damus +// +// Created by William Casarin on 2023-04-09. +// + +#ifndef nostr_bech32_h +#define nostr_bech32_h + +#include +#include "str_block.h" +#include "cursor.h" +typedef unsigned char u8; +#define MAX_RELAYS 10 + +struct relays { + struct str_block relays[MAX_RELAYS]; + int num_relays; +}; + +enum nostr_bech32_type { + NOSTR_BECH32_NOTE = 1, + NOSTR_BECH32_NPUB = 2, + NOSTR_BECH32_NPROFILE = 3, + NOSTR_BECH32_NEVENT = 4, + NOSTR_BECH32_NRELAY = 5, + NOSTR_BECH32_NADDR = 6, + NOSTR_BECH32_NSEC = 7, +}; + +struct bech32_note { + const u8 *event_id; +}; + +struct bech32_npub { + const u8 *pubkey; +}; + +struct bech32_nsec { + const u8 *nsec; +}; + +struct bech32_nevent { + struct relays relays; + const u8 *event_id; + const u8 *pubkey; // optional +}; + +struct bech32_nprofile { + struct relays relays; + const u8 *pubkey; +}; + +struct bech32_naddr { + struct relays relays; + struct str_block identifier; + const u8 *pubkey; +}; + +struct bech32_nrelay { + struct str_block relay; +}; + +typedef struct nostr_bech32 { + enum nostr_bech32_type type; + u8 *buffer; // holds strings and tlv stuff + size_t buflen; + + union { + struct bech32_note note; + struct bech32_npub npub; + struct bech32_nsec nsec; + struct bech32_nevent nevent; + struct bech32_nprofile nprofile; + struct bech32_naddr naddr; + struct bech32_nrelay nrelay; + } data; +} nostr_bech32_t; + + +int parse_nostr_bech32(struct cursor *cur, struct nostr_bech32 *obj); + +#endif /* nostr_bech32_h */ diff --git a/nostrdb/nostrdb.c b/nostrdb/nostrdb.c index 8a8573f5..f16aa070 100644 --- a/nostrdb/nostrdb.c +++ b/nostrdb/nostrdb.c @@ -5,6 +5,8 @@ #include "cursor.h" #include "random.h" #include "sha256.h" +#include "bolt11/bolt11.h" +#include "bolt11/amount.h" #include "lmdb.h" #include "util.h" #include "cpu.h"