Rename sequence_before_author => flags. #29

This commit is contained in:
Cory McWilliams 2024-03-13 19:40:09 -04:00
parent 9de33d06d2
commit 537a8654fa
5 changed files with 50 additions and 41 deletions

View File

@ -1003,14 +1003,13 @@ static bool _tf_ssb_verify_and_strip_signature_internal(JSContext* context, JSVa
return verified; return verified;
} }
bool tf_ssb_verify_and_strip_signature( bool tf_ssb_verify_and_strip_signature(JSContext* context, JSValue val, char* out_id, size_t out_id_size, char* out_signature, size_t out_signature_size, int* out_flags)
JSContext* context, JSValue val, char* out_id, size_t out_id_size, char* out_signature, size_t out_signature_size, bool* out_sequence_before_author)
{ {
if (_tf_ssb_verify_and_strip_signature_internal(context, val, out_id, out_id_size, out_signature, out_signature_size)) if (_tf_ssb_verify_and_strip_signature_internal(context, val, out_id, out_id_size, out_signature, out_signature_size))
{ {
if (out_sequence_before_author) if (out_flags)
{ {
*out_sequence_before_author = false; *out_flags = 0;
} }
return true; return true;
} }
@ -1028,9 +1027,9 @@ bool tf_ssb_verify_and_strip_signature(
JS_FreeValue(context, reordered); JS_FreeValue(context, reordered);
if (result) if (result)
{ {
if (out_sequence_before_author) if (out_flags)
{ {
*out_sequence_before_author = true; *out_flags = k_tf_ssb_message_flag_sequence_before_author;
} }
return true; return true;
} }
@ -3562,11 +3561,11 @@ void tf_ssb_verify_strip_and_store_message(tf_ssb_t* ssb, JSValue value, tf_ssb_
.user_data = user_data, .user_data = user_data,
}; };
char signature[crypto_sign_BYTES + 128] = { 0 }; char signature[crypto_sign_BYTES + 128] = { 0 };
bool sequence_before_author = false; int flags = 0;
if (tf_ssb_verify_and_strip_signature(context, value, async->id, sizeof(async->id), signature, sizeof(signature), &sequence_before_author)) if (tf_ssb_verify_and_strip_signature(context, value, async->id, sizeof(async->id), signature, sizeof(signature), &flags))
{ {
async->verified = true; async->verified = true;
tf_ssb_db_store_message(ssb, context, async->id, value, signature, sequence_before_author, _tf_ssb_verify_strip_and_store_callback, async); tf_ssb_db_store_message(ssb, context, async->id, value, signature, flags, _tf_ssb_verify_strip_and_store_callback, async);
} }
else else
{ {

View File

@ -103,7 +103,7 @@ void tf_ssb_db_init(tf_ssb_t* ssb)
" hash TEXT," " hash TEXT,"
" content BLOB," " content BLOB,"
" signature TEXT," " signature TEXT,"
" sequence_before_author INTEGER," " flags INTEGER,"
" UNIQUE(author, sequence)" " UNIQUE(author, sequence)"
")"); ")");
@ -123,6 +123,12 @@ void tf_ssb_db_init(tf_ssb_t* ssb)
_tf_ssb_db_exec(db, "COMMIT TRANSACTION"); _tf_ssb_db_exec(db, "COMMIT TRANSACTION");
} }
if (_tf_ssb_db_has_rows(db, "SELECT name FROM pragma_table_info('messages') WHERE name = 'sequence_before_author'"))
{
tf_printf("Renaming sequence_before_author -> flags.\n");
_tf_ssb_db_exec(db, "ALTER TABLE messages RENAME COLUMN sequence_before_author TO flags");
}
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_author_id_index ON messages (author, id)"); _tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_author_id_index ON messages (author, id)");
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_author_sequence_index ON messages (author, sequence)"); _tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_author_sequence_index ON messages (author, sequence)");
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_author_timestamp_index ON messages (author, timestamp)"); _tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_author_timestamp_index ON messages (author, timestamp)");
@ -232,7 +238,7 @@ void tf_ssb_db_init(tf_ssb_t* ssb)
" AND LENGTH(messages_refs.ref) = 52 " " AND LENGTH(messages_refs.ref) = 52 "
" AND messages_refs.ref LIKE '&%.sha256'"); " AND messages_refs.ref LIKE '&%.sha256'");
bool need_add_sequence_before_author = true; bool need_add_flags = true;
bool need_convert_timestamp_to_real = false; bool need_convert_timestamp_to_real = false;
if (sqlite3_prepare(db, "PRAGMA table_info(messages)", -1, &statement, NULL) == SQLITE_OK) if (sqlite3_prepare(db, "PRAGMA table_info(messages)", -1, &statement, NULL) == SQLITE_OK)
@ -246,9 +252,9 @@ void tf_ssb_db_init(tf_ssb_t* ssb)
{ {
need_convert_timestamp_to_real = true; need_convert_timestamp_to_real = true;
} }
if (name && strcmp(name, "sequence_before_author") == 0) if (name && strcmp(name, "flags") == 0)
{ {
need_add_sequence_before_author = false; need_add_flags = false;
} }
} }
sqlite3_finalize(statement); sqlite3_finalize(statement);
@ -266,10 +272,10 @@ void tf_ssb_db_init(tf_ssb_t* ssb)
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_author_timestamp_index ON messages (author, timestamp)"); _tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_author_timestamp_index ON messages (author, timestamp)");
_tf_ssb_db_exec(db, "COMMIT TRANSACTION"); _tf_ssb_db_exec(db, "COMMIT TRANSACTION");
} }
if (need_add_sequence_before_author) if (need_add_flags)
{ {
tf_printf("Adding sequence_before_author column.\n"); tf_printf("Adding flags column.\n");
_tf_ssb_db_exec(db, "ALTER TABLE messages ADD COLUMN sequence_before_author INTEGER"); _tf_ssb_db_exec(db, "ALTER TABLE messages ADD COLUMN flags INTEGER");
} }
tf_ssb_release_db_writer(ssb, db); tf_ssb_release_db_writer(ssb, db);
} }
@ -298,14 +304,14 @@ static bool _tf_ssb_db_previous_message_exists(sqlite3* db, const char* author,
} }
static int64_t _tf_ssb_db_store_message_raw(tf_ssb_t* ssb, const char* id, const char* previous, const char* author, int64_t sequence, double timestamp, const char* content, static int64_t _tf_ssb_db_store_message_raw(tf_ssb_t* ssb, const char* id, const char* previous, const char* author, int64_t sequence, double timestamp, const char* content,
size_t content_len, const char* signature, bool sequence_before_author) size_t content_len, const char* signature, int flags)
{ {
sqlite3* db = tf_ssb_acquire_db_writer(ssb); sqlite3* db = tf_ssb_acquire_db_writer(ssb);
int64_t last_row_id = -1; int64_t last_row_id = -1;
if (_tf_ssb_db_previous_message_exists(db, author, sequence, previous)) if (_tf_ssb_db_previous_message_exists(db, author, sequence, previous))
{ {
const char* query = "INSERT INTO messages (id, previous, author, sequence, timestamp, content, hash, signature, sequence_before_author) VALUES (?, ?, ?, ?, ?, jsonb(?), " const char* query = "INSERT INTO messages (id, previous, author, sequence, timestamp, content, hash, signature, flags) VALUES (?, ?, ?, ?, ?, jsonb(?), "
"?, ?, ?) ON CONFLICT DO NOTHING"; "?, ?, ?) ON CONFLICT DO NOTHING";
sqlite3_stmt* statement; sqlite3_stmt* statement;
if (sqlite3_prepare(db, query, -1, &statement, NULL) == SQLITE_OK) if (sqlite3_prepare(db, query, -1, &statement, NULL) == SQLITE_OK)
@ -315,7 +321,7 @@ static int64_t _tf_ssb_db_store_message_raw(tf_ssb_t* ssb, const char* id, const
sqlite3_bind_text(statement, 3, author, -1, NULL) == SQLITE_OK && sqlite3_bind_int64(statement, 4, sequence) == SQLITE_OK && sqlite3_bind_text(statement, 3, author, -1, NULL) == SQLITE_OK && sqlite3_bind_int64(statement, 4, sequence) == SQLITE_OK &&
sqlite3_bind_double(statement, 5, timestamp) == SQLITE_OK && sqlite3_bind_text(statement, 6, content, content_len, NULL) == SQLITE_OK && sqlite3_bind_double(statement, 5, timestamp) == SQLITE_OK && sqlite3_bind_text(statement, 6, content, content_len, NULL) == SQLITE_OK &&
sqlite3_bind_text(statement, 7, "sha256", 6, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 8, signature, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 7, "sha256", 6, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 8, signature, -1, NULL) == SQLITE_OK &&
sqlite3_bind_int(statement, 9, sequence_before_author) == SQLITE_OK) sqlite3_bind_int(statement, 9, flags) == SQLITE_OK)
{ {
int r = sqlite3_step(statement); int r = sqlite3_step(statement);
if (r != SQLITE_DONE) if (r != SQLITE_DONE)
@ -397,7 +403,7 @@ typedef struct _message_store_t
tf_ssb_t* ssb; tf_ssb_t* ssb;
char id[k_id_base64_len]; char id[k_id_base64_len];
char signature[512]; char signature[512];
bool sequence_before_author; int flags;
char previous[k_id_base64_len]; char previous[k_id_base64_len];
char author[k_id_base64_len]; char author[k_id_base64_len];
int64_t sequence; int64_t sequence;
@ -421,7 +427,7 @@ static void _tf_ssb_db_store_message_work(uv_work_t* work)
tf_trace_t* trace = tf_ssb_get_trace(store->ssb); tf_trace_t* trace = tf_ssb_get_trace(store->ssb);
tf_trace_begin(trace, "message_store_work"); tf_trace_begin(trace, "message_store_work");
int64_t last_row_id = _tf_ssb_db_store_message_raw(store->ssb, store->id, *store->previous ? store->previous : NULL, store->author, store->sequence, store->timestamp, int64_t last_row_id = _tf_ssb_db_store_message_raw(store->ssb, store->id, *store->previous ? store->previous : NULL, store->author, store->sequence, store->timestamp,
store->content, store->length, store->signature, store->sequence_before_author); store->content, store->length, store->signature, store->flags);
if (last_row_id != -1) if (last_row_id != -1)
{ {
store->out_stored = true; store->out_stored = true;
@ -477,8 +483,8 @@ static void _tf_ssb_db_store_message_after_work(uv_work_t* work, int status)
{ {
tf_trace_begin(trace, "notify_message_added"); tf_trace_begin(trace, "notify_message_added");
JSContext* context = tf_ssb_get_context(store->ssb); JSContext* context = tf_ssb_get_context(store->ssb);
JSValue formatted = tf_ssb_format_message( JSValue formatted =
context, store->previous, store->author, store->sequence, store->timestamp, "sha256", store->content, store->signature, store->sequence_before_author); tf_ssb_format_message(context, store->previous, store->author, store->sequence, store->timestamp, "sha256", store->content, store->signature, store->flags);
JSValue message = JS_NewObject(context); JSValue message = JS_NewObject(context);
JS_SetPropertyStr(context, message, "key", JS_NewString(context, store->id)); JS_SetPropertyStr(context, message, "key", JS_NewString(context, store->id));
JS_SetPropertyStr(context, message, "value", formatted); JS_SetPropertyStr(context, message, "value", formatted);
@ -503,8 +509,8 @@ static void _tf_ssb_db_store_message_after_work(uv_work_t* work, int status)
tf_trace_end(trace); tf_trace_end(trace);
} }
void tf_ssb_db_store_message(tf_ssb_t* ssb, JSContext* context, const char* id, JSValue val, const char* signature, bool sequence_before_author, void tf_ssb_db_store_message(
tf_ssb_db_store_message_callback_t* callback, void* user_data) tf_ssb_t* ssb, JSContext* context, const char* id, JSValue val, const char* signature, int flags, tf_ssb_db_store_message_callback_t* callback, void* user_data)
{ {
JSValue previousval = JS_GetPropertyStr(context, val, "previous"); JSValue previousval = JS_GetPropertyStr(context, val, "previous");
const char* previous = JS_IsNull(previousval) ? NULL : JS_ToCString(context, previousval); const char* previous = JS_IsNull(previousval) ? NULL : JS_ToCString(context, previousval);
@ -543,7 +549,7 @@ void tf_ssb_db_store_message(tf_ssb_t* ssb, JSContext* context, const char* id,
.timestamp = timestamp, .timestamp = timestamp,
.content = contentstr, .content = contentstr,
.length = content_len, .length = content_len,
.sequence_before_author = sequence_before_author, .flags = flags,
.callback = callback, .callback = callback,
.user_data = user_data, .user_data = user_data,
@ -1002,12 +1008,12 @@ JSValue tf_ssb_db_visit_query(tf_ssb_t* ssb, const char* query, const JSValue bi
return result; return result;
} }
JSValue tf_ssb_format_message(JSContext* context, const char* previous, const char* author, int64_t sequence, double timestamp, const char* hash, const char* content, JSValue tf_ssb_format_message(
const char* signature, bool sequence_before_author) JSContext* context, const char* previous, const char* author, int64_t sequence, double timestamp, const char* hash, const char* content, const char* signature, int flags)
{ {
JSValue value = JS_NewObject(context); JSValue value = JS_NewObject(context);
JS_SetPropertyStr(context, value, "previous", (previous && *previous) ? JS_NewString(context, previous) : JS_NULL); JS_SetPropertyStr(context, value, "previous", (previous && *previous) ? JS_NewString(context, previous) : JS_NULL);
if (sequence_before_author) if (flags & k_tf_ssb_message_flag_sequence_before_author)
{ {
JS_SetPropertyStr(context, value, "sequence", JS_NewInt64(context, sequence)); JS_SetPropertyStr(context, value, "sequence", JS_NewInt64(context, sequence));
JS_SetPropertyStr(context, value, "author", JS_NewString(context, author)); JS_SetPropertyStr(context, value, "author", JS_NewString(context, author));
@ -1499,8 +1505,8 @@ JSValue tf_ssb_db_get_message_by_id(tf_ssb_t* ssb, const char* id, bool is_keys)
JSContext* context = tf_ssb_get_context(ssb); JSContext* context = tf_ssb_get_context(ssb);
sqlite3* db = tf_ssb_acquire_db_reader(ssb); sqlite3* db = tf_ssb_acquire_db_reader(ssb);
sqlite3_stmt* statement; sqlite3_stmt* statement;
if (sqlite3_prepare(db, "SELECT previous, author, id, sequence, timestamp, hash, json(content), signature, sequence_before_author FROM messages WHERE id = ?", -1, &statement, if (sqlite3_prepare(db, "SELECT previous, author, id, sequence, timestamp, hash, json(content), signature, flags FROM messages WHERE id = ?", -1, &statement, NULL) ==
NULL) == SQLITE_OK) SQLITE_OK)
{ {
if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK) if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK)
{ {

View File

@ -70,12 +70,12 @@ typedef void(tf_ssb_db_store_message_callback_t)(const char* id, bool stored, vo
** @param id The message identifier. ** @param id The message identifier.
** @param val The message object. ** @param val The message object.
** @param signature The signature of the message. ** @param signature The signature of the message.
** @param sequence_before_author The order of the message fields. ** @param flags tf_ssb_message_flags_t describing the message.
** @param callback A callback to call upon completion. ** @param callback A callback to call upon completion.
** @param user_data User data for the callback. ** @param user_data User data for the callback.
*/ */
void tf_ssb_db_store_message(tf_ssb_t* ssb, JSContext* context, const char* id, JSValue val, const char* signature, bool sequence_before_author, void tf_ssb_db_store_message(
tf_ssb_db_store_message_callback_t* callback, void* user_data); tf_ssb_t* ssb, JSContext* context, const char* id, JSValue val, const char* signature, int flags, tf_ssb_db_store_message_callback_t* callback, void* user_data);
/** /**
** A function called when a block is stored in the database. ** A function called when a block is stored in the database.
@ -233,10 +233,10 @@ bool tf_ssb_db_identity_get_private_key(tf_ssb_t* ssb, const char* user, const c
** @param hash The hash type (probably "sha256"). ** @param hash The hash type (probably "sha256").
** @param content The message content. ** @param content The message content.
** @param signature The signature of the message. ** @param signature The signature of the message.
** @param sequence_before_author The order of the message fields (prefer false). ** @param flags tf_ssb_message_flags_t describing the message.
*/ */
JSValue tf_ssb_format_message(JSContext* context, const char* previous, const char* author, int64_t sequence, double timestamp, const char* hash, const char* content, JSValue tf_ssb_format_message(
const char* signature, bool sequence_before_author); JSContext* context, const char* previous, const char* author, int64_t sequence, double timestamp, const char* hash, const char* content, const char* signature, int flags);
/** Information about a single followed account. */ /** Information about a single followed account. */
typedef struct _tf_ssb_following_t typedef struct _tf_ssb_following_t

View File

@ -40,6 +40,11 @@ typedef enum _tf_ssb_change_t
k_tf_ssb_change_remove, k_tf_ssb_change_remove,
} tf_ssb_change_t; } tf_ssb_change_t;
typedef enum _tf_ssb_message_flags_t
{
k_tf_ssb_message_flag_sequence_before_author = 1,
} tf_ssb_message_flags_t;
/** An SSB instance. */ /** An SSB instance. */
typedef struct _tf_ssb_t tf_ssb_t; typedef struct _tf_ssb_t tf_ssb_t;
/** An SSB connection. */ /** An SSB connection. */
@ -363,11 +368,10 @@ bool tf_ssb_id_bin_to_str(char* str, size_t str_size, const uint8_t* bin);
** @param out_id_size The size of out_id. ** @param out_id_size The size of out_id.
** @param[out] out_signature A buffer to receive the message's signature. ** @param[out] out_signature A buffer to receive the message's signature.
** @param out_signature_size The size of out_signature. ** @param out_signature_size The size of out_signature.
** @param[out] out_sequence_before_author A flag describing the order of the sequence and author fields. ** @param[out] out_flags tf_ssb_message_flags_t describing the message.
** @return True if the signature is valid and was successfully extracted. ** @return True if the signature is valid and was successfully extracted.
*/ */
bool tf_ssb_verify_and_strip_signature( bool tf_ssb_verify_and_strip_signature(JSContext* context, JSValue val, char* out_id, size_t out_id_size, char* out_signature, size_t out_signature_size, int* out_flags);
JSContext* context, JSValue val, char* out_id, size_t out_id_size, char* out_signature, size_t out_signature_size, bool* out_sequence_before_author);
/** /**
** Determine the message identifier. ** Determine the message identifier.

View File

@ -678,7 +678,7 @@ static void _tf_ssb_connection_send_history_stream_work(tf_ssb_connection_t* con
sqlite3_stmt* statement; sqlite3_stmt* statement;
const int k_max = 32; const int k_max = 32;
if (sqlite3_prepare(db, if (sqlite3_prepare(db,
"SELECT previous, author, id, sequence, timestamp, hash, json(content), signature, sequence_before_author FROM messages WHERE author = ?1 AND sequence > ?2 AND " "SELECT previous, author, id, sequence, timestamp, hash, json(content), signature, flags FROM messages WHERE author = ?1 AND sequence > ?2 AND "
"sequence " "sequence "
"< ?3 ORDER BY sequence", "< ?3 ORDER BY sequence",
-1, &statement, NULL) == SQLITE_OK) -1, &statement, NULL) == SQLITE_OK)