前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >写给Solidity开发者的Solana入门指南

写给Solidity开发者的Solana入门指南

作者头像
Tiny熊
发布2022-11-07 10:17:00
1.3K0
发布2022-11-07 10:17:00
举报
文章被收录于专栏:深入浅出区块链技术

译文出自:登链翻译计划[1] 译者:Tiny 熊[2]

如果你熟悉以太坊和 Solidity,你可能有兴趣涉足 Solana 生态系统。Solana 的快速区块链很有前景,也很令人兴奋。另外也增加了对 web3 知识的认知。

但是,如果你从来没有见过 Solana 程序,它的语法是非常可怕的,而且文档看起来就像一个开发者的重复性笔记。它没有连贯性,你要到后面的章节才会明白某些部分。

这就是为什么我写“ 给 Solidity 开发者的 Solana 开发之路系列”的原因,我会向你温和地、没有痛苦和挫折地介绍 Solana。这篇介绍 以太坊与 Solana 的编程模型比较,基本上它只是在 ETH 与 SOL 中如何写程序的概念性差异。

我们不会去讨论 Solana 在背后是如何工作,比如它的历史证明(POH)等等。这将是另一篇文章的内容。

以下是这篇文章的大纲:

  • 以太坊与 Solana 存储状态的不同
  • Solana 账户
  • 程序衍生地址(Program Derived Addresses)

以太坊与 Solana 存储状态的不同

在以太坊中,你习惯于将状态直接存储在智能合约中。看一下这个简单的合约(使用 Solidity[3] 编写):

代码语言:javascript
复制
contract EthereumExample {
  struct Author {
    uint256 publications;
    uint256 likes;
  }

  Author public author;

  function publish() public {
      author.publications += 1;
  }
}

它只是存储了一个变量author,并有一个辅助的publish函数来改变author这个变量。当你部署这个合约,代码和它的状态一起被存储在一个地址。你可以使用该地址来引用合约并读取其数据(例如,在 Etherscan 上)。

但 Solana 是不同的。

Solana 合约是无状态的。把它们想象成只是指令。他们不存储任何数据/状态。那么,数据存储在哪里呢?它被存储在独立的 账户中。账户持有数据。当你调用 Solana 合约的函数时,你需要把数据传给函数。

因此,上面的publish函数需要一个对存储数据的账户的引用。该函数将增加出版物的数量,但作者变量仍将存储在同一个账户中(而不是在合约中)。合约的状态并没有改变。如果你熟悉 Java,Solana 合约就像 Java 中的静态类。

BTW,智能合约在 Solana 中被称为程序(programs)。

下面是上面的简单合约在 Solana 中的样子:

代码语言:javascript
复制
#[program]
pub mod solana_example {
    use super::*;
    pub fn publish(ctx: Context<AuthorData>) -> ProgramResult {
        let author_account = &mut ctx.accounts.author_account;
        author_account.publications += 1;
        Ok(())
    }
}

#[derive(Accounts)]
pub struct AuthorData<'info> {
    #[account(mut)]
    pub author_account: Account<'info, AuthorAccount>,
}

#[account]
pub struct AuthorAccount {
    pub publications: u64,
    pub likes: u64,
}

注意数据是如何存储在一个单独的AuthorAccount中的,这个数据是通过引用传递到publish函数中的(通过Context)。solana_example程序本身并不存储任何东西。它只是对传入的数据进行操作。(AuthorData有点像一个包装器,需要把AuthorAccount传给publish函数)。

这个语法很吓人,我知道。这就是 Rust 和 Anchor(Solana 框架)。这让我想起了我开始开发 iOS 和第一次遇到 Objective C 的日子。别担心,我们将在之后的文章中更详细地研究这个语法。它将会更有意义,我保证。

将代码与数据分开,使程序的升级变得容易。在 Solana 中,有可能将一个新版本的程序重新部署到同一地址,同时重复使用相同的数据账户--在不损失数据的情况下进行升级。(这在以太坊中更难做到)。

