commit 40d3a7069fec8e54f88a23a6398f45478aeb36f7
parent c4d8fc63a9a367643dc080bd3f3fac89c3640c4e
Author: William Casarin <jb55@jb55.com>
Date: Thu, 28 Dec 2023 16:11:29 -0800
parser: fix bech32 block decoding
Diffstat:
6 files changed, 142 insertions(+), 87 deletions(-)
diff --git a/src/block.c b/src/block.c
@@ -32,7 +32,7 @@ static int pull_nostr_bech32_type(struct cursor *cur, enum nostr_bech32_type *ty
if (!cursor_pull_varint(cur, &inttype))
return 0;
- if (inttype > NOSTR_BECH32_KNOWN_TYPES)
+ if (inttype <= 0 || inttype > NOSTR_BECH32_KNOWN_TYPES)
return 0;
*type = inttype;
@@ -43,9 +43,7 @@ static int pull_nostr_bech32_type(struct cursor *cur, enum nostr_bech32_type *ty
static int pull_bech32_mention(const char *content, struct cursor *cur, struct ndb_mention_bech32_block *block) {
uint16_t size;
unsigned char *start;
- enum nostr_bech32_type type;
-
- start = cur->p;
+ struct cursor bech32;
if (!pull_str_block(cur, content, &block->str))
return 0;
@@ -53,12 +51,17 @@ static int pull_bech32_mention(const char *content, struct cursor *cur, struct n
if (!cursor_pull_u16(cur, &size))
return 0;
- if (!pull_nostr_bech32_type(cur, &type))
+ if (!pull_nostr_bech32_type(cur, &block->bech32.type))
return 0;
- if (!parse_nostr_bech32_buffer(cur, type, &block->bech32))
+ make_cursor(cur->p, cur->p + size, &bech32);
+
+ start = cur->p;
+
+ if (!parse_nostr_bech32_buffer(&bech32, block->bech32.type, &block->bech32))
return 0;
+ //assert(bech32.p == start + size);
cur->p = start + size;
return 1;
}
@@ -153,10 +156,11 @@ void ndb_blocks_iterate_free(struct ndb_block_iterator *iter)
struct ndb_block *ndb_blocks_iterate_next(struct ndb_block_iterator *iter)
{
while (iter->cur.p < iter->cur.end) {
- if (!pull_block(iter->content, &iter->cur, &iter->block))
+ if (!pull_block(iter->content, &iter->cur, &iter->block)) {
return NULL;
- else
+ } else {
return &iter->block;
+ }
}
return NULL;
@@ -180,5 +184,15 @@ struct ndb_str_block *ndb_block_str(struct ndb_block *block)
return NULL;
}
-//const char *ndb_str_block_ptr(struct ndb_str_block *);
-//uint32_t ndb_str_block_len(struct ndb_str_block *);
+
+const char *ndb_str_block_ptr(struct ndb_str_block *str_block) {
+ return str_block->str;
+}
+
+uint32_t ndb_str_block_len(struct ndb_str_block *str_block) {
+ return str_block->len;
+}
+
+struct nostr_bech32 *ndb_bech32_block(struct ndb_block *block) {
+ return &block->block.mention_bech32.bech32;
+}
diff --git a/src/content_parser.c b/src/content_parser.c
@@ -119,15 +119,15 @@ static int push_bech32_mention(struct ndb_content_parser *p, struct ndb_str_bloc
// make sure to push the str block!
if (!push_str_block(&p->buffer, (const char*)p->content.start, bech32))
goto fail;
-
- if (!cursor_push_varint(&p->buffer, type))
- goto fail;
-
+ //
// save a spot for the raw bech32 buffer size
u8_size = (uint16_t*)p->buffer.p;
if (!cursor_skip(&p->buffer, 2))
goto fail;
+ if (!cursor_push_varint(&p->buffer, type))
+ goto fail;
+
if (!cursor_malloc_slice(&p->buffer, &u8, bech32->len))
goto fail;
diff --git a/src/nostr_bech32.c b/src/nostr_bech32.c
@@ -88,11 +88,11 @@ static int parse_nostr_bech32_nsec(struct cursor *cur, struct bech32_nsec *nsec)
return pull_bytes(cur, 32, &nsec->nsec);
}
-static int add_relay(struct relays *relays, struct nostr_tlv *tlv)
+static int add_relay(struct ndb_relays *relays, struct nostr_tlv *tlv)
{
struct ndb_str_block *str;
- if (relays->num_relays + 1 > MAX_RELAYS)
+ if (relays->num_relays + 1 > NDB_MAX_RELAYS)
return 0;
str = &relays->relays[relays->num_relays++];
@@ -116,11 +116,13 @@ static int parse_nostr_bech32_nevent(struct cursor *cur, struct bech32_nevent *n
switch (tlv.type) {
case TLV_SPECIAL:
- if (tlv.len != 32) return 0;
+ if (tlv.len != 32)
+ return 0;
nevent->event_id = tlv.value;
break;
case TLV_AUTHOR:
- if (tlv.len != 32) return 0;
+ if (tlv.len != 32)
+ return 0;
nevent->pubkey = tlv.value;
break;
case TLV_RELAY:
@@ -269,7 +271,7 @@ int parse_nostr_bech32(unsigned char *buf, int buflen,
size_t parsed_len, u5_out_len, u8_out_len;
enum nostr_bech32_type type;
static const int MAX_PREFIX = 8;
- struct cursor cur, bech32;
+ struct cursor cur, bech32, u8;
make_cursor(buf, buf + buflen, &cur);
make_cursor((unsigned char*)bech32_str, (unsigned char*)bech32_str + bech32_len, &bech32);
@@ -296,6 +298,8 @@ int parse_nostr_bech32(unsigned char *buf, int buflen,
if (!bech32_convert_bits(cur.p, &u8_out_len, 8, u5, u5_out_len, 5, 0))
return 0;
- return parse_nostr_bech32_buffer(&cur, type, obj);
+ make_cursor(cur.p, cur.p + u8_out_len, &u8);
+
+ return parse_nostr_bech32_buffer(&u8, type, obj);
}
diff --git a/src/nostr_bech32.h b/src/nostr_bech32.h
@@ -10,72 +10,8 @@
#include <stdio.h>
#include "str_block.h"
+#include "nostrdb.h"
#include "cursor.h"
-#define MAX_RELAYS 24
-
-struct relays {
- struct ndb_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,
-};
-#define NOSTR_BECH32_KNOWN_TYPES 7
-
-struct bech32_note {
- const unsigned char *event_id;
-};
-
-struct bech32_npub {
- const unsigned char *pubkey;
-};
-
-struct bech32_nsec {
- const unsigned char *nsec;
-};
-
-struct bech32_nevent {
- struct relays relays;
- const unsigned char *event_id;
- const unsigned char *pubkey; // optional
-};
-
-struct bech32_nprofile {
- struct relays relays;
- const unsigned char *pubkey;
-};
-
-struct bech32_naddr {
- struct relays relays;
- struct ndb_str_block identifier;
- const unsigned char *pubkey;
-};
-
-struct bech32_nrelay {
- struct ndb_str_block relay;
-};
-
-struct nostr_bech32 {
- enum nostr_bech32_type type;
-
- 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;
- };
-};
-
int parse_nostr_bech32_str(struct cursor *bech32, enum nostr_bech32_type *type);
int parse_nostr_bech32_type(const char *prefix, enum nostr_bech32_type *type);
diff --git a/src/nostrdb.h b/src/nostrdb.h
@@ -18,6 +18,8 @@
#define ndb_debug(...) (void)0
#endif
+#include "str_block.h"
+
struct ndb_json_parser;
struct ndb;
struct ndb_blocks;
@@ -402,6 +404,72 @@ enum ndb_block_type {
};
#define NDB_NUM_BLOCK_TYPES 6
+#define NDB_MAX_RELAYS 24
+
+struct ndb_relays {
+ struct ndb_str_block relays[NDB_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,
+};
+#define NOSTR_BECH32_KNOWN_TYPES 7
+
+struct bech32_note {
+ const unsigned char *event_id;
+};
+
+struct bech32_npub {
+ const unsigned char *pubkey;
+};
+
+struct bech32_nsec {
+ const unsigned char *nsec;
+};
+
+struct bech32_nevent {
+ struct ndb_relays relays;
+ const unsigned char *event_id;
+ const unsigned char *pubkey; // optional
+};
+
+struct bech32_nprofile {
+ struct ndb_relays relays;
+ const unsigned char *pubkey;
+};
+
+struct bech32_naddr {
+ struct ndb_relays relays;
+ struct ndb_str_block identifier;
+ const unsigned char *pubkey;
+};
+
+struct bech32_nrelay {
+ struct ndb_str_block relay;
+};
+
+struct nostr_bech32 {
+ enum nostr_bech32_type type;
+
+ 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;
+ };
+};
+
+
enum ndb_block_type ndb_block_type(struct ndb_blocks *blocks);
// BLOCK ITERATORS
@@ -414,5 +482,8 @@ enum ndb_block_type ndb_get_block_type(struct ndb_block *block);
struct ndb_str_block *ndb_block_str(struct ndb_block *);
const char *ndb_str_block_ptr(struct ndb_str_block *);
uint32_t ndb_str_block_len(struct ndb_str_block *);
+struct nostr_bech32 *ndb_bech32_block(struct ndb_block *block);
+
+// BECH32 BLOCKS
#endif
diff --git a/test.c b/test.c
@@ -774,12 +774,42 @@ static void test_strings_work_before_finalization() {
}
static void test_parse_content() {
+}
+
+static void test_parse_nevent() {
unsigned char buf[4096];
- const char *content = "hello,#world,https://github.com/damus-io";
+ const char *content = "nostr:nevent1qqs9qhc0pjvp6jl2w6ppk5cft8ets8fhxy7fcqcjnp7g38whjy0x5aqpzpmhxue69uhkummnw3ezuamfdejsyg86np9a0kajstc8u9h846rmy6320wdepdeydfz8w8cv7kh9sqv02g947d58,#hashtag";
struct ndb_blocks *blocks;
+ struct ndb_block *block = NULL;
+ struct nostr_bech32 *bech32;
+ int ok = 0;
+
+ static unsigned char event_id[] = { 0x50, 0x5f, 0x0f, 0x0c, 0x98, 0x1d, 0x4b, 0xea, 0x76, 0x82, 0x1b, 0x53,
+ 0x09, 0x59, 0xf2, 0xb8, 0x1d, 0x37, 0x31, 0x3c, 0x9c, 0x03, 0x12, 0x98,
+ 0x7c, 0x88, 0x9d, 0xd7, 0x91, 0x1e, 0x6a, 0x74 };
assert(ndb_parse_content(buf, sizeof(buf), content, strlen(content), &blocks));
- assert(blocks->num_blocks == 4);
+ struct ndb_block_iterator *iter = ndb_blocks_iterate_start(content, blocks);
+ assert(blocks->num_blocks == 3);
+ while ((block = ndb_blocks_iterate_next(iter))) {
+ switch (++ok) {
+ case 1:
+ assert(ndb_get_block_type(block) == BLOCK_MENTION_BECH32);
+ bech32 = ndb_bech32_block(block);
+ assert(bech32->type == NOSTR_BECH32_NEVENT);
+ assert(!memcmp(bech32->nevent.event_id, event_id, 32));
+ break;
+ case 2:
+ assert(ndb_get_block_type(block) == BLOCK_TEXT);
+ assert(ndb_str_block_ptr(ndb_block_str(block))[0] == ',');
+ break;
+ case 3:
+ assert(ndb_get_block_type(block) == BLOCK_HASHTAG);
+ assert(!strncmp("hashtag", ndb_str_block_ptr(ndb_block_str(block)), 7));
+ break;
+ }
+ }
+ assert(ok == 3);
}
static void test_url_parsing() {