main.go

Обзор

Файл main.go реализует основной off-chain клиент для игрового нода, который взаимодействует с блокчейнами на базе Ethereum (через несколько RPC), смарт-контрактами игрового менеджера, а также с Relay API для обработки игровых действий и их батчевой обработки. Это ядро системы, обеспечивающее сбор, валидацию, обработку и синхронизацию игровых действий, включая кросс-чейн взаимодействия.

Основная функциональность:


Структуры и функции

Константы

Определены статусы игровых действий (ActionStatusCreated, ActionStatusProcessed, ActionStatusExpired, ActionStatusNotFound) и типы игровых действий (ActionTypeSpendMana, ActionTypeEarnMana и т.д.), используемые для классификации и фильтрации игровых событий.


config — структура конфигурации

Параметры конфигурации для запуска ноды:

Поле

Тип

Описание

relayApiURL

string

URL Relay API

evmRpcURLs

[]string

Список RPC URL Ethereum цепочек

contractAddresses

[]string

Адреса смарт-контрактов GameManager

privateKey

string

Приватный ключ валидатора

logLevel

string

Уровень логирования (debug/info/warn/error)


GameNode — основная структура ноды

Ключевые поля:

Поле

Тип

Описание

relayClient

*v1.SymbioticClient

Клиент Relay API

evmClients

map[int64]*ethclient.Client

Клиенты Ethereum для разных chainID

gameContracts

map[int64]*contracts.GameContracts

Смарт-контракты GameManager для каждой цепочки

batchProcessor

*game.BatchProcessor

Обработка батчей игровых действий

gameEngine

*game.GameEngine

Игровой движок (валидация, бизнес-логика)

lastBlocks

map[int64]uint64

Последние обработанные номера блоков по цепочкам


Основные функции и методы

main()

Точка входа приложения. Инициализирует логирование и вызывает run(). В случае ошибки завершает приложение с кодом 1.


run() error

Настраивает параметры командной строки через библиотеку cobra, требует обязательные параметры и запускает парсинг команд.


rootCmd

Команда cobra, которая при запуске:


NewGameNode(ctx context.Context, cfg config) (*GameNode, error)

Функция инициализации игровой ноды:


(gn *GameNode) Start(ctx context.Context) error

Главный цикл работы ноды:


(gn *GameNode) processNewActions(ctx context.Context) error

Обрабатывает новые игровые действия с каждой цепочки:

  1. Получает последний блок.

  2. Фильтрует события GameActionSubmitted.

  3. Проверяет статус действия, тип и валидирует.

  4. Добавляет валидные действия в батч-процессор.


(gn *GameNode) monitorBatchResults(ctx context.Context)

Горутина, которая слушает канал результатов батчей. Логирует успешные и неуспешные обработки.


(gn *GameNode) getActionTypeName(actionType uint8) string

Возвращает строковое имя действия по коду actionType. Используется для логирования и отладки.


(gn *GameNode) isValidActionType(actionType uint8) bool

Проверяет корректность типа действия.


(gn *GameNode) filterGameActionEvents(ctx, contract, fromBlock, toBlock)

Фильтрует события GameActionSubmitted в заданном диапазоне блоков.


(gn *GameNode) processActionByType(ctx, actionEvent) error

Выполняет обработку действия, делегируя по типу в соответствующие методы:

Каждый из них проверяет корректность параметров и логирует процесс.


(gn *GameNode) processCrossChainActions(ctx) error

Обрабатывает кросс-чейн события CrossChainGameActionSubmitted аналогично локальным.


(gn *GameNode) processCrossChainAction(ctx, evt, sourceChain) error

Обрабатывает отдельное кросс-чейн действие:


(gn *GameNode) synchronizePlayerStates(ctx) error

Периодическая синхронизация состояний игроков между цепочками:


Вспомогательные методы:


signalContext(ctx context.Context) context.Context

Создаёт контекст, который отменяется при получении сигналов SIGTERM и SIGINT.


Взаимодействие с другими модулями


Важные детали реализации


Пример использования

Запуск ноды с требуемыми параметрами:

game-node \
  --relay-api-url "grpc://relay.api:443" \
  --evm-rpc-urls "https://rpc1.eth" --evm-rpc-urls "https://rpc2.eth" \
  --contract-addresses "0x1234...abcd" --contract-addresses "0x5678...efgh" \
  --private-key "abcdef0123456789..." \
  --log-level info

Диаграмма структуры

classDiagram
    class GameNode {
        -relayClient: *v1.SymbioticClient
        -evmClients: map[int64]*ethclient.Client
        -gameContracts: map[int64]*contracts.GameContracts
        -batchProcessor: *game.BatchProcessor
        -gameEngine: *game.GameEngine
        -lastBlocks: map[int64]uint64
        +Start(ctx context.Context) error
        +processNewActions(ctx context.Context) error
        +processCrossChainActions(ctx context.Context) error
        +synchronizePlayerStates(ctx context.Context) error
        +processActionByType(ctx context.Context, actionEvent game.GameActionEvent) error
        +getActionTypeName(actionType uint8) string
        +isValidActionType(actionType uint8) bool
    }

    class config {
        +relayApiURL: string
        +evmRpcURLs: []string
        +contractAddresses: []string
        +privateKey: string
        +logLevel: string
    }

    GameNode "1" --> "1" game.BatchProcessor : batchProcessor
    GameNode "1" --> "1" game.GameEngine : gameEngine
    GameNode "1" --> "*" ethclient.Client : evmClients
    GameNode "1" --> "*" contracts.GameContracts : gameContracts
    GameNode "1" --> "1" v1.SymbioticClient : relayClient

    main --> GameNode : создает и запускает
    main --> config : конфигурирует через флаги

Заключение

main.go — это центральный компонент off-chain клиента игрового нода, который координирует взаимодействие с блокчейном, Relay API и внутренними игровыми структурами для эффективной и корректной обработки игровых действий и их синхронизации между цепочками.

Документированный код обеспечивает надёжный фундамент для масштабируемой и отказоустойчивой архитектуры многосетевой игровой платформы.