Solana 账户

账户是一个模棱两可的词。它在不同的语境中意味着很多东西。在 Solana 中,一个账户只是意味着一个存储单元。它只是一个存储任意数据的容器。

有 2 种类型的账户:首先是 数据账户,它只是为程序存储数据,如我们已经提到的 AuthorAccount。第二种类型是 程序账户,用于 托管程序的代码。当你在 Solana 上部署一个程序时,它的代码被存储在一个 程序账户中。

一个例子:如果你有一个计数器程序,让你增加一个计数器,你必须创建两个账户:一个账户存储程序的代码,一个账户存储计数器的值。

账户有公钥/地址,以便能够引用它们,它们有私钥,用于签名以证明修改账户的权限(authority)

authority这个词在 Solana 世界中使用得相当多。它只是意味着所有者(owner)--私钥的持有人。

账户也存储余额,Solana 余额。Solana 的原生货币单位是 SOL 和 Lamport(为纪念 Solana 最大的技术影响者Leslie Lamport[4]而命名)。1 SOL = 10⁹ Lamports。他们和 ETH 和 Wei 类似。

为了创建一个账户,Solana 需要在其存储上分配空间。Solana 的存储空间不是免费的,所以创建一个账户也不是免费的。你需要向 Solana 支付租金来 托管账户。但是不要担心。如果你把 2 年的租金存入你的账户,你就可以免去租金。每个人都只是这样做,所以在 Solana 上的存储基本上是免费的。

以下是一个 Solana 账户中存储的所有内容的摘要:

来自 Solana wiki[5]

data字段要么存储代码,要么存储任意数据,取决于账户是否是可执行(executable)。我们将在稍后讨论owner字段。

以太坊也有 2 种类型的账户:

  • 外部拥有账户 - 普通账户,可以由钱包软件生成(只需要生成一个私钥,然后导出公钥和地址,你就有一个账户)。这些账户只是存储余额和 nonce。
  • 智能合约账户 - 这些存储 EVM 代码,还有一个存储型 map,可用于存储任意数据。

以下是存储在以太坊账户中的内容,供比较:

来自 Solana wiki[6]

codeHash是用来存储代码的,storageRoot是用来存储任意数据的。对于不可执行的账户,storageRoot被设置为一个特殊的 null哈希值,表示该账户没有存储。

在以太坊中,只有 “可执行账户"有存储。但在 Solana 中,所有账户都可以存储数据。然而,可执行账户数据专门用于不可变的字节码。所有其他数据都存储在非可执行账户中,非可执行账户是由可执行账户拥有的。

现在,让我们来谈谈 Solana 账户的owner(所有者)字段:

为了确保合约不能修改另一个合约的状态,每个数据账户都指定了一个所有者程序,该程序对状态更改有独占控制权。默认情况下,所有者程序是 Solana 的系统程序(有点像一个操作系统)。

除了所有者之外,没有人可以修改数据账户的状态。任何人都可以把钱存入账户,但只有所有者可以提取余额。

在这一点上,你知道程序(programs)和账户在 Solana 上的工作。但是,在 Solana 中有一个小尴尬,在以太坊中是没有的。

想象一下,你在 Solana 上部署了一个程序,你也在 AWS 上部署了一个传统的 web2 前端,用于与该程序进行交互。每次你调用程序时,你需要传入数据账户(以修改状态)。你需要拥有数据账户的私钥,以便能够改变数据账户的状态。

钥匙的管理落在你身上。你打算把它储存在哪里?在 web2 服务器中作为环境变量?这不太像 web3 的做法。最好是把这个密钥存储在程序本身,使其更像以太坊--一种将存储附加到程序的方式。

程序衍生地址(PDA)解决了这个问题。

程序衍生地址(PDA)

