PDA看起来像普通Solana地址,却没有对应私钥。程序用种子和自己的program id确定业务账户,运行时再验证同一组材料,让该程序在CPI中代表PDA“签名”。bump的作用是把候选哈希推到Ed25519曲线外;canonical bump则让多组可用结果收敛到一个约定地址。
| 输入 | 谁决定 | 是否应稳定 |
|---|---|---|
| seeds | 业务协议 | 是,需定义编码与顺序 |
| program id | 部署程序 | 升级程序代码可不变,换ID会改变PDA |
| bump | 从255向下搜索 | 应使用首个有效值 |
| PDA地址 | 三者共同结果 | 可由所有客户端重算 |
为何一个种子集合可能有多个bump
并非每个哈希结果都在曲线外,因此SDK尝试不同bump。多个bump可能都得到合法PDA;若程序接受调用者随意提供的任意可用bump,同一业务键可能映射到多个账户,破坏“每个用户只有一个金库”之类不变量。canonical bump固定为从255向下找到的第一个有效值。
种子编码比看起来更重要
字符串、整数、地址和前缀都要变成字节数组,顺序与边界必须一致。把可变长字段直接拼接可能产生歧义;把用户可控长字符串当种子还会触及单个种子与总长度限制。协议应写清域前缀、数字字节序和是否预哈希。
PDA地址由三组材料锁定
- PDA由一组种子、程序ID和bump确定,并被设计为不对应Ed25519私钥。
- findProgramAddress从255向下尝试bump,首个产生离曲线地址的值就是canonical bump。
- 只有派生PDA所属程序在运行时通过对应种子和bump调用invoke_signed时,运行时才会把该PDA视为签名者。
invoke_signed不是伪造私钥
程序发起CPI时提交原始种子和bump,运行时重新派生PDA;只有当前执行程序能为属于自己的PDA获得签名权限。这个权限只在该次调用中生效,不会生成或暴露私钥。被调用程序仍需检查PDA是否为预期账户、owner和可写权限。
Solana账户索引与地址压缩可参考ALT地址查找表,离线交易权限可看Durable Nonce,交易执行日志则结合回执与状态核验。
程序账户约束清单
- 用官方SDK重新计算PDA和canonical bump
- 给每组种子增加稳定域前缀
- 核对数字编码、顺序和长度
- 账户约束同时验证PDA、owner与数据类型
- CPI前限制可写账户和目标program id
程序控制PDA不等于任意PDA可用
保存bump可以省计算,但不能因此跳过地址约束;客户端传来的bump也不能直接信任。“PDA由程序控制”不表示任何该程序派生地址都可互换,业务种子与账户类型仍是授权边界。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。