# Как устроены каналы в блокчейне 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 может показывать удобный “чатовый” вид, но источник истины — блоки.
