171 lines
7.5 KiB
Markdown
171 lines
7.5 KiB
Markdown
# Как устроены каналы в блокчейне 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`.
|
||
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);
|
||
- допустимые символы: только латиница `A-Z a-z`, цифры `0-9`, `_`, `-`;
|
||
- имя нормализуется как `trim`;
|
||
- канонический slug: lower-case того же имени (без дополнительных преобразований).
|
||
|
||
### Уникальность
|
||
|
||
Проверяется по slug. При конфликте сервер возвращает `channel_name_already_exists`.
|
||
|
||
### Описание канала
|
||
|
||
В `CreateChannelBody v2` описание хранится прямо в блоке (до 200 байт UTF-8).
|
||
После создания описание в текущей реализации не редактируется (отдельного механизма обновления пока нет).
|
||
|
||
---
|
||
|
||
## 4) Канал “news” (root 0)
|
||
|
||
`rootBlockNumber=0` — системный канал `news` (новостной канал по умолчанию).
|
||
Публикации `TEXT_POST` в `news` сейчас отключены (на сервере есть явный запрет записи в root 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 может показывать удобный “чатовый” вид, но источник истины — блоки.
|