什么是程序派生地址(PDA)?
Program Derived Addresses(PDAs)是 Solana 区块链上具有特殊属性的账户。正确使用 PDA 能让Solana dApp 开发变得快速且高效,因为它们有助于跨程序通信。
本文将解释什么是 PDA、它们解决了哪些问题、其工作原理,以及它们与Solana 账户模型中其他账户的区别。
什么是程序派生地址(pda)?
Program Derived Address 是 Solana 区块链上没有私钥的账户。由于 PDA 不是公钥,其账户地址是通过程序 ID、SHA-512 哈希函数、种子数组和一个特殊的 bump seed 计算得出的。
Solana 上的标准账户是什么?
一个标准的 Solana 账户同时拥有私钥和公钥(各 32 字节),两者共同组成一个密钥对,长度为 64 字节,位于椭圆曲线(ED25519)上。密钥对要有效,必须位于这条曲线上。
以下是 ED25519 椭圆曲线的示意图:

程序地址是如何派生的?
PDA 需要三个主要组成部分:
- 父程序 ID - 创建该 PDA 的父程序的 ID
- 种子(Seeds) - 一个字符串数组
- Bump Seed - 确保该 PDA 没有私钥
要生成一个有效的 Program Derived Address,需要将父程序的 ID 和种子数组一起输入 SHA-512 哈希函数运算。
然而,大约有 50% 的情况下,该哈希运算的结果会落在 ED25519 椭圆曲线 上,形成一个密钥对。由于 PDA 不能有私钥,Program Derived Address 不能落在椭圆曲线上。为防止 PDA 拥有私钥,会使用一个特殊的 bump seed 将哈希结果“撞”离曲线。
bump seed 本质上只是一个数字,从 255 开始。如果即便加上 bump seed,哈希结果仍然落在曲线上,就会再次运行哈希函数,将 bump 依次改为 254、253,以此类推,直到生成的结果不在曲线上为止。
注意:种子可以是任意字符串,但开发者通常会结合父程序的状态变量来使用它们,以此构建出类似哈希表的结构。
PDA 解决了什么问题?
Program Derived Address 通过以编程方式生成交易签名来简化交易确认流程,从而帮助 DeFi 账户等去信任化服务顺畅运行。
以下是一个假设的 PDA 使用场景。
设想一个 Solana 程序,允许用户将某个 NFT 设置为默认头像(PFP)。该程序由两个部分组成:
- PFP 程序 - 创建账户以存储用户选择的头像
- 核心程序 - 充当用户输入和 PFP 程序之间的代理
若要让 PFP 程序更新用户所选的头像,它需要用自己的私钥对交易签名以完成头像的更改。但这也意味着该程序需要将其私钥存储在链上。
Solana 程序不能用自己的私钥代表自己对交易签名,因为该密钥本身会被存储在链上,对所有人可见。如果这样做,该私钥就可能被用来代表该程序签署交易,从而更改任意用户的头像。
设想 PFP 程序管理着数百万枚 SOL 代币。这样的漏洞会演变成一场重大黑客攻击。Program Derived Address 正是为解决这一问题而生。
PDA 为什么重要?
Program Derived Address 在 Solana 编程中扮演着重要角色,因为它们有助于不同程序之间的通信(跨程序调用),并且可以充当哈希表,用于存储特定数据,而其父程序可以轻松更新和修改这些数据。
1. 存储程序的状态变量
PDA 让 Solana 开发者能够存储并追踪与特定用户相关的一个或一组变量。PDA 最适合的用途是为其父程序存储状态变量或数据,因为默认情况下它已授权父程序代表自己进行修改。
2. 将 PDA 用作哈希表
映射(Mapping)表示一组键值对,用于根据某个键便捷地查找与之关联的信息。在 Solana 开发中,可以利用 PDA 的种子和相应字符串实现同样的效果。
让我们回到之前钱包头像的例子。
一旦用户选定了钱包的 PFP,PFP 程序会取用所选图片和用户的地址作为“种子”,创建一个用于存储用户选择的 PDA。
一旦哈希算法成功找到该 Program Derived Address,其公钥就会“映射”到用户的地址和所选的 NFT 头像上。
通过再提供一个 PDA 作为第三个种子,这种哈希表功能可以得到更好的利用。我们可以把所有可用的头像存储在一个单独的 PDA 中,将每张头像作为其种子传入,最终得到一个存储了所有头像的 PDA。
这样一来,当用户前来选择头像时,这个 PDA 看起来就像一个哈希表,因为通过传入的种子,你可以看出:在众多头像中(PFP 组 PDA),我们作为第一个种子传入的用户地址,选择了我们作为第二个种子传入的那张头像。
在此基础上,还可以进一步构建更深层次的哈希表结构。

