From b1bf094bfdae065d3dd0ccaad51673561adc8d7c Mon Sep 17 00:00:00 2001 From: evgeny Date: Wed, 7 Oct 2026 08:17:52 +0200 Subject: [PATCH] Verify signed multi-reaction rejection and document the single-choice rule --- src/chat/merkle_sync_doc.md | 3 ++- tests/test_chat_feedback.c | 6 +++++- tools/chatcli_commands.txt | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/chat/merkle_sync_doc.md b/src/chat/merkle_sync_doc.md index 7408293d..cf473ade 100644 --- a/src/chat/merkle_sync_doc.md +++ b/src/chat/merkle_sync_doc.md @@ -130,7 +130,8 @@ Wire-запись: message_id:32, node_id:8, kind:1, ver:8, data_len:2, data, si ## Опросы и реакции `chat_poll_codec` задаёт общий каталог 16 эмодзи и канонические кодеки. -Реакции: count:1 и отсортированные уникальные номера; максимум 8 реакций автора. +Реакция: count=1 и номер эмодзи; автор выбирает только один смайлик на сообщение. +Выбор другого смайлика заменяет предыдущий с новым ver; повторное нажатие отменяет реакцию. Ответ: count:1, отсортированные уникальные номера пунктов, custom_len:2, UTF-8 текст. Пустой набор/ответ кодируется нулевой длиной. Собственный текст — максимум 1024 байта. Структурно неверные состояния не применяются; семантически неверные подписанные ответы diff --git a/tests/test_chat_feedback.c b/tests/test_chat_feedback.c index 48557043..cdec10c5 100644 --- a/tests/test_chat_feedback.c +++ b/tests/test_chat_feedback.c @@ -115,8 +115,12 @@ int main(int argc, char** argv) { assert(chat_feedback_get(&source, "1001", message, source.node_id, CHAT_FEEDBACK_REACTION, &first) == 1); uint8_t invalid_multi[] = {2, 0, 1}; assert(chat_feedback_set(&source, "1001", message, CHAT_FEEDBACK_REACTION, invalid_multi, sizeof(invalid_multi), NULL) < 0); - struct chat_feedback_record invalid = first; invalid.ver++; invalid.data_len = sizeof(invalid_multi); + struct chat_feedback_record invalid = first; invalid.data_len = sizeof(invalid_multi); memcpy(invalid.data, invalid_multi, sizeof(invalid_multi)); + uint8_t invalid_body[FB_WIRE_MAX + 32]; int invalid_bytes = fb_signed_bytes(1001, &first, invalid_body); + assert(invalid_bytes > 4); + invalid_body[invalid_bytes - 3] = sizeof(invalid_multi); invalid_body[invalid_bytes - 2] = 2; invalid_body[invalid_bytes] = 1; + assert(sc_ed25519_sign(source.my_ed25519_privkey, invalid_body, invalid_bytes + 1, invalid.signature) == SC_OK); assert(chat_feedback_apply(&target, "1001", &invalid) < 0); int saved_events = events; assert(chat_feedback_set(&source, "1001", message, CHAT_FEEDBACK_REACTION, a, sizeof(a), &ver) == 0 && ver == 1); diff --git a/tools/chatcli_commands.txt b/tools/chatcli_commands.txt index 305996c4..cd49a007 100644 --- a/tools/chatcli_commands.txt +++ b/tools/chatcli_commands.txt @@ -71,7 +71,7 @@ vote [option_id ...] [--custom ] chatcli vote 12345 react [emoji_or_id] [--off] [--clear] - Установить реакцию; --off снимает выбранную, --clear снимает все свои реакции. + Установить единственную реакцию, заменив предыдущую; --off снимает выбранную, --clear отменяет свою реакцию. Пример: chatcli react 12345 "👍" chatcli react 12345 0 --off chatcli react 12345 --clear