nostrdb/bech32: retab

Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
William Casarin
2023-12-23 15:42:36 -08:00
committed by Daniel D’Aquino
parent 373cd71f69
commit 30ba0d72cc
2 changed files with 280 additions and 280 deletions

View File

@@ -1,8 +1,8 @@
// //
// nostr_bech32.c // nostr_bech32.c
// damus // damus
// //
// Created by William Casarin on 2023-04-09. // Created by William Casarin on 2023-04-09.
// //
#include "nostr_bech32.h" #include "nostr_bech32.h"
@@ -19,288 +19,288 @@
#define TLV_KNOWN_TLVS 4 #define TLV_KNOWN_TLVS 4
struct nostr_tlv { struct nostr_tlv {
u8 type; u8 type;
u8 len; u8 len;
const u8 *value; const u8 *value;
}; };
struct nostr_tlvs { struct nostr_tlvs {
struct nostr_tlv tlvs[MAX_TLVS]; struct nostr_tlv tlvs[MAX_TLVS];
int num_tlvs; int num_tlvs;
}; };
static int parse_nostr_tlv(struct cursor *cur, struct nostr_tlv *tlv) { static int parse_nostr_tlv(struct cursor *cur, struct nostr_tlv *tlv) {
// get the tlv tag // get the tlv tag
if (!pull_byte(cur, &tlv->type)) if (!cursor_pull_byte(cur, &tlv->type))
return 0; return 0;
// unknown, fail! // unknown, fail!
if (tlv->type >= TLV_KNOWN_TLVS) if (tlv->type >= TLV_KNOWN_TLVS)
return 0; return 0;
// get the length // get the length
if (!pull_byte(cur, &tlv->len)) if (!cursor_pull_byte(cur, &tlv->len))
return 0; return 0;
// is the reported length greater then our buffer? if so fail // is the reported length greater then our buffer? if so fail
if (cur->p + tlv->len > cur->end) if (cur->p + tlv->len > cur->end)
return 0; return 0;
tlv->value = cur->p; tlv->value = cur->p;
cur->p += tlv->len; cur->p += tlv->len;
return 1; return 1;
} }
static int parse_nostr_tlvs(struct cursor *cur, struct nostr_tlvs *tlvs) { static int parse_nostr_tlvs(struct cursor *cur, struct nostr_tlvs *tlvs) {
int i; int i;
tlvs->num_tlvs = 0; tlvs->num_tlvs = 0;
for (i = 0; i < MAX_TLVS; i++) { for (i = 0; i < MAX_TLVS; i++) {
if (parse_nostr_tlv(cur, &tlvs->tlvs[i])) { if (parse_nostr_tlv(cur, &tlvs->tlvs[i])) {
tlvs->num_tlvs++; tlvs->num_tlvs++;
} else { } else {
break; break;
} }
} }
if (tlvs->num_tlvs == 0) if (tlvs->num_tlvs == 0)
return 0; return 0;
return 1; return 1;
} }
static int find_tlv(struct nostr_tlvs *tlvs, u8 type, struct nostr_tlv **tlv) { static int find_tlv(struct nostr_tlvs *tlvs, u8 type, struct nostr_tlv **tlv) {
*tlv = NULL; *tlv = NULL;
for (int i = 0; i < tlvs->num_tlvs; i++) { for (int i = 0; i < tlvs->num_tlvs; i++) {
if (tlvs->tlvs[i].type == type) { if (tlvs->tlvs[i].type == type) {
*tlv = &tlvs->tlvs[i]; *tlv = &tlvs->tlvs[i];
return 1; return 1;
} }
} }
return 0; return 0;
} }
static int parse_nostr_bech32_type(const char *prefix, enum nostr_bech32_type *type) { static int parse_nostr_bech32_type(const char *prefix, enum nostr_bech32_type *type) {
// Parse type // Parse type
if (strcmp(prefix, "note") == 0) { if (strcmp(prefix, "note") == 0) {
*type = NOSTR_BECH32_NOTE; *type = NOSTR_BECH32_NOTE;
return 1; return 1;
} else if (strcmp(prefix, "npub") == 0) { } else if (strcmp(prefix, "npub") == 0) {
*type = NOSTR_BECH32_NPUB; *type = NOSTR_BECH32_NPUB;
return 1; return 1;
} else if (strcmp(prefix, "nsec") == 0) { } else if (strcmp(prefix, "nsec") == 0) {
*type = NOSTR_BECH32_NSEC; *type = NOSTR_BECH32_NSEC;
return 1; return 1;
} else if (strcmp(prefix, "nprofile") == 0) { } else if (strcmp(prefix, "nprofile") == 0) {
*type = NOSTR_BECH32_NPROFILE; *type = NOSTR_BECH32_NPROFILE;
return 1; return 1;
} else if (strcmp(prefix, "nevent") == 0) { } else if (strcmp(prefix, "nevent") == 0) {
*type = NOSTR_BECH32_NEVENT; *type = NOSTR_BECH32_NEVENT;
return 1; return 1;
} else if (strcmp(prefix, "nrelay") == 0) { } else if (strcmp(prefix, "nrelay") == 0) {
*type = NOSTR_BECH32_NRELAY; *type = NOSTR_BECH32_NRELAY;
return 1; return 1;
} else if (strcmp(prefix, "naddr") == 0) { } else if (strcmp(prefix, "naddr") == 0) {
*type = NOSTR_BECH32_NADDR; *type = NOSTR_BECH32_NADDR;
return 1; return 1;
} }
return 0; return 0;
} }
static int parse_nostr_bech32_note(struct cursor *cur, struct bech32_note *note) { static int parse_nostr_bech32_note(struct cursor *cur, struct bech32_note *note) {
return pull_bytes(cur, 32, &note->event_id); return pull_bytes(cur, 32, &note->event_id);
} }
static int parse_nostr_bech32_npub(struct cursor *cur, struct bech32_npub *npub) { static int parse_nostr_bech32_npub(struct cursor *cur, struct bech32_npub *npub) {
return pull_bytes(cur, 32, &npub->pubkey); return pull_bytes(cur, 32, &npub->pubkey);
} }
static int parse_nostr_bech32_nsec(struct cursor *cur, struct bech32_nsec *nsec) { static int parse_nostr_bech32_nsec(struct cursor *cur, struct bech32_nsec *nsec) {
return pull_bytes(cur, 32, &nsec->nsec); return pull_bytes(cur, 32, &nsec->nsec);
} }
static int tlvs_to_relays(struct nostr_tlvs *tlvs, struct relays *relays) { static int tlvs_to_relays(struct nostr_tlvs *tlvs, struct relays *relays) {
struct nostr_tlv *tlv; struct nostr_tlv *tlv;
struct str_block *str; struct str_block *str;
relays->num_relays = 0; relays->num_relays = 0;
for (int i = 0; i < tlvs->num_tlvs; i++) { for (int i = 0; i < tlvs->num_tlvs; i++) {
tlv = &tlvs->tlvs[i]; tlv = &tlvs->tlvs[i];
if (tlv->type != TLV_RELAY) if (tlv->type != TLV_RELAY)
continue; continue;
if (relays->num_relays + 1 > MAX_RELAYS) if (relays->num_relays + 1 > MAX_RELAYS)
break; break;
str = &relays->relays[relays->num_relays++]; str = &relays->relays[relays->num_relays++];
str->start = (const char*)tlv->value; str->start = (const char*)tlv->value;
str->end = (const char*)(tlv->value + tlv->len); str->end = (const char*)(tlv->value + tlv->len);
} }
return 1; return 1;
} }
static int parse_nostr_bech32_nevent(struct cursor *cur, struct bech32_nevent *nevent) { static int parse_nostr_bech32_nevent(struct cursor *cur, struct bech32_nevent *nevent) {
struct nostr_tlvs tlvs; struct nostr_tlvs tlvs;
struct nostr_tlv *tlv; struct nostr_tlv *tlv;
if (!parse_nostr_tlvs(cur, &tlvs)) if (!parse_nostr_tlvs(cur, &tlvs))
return 0; return 0;
if (!find_tlv(&tlvs, TLV_SPECIAL, &tlv)) if (!find_tlv(&tlvs, TLV_SPECIAL, &tlv))
return 0; return 0;
if (tlv->len != 32) if (tlv->len != 32)
return 0; return 0;
nevent->event_id = tlv->value; nevent->event_id = tlv->value;
if (find_tlv(&tlvs, TLV_AUTHOR, &tlv)) { if (find_tlv(&tlvs, TLV_AUTHOR, &tlv)) {
nevent->pubkey = tlv->value; nevent->pubkey = tlv->value;
} else { } else {
nevent->pubkey = NULL; nevent->pubkey = NULL;
} }
return tlvs_to_relays(&tlvs, &nevent->relays); return tlvs_to_relays(&tlvs, &nevent->relays);
} }
static int parse_nostr_bech32_naddr(struct cursor *cur, struct bech32_naddr *naddr) { static int parse_nostr_bech32_naddr(struct cursor *cur, struct bech32_naddr *naddr) {
struct nostr_tlvs tlvs; struct nostr_tlvs tlvs;
struct nostr_tlv *tlv; struct nostr_tlv *tlv;
if (!parse_nostr_tlvs(cur, &tlvs)) if (!parse_nostr_tlvs(cur, &tlvs))
return 0; return 0;
if (!find_tlv(&tlvs, TLV_SPECIAL, &tlv)) if (!find_tlv(&tlvs, TLV_SPECIAL, &tlv))
return 0; return 0;
naddr->identifier.start = (const char*)tlv->value; naddr->identifier.start = (const char*)tlv->value;
naddr->identifier.end = (const char*)tlv->value + tlv->len; naddr->identifier.end = (const char*)tlv->value + tlv->len;
if (!find_tlv(&tlvs, TLV_AUTHOR, &tlv)) if (!find_tlv(&tlvs, TLV_AUTHOR, &tlv))
return 0; return 0;
naddr->pubkey = tlv->value; naddr->pubkey = tlv->value;
return tlvs_to_relays(&tlvs, &naddr->relays); return tlvs_to_relays(&tlvs, &naddr->relays);
} }
static int parse_nostr_bech32_nprofile(struct cursor *cur, struct bech32_nprofile *nprofile) { static int parse_nostr_bech32_nprofile(struct cursor *cur, struct bech32_nprofile *nprofile) {
struct nostr_tlvs tlvs; struct nostr_tlvs tlvs;
struct nostr_tlv *tlv; struct nostr_tlv *tlv;
if (!parse_nostr_tlvs(cur, &tlvs)) if (!parse_nostr_tlvs(cur, &tlvs))
return 0; return 0;
if (!find_tlv(&tlvs, TLV_SPECIAL, &tlv)) if (!find_tlv(&tlvs, TLV_SPECIAL, &tlv))
return 0; return 0;
if (tlv->len != 32) if (tlv->len != 32)
return 0; return 0;
nprofile->pubkey = tlv->value; nprofile->pubkey = tlv->value;
return tlvs_to_relays(&tlvs, &nprofile->relays); return tlvs_to_relays(&tlvs, &nprofile->relays);
} }
static int parse_nostr_bech32_nrelay(struct cursor *cur, struct bech32_nrelay *nrelay) { static int parse_nostr_bech32_nrelay(struct cursor *cur, struct bech32_nrelay *nrelay) {
struct nostr_tlvs tlvs; struct nostr_tlvs tlvs;
struct nostr_tlv *tlv; struct nostr_tlv *tlv;
if (!parse_nostr_tlvs(cur, &tlvs)) if (!parse_nostr_tlvs(cur, &tlvs))
return 0; return 0;
if (!find_tlv(&tlvs, TLV_SPECIAL, &tlv)) if (!find_tlv(&tlvs, TLV_SPECIAL, &tlv))
return 0; return 0;
nrelay->relay.start = (const char*)tlv->value; nrelay->relay.start = (const char*)tlv->value;
nrelay->relay.end = (const char*)tlv->value + tlv->len; nrelay->relay.end = (const char*)tlv->value + tlv->len;
return 1; return 1;
} }
int parse_nostr_bech32(struct cursor *cur, struct nostr_bech32 *obj) { int parse_nostr_bech32(struct cursor *cur, struct nostr_bech32 *obj) {
u8 *start, *end; u8 *start, *end;
start = cur->p; start = cur->p;
if (!consume_until_non_alphanumeric(cur, 1)) { if (!consume_until_non_alphanumeric(cur, 1)) {
cur->p = start; cur->p = start;
return 0; return 0;
} }
end = cur->p; end = cur->p;
size_t data_len; size_t data_len;
size_t input_len = end - start; size_t input_len = end - start;
if (input_len < 10 || input_len > 10000) { if (input_len < 10 || input_len > 10000) {
return 0; return 0;
} }
obj->buffer = malloc(input_len * 2); obj->buffer = malloc(input_len * 2);
if (!obj->buffer) if (!obj->buffer)
return 0; return 0;
u8 data[input_len]; u8 data[input_len];
char prefix[input_len]; char prefix[input_len];
if (bech32_decode_len(prefix, data, &data_len, (const char*)start, input_len) == BECH32_ENCODING_NONE) { if (bech32_decode_len(prefix, data, &data_len, (const char*)start, input_len) == BECH32_ENCODING_NONE) {
cur->p = start; cur->p = start;
return 0; return 0;
} }
obj->buflen = 0; obj->buflen = 0;
if (!bech32_convert_bits(obj->buffer, &obj->buflen, 8, data, data_len, 5, 0)) { if (!bech32_convert_bits(obj->buffer, &obj->buflen, 8, data, data_len, 5, 0)) {
goto fail; goto fail;
} }
if (!parse_nostr_bech32_type(prefix, &obj->type)) { if (!parse_nostr_bech32_type(prefix, &obj->type)) {
goto fail; goto fail;
} }
struct cursor bcur; struct cursor bcur;
make_cursor(obj->buffer, obj->buffer + obj->buflen, &bcur); make_cursor(obj->buffer, obj->buffer + obj->buflen, &bcur);
switch (obj->type) { switch (obj->type) {
case NOSTR_BECH32_NOTE: case NOSTR_BECH32_NOTE:
if (!parse_nostr_bech32_note(&bcur, &obj->data.note)) if (!parse_nostr_bech32_note(&bcur, &obj->data.note))
goto fail; goto fail;
break; break;
case NOSTR_BECH32_NPUB: case NOSTR_BECH32_NPUB:
if (!parse_nostr_bech32_npub(&bcur, &obj->data.npub)) if (!parse_nostr_bech32_npub(&bcur, &obj->data.npub))
goto fail; goto fail;
break; break;
case NOSTR_BECH32_NSEC: case NOSTR_BECH32_NSEC:
if (!parse_nostr_bech32_nsec(&bcur, &obj->data.nsec)) if (!parse_nostr_bech32_nsec(&bcur, &obj->data.nsec))
goto fail; goto fail;
break; break;
case NOSTR_BECH32_NEVENT: case NOSTR_BECH32_NEVENT:
if (!parse_nostr_bech32_nevent(&bcur, &obj->data.nevent)) if (!parse_nostr_bech32_nevent(&bcur, &obj->data.nevent))
goto fail; goto fail;
break; break;
case NOSTR_BECH32_NADDR: case NOSTR_BECH32_NADDR:
if (!parse_nostr_bech32_naddr(&bcur, &obj->data.naddr)) if (!parse_nostr_bech32_naddr(&bcur, &obj->data.naddr))
goto fail; goto fail;
break; break;
case NOSTR_BECH32_NPROFILE: case NOSTR_BECH32_NPROFILE:
if (!parse_nostr_bech32_nprofile(&bcur, &obj->data.nprofile)) if (!parse_nostr_bech32_nprofile(&bcur, &obj->data.nprofile))
goto fail; goto fail;
break; break;
case NOSTR_BECH32_NRELAY: case NOSTR_BECH32_NRELAY:
if (!parse_nostr_bech32_nrelay(&bcur, &obj->data.nrelay)) if (!parse_nostr_bech32_nrelay(&bcur, &obj->data.nrelay))
goto fail; goto fail;
break; break;
} }
return 1; return 1;
fail: fail:
free(obj->buffer); free(obj->buffer);
cur->p = start; cur->p = start;
return 0; return 0;
} }

