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;
}
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, bool* out_sequence_before_author)
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)
{
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;
}
@ -1028,9 +1027,9 @@ bool tf_ssb_verify_and_strip_signature(
JS_FreeValue(context, reordered);
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;
}
@ -3562,11 +3561,11 @@ void tf_ssb_verify_strip_and_store_message(tf_ssb_t* ssb, JSValue value, tf_ssb_
.user_data = user_data,
};
char signature[crypto_sign_BYTES + 128] = { 0 };
bool sequence_before_author = false;
if (tf_ssb_verify_and_strip_signature(context, value, async->id, sizeof(async->id), signature, sizeof(signature), &sequence_before_author))
int flags = 0;
if (tf_ssb_verify_and_strip_signature(context, value, async->id, sizeof(async->id), signature, sizeof(signature), &flags))
{
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
{

View File

@ -103,7 +103,7 @@ void tf_ssb_db_init(tf_ssb_t* ssb)
" hash TEXT,"
" content BLOB,"
" signature TEXT,"
" sequence_before_author INTEGER,"
" flags INTEGER,"
" UNIQUE(author, sequence)"
")");
@ -123,6 +123,12 @@ void tf_ssb_db_init(tf_ssb_t* ssb)
_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_sequence_index ON messages (author, sequence)");
_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 messages_refs.ref LIKE '&%.sha256'");
bool need_add_sequence_before_author = true;
bool need_add_flags = true;
bool need_convert_timestamp_to_real = false;
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;
}
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);
@ -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, "COMMIT TRANSACTION");
}
if (need_add_sequence_before_author)
if (need_add_flags)
{
tf_printf("Adding sequence_before_author column.\n");
_tf_ssb_db_exec(db, "ALTER TABLE messages ADD COLUMN sequence_before_author INTEGER");
tf_printf("Adding flags column.\n");
_tf_ssb_db_exec(db, "ALTER TABLE messages ADD COLUMN flags INTEGER");
}
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,
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);
int64_t last_row_id = -1;
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";
sqlite3_stmt* statement;
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_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_int(statement, 9, sequence_before_author) == SQLITE_OK)
sqlite3_bind_int(statement, 9, flags) == SQLITE_OK)
{
int r = sqlite3_step(statement);
if (r != SQLITE_DONE)
@ -397,7 +403,7 @@ typedef struct _message_store_t
tf_ssb_t* ssb;
char id[k_id_base64_len];
char signature[512];
bool sequence_before_author;
int flags;
char previous[k_id_base64_len];
char author[k_id_base64_len];
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_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,
store->content, store->length, store->signature, store->sequence_before_author);
store->content, store->length, store->signature, store->flags);
if (last_row_id != -1)
{
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");
JSContext* context = tf_ssb_get_context(store->ssb);
JSValue formatted = tf_ssb_format_message(
context, store->previous, store->author, store->sequence, store->timestamp, "sha256", store->content, store->signature, store->sequence_before_author);
JSValue formatted =
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);
JS_SetPropertyStr(context, message, "key", JS_NewString(context, store->id));
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);
}
void tf_ssb_db_store_message(tf_ssb_t* ssb, JSContext* context, const char* id, JSValue val, const char* signature, bool sequence_before_author,
tf_ssb_db_store_message_callback_t* callback, void* user_data)
void tf_ssb_db_store_message(
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");
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,
.content = contentstr,
.length = content_len,
.sequence_before_author = sequence_before_author,
.flags = flags,
.callback = callback,
.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;
}
JSValue tf_ssb_format_message(JSContext* context, const char* previous, const char* author, int64_t sequence, double timestamp, const char* hash, const char* content,
const char* signature, bool sequence_before_author)
JSValue tf_ssb_format_message(
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);
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, "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);
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
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,
NULL) == SQLITE_OK)
if (sqlite3_prepare(db, "SELECT previous, author, id, sequence, timestamp, hash, json(content), signature, flags FROM messages WHERE id = ?", -1, &statement, 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 val The message object.
** @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 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,
tf_ssb_db_store_message_callback_t* callback, void* user_data);
void tf_ssb_db_store_message(
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.
@ -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 content The message content.
** @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,
const char* signature, bool sequence_before_author);
JSValue tf_ssb_format_message(
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. */
typedef struct _tf_ssb_following_t

View File

@ -40,6 +40,11 @@ typedef enum _tf_ssb_change_t
k_tf_ssb_change_remove,
} 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. */
typedef struct _tf_ssb_t tf_ssb_t;
/** 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] out_signature A buffer to receive the message's 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.
*/
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, bool* out_sequence_before_author);
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);
/**
** 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;
const int k_max = 32;
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 "
"< ?3 ORDER BY sequence",
-1, &statement, NULL) == SQLITE_OK)