什么是程序派生地址(PDA)?

  • Alchemy
  • 发布于 2023-02-10 22:32
  • 阅读 11

本文详尽介绍了Solana区块链上的程序派生地址(PDA),包括其定义、工作原理、与标准账户的比较及其优点。文章通过实例说明了PDA在简化跨程序通信和存储数据方面的重要性,并且涵盖了相关的实际应用和开发考虑。

程序派生地址(PDAs)是Solana区块链上的一种账户,具有特别的属性。正确使用PDAs可以让Solana dApp开发快速且高效,因为它们有助于跨程序通信。

本文将解释PDAs是什么,它们解决了哪些问题,它们如何工作,以及它们与Solana账户模型中其他账户的不同之处。

什么是程序派生地址(PDA)?

程序派生地址是一个在Solana区块链上没有私钥的账户。由于PDA不是公钥,因此通过程序ID、SHA-512哈希函数、种子数组和特殊的bump种子来找到账户的地址。

Solana上的标准账户是什么?

标准Solana账户具有私钥和公钥(各32字节),合在一起形成一个密钥对,总长度为64字节并位于椭圆曲线(ED25519)上。为了使这个密钥对有效,它必须位于这个曲线上。

以下是ED25519椭圆曲线的表示:

Solana上的ED25519椭圆曲线Solana上的ED25519椭圆曲线

程序地址是如何派生的?

PDAs需要三个主要组件:

  1. 父程序ID - 创建PDA的父程序的ID

  2. 种子 - 字符串数组*

  3. bump种子 - 确保PDA没有私钥

创建有效的程序派生地址需要获取其父程序的ID、种子数组,并通过SHA-512哈希函数运行它们

然而,在大约50%的情况下,这个哈希的结果是一个位于_ED25519椭圆曲线_上的密钥对。由于PDAs没有私钥,因此程序派生地址不能位于椭圆曲线上。为防止PDAs拥有私钥,使用特殊的_bump_种子把哈希结果“推动”到曲线外。

bump种子仅仅是一个数字,从255开始。在即使使用bump种子的情况下,如果哈希结果仍然处于曲线内,则再次运行哈希函数,bump逐渐递减至254、253等,直到生成的结果不在曲线上。

*注:种子可以是任何任意字符串,但开发人员在与父程序的状态变量特定上下文中使用它们,以创建类似于哈希映射的结构。

PDAs解决了哪些问题?

程序派生地址通过程序性生成交易签名来简化交易确认,从而帮助无信任服务如DeFi账户无缝运作。

以下是PDAs的一个假设用例。

考虑一个允许用户将NFT设为默认头像(PFP)的Solana程序。该程序将由两个程序组成:

  1. PFP程序 - 创建账户以存储用户所选的头像

  2. 核心程序 - 充当用户输入与PFP程序之间的桥梁

为了更新用户选择的头像,PFP程序需要使用其私钥来签署将更改用户头像的交易。然而,这也意味着程序需要在链上存储其私钥。

Solana程序无法使用其私钥为自己签署交易,因为私钥本身将存储在链上,使每个人都可见。如果发生这种情况,私钥可以被用于代表程序签署交易并更改任何用户的头像。

想象一下,如果PFP程序负责管理数百万的SOL代币。这样的漏洞将成为一个重大的黑客攻击。程序派生地址解决了这个问题。

为什么PDAs重要?

程序派生地址在Solana编程中起着重要作用,因为它们有助于不同程序之间的沟通(跨程序调用),并且可以充当存储特定数据的哈希映射,使其父程序能够轻松更新和更改。

1. 存储程序的状态变量

PDAs允许Solana开发人员存储和跟踪与特定用户相关的变量或变量集。PDA的最佳用例是存储其父程序的状态变量或数据,因为默认情况下它已授权父程序代表其进行更改。

2. 将PDAs用作哈希映射

映射表示一组键-值对,用于轻松查找与键相关的信息。在Solana开发中,PDA的种子和正确的字符串可以被用来实现同样的结果。

让我们回到之前的钱包头像示例。

一旦用户选择了他们钱包的PFP,PFP程序将选定的图像、用户地址,并将这些作为“种子”来创建一个PDA,用于存储用户的选择。

一旦通过哈希算法成功找到了程序派生地址,其公钥将“映射”到用户的地址和选定的NFT头像。

通过提供另一个PDA作为第三个种子,可以更好地利用哈希映射功能。我们可以将所有可用的头像存储在一个单独的PDA中,并将每个头像作为其种子传递,从而最终得到一个存储所有头像的PDA。

现在,当用户前来选择他们的头像时,PDA将看起来像一个哈希映射,因为种子被传递,使得如果你查看它们,你会知道在一组头像(PFP组PDA)中,我们传递的作为第一个种子的用户地址,选择了我们传递的作为第二个种子的头像。

这个示例可以被进一步扩展,以创建更深层次的哈希映射结构。

PDA作为哈希映射程序流程 - NFT示例PDA作为哈希映射程序流程 - NFT示例

3. 跨程序调用

跨程序调用(CPI)是一个程序调用另一个程序中的函数的过程。CPI很有用,因为它们允许更好的代码组合性。

回到我们的示例,假设用户想将他们的头像从一个Degen Ape更改为一个Solana Monkey Business头像。

以下是后台发生的事情:

在登录他们的钱包时,核心合约将获取用户的地址(公钥)并查找已经创建的PDA,其种子包括用户的公钥。

找到后,核心程序将调用PFP程序中的一个名为‘changePFP()’的函数(这是一个跨程序调用),它将已经被核心程序“选择”的PDA作为参数。

一旦调用此函数,选定的PDA将检查请求更改的账户是否为其父程序。如果PDA不匹配,则交易将被拒绝,因为只有父程序可以修改PDA的数据。

由于PFP程序是选定PDA的父程序,因此它将被允许将用户的选定头像从Degen Ape更改为SMB头像。

使用PDA跨程序调用 - 更改NFT图像使用PDA跨程序调用 - 更改NFT图像

程序派生地址允许其父程序代表它签署,并可用于存储程序的状态、哈希映射和跨程序调用。PDAs是Solana编程领域的基础主题,能够实现快速高效的dApp开发。

程序派生地址常见问题

在使用程序派生地址时,了解Solana如何处理交易和数据可能会有所帮助。两种主要类型的账户是可执行账户和非可执行账户。

什么是可执行账户?

可执行账户,也称为程序,类似于以太坊智能合约 — 一段在账户与其交互时改变其状态的代码。

什么是非可执行账户?

非可执行数据账户仅用于存储数据(例如,账户拥有的SOL数量、NFT、代币余额等),本质上是程序的状态变量。

Solana程序数据存储与以太坊智能合约有什么不同?

以太坊和Solana之间的一个基本区别在于可执行代码的存储方式。以太坊上的智能合约是“预构建”的,带有存储,存储智能合约存储的所有状态变量。相比之下,Solana上的程序没有预构建的存储,但它们有单独的数据账户,用于保存它们想要存储和引用的各种状态变量。

  • 原文链接: alchemy.com/overviews/pr...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Alchemy
Alchemy
江湖只有他的大名,没有他的介绍。