SHA256
147 lines
5.9 KiB
Markdown
147 lines
5.9 KiB
Markdown
# Программа `shine_login_guard`
|
|
|
|
Документ описывает целевое поведение программы классификации логинов SHiNE.
|
|
|
|
Задача программы:
|
|
|
|
- по логину определить класс регистрации;
|
|
- вернуть результат в `return_data`;
|
|
- не хранить PDA и не вести собственное состояние.
|
|
|
|
## 1. Назначение
|
|
|
|
`shine_login_guard` — маленькая служебная программа, которую вызывает `shine_users` через CPI до регистрации пользователя.
|
|
|
|
Она отвечает только на вопрос:
|
|
|
|
- можно ли зарегистрировать логин автоматически;
|
|
- является ли логин premium;
|
|
- является ли логин trademark/company.
|
|
|
|
## 2. Program ID
|
|
|
|
Текущий program id:
|
|
|
|
- `SHiGxGsXGioQYCYhchQ5R7KWoxN5UjFAFsucPf6sfnh`
|
|
|
|
## 3. Состояние
|
|
|
|
У программы нет PDA-состояний и persistent storage.
|
|
|
|
Она опирается на статически сгенерированные словари, встроенные в бинарник на этапе сборки.
|
|
|
|
## 4. Внешние артефакты
|
|
|
|
Словари хранятся в:
|
|
|
|
- `src/dictionaries/premium/**/*.txt`
|
|
- `src/dictionaries/trademarks/**/*.txt`
|
|
|
|
На этапе build:
|
|
|
|
- все `.txt` файлы рекурсивно собираются;
|
|
- слова нормализуются;
|
|
- дубль-слова детектятся и логируются как warning;
|
|
- итоговые массивы слов вшиваются в generated Rust file.
|
|
|
|
## 5. Нормализация словаря
|
|
|
|
Слово словаря считается валидным, если:
|
|
|
|
- не пустое;
|
|
- длина не больше `20`;
|
|
- содержит только ASCII-буквы и цифры;
|
|
- после `trim()` и `lowercase()` остаётся валидным.
|
|
|
|
Символ `_` в словарных словах не допускается.
|
|
|
|
## 6. Единственная инструкция
|
|
|
|
Инструкция:
|
|
|
|
- `classify_login(login: String)`
|
|
|
|
Бинарный ABI инструкции:
|
|
|
|
```text
|
|
- tag: u8 = 1
|
|
- login_len: u32 LE
|
|
- login_bytes[login_len]: UTF-8
|
|
```
|
|
|
|
Аккаунты:
|
|
|
|
- аккаунты не требуются
|
|
|
|
Подпись транзакции для самой классификации не имеет бизнес-смысла. Если вызов идёт через CPI из `shine_users`, программа `shine_login_guard` не требует signer-аккаунтов вообще.
|
|
|
|
## 7. Выходные классы
|
|
|
|
Программа возвращает `u32` через `set_return_data`:
|
|
|
|
- `0` — `CLASS_FREE`
|
|
- `1` — `CLASS_PREMIUM`
|
|
- `2` — `CLASS_TRADEMARK`
|
|
|
|
## 8. Правила нормализации логина
|
|
|
|
Перед классификацией логин нормализуется:
|
|
|
|
- пустой логин запрещён;
|
|
- длина исходного логина не больше `20`;
|
|
- символ `_` удаляется;
|
|
- остальные символы обязаны быть ASCII alnum;
|
|
- буквы приводятся к нижнему регистру.
|
|
|
|
Если нормализация не удалась:
|
|
|
|
- логин считается `CLASS_PREMIUM`.
|
|
|
|
Это намеренно жёсткое поведение: сомнительный логин не должен автоматически попадать в free-класс.
|
|
|
|
## 9. Правила классификации
|
|
|
|
Алгоритм:
|
|
|
|
1. Нормализовать логин.
|
|
2. Попробовать разрезать его на `1..3` слов из словарей.
|
|
3. Если среди найденных частей есть trademark-слово, вернуть `CLASS_TRADEMARK`.
|
|
4. Если есть только premium-слова, вернуть `CLASS_PREMIUM`.
|
|
5. Если словарное совпадение не найдено и длина нормализованного логина `<= 7`, вернуть `CLASS_PREMIUM`.
|
|
6. Иначе вернуть `CLASS_FREE`.
|
|
|
|
## 10. Разбиение на слова
|
|
|
|
Максимум слов в логине:
|
|
|
|
- `3`
|
|
|
|
Алгоритм разбиения:
|
|
|
|
- DFS/backtracking по префиксам строки;
|
|
- на каждом шаге берётся префикс длиной `1..20`;
|
|
- если префикс найден в premium или trademark словаре, поиск продолжается на остатке строки;
|
|
- если найден хотя бы один путь с trademark-словом, итог = `CLASS_TRADEMARK`;
|
|
- если найден путь только с premium-словами, итог = `CLASS_PREMIUM`.
|
|
|
|
## 11. Инварианты
|
|
|
|
Должно быть сохранено при переписи:
|
|
|
|
- тот же способ нормализации логина;
|
|
- та же семантика классов `0/1/2`;
|
|
- тот же лимит `MAX_WORDS_PER_LOGIN = 3`;
|
|
- тот же fallback `len <= 7 => premium`, если словарь ничего не нашёл;
|
|
- тот же порядок приоритета `TRADEMARK > PREMIUM > FREE`.
|
|
|
|
## 12. Что не обязано сохраниться при переписи
|
|
|
|
Можно менять без изменения бизнес-логики:
|
|
|
|
- build pipeline словарей;
|
|
- структуру хранения слов внутри бинарника;
|
|
- способ поиска слов, если сохраняется тот же результат;
|
|
- техническую форму возврата, если внешний контракт для `shine_users` останется совместимым.
|
|
|
|
Но если меняется именно интерфейс `return_data` или классы, это уже требует обновления `shine_users` и документации.
|