Архитектура

Kora — это рабочее пространство Rust из трёх крейтов:

  • kora-lib содержит основную логику и RPC-сервер,
  • kora-cli собирает бинарный файл kora, который запускают операторы, а
  • kora-deploy — специализированный инструмент для развёртывания программ, версионируется отдельно. Всё описанное ниже находится в crates/lib/src, если не указано иное.

Жизненный цикл запроса

На диаграмме ниже показан общий путь транзакции через Kora. Понимание цепочки вызовов важно для настройки ноды Kora и добавления новых функций.

A transaction travels from the client app through the gateway, validation, plugins, and signing, before Kora either returns it or broadcasts it. Each stage is governed by a matching section of kora.toml or signers.toml.

Где находится каждый этап

Этап на диаграммеИсходный кодТочка входа
Шлюзrpc_server/server.rsrun_rpc_server
Диспетчеризацияrpc_server/rpc.rsKoraRpc
Логика отдельных методовrpc_server/method/по одному файлу на каждый метод JSON-RPC
Валидацияvalidator/transaction_validator.rsTransactionValidator
Плагиныplugin/mod.rsTransactionPluginRunner
Подписаниеsigner/реализовано на основе крейта solana-keychain

Ещё два файла, о которых стоит знать: config.rs определяет всю схему kora.toml, а state.rs хранит десериализованную конфигурацию в глобальном состоянии процесса.

Изучаем RPC-сервер

rpc.rs — тонкий слой диспетчеризации: один метод на каждую конечную точку JSON-RPC. Это самый быстрый способ увидеть весь API. Логика каждого метода находится в отдельном файле в rpc_server/method/. Прочитайте sign_transaction.rs от начала до конца: остальные методы подписания являются его вариациями.

Изучаем валидатор

transaction_validator.rs и transaction/instruction_util.rs содержат логику валидации транзакций и инструкций. Кроме того, здесь находятся тесты свойств безопасности для fee-payer-policy: по одному файлу на каждую программу с ограничением доступа в validator/transaction_validator/fee_payer_policy_props/.

Полезные соглашения

Валидация по умолчанию. Каждый флаг в разделе [validation.fee_payer_policy] по умолчанию равен false, а у структур политики есть атрибут #[serde(default)]. Такое сочетание сделано намеренно: добавление новой инструкции с ограничением доступа не должно ломать конфигурацию существующего оператора и должно приводить к отказу, а не к случайному разрешению. Сохраняйте оба условия при добавлении флага.

Всегда валидируйте разрешённую транзакцию, а не исходную. Исходная VersionedTransaction содержит только статические ключи аккаунтов, поэтому при валидации или расчёте стоимости транзакции V0 по ней аккаунты из таблиц поиска молча пропускаются, а комиссия оказывается заниженной. VersionedTransactionResolved::from_transaction заранее разрешает эти адреса, поэтому все последующие этапы принимают разрешённый тип.

Добавление плагина транзакций

Плагины реализуют трейт TransactionPlugin из plugin/mod.rs. В нём два метода: validate выполняется для каждой транзакции во время подписания, а validate_config выполняется один раз при запуске и возвращает оператору ошибки и предупреждения. PluginExecutionContext сообщает плагину, какой из четырёх методов подписания его вызвал.

TransactionPluginRunner::from_config выполняет сопоставление по TransactionPluginType, определённому в config.rs. Новый встроенный плагин — это новый вариант в нём плюс новая ветка match в раннере. Сейчас поставляются два плагина: gas_swap и deploy_authority.

Тестирование

Kora хранит конфигурацию в глобальном состоянии процесса, поэтому в tests/ объявлена одна цель [[test]] на каждую фазу, и каждая цель запускает собственный встроенный surfnet и ноду Kora, инициализируемые с нуля. Одна конфигурация на бинарный файл: новой фазе нужна новая цель, а не новый модуль в существующей.

cargo test -p tests --test <target>

Всё остальное настраивается через justfile. Читайте его, а не восстанавливайте команды вручную.

Is this page helpful?