Архитектура

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-транзакции по ней аккаунты из lookup-таблиц молча пропускаются, а комиссия занижается. 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?