PDA(Program Derived Addresses)本质上允许你将一个数据存储账户附加到一个无状态的程序账户。一种使 Solana 类似以太坊的方式。

它是如何工作的?在程序中,你只是从程序控制的变量中生成一个地址。这就成为一个衍生账户(一个程序衍生的地址)。Solana 操作系统提供了一个辅助函数来推导这个地址。

更具体地说,PDA 是由一个程序 ID 和一个种子集合衍生的。程序 ID 是 Solana 程序的地址。种子可以由程序任意选择(我们将看到种子的用处)。

这个过程是确定的:种子和程序 ID 的组合通过 sha256 哈希函数运行,看它们是否产生一个位于椭圆曲线上的公钥(产生的公钥有~50%位于椭圆曲线上)。如果它确实位于椭圆曲线上,我们只需添加一些东西,对我们的输入进行一些修改,然后再试一次。这个模糊因素的技术术语是 凸点。在 Solana 中,我们从 bump = 255开始,然后简单地向下迭代 bump = 254bump = 253,等等,直到我们得到一个不在椭圆曲线上的地址。

**位于椭圆曲线上是什么意思**?当一个公钥位于椭圆曲线上时,意味着存在一个相应的私钥,可以使整个私钥加密算法工作。

有一个叫 findProgramDerivedAddress的函数将整个过程抽象化了。

嗯,这里有很多技术上的东西。如果我把你弄糊涂了,你只需要理解:PDA 是基本上由程序 ID 和一些种子生成的,这样产生的地址就没有相应的私钥。

现在,这个 PDA 对于给 Solana 程序附加存储有什么用?

PDA 解决了几件事:

  • 不需要管理/跟踪存储账户的私钥。只需从程序中导出一个地址,并将该地址/账户作为存储。你如何确保其他人不会修改衍生账户?因为衍生地址没有相应的私钥。所以没有人可以修改这个账户。Solana 操作系统确保只有程序被允许修改 PDA。你如何确保其他程序不能衍生出相同的 PDA?他们不能,因为他们的程序 ID 是不同的。
  • PDA 也可以用来在独立的账户中存储用户的特定信息。这就是种子变得有用的地方。一个常见的做法是使用最终用户的公钥作为种子生成 PDA,允许程序将该用户的信息存储在自己的独立账户中。程序可以通过使用不同的种子来确定地得出任何数量的地址。这些种子可以象征性地确定地址的使用方式。例如,你可以使用用户的公钥和一个代币的符号作为种子,得到一个用于存储用户关于特定代币信息的账户(每个用户和每个代币将有一个新的 PDA 账户)。

总结一下,PDA 只是一个账户,其所有者是一个程序,PDA 不像其他账户那样有私钥由于没有相关的私钥,外部用户不能为 PDA 生成有效的签名。只有其种子推导 PDA 的程序可以控制它 -- 这是 Solana OS 的强制要求。

作为写给 Solidity 开发者的 Solana 入门指南,本文关于 以太坊的编程模型差异就到此为止了。


本翻译由 Duet Protocol[7] 赞助支持。

原文:https://betterprogramming.pub/getting-started-with-solana-for-solidity-developers-ee97a9bdf7ed

参考资料

[1]

登链翻译计划: https://github.com/lbc-team/Pioneer

[2]

Tiny 熊: https://learnblockchain.cn/people/15

[3]

Solidity: https://learnblockchain.cn/docs/solidity/

[4]

Leslie Lamport: https://en.wikipedia.org/wiki/Leslie_Lamport

[5]

wiki: https://solana.wiki/zh-cn/docs/account-model/

[6]

wiki: https://solana.wiki/zh-cn/docs/account-model/

[7]

Duet Protocol: https://duet.finance/?utm_souce=learnblockchain

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-07-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 深入浅出区块链技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 以太坊与 Solana 存储状态的不同
  • Solana 账户
  • 程序衍生地址(PDA)
    • 参考资料
    相关产品与服务
    对象存储
    对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档