Check complete Merkle cleanup before committing channel deletion
This commit is contained in:
1 parent
8850121984
commit
c3ac2059f4
2 files changed
+18
-8
No files matched your search
@@ -646,6 +646,13 @@ int topo_node_sqlite_channel_delete(sqlite3* db, const char* channel_id) {
|
||||
if (rc != SQLITE_DONE) goto fail;
|
||||
rc = sqlite3_finalize(st); st = NULL;
|
||||
if (rc != SQLITE_OK) goto fail;
|
||||
rc = sqlite3_prepare_v2(db, "SELECT 1 FROM merkle_tree_hash WHERE substr(namespace,instr(namespace,':')+1)=? LIMIT 1",
|
||||
-1, &st, NULL);
|
||||
if (rc == SQLITE_OK) rc = sqlite3_bind_text(st, 1, channel_id, -1, SQLITE_STATIC);
|
||||
if (rc == SQLITE_OK) rc = sqlite3_step(st);
|
||||
if (rc != SQLITE_DONE) goto fail;
|
||||
rc = sqlite3_finalize(st); st = NULL;
|
||||
if (rc != SQLITE_OK) goto fail;
|
||||
}
|
||||
if ((rc = sqlite3_exec(db, "RELEASE delete_topo_channel", NULL, NULL, NULL)) != SQLITE_OK) goto fail;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_BGP, "channel deleted: channel=%s tables=peers/msg/feedback merkle=%d", channel_id, has_merkle);
|
||||
|
||||
@@ -531,10 +531,11 @@ static void channel_state(struct fixture* f, int deleted) {
|
||||
sqlite3_stmt* st = NULL;
|
||||
assert(sqlite3_prepare_v2(f->reader, "SELECT EXISTS(SELECT 1 FROM channels WHERE channel_id=?1),"
|
||||
"EXISTS(SELECT 1 FROM attachment_keys WHERE channel=?1),EXISTS(SELECT 1 FROM attachment_key_requests WHERE channel=?1),"
|
||||
"EXISTS(SELECT 1 FROM attachment_key_outbox WHERE channel=?1),EXISTS(SELECT 1 FROM sqlite_master WHERE name='msg_'||?1)",
|
||||
"EXISTS(SELECT 1 FROM attachment_key_outbox WHERE channel=?1),EXISTS(SELECT 1 FROM sqlite_master WHERE name='msg_'||?1),"
|
||||
"EXISTS(SELECT 1 FROM merkle_tree_hash WHERE namespace='audit:'||?1)",
|
||||
-1, &st, NULL) == SQLITE_OK);
|
||||
assert(sqlite3_bind_text(st, 1, f->channel, -1, SQLITE_STATIC) == SQLITE_OK && sqlite3_step(st) == SQLITE_ROW);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (sqlite3_column_int(st, i) != !deleted)
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "delete test: reader column=%d exists=%d expected=%d", i, sqlite3_column_int(st, i), !deleted);
|
||||
assert(sqlite3_column_int(st, i) == !deleted);
|
||||
@@ -556,7 +557,9 @@ static void channel_seed(struct fixture* f) {
|
||||
snprintf(query, sizeof(query), "INSERT INTO attachment_key_requests(channel,message_id,peer,incoming,state,created_at)"
|
||||
" SELECT channel,message_id,99,1,2,123 FROM attachment_keys WHERE channel='%s';"
|
||||
" INSERT INTO attachment_key_outbox(channel,message_id,peer,command,retry_at)"
|
||||
" SELECT channel,message_id,99,3,17 FROM attachment_keys WHERE channel='%s'", f->channel, f->channel);
|
||||
" SELECT channel,message_id,99,3,17 FROM attachment_keys WHERE channel='%s';"
|
||||
" INSERT INTO merkle_tree_hash(namespace,level,prefix64,hash) VALUES('audit:%s',0,0,zeroblob(32))",
|
||||
f->channel, f->channel, f->channel);
|
||||
sql(f->inst->topo_sqlite_db, query); channel_state(f, 0);
|
||||
}
|
||||
|
||||
@@ -567,11 +570,11 @@ static int veto_channel(void* arg) {
|
||||
}
|
||||
|
||||
static void test_channel_delete_rollback(void) {
|
||||
const char* tables[] = {"channels", "attachment_keys", "attachment_key_requests", "attachment_key_outbox"};
|
||||
for (unsigned table = 0; table < 4; table++) for (int ignored = 0; ignored < 2; ignored++) {
|
||||
const char* tables[] = {"channels", "attachment_keys", "attachment_key_requests", "attachment_key_outbox", "merkle_tree_hash"};
|
||||
for (unsigned table = 0; table < 5; table++) for (int ignored = 0; ignored < 2; ignored++) {
|
||||
struct fixture f; setup(&f); channel_seed(&f); char path[512], trigger[384]; plaintext_path(&f, path);
|
||||
snprintf(trigger, sizeof(trigger), "CREATE TEMP TRIGGER reject_channel BEFORE DELETE ON %s BEGIN SELECT RAISE(%s); END",
|
||||
tables[table], ignored ? "IGNORE" : "ABORT,'channel'");
|
||||
snprintf(trigger, sizeof(trigger), "CREATE TEMP TRIGGER reject_channel BEFORE DELETE ON %s%s BEGIN SELECT RAISE(%s); END",
|
||||
tables[table], table == 4 ? " WHEN OLD.namespace LIKE 'audit:%'" : "", ignored ? "IGNORE" : "ABORT,'channel'");
|
||||
sql(f.inst->topo_sqlite_db, trigger); chat_core_delete_channel(f.inst, f.channel);
|
||||
assert(!f.deleted_events && rows(&f) == f.rows && ma_file_size(path) == sizeof(content)); committed(&f, 1); channel_state(&f, 0);
|
||||
sql(f.inst->topo_sqlite_db, "DROP TRIGGER reject_channel"); chat_core_delete_channel(f.inst, f.channel);
|
||||
@@ -601,7 +604,7 @@ static void test_channel_delete_rollback(void) {
|
||||
channel_state(&f, 0); decryption_state(&f, 1, 0, 0); assert(ma_file_size(path) == sizeof(content));
|
||||
assert(sqlite3_close(f.reader) == SQLITE_OK); uasync_destroy(f.ua, 0); active = NULL; channel_transaction = 0;
|
||||
chat_core_delete_channel(NULL, "1");
|
||||
DEBUG_INFO(DEBUG_CATEGORY_MEDIA, "PASS channel delete:12 SQL faults, cascade ABORT/IGNORE, commit veto and foreign transaction preserve key/files; reader in event sees all deleted");
|
||||
DEBUG_INFO(DEBUG_CATEGORY_MEDIA, "PASS channel delete:14 SQL faults, cascade/Merkle ABORT/IGNORE, veto/foreign transaction/rollback fault; key/files preserved until committed event");
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
|
||||
Reference in new issue
Block a user