1
0
mirror of git://jb55.com/damus synced 2024-10-04 10:50:43 +00:00

ndb: update nostrdb

This include various fixes for parsing and key decoding
This commit is contained in:
William Casarin 2023-08-01 16:35:40 -07:00
parent 88306d00a3
commit 07dfa3b1fb
2 changed files with 170 additions and 36 deletions

View File

@ -18,6 +18,7 @@ struct ndb_json_parser {
struct ndb_builder builder;
jsmn_parser json_parser;
jsmntok_t *toks, *toks_end;
int i;
int num_tokens;
};
@ -102,6 +103,8 @@ static inline int ndb_json_parser_parse(struct ndb_json_parser *p)
p->num_tokens =
jsmn_parse(&p->json_parser, p->json, p->json_len, p->toks, cap);
p->i = 0;
return p->num_tokens;
}
@ -242,7 +245,7 @@ static int ndb_event_commitment(struct ndb_note *ev, unsigned char *buf, int buf
struct cursor cur;
int ok;
if (!hex_encode(ev->pubkey, sizeof(ev->pubkey), pubkey, 32))
if (!hex_encode(ev->pubkey, sizeof(ev->pubkey), pubkey, sizeof(pubkey)))
return 0;
make_cursor(buf, buf + buflen, &cur);
@ -351,7 +354,9 @@ int ndb_builder_finalize(struct ndb_builder *builder, struct ndb_note **note,
unsigned char *end = builder->mem.end;
unsigned char *start = (unsigned char*)(*note) + total_size;
if (!ndb_calculate_id(*note, start, end - start))
ndb_builder_set_pubkey(builder, keypair->pubkey);
if (!ndb_calculate_id(builder->note, start, end - start))
return 0;
if (!ndb_sign_id(keypair, (*note)->id, (*note)->sig))
@ -645,92 +650,181 @@ static int parse_unsigned_int(const char *start, int len, unsigned int *num)
return 1;
}
int ndb_ws_event_from_json(const char *json, int len, struct ndb_tce *tce,
unsigned char *buf, int bufsize)
{
jsmntok_t *tok = NULL;
int tok_len, res;
struct ndb_json_parser parser;
int ndb_note_from_json(const char *json, int len, struct ndb_note **note,
unsigned char *buf, int bufsize)
tce->subid_len = 0;
tce->subid = "";
ndb_json_parser_init(&parser, json, len, buf, bufsize);
if ((res = ndb_json_parser_parse(&parser)) < 0)
return res;
if (parser.num_tokens < 3 || parser.toks[0].type != JSMN_ARRAY)
return 0;
parser.i = 1;
tok = &parser.toks[parser.i++];
tok_len = toksize(tok);
if (tok->type != JSMN_STRING)
return 0;
if (tok_len == 5 && !memcmp("EVENT", json + tok->start, 5)) {
tce->evtype = NDB_TCE_EVENT;
struct ndb_event *ev = &tce->event;
tok = &parser.toks[parser.i++];
if (tok->type != JSMN_STRING)
return 0;
tce->subid = json + tok->start;
tce->subid_len = toksize(tok);
return ndb_parse_json_note(&parser, &ev->note);
} else if (tok_len == 4 && !memcmp("EOSE", json + tok->start, 4)) {
tce->evtype = NDB_TCE_EOSE;
tok = &parser.toks[parser.i++];
if (tok->type != JSMN_STRING)
return 0;
tce->subid = json + tok->start;
tce->subid_len = toksize(tok);
return 1;
} else if (tok_len == 2 && !memcmp("OK", json + tok->start, 2)) {
if (parser.num_tokens != 5)
return 0;
struct ndb_command_result *cr = &tce->command_result;
tce->evtype = NDB_TCE_OK;
tok = &parser.toks[parser.i++];
if (tok->type != JSMN_STRING)
return 0;
tce->subid = json + tok->start;
tce->subid_len = toksize(tok);
tok = &parser.toks[parser.i++];
if (tok->type != JSMN_PRIMITIVE || toksize(tok) == 0)
return 0;
cr->ok = (json + tok->start)[0] == 't';
tok = &parser.toks[parser.i++];
if (tok->type != JSMN_STRING)
return 0;
tce->command_result.msg = json + tok->start;
tce->command_result.msglen = toksize(tok);
return 1;
}
return 0;
}
int ndb_parse_json_note(struct ndb_json_parser *parser, struct ndb_note **note)
{
jsmntok_t *tok = NULL;
unsigned char hexbuf[64];
int i, tok_len, res;
const char *json = parser->json;
const char *start;
struct ndb_json_parser parser;
int i, tok_len;
ndb_json_parser_init(&parser, json, len, buf, bufsize);
res = ndb_json_parser_parse(&parser);
if (res < 0)
return res;
if (parser.num_tokens < 1 || parser.toks[0].type != JSMN_OBJECT)
if (parser->toks[parser->i].type != JSMN_OBJECT)
return 0;
for (i = 1; i < parser.num_tokens; i++) {
tok = &parser.toks[i];
// TODO: build id buffer and verify at end
for (i = parser->i + 1; i < parser->num_tokens; i++) {
tok = &parser->toks[i];
start = json + tok->start;
tok_len = toksize(tok);
//printf("toplevel %.*s %d\n", tok_len, json + tok->start, tok->type);
if (tok_len == 0 || i + 1 >= parser.num_tokens)
if (tok_len == 0 || i + 1 >= parser->num_tokens)
continue;
if (start[0] == 'p' && jsoneq(json, tok, tok_len, "pubkey")) {
// pubkey
tok = &parser.toks[i+1];
tok = &parser->toks[i+1];
hex_decode(json + tok->start, toksize(tok), hexbuf, sizeof(hexbuf));
ndb_builder_set_pubkey(&parser.builder, hexbuf);
ndb_builder_set_pubkey(&parser->builder, hexbuf);
} else if (tok_len == 2 && start[0] == 'i' && start[1] == 'd') {
// id
tok = &parser.toks[i+1];
tok = &parser->toks[i+1];
hex_decode(json + tok->start, toksize(tok), hexbuf, sizeof(hexbuf));
// TODO: validate id
ndb_builder_set_id(&parser.builder, hexbuf);
ndb_builder_set_id(&parser->builder, hexbuf);
} else if (tok_len == 3 && start[0] == 's' && start[1] == 'i' && start[2] == 'g') {
// sig
tok = &parser.toks[i+1];
tok = &parser->toks[i+1];
hex_decode(json + tok->start, toksize(tok), hexbuf, sizeof(hexbuf));
ndb_builder_set_sig(&parser.builder, hexbuf);
ndb_builder_set_sig(&parser->builder, hexbuf);
} else if (start[0] == 'k' && jsoneq(json, tok, tok_len, "kind")) {
// kind
tok = &parser.toks[i+1];
tok = &parser->toks[i+1];
start = json + tok->start;
if (tok->type != JSMN_PRIMITIVE || tok_len <= 0)
return 0;
if (!parse_unsigned_int(start, toksize(tok),
&parser.builder.note->kind))
&parser->builder.note->kind))
return 0;
} else if (start[0] == 'c') {
if (jsoneq(json, tok, tok_len, "created_at")) {
// created_at
tok = &parser.toks[i+1];
tok = &parser->toks[i+1];
start = json + tok->start;
if (tok->type != JSMN_PRIMITIVE || tok_len <= 0)
return 0;
if (!parse_unsigned_int(start, toksize(tok),
&parser.builder.note->created_at))
&parser->builder.note->created_at))
return 0;
} else if (jsoneq(json, tok, tok_len, "content")) {
// content
tok = &parser.toks[i+1];
tok = &parser->toks[i+1];
union ndb_packed_str pstr;
tok_len = toksize(tok);
int written, pack_ids = 0;
if (!ndb_builder_make_json_str(&parser.builder,
if (!ndb_builder_make_json_str(&parser->builder,
json + tok->start,
tok_len, &pstr,
&written, pack_ids)) {
return 0;
}
parser.builder.note->content_length = written;
parser.builder.note->content = pstr;
parser->builder.note->content_length = written;
parser->builder.note->content = pstr;
}
} else if (start[0] == 't' && jsoneq(json, tok, tok_len, "tags")) {
tok = &parser.toks[i+1];
ndb_builder_process_json_tags(&parser, tok);
tok = &parser->toks[i+1];
ndb_builder_process_json_tags(parser, tok);
i += tok->size;
}
}
return ndb_builder_finalize(&parser.builder, note, NULL);
return ndb_builder_finalize(&parser->builder, note, NULL);
}
int ndb_note_from_json(const char *json, int len, struct ndb_note **note,
unsigned char *buf, int bufsize)
{
struct ndb_json_parser parser;
int res;
ndb_json_parser_init(&parser, json, len, buf, bufsize);
if ((res = ndb_json_parser_parse(&parser)) < 0)
return res;
if (parser.num_tokens < 1)
return 0;
return ndb_parse_json_note(&parser, note);
}
void ndb_builder_set_pubkey(struct ndb_builder *builder, unsigned char *pubkey)

