SHiNE-server/shine-solana/shine/doc/programs/shine_login_guard.md

5.9 KiB
Raw Blame History

Программа 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)

Бинарный ABI инструкции:

- 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:

  • 0CLASS_FREE
  • 1CLASS_PREMIUM
  • 2CLASS_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 и документации.