Browse Source

common/bolt11.c: fix up BOLT 11 references.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 7 years ago
committed by Christian Decker
parent
commit
0dc406c07a
  1. 78
      common/bolt11.c
  2. 12
      common/test/run-bolt11.c

78
common/bolt11.c

@ -141,8 +141,8 @@ static char *unknown_field(struct bolt11 *b11,
/* BOLT #11: /* BOLT #11:
* *
* `p` (1): `data_length` 52. 256-bit SHA256 payment_hash: preimage of this * `p` (1): `data_length` 52. 256-bit SHA256 payment_hash. Preimage of this
* provides proof of payment. * provides proof of payment
*/ */
static void decode_p(struct bolt11 *b11, static void decode_p(struct bolt11 *b11,
struct hash_u5 *hu5, struct hash_u5 *hu5,
@ -151,8 +151,8 @@ static void decode_p(struct bolt11 *b11,
{ {
/* BOLT #11: /* BOLT #11:
* *
* A payer SHOULD use the first `p` field did not skip as the payment * A payer SHOULD use the first `p` field that it did not skip as the
* hash. * payment hash.
*/ */
if (*have_p) { if (*have_p) {
unknown_field(b11, hu5, data, data_len, 'p', data_length); unknown_field(b11, hu5, data, data_len, 'p', data_length);
@ -162,7 +162,7 @@ static void decode_p(struct bolt11 *b11,
/* BOLT #11: /* BOLT #11:
* *
* A reader MUST skip over unknown fields, an `f` field with unknown * A reader MUST skip over unknown fields, an `f` field with unknown
* `version`, or a `p`, `h`, or `n` field which does not have * `version`, or a `p`, `h`, or `n` field that does not have
* `data_length` 52, 52, or 53 respectively. */ * `data_length` 52, 52, or 53 respectively. */
if (data_length != 52) { if (data_length != 52) {
unknown_field(b11, hu5, data, data_len, 'p', data_length); unknown_field(b11, hu5, data, data_len, 'p', data_length);
@ -175,8 +175,8 @@ static void decode_p(struct bolt11 *b11,
/* BOLT #11: /* BOLT #11:
* *
* `d` (13): `data_length` variable. short description of purpose of payment * `d` (13): `data_length` variable. Short description of purpose of payment
* (ASCII), e.g. '1 cup of coffee' * (UTF-8), e.g. '1 cup of coffee' or ' 1'
*/ */
static void decode_d(struct bolt11 *b11, static void decode_d(struct bolt11 *b11,
struct hash_u5 *hu5, struct hash_u5 *hu5,
@ -197,8 +197,9 @@ static void decode_d(struct bolt11 *b11,
/* BOLT #11: /* BOLT #11:
* *
* `h` (23): `data_length` 52. 256-bit description of purpose of payment * `h` (23): `data_length` 52. 256-bit description of purpose of payment
* (SHA256). This is used to commit to an associated description which is too * (SHA256). This is used to commit to an associated description that is over
* long to fit, such as may be contained in a web page. * 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, static void decode_h(struct bolt11 *b11,
struct hash_u5 *hu5, struct hash_u5 *hu5,
@ -213,7 +214,7 @@ static void decode_h(struct bolt11 *b11,
/* BOLT #11: /* BOLT #11:
* *
* A reader MUST skip over unknown fields, an `f` field with unknown * A reader MUST skip over unknown fields, an `f` field with unknown
* `version`, or a `p`, `h`, or `n` field which does not have * `version`, or a `p`, `h`, or `n` field that does not have
* `data_length` 52, 52, or 53 respectively. */ * `data_length` 52, 52, or 53 respectively. */
if (data_length != 52) { if (data_length != 52) {
unknown_field(b11, hu5, data, data_len, 'h', data_length); unknown_field(b11, hu5, data, data_len, 'h', data_length);
@ -290,7 +291,7 @@ static char *decode_n(struct bolt11 *b11,
/* BOLT #11: /* BOLT #11:
* *
* A reader MUST skip over unknown fields, an `f` field with unknown * A reader MUST skip over unknown fields, an `f` field with unknown
* `version`, or a `p`, `h`, or `n` field which does not have * `version`, or a `p`, `h`, or `n` field that does not have
* `data_length` 52, 52, or 53 respectively. */ * `data_length` 52, 52, or 53 respectively. */
if (data_length != 53) if (data_length != 53)
return unknown_field(b11, hu5, data, data_len, 'n', return unknown_field(b11, hu5, data, data_len, 'n',
@ -308,8 +309,8 @@ static char *decode_n(struct bolt11 *b11,
/* BOLT #11: /* BOLT #11:
* *
* `f` (9): `data_length` variable, depending on version. Fallback on-chain * `f` (9): `data_length` variable, depending on version. Fallback on-chain
* address: for bitcoin, this starts with a 5 bit `version`; a witness program * address: for bitcoin, this starts with a 5-bit `version` and contains a
* or P2PKH or P2SH address. * witness program or P2PKH or P2SH address.
*/ */
static char *decode_f(struct bolt11 *b11, static char *decode_f(struct bolt11 *b11,
struct hash_u5 *hu5, struct hash_u5 *hu5,
@ -399,7 +400,7 @@ static void towire_route_info(u8 **pptr, const struct route_info *route_info)
* *
* `r` (3): `data_length` variable. One or more entries containing * `r` (3): `data_length` variable. One or more entries containing
* extra routing information for a private route; there may be more * extra routing information for a private route; there may be more
* than one `r` field, too. * than one `r` field
* *
* * `pubkey` (264 bits) * * `pubkey` (264 bits)
* * `short_channel_id` (64 bits) * * `short_channel_id` (64 bits)
@ -486,10 +487,12 @@ struct bolt11 *bolt11_decode(const tal_t *ctx, const char *str,
/* BOLT #11: /* BOLT #11:
* *
* The human readable part consists of two sections: * The human-readable part of a Lightning invoice consists of two
* 1. `prefix`: `ln` + BIP-0173 currency prefix (e.g. `lnbc`, `lntb`) * sections:
* 1. `amount`: optional number in that currency, followed by optional * 1. `prefix`: `ln` + BIP-0173 currency prefix (e.g. `lnbc` for
* `multiplier`. * bitcoins or `lntb` for testnet bitcoins)
* 1. `amount`: optional number in that currency, followed by an optional
* `multiplier` letter
*/ */
prefix = tal_strndup(tmpctx, hrp, strcspn(hrp, "0123456789")); prefix = tal_strndup(tmpctx, hrp, strcspn(hrp, "0123456789"));
@ -507,7 +510,7 @@ struct bolt11 *bolt11_decode(const tal_t *ctx, const char *str,
/* BOLT #11: /* BOLT #11:
* *
* A reader SHOULD fail if `amount` contains a non-digit, or * A reader SHOULD fail if `amount` contains a non-digit or
* is followed by anything except a `multiplier` in the table * is followed by anything except a `multiplier` in the table
* above. */ * above. */
amountstr = tal_strdup(tmpctx, hrp + strlen(prefix)); amountstr = tal_strdup(tmpctx, hrp + strlen(prefix));
@ -534,7 +537,7 @@ struct bolt11 *bolt11_decode(const tal_t *ctx, const char *str,
/* BOLT #11: /* BOLT #11:
* *
* A reader SHOULD fail if `amount` contains a non-digit, or * A reader SHOULD fail if `amount` contains a non-digit or
* is followed by anything except a `multiplier` in the table * is followed by anything except a `multiplier` in the table
* above. * above.
*/ */
@ -553,11 +556,11 @@ struct bolt11 *bolt11_decode(const tal_t *ctx, const char *str,
/* BOLT #11: /* BOLT #11:
* *
* The data part consists of multiple sections: * The data part of a Lightning invoice consists of multiple sections:
* *
* 1. `timestamp`: seconds-since-1970 (35 bits, big-endian) * 1. `timestamp`: seconds-since-1970 (35 bits, big-endian)
* 1. Zero or more tagged parts. * 1. zero or more tagged parts
* 1. `signature`: bitcoin-style signature of above. (520 bits) * 1. `signature`: bitcoin-style signature of above (520 bits)
*/ */
if (!pull_uint(&hu5, &data, &data_len, &b11->timestamp, 35)) if (!pull_uint(&hu5, &data, &data_len, &b11->timestamp, 35))
return decode_fail(b11, fail, "Can't get 35-bit timestamp"); return decode_fail(b11, fail, "Can't get 35-bit timestamp");
@ -568,7 +571,7 @@ struct bolt11 *bolt11_decode(const tal_t *ctx, const char *str,
/* BOLT #11: /* BOLT #11:
* *
* Each Tagged Field is of format: * Each Tagged Field is of the form:
* *
* 1. `type` (5 bits) * 1. `type` (5 bits)
* 1. `data_length` (10 bits, big-endian) * 1. `data_length` (10 bits, big-endian)
@ -659,10 +662,11 @@ struct bolt11 *bolt11_decode(const tal_t *ctx, const char *str,
/* BOLT #11: /* BOLT #11:
* *
* A writer MUST set `signature` to a valid 512-bit secp256k1 * A writer MUST set `signature` to a valid 512-bit secp256k1
* signature of the SHA2 256-bit hash of the Human Readable Part * signature of the SHA2 256-bit hash of the human-readable part,
* concatenated with the Data Part and zero bits appended to the next * represented as UTF-8 bytes, concatenated with the data part
* byte boundary, with a trailing byte containing the recovery ID (0, * (excluding the signature) with zero bits appended to pad the data
* 1, 2 or 3). * to the next byte boundary, with a trailing byte containing the
* recovery ID (0, 1, 2 or 3).
*/ */
if (!pull_bits(NULL, &data, &data_len, sig_and_recid, 520, false)) if (!pull_bits(NULL, &data, &data_len, sig_and_recid, 520, false))
return decode_fail(b11, fail, "signature truncated"); return decode_fail(b11, fail, "signature truncated");
@ -710,7 +714,7 @@ static void push_varlen_uint(u5 **data, u64 val, size_t nbits)
/* BOLT #11: /* BOLT #11:
* *
* Each Tagged Field is of format: * Each Tagged Field is of the form:
* *
* 1. `type` (5 bits) * 1. `type` (5 bits)
* 1. `data_length` (10 bits, big-endian) * 1. `data_length` (10 bits, big-endian)
@ -746,12 +750,10 @@ static void push_varlen_field(u5 **data, char type, u64 val)
/* BOLT #11: /* BOLT #11:
* *
* The fallback field is of format: * `f` (9): `data_length` variable, depending on version.
* *
* 1. `type` (5 bits) * Fallback on-chain address: for bitcoin, this starts with a 5-bit `version`
* 2. `data_length` (10 bits, big-endian) * and contains a witness program or P2PKH or P2SH address.
* 3. `version` (5 bits)
* 4. `data` (addr_len * 8 bits)
*/ */
static void push_fallback_addr(u5 **data, u5 version, const void *addr, u16 addr_len) static void push_fallback_addr(u5 **data, u5 version, const void *addr, u16 addr_len)
{ {
@ -872,8 +874,8 @@ char *bolt11_encode_(const tal_t *ctx,
/* BOLT #11: /* BOLT #11:
* *
* A writer MUST encode `amount` as a positive decimal integer * A writer MUST encode `amount` as a positive decimal integer
* with no leading zeroes, SHOULD use the shortest * with no leading zeroes and SHOULD use the shortest representation
* representation possible. * possible.
*/ */
if (b11->msatoshi) { if (b11->msatoshi) {
char postfix; char postfix;
@ -897,8 +899,8 @@ char *bolt11_encode_(const tal_t *ctx,
/* BOLT #11: /* BOLT #11:
* *
* 1. `timestamp`: seconds-since-1970 (35 bits, big-endian) * 1. `timestamp`: seconds-since-1970 (35 bits, big-endian)
* 1. Zero or more tagged parts. * 1. zero or more tagged parts
* 1. `signature`: bitcoin-style signature of above. (520 bits) * 1. `signature`: bitcoin-style signature of above (520 bits)
*/ */
push_varlen_uint(&data, b11->timestamp, 35); push_varlen_uint(&data, b11->timestamp, 35);

12
common/test/run-bolt11.c

@ -151,10 +151,10 @@ int main(void)
* * `1`: Bech32 separator * * `1`: Bech32 separator
* * `pvjluez`: timestamp (1496314658) * * `pvjluez`: timestamp (1496314658)
* * `p`: payment hash * * `p`: payment hash
* * `p5`: `data_length` (`p` = 1, `5` = 20. 1 * 32 + 20 == 52) * * `p5`: `data_length` (`p` = 1, `5` = 20; 1 * 32 + 20 == 52)
* * `qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypq`: payment hash 0001020304050607080900010203040506070809000102030405060708090102 * * `qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypq`: payment hash 0001020304050607080900010203040506070809000102030405060708090102
* * `d`: short description * * `d`: short description
* * `pl`: `data_length` (`p` = 1, `l` = 31. 1 * 32 + 31 == 63) * * `pl`: `data_length` (`p` = 1, `l` = 31; 1 * 32 + 31 == 63)
* * `2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6twvus8g6rfwvs8qun0dfjkxaq`: 'Please consider supporting this project' * * `2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6twvus8g6rfwvs8qun0dfjkxaq`: 'Please consider supporting this project'
* * `8rkx3yf5tcsyz3d73gafnh3cax9rn449d9p5uxz9ezhhypd0elx87sjle52x86fux2ypatgddc6k63n7erqz25le42c4u4ecky03ylcq`: signature * * `8rkx3yf5tcsyz3d73gafnh3cax9rn449d9p5uxz9ezhhypd0elx87sjle52x86fux2ypatgddc6k63n7erqz25le42c4u4ecky03ylcq`: signature
* * `ca784w`: Bech32 checksum * * `ca784w`: Bech32 checksum
@ -184,11 +184,11 @@ int main(void)
* * `pvjluez`: timestamp (1496314658) * * `pvjluez`: timestamp (1496314658)
* * `p`: payment hash... * * `p`: payment hash...
* * `d`: short description * * `d`: short description
* * `q5`: `data_length` (`q` = 0, `5` = 20. 0 * 32 + 20 == 20) * * `q5`: `data_length` (`q` = 0, `5` = 20; 0 * 32 + 20 == 20)
* * `xysxxatsyp3k7enxv4js`: '1 cup coffee' * * `xysxxatsyp3k7enxv4js`: '1 cup coffee'
* * `x`: expiry time * * `x`: expiry time
* * `qz`: `data_length` (`q` = 0, `z` = 2. 0 * 32 + 2 == 2) * * `qz`: `data_length` (`q` = 0, `z` = 2; 0 * 32 + 2 == 2)
* * `pu`: 60 seconds (`p` = 1, `u` = 28. 1 * 32 + 28 == 60) * * `pu`: 60 seconds (`p` = 1, `u` = 28; 1 * 32 + 28 == 60)
* * `aztrnwngzn3kdzw5hydlzf03qdgm2hdq27cqv3agm2awhz5se903vruatfhq77w3ls4evs3ch9zw97j25emudupq63nyw24cg27h2rsp`: signature * * `aztrnwngzn3kdzw5hydlzf03qdgm2hdq27cqv3agm2awhz5se903vruatfhq77w3ls4evs3ch9zw97j25emudupq63nyw24cg27h2rsp`: signature
* * `fj9srp`: Bech32 checksum * * `fj9srp`: Bech32 checksum
*/ */
@ -219,7 +219,7 @@ int main(void)
* * `pvjluez`: timestamp (1496314658) * * `pvjluez`: timestamp (1496314658)
* * `p`: payment hash... * * `p`: payment hash...
* * `h`: tagged field: hash of description * * `h`: tagged field: hash of description
* * `p5`: `data_length` (`p` = 1, `5` = 20. 1 * 32 + 20 == 52) * * `p5`: `data_length` (`p` = 1, `5` = 20; 1 * 32 + 20 == 52)
* * `8yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqs`: SHA256 of 'One piece of chocolate cake, one icecream cone, one pickle, one slice of swiss cheese, one slice of salami, one lollypop, one piece of cherry pie, one sausage, one cupcake, and one slice of watermelon' * * `8yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqs`: SHA256 of 'One piece of chocolate cake, one icecream cone, one pickle, one slice of swiss cheese, one slice of salami, one lollypop, one piece of cherry pie, one sausage, one cupcake, and one slice of watermelon'
* * `cc6gd6ql3jrc5yzme8v4ntcewwz5cnw92tz0pc8qcuufvq7khhr8wpald05e92xw006sq94mg8v2ndf4sefvf9sygkshp5zfem29trqq`: signature * * `cc6gd6ql3jrc5yzme8v4ntcewwz5cnw92tz0pc8qcuufvq7khhr8wpald05e92xw006sq94mg8v2ndf4sefvf9sygkshp5zfem29trqq`: signature
* * `2yxxz7`: Bech32 checksum * * `2yxxz7`: Bech32 checksum

Loading…
Cancel
Save