View File

@ -4,6 +4,19 @@
#include <inttypes.h>
#include "cursor.h"
#define NDB_PACKED_STR 0x1
#define NDB_PACKED_ID 0x2
struct ndb_json_parser;
// To-client event types
enum tce_type {
NDB_TCE_EVENT = 0x1,
NDB_TCE_OK = 0x2,
NDB_TCE_NOTICE = 0x3,
NDB_TCE_EOSE = 0x4,
};
struct ndb_str {
unsigned char flag;
union {
@ -12,9 +25,36 @@ struct ndb_str {
};
};
struct ndb_event {
struct ndb_note *note;
};
struct ndb_command_result {
int ok;
const char *msg;
int msglen;
};
// To-client event
struct ndb_tce {
enum tce_type evtype;
const char *subid;
int subid_len;
union {
struct ndb_event event;
struct ndb_command_result command_result;
};
};
struct ndb_keypair {
unsigned char pubkey[32];
unsigned char secret[32];
// this corresponds to secp256k1's keypair type. it's guaranteed to
// be 96 bytes according to their docs. I don't want to depend on
// the secp256k1 header here so we just use raw bytes.
unsigned char pair[96];
};
@ -22,9 +62,6 @@ struct ndb_keypair {
// representation
#pragma pack(push, 1)
/// We can store byte data in the string table, so
#define NDB_PACKED_STR 0x1
#define NDB_PACKED_ID 0x2
union ndb_packed_str {
struct {
@ -91,6 +128,9 @@ int ndb_create_keypair(struct ndb_keypair *key);
int ndb_decode_key(const char *secstr, struct ndb_keypair *keypair);
// BUILDER
int ndb_parse_json_note(struct ndb_json_parser *, struct ndb_note **);
int ndb_ws_event_from_json(const char *json, int len, struct ndb_tce *tce, unsigned char *buf, int bufsize);
int ndb_note_from_json(const char *json, int len, struct ndb_note **, unsigned char *buf, int buflen);
int ndb_builder_init(struct ndb_builder *builder, unsigned char *buf, int bufsize);
int ndb_builder_finalize(struct ndb_builder *builder, struct ndb_note **note, struct ndb_keypair *privkey);