View File

@@ -1,8 +1,8 @@
// //
// nostr_bech32.h // nostr_bech32.h
// damus // damus
// //
// Created by William Casarin on 2023-04-09. // Created by William Casarin on 2023-04-09.
// //
#ifndef nostr_bech32_h #ifndef nostr_bech32_h
@@ -15,67 +15,67 @@ typedef unsigned char u8;
#define MAX_RELAYS 10 #define MAX_RELAYS 10
struct relays { struct relays {
struct str_block relays[MAX_RELAYS]; struct str_block relays[MAX_RELAYS];
int num_relays; int num_relays;
}; };
enum nostr_bech32_type { enum nostr_bech32_type {
NOSTR_BECH32_NOTE = 1, NOSTR_BECH32_NOTE = 1,
NOSTR_BECH32_NPUB = 2, NOSTR_BECH32_NPUB = 2,
NOSTR_BECH32_NPROFILE = 3, NOSTR_BECH32_NPROFILE = 3,
NOSTR_BECH32_NEVENT = 4, NOSTR_BECH32_NEVENT = 4,
NOSTR_BECH32_NRELAY = 5, NOSTR_BECH32_NRELAY = 5,
NOSTR_BECH32_NADDR = 6, NOSTR_BECH32_NADDR = 6,
NOSTR_BECH32_NSEC = 7, NOSTR_BECH32_NSEC = 7,
}; };
struct bech32_note { struct bech32_note {
const u8 *event_id; const u8 *event_id;
}; };
struct bech32_npub { struct bech32_npub {
const u8 *pubkey; const u8 *pubkey;
}; };
struct bech32_nsec { struct bech32_nsec {
const u8 *nsec; const u8 *nsec;
}; };
struct bech32_nevent { struct bech32_nevent {
struct relays relays; struct relays relays;
const u8 *event_id; const u8 *event_id;
const u8 *pubkey; // optional const u8 *pubkey; // optional
}; };
struct bech32_nprofile { struct bech32_nprofile {
struct relays relays; struct relays relays;
const u8 *pubkey; const u8 *pubkey;
}; };
struct bech32_naddr { struct bech32_naddr {
struct relays relays; struct relays relays;
struct str_block identifier; struct str_block identifier;
const u8 *pubkey; const u8 *pubkey;
}; };
struct bech32_nrelay { struct bech32_nrelay {
struct str_block relay; struct str_block relay;
}; };
typedef struct nostr_bech32 { typedef struct nostr_bech32 {
enum nostr_bech32_type type; enum nostr_bech32_type type;
u8 *buffer; // holds strings and tlv stuff u8 *buffer; // holds strings and tlv stuff
size_t buflen; size_t buflen;
union { union {
struct bech32_note note; struct bech32_note note;
struct bech32_npub npub; struct bech32_npub npub;
struct bech32_nsec nsec; struct bech32_nsec nsec;
struct bech32_nevent nevent; struct bech32_nevent nevent;
struct bech32_nprofile nprofile; struct bech32_nprofile nprofile;
struct bech32_naddr naddr; struct bech32_naddr naddr;
struct bech32_nrelay nrelay; struct bech32_nrelay nrelay;
} data; } data;
} nostr_bech32_t; } nostr_bech32_t;