Материал проверен 7 ноября 2026?
БК

ГЛАВНАЯ / ИНСТРУКЦИИ / PDA В SOLANA: КАК ПРОГРАММА ВЫВОДИТ АДРЕС БЕЗ ПРИВАТНОГО КЛЮЧА

PDA в Solana: как программа выводит адрес без приватного ключа

Program Derived Address (PDA) – детерминированный адрес, вычисленный из идентификатора программы и набора seeds. Он находится вне кривой Ed25519, поэтому для него нельзя создать обычный приватный ключ. Программа, чей ID участвовал в деривации, может представить PDA как signer во внутреннем вызове через invoke_signed, если runtime подтвердит seeds. Само вычисление адреса аккаунт в сети не создаёт.

Как получается адрес

Program ID и последовательность seeds задают пространство PDA

Алгоритм хеширует последовательность seed bytes, program ID, bump и служебную строку деривации. Результат проверяется на принадлежность кривой Ed25519. Если адрес оказался бы допустимым ключом на кривой, он не подходит как PDA; алгоритм пробует другое однобайтовое значение bump, пока не получит off-curve адрес.

Seeds – это байты, а не абстрактные строки. Кодировка, порядок, длина и границы компонентов важны. Простая конкатенация переменных строк может создать неоднозначность: разные наборы вроде ["ab", "cd"] и ["abcd"] дают одинаковую последовательность байтов. Используйте разделитель или фиксированное кодирование для переменных компонентов.

  • program ID и точные байты seeds сохранены
  • порядок и кодировка seeds однозначны
  • canonical bump воспроизводится
Bump и воспроизводимость

Canonical bump помогает не допустить несколько адресов одной сущности

Bump – дополнительный байт в наборе деривации. SDK-функция поиска пробует значения по установленному алгоритму и возвращает допустимый PDA вместе с bump. В приложении важно придерживаться canonical bump, который выбирает соответствующий API, а не принимать любой bump, ведущий на off-curve адрес.

Если программа принимает неканонический bump без проверки, один логический объект может получить несколько адресов. Это усложняет проверку аккаунтов и может открыть подмену ожидаемого состояния. Сверяйте PDA по тем же seed bytes и program ID, которые проверяет сама программа; визуально похожий адрес или поле bump из пользовательского ввода недостаточны.

Кто может подписывать

PDA не подписывает обычную транзакцию как кошелёк

У PDA нет закрытого ключа и он не может создать обычную Ed25519-подпись для внешней транзакции. Во время CPI программа, чей ID использован при деривации, вызывает invoke_signed и передаёт seeds. Runtime заново вычисляет адрес и временно считает PDA подписантом для этого внутреннего вызова, если вычисление совпало.

Другие программы не могут выдать себя за этот PDA: их program ID в проверке будет другим. При этом внешний пользователь может подписать транзакцию своим обычным ключом и попросить программу выполнить инструкцию с PDA. Кто вправе инициировать операцию, определяется проверками программы, authority и данными аккаунтов, а не одним фактом, что адрес является PDA.

  • PDA не заявлен как обычный signer
  • invoke_signed вызван программой-источником деривации
  • runtime проверяет seeds
Адрес и аккаунт

Вычисление PDA не выделяет данные и не переводит лампорты

PDA можно вычислить локально даже тогда, когда по этому адресу ещё нет записи в состоянии сети. Для создания data account нужна отдельная инструкция, обычно вызов System Program от имени программы с нужными seeds через invoke_signed. Впоследствии запрос RPC подтверждает, существует ли аккаунт и какие у него данные.

Не смешивайте program ID, использованный для вычисления PDA, с runtime-полем owner аккаунта. Первый входит в адресную формулу и определяет, какая программа может представить PDA signer в CPI. Второе указывает, какая программа управляет данными уже созданного аккаунта. Проверяйте оба значения для конкретного протокола.

  • вычисление адреса отделено от создания account
  • runtime owner прочитан отдельно
  • существование и data проверены RPC
FAQ

Частые вопросы

Можно ли восстановить приватный ключ PDA?

Нет. PDA выбирается вне кривой Ed25519, поэтому соответствующего обычного приватного ключа нет.

Кто может вызвать invoke_signed для PDA?

Программа, чей program ID использован при деривации, передаёт seeds; runtime проверяет вычисленный адрес.

PDA автоматически является аккаунтом?

Нет. Derivation вычисляет адрес, но не создаёт запись с данными в сети.

Можно использовать любой bump?

Программа должна проверять ожидаемую деривацию; canonical bump исключает альтернативный адрес для той же логической схемы.

PDA и owner аккаунта – одно и то же?

Нет. Program ID задаёт деривацию, а поле Account.owner показывает программу, которой принадлежит уже существующий аккаунт.

Итоговая проверка

Чек-лист: pda в solana: как программа выводит адрес без приватного ключа

  • program ID скопирован из проверенного источника;
  • seeds переданы как точные байты и в правильном порядке;
  • переменные компоненты кодированы без неоднозначности;
  • использован canonical bump и проверен ожидаемый PDA;
  • внешняя подпись не приписана самому PDA;
  • для CPI проверены вызывающая программа и seeds;
  • существование аккаунта, данные и поле owner проверены отдельно.

Материал подготовлен редакцией сайта и проверен 7 ноября 2026 года. Условия бирж, кошельков и блокчейн-сетей могут меняться. Перед операцией сверяйте данные в интерфейсе выбранного сервиса.