Каналы: новый роутинг, поиск, вход-возврат, удаление просмотров и документация

This commit is contained in:
AidarKC
2026-05-08 01:15:54 +03:00
parent 6774c26ea1
commit acdd6c928b
18 changed files with 657 additions and 458 deletions
@@ -0,0 +1,175 @@
# Как устроены каналы в блокчейне SHiNE
## 1) Коротко: что такое “канал” в текущей реализации
В SHiNE канал — это не отдельная таблица сообщений, а **линия блоков** внутри блокчейна пользователя:
- канал создается TECH-блоком `CreateChannelBody` (`msg_type=0`, `msg_sub_type=1`);
- сообщения канала — это `TEXT_POST` (`msg_type=1`, `msg_sub_type=10`) с `line_code = rootBlockNumber канала`;
- ответы (треды) — это `TEXT_REPLY` (`msg_sub_type=20`) с target-ссылкой на конкретный блок-сообщение.
То есть канал = “корневой блок канала” + все посты в его линии + связанные ответы.
---
## 2) Как канал появляется
Создание канала идет через `AddBlock`:
1. UI собирает `CreateChannelBody` (v2, а при legacy-ошибке fallback на v1).
2. UI подписывает блок приватным blockchain-ключом на устройстве.
3. UI отправляет на сервер `AddBlock` с `blockBytesB64` (полный бинарный блок: preimage + sigMarker + signature).
4. Сервер:
- проверяет цепочку (`prevHash`, `blockNumber=last+1`);
- парсит body;
- валидирует подпись;
- валидирует имя канала;
- сохраняет блок и обновляет state.
Дополнительно сервер поддерживает `channel_names_state` как нормализованное состояние названий каналов.
---
## 3) Правила имени и описания канала
### Имя канала (`ChannelNameRules`)
- длина: `3..32` символов (code points);
- допустимые символы: Latin/Cyrillic, цифры, пробел, `_`, `-`;
- имя нормализуется (trim + схлопывание пробелов);
- канонический slug строится в lower-case, `ё -> е`, разделители -> `-`.
### Уникальность
Проверяется по slug. При конфликте сервер возвращает `channel_name_already_exists`.
### Описание канала
В `CreateChannelBody v2` описание хранится прямо в блоке (до 200 байт UTF-8).
Для совместимости с legacy-v1 есть fallback: описание может сохраняться как `USER_PARAM` ключа вида:
`channel_desc:{ownerBlockchainName}:{rootBlockNumber}:{rootBlockHash}`
В UI при чтении описание берется из ответа канала и при наличии override — перекрывается значением из `USER_PARAM`.
---
## 4) Канал “0”
`rootBlockNumber=0` — технический root-канал.
Публикации `TEXT_POST` в канал `0` сейчас отключены (на сервере есть явный запрет).
---
## 5) Как идут сообщения в канале
### Публикация поста
UI вызывает `addBlockTextPost` -> `AddBlock` с `TEXT_POST`.
Ограничения:
- писать можно только в **свой** блокчейн и свои каналы;
- для поста задается `line_code` канала;
- пост в канале — это новый неизменяемый блок.
### Ответы
Ответы (`TEXT_REPLY`) не обязаны лежать в той же линии.
Они ссылаются на целевой блок через target (`to_bch_name`, `to_block_number`, `to_block_hash`).
Это позволяет отвечать и из других блокчейнов (межпользовательский тред).
---
## 6) Редактирование и удаление сообщений
### Редактирование
Поддержано на уровне протокола:
- `TEXT_EDIT_POST` (11) — правка поста;
- `TEXT_EDIT_REPLY` (21) — правка ответа.
Правка — это **новый блок**, ссылающийся на оригинал.
Оригинальный блок не меняется.
Серверные read-API уже собирают `versions[]` и `versionsTotal`.
### Удаление
Сейчас отдельного subtype “delete post/reply” нет.
Физического удаления блоков из цепочки нет (блоки иммутабельны).
Итог:
- изменить можно через edit-блок;
- удалить “как в чате” сейчас нельзя.
---
## 7) Как UI получает канал
Основные read-API:
- `ListSubscriptionsFeed` — список каналов/подписок;
- `GetChannelMessages` — посты канала;
- `GetMessageThread` — тред вокруг выбранного сообщения.
Важно: UI получает **JSON-представление**, собранное сервером из блоков БД, а не сырые блоки по умолчанию.
В JSON возвращаются:
- `messageRef` (номер и hash блока),
- автор,
- текущий текст,
- `versions[]` (оригинал + правки),
- counters (`likesCount`, `repliesCount`).
---
## 8) Как строится тред
`GetMessageThread`:
1. Находит focus-сообщение по `(blockchainName, blockNumber)`.
2. Строит `ancestors` вверх по target-ссылкам.
3. Строит `descendants` вниз: replies, где target = focus.
Запросы в БД идут по `to_bch_name + to_block_number + to_block_hash`, поэтому ответы из других блокчейнов тоже связываются.
---
## 9) Что проверяется криптографически
При записи (`AddBlock`) сервер проверяет:
- корректность формата блока;
- непрерывность цепочки;
- `SHA-256(preimage)` и Ed25519-подпись;
- соответствие публичного blockchain-ключа пользователя.
На чтении (`GetChannelMessages`, `GetMessageThread`) сервер отдает уже сохраненные данные (JSON из БД).
Повторная верификация каждой записи при каждом чтении не делается.
---
## 10) UI-статус на сегодня (важно)
На момент этого документа:
- в UI нет полноценного экрана истории правок сообщения (хотя `versions` уже приходят);
- нет операции удаления сообщений (и на протоколе нет delete subtype);
- канал читается как JSON-слой поверх блоков, а не как “сырой бинарный блок-объект”.
---
## 11) Практический вывод по модели данных
Каналы в SHiNE — это append-only модель:
- каждое действие = новый подписанный блок;
- “изменение” = добавление новой версии, не перезапись старой;
- целостность и авторство обеспечиваются подписью и связностью цепочки;
- UI может показывать удобный “чатовый” вид, но источник истины — блоки.