Skip to content

Commit

Permalink
parser: fix bech32 block decoding
Browse files Browse the repository at this point in the history
  • Loading branch information
jb55 committed Dec 29, 2023
1 parent c4d8fc6 commit 40d3a70
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 87 deletions.
34 changes: 24 additions & 10 deletions src/block.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -43,22 +43,25 @@ 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;

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;
}
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
8 changes: 4 additions & 4 deletions src/content_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
16 changes: 10 additions & 6 deletions src/nostr_bech32.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++];
Expand All @@ -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:
Expand Down Expand Up @@ -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);
Expand All @@ -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);
}

66 changes: 1 addition & 65 deletions src/nostr_bech32.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
71 changes: 71 additions & 0 deletions src/nostrdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#define ndb_debug(...) (void)0
#endif

#include "str_block.h"

struct ndb_json_parser;
struct ndb;
struct ndb_blocks;
Expand Down Expand Up @@ -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
Expand All @@ -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
34 changes: 32 additions & 2 deletions test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down

0 comments on commit 40d3a70

Please sign in to comment.