SHA256
Добавить спецификации Solana программ и вынести формат PDA
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
# Программа `shine_login_guard`
|
||||
|
||||
Документ описывает целевое поведение программы классификации логинов SHiNE.
|
||||
|
||||
Задача программы:
|
||||
|
||||
- по логину определить класс регистрации;
|
||||
- вернуть результат в `return_data`;
|
||||
- не хранить PDA и не вести собственное состояние.
|
||||
|
||||
## 1. Назначение
|
||||
|
||||
`shine_login_guard` — маленькая служебная программа, которую вызывает `shine_users` через CPI до регистрации пользователя.
|
||||
|
||||
Она отвечает только на вопрос:
|
||||
|
||||
- можно ли зарегистрировать логин автоматически;
|
||||
- является ли логин premium;
|
||||
- является ли логин trademark/company.
|
||||
|
||||
## 2. Program ID
|
||||
|
||||
Текущий program id:
|
||||
|
||||
- `3xkopA7cXagxzMFrKdv3NCBfV6BKiRJCk69kr27M2sRo`
|
||||
|
||||
## 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)`
|
||||
|
||||
Аккаунты:
|
||||
|
||||
- signer
|
||||
|
||||
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` и документации.
|
||||
Reference in New Issue
Block a user