3. 跨程序调用
跨程序调用(Cross Program Invocations,CPI)是指一个程序调用另一个程序中函数的过程。CPI 之所以有用,是因为它们让代码具备更好的可组合性。
回到我们的例子,假设某用户想把头像从 Degen Ape 换成 Solana Monkey Business 头像。
其底层运作方式如下:
用户登录钱包后,核心程序会取用户的地址(公钥),并查找一个已经创建的、其种子中包含该用户公钥的 PDA。
找到之后,核心程序会调用 PFP 程序中名为 changePFP() 的函数(这就是一次跨程序调用),并将核心程序已经“选定”的 PDA 作为参数传入。
函数被调用后,被选中的 PDA 会检查“请求”该变更的账户是否为其父程序。如果不匹配,交易将被拒绝,因为只有父程序才能修改 PDA 的数据。
由于 PFP 程序正是该 PDA 的父程序,因此它被允许将用户所选的头像从 Degen Ape 更改为 SMB 头像。

Program Derived Address 让其父程序能够代表自己签名,并可用于存储程序状态、构建哈希表,以及用于跨程序调用。PDA 是 Solana 编程领域中的一个基础性主题,它使快速、高效的 dApp 开发成为可能。
Program Derived Address 常见问题
在使用 Program Derived Address 时,了解 Solana 如何处理交易和数据会很有帮助。账户主要分为两种类型:可执行账户和不可执行账户。
什么是可执行账户?
可执行账户,也被称为程序(programs),类似于 Ethereum 智能合约——一段在账户与其交互时会改变自身状态的代码。
什么是不可执行账户?
不可执行的数据账户仅用于存储数据(例如账户持有的 SOL 数量、NFT、代币余额等),本质上就是某个程序的状态变量。
Solana 的程序数据存储方式与 Ethereum 智能合约有何不同?
Ethereum 与 Solana 之间一个根本性的区别在于可执行代码的存储组织方式。Ethereum 上的智能合约自带“预建”的存储,智能合约会将其所有状态变量存储在其中。相比之下,Solana 上的程序没有预建的存储,而是拥有独立的数据账户,用于存放它们想要存储和引用的各种状态变量。
相关概览
Solana2026年7月27日
Solana 节点:验证者节点、RPC 节点与自建节点
Solana 节点是什么,验证者节点、RPC 节点与辅助数据系统有何区别,以及何时应自建节点、何时应使用第三方服务。
Solana2026年7月22日
Solana 归档数据:如何查询完整的区块与交易历史
Solana 归档数据详解:节点为何修剪历史数据、哪些 RPC 方法需要归档访问权限,以及如何大规模查询完整的区块与交易历史。
Solana2026年5月28日
Solana Agent Kit 与 GOAT 与 ElizaOS:该选哪个框架?
对比 Solana Agent Kit、GOAT 与 ElizaOS:Solana 原生深度、多链广度还是完整的 agent 运行时。包含代码示例与决策框架。

构建区块链应用
Alchemy 将最强大的 Web3 开发者产品和工具与资源、社区及专业支持结合在一起。