跟我一起从0开始学习Solana合约开发,一起实操,一起做项目。这是一个系列文章,系统地记录了我的学习笔记。
本文是对Solana官网文档的翻译。我会根据我的实操对原文修改,并且针对初学者不容易理解的地方做了更多的翻译。
在 Solana 中,所有的数据都存储在账户里。你可以把账户(accounts)类比为一个键值对数据库
。如下图所示:
账户最大可以存储 10MB
的数据,这些数据由可执行程序代码
(编译后的程序字节码)或程序状态
(程序用到的数据)组成。
账户需要用 SOL(Solana 原生代币)来支付租金,根据存储的数据量按比例收取,当账户关闭时,这个租金可以全额退回。
租金的机制可以防止过多的存储资源被长期占用,有助于减少 Solana 网络上的垃圾数据和不必要的存储占用。
每一个账户都有一个 程序所有者(owner)
。只有程序(owner)
可以修改账户的数据和扣除账户的余额,任何人都可以增加账户的余额。
这个
程序所有者
的意思是:账户的所有权掌握在程序
手里,而不是人(钱包)的手里,这个概念第一次不容易理解,先有个印象,等到实操多了,慢慢就掌握了。
程序(智能合约)是存储可执行代码的无状态
账户。
数据账户是由程序创建的,用于存储和管理程序的状态。
原生程序是随 Solana 运行时一同提供的内置程序。
原生程序是内置在 Solana 运行时中的程序,处理账户创建、资金转移等基本功能。创建账户和构建基于代币的应用都需要依赖这些原生程序。
Sysvar 账户是用于存储网络集群状态的特殊账户。
Sysvar 账户存储与网络状态相关的只读信息,比如区块时间戳等。
每一个账户都对应一个唯一地址,这个地址以 32 字节的 Ed25519 公钥格式表示。
账户和地址之间的关系可以看作是一个键值对,其中地址作为键,用于定位账户在链上的对应数据。
账户的最大大小为 10MB(10 兆字节),存储在 Solana 上的每个账户的数据具有以下结构,被称为 AccountInfo。
我们解释下每个字段:
data
: 是一个字节数组,用于存储账户的状态。如果账户是一个程序(智能合约),则它存储可执行的程序代码。这个字段通常被称为“账户数据”(account data)。
executable
: 是一个布尔标志,用于指示该账户是否是一个程序(智能合约)。
lamports
: 是一个数字,表示账户的余额,以 lamports 为单位,lamports 是 SOL 的最小单位(1 SOL = 10亿 lamports)。可以类比为以太坊的 wei。
owner
: 是一个公钥(Program ID),这个公钥对应的程序拥有这个账户。
作为Solana账户模型的关键部分,Solana上的每个账户都有一个指定的“所有者”,通常是一个程序。只有被指定为账户所有者的程序才能修改账户上存储的数据或扣除账户中的lamport余额。需要注意的是,虽然只有所有者可以扣除余额,但任何人都可以增加账户的余额。
提示
为了将数据存储在链上,必须将一定数量的SOL转移到账户中。转移的金额与存储在账户中的数据大小成正比。这个概念通常被称为“租金”(rent)。然而,你可以把“租金”看作是一个“押金”,因为分配给账户的SOL在账户关闭时可以全部取回。
Solana包含了一些原生程序,这些程序是验证节点实现的一部分,并为网络提供各种核心功能。
在开发Solana程序时,通常与两个原生程序进行交互,即系统程序(System Program)
和BPF加载程序(BPF Loader)
。这两个程序是Solana网络中的关键组成部分,提供了基本的账户管理、内存分配等核心功能。
注意:当使用 rust 开发solana程序时,需要经常与原生程序直接交互。 如果你使用 anchor 框架开发,因为 anchor 已经封装好了这些功能,只关注业务逻辑即可,无需与原生程序直接交互。
默认情况下,所有新创建的账户都由 System Program 所拥有。System Program 执行多个关键任务:
新账户创建:只有 System Program 能够创建新账户。
空间分配:设置每个账户data
字段的字节容量。
分配程序所有权:一旦 System Program 创建了一个新账户,它可以将指定的程序所有者重新分配给另一个程序账户。一个新账户刚创建时,所有者都是系统程序,之后系统程序会把所有权转移,分配给用户自定义的程序。
在 Solana 中,“钱包”本质上是一个由系统程序(System Program)拥有的账户。钱包的 lamport 余额表示账户拥有的 SOL 数量。
提示
只有由系统程序(System Program)拥有的账户才能用作交易费用支付者。
BPF加载程序是 Solana 网络上所有其他程序(原生程序除外)的“拥有者(owner)”。它负责部署、升级以及执行用户自定义的程序。
Sysvar账户是预定义的特殊账户,提供对集群状态数据的访问。这些账户会动态更新网络集群的相关数据。
在 Solana 中,“智能合约”被称为程序(programs)。程序是一个包含可执行代码的账户,通过将“executable”标志设置为 true 来表示其为可执行程序。
用户自定义程序主要包括Program Account
和Data Account
。
在 Solana 上部署新程序时,在技术实现上,会创建三个独立的账户:
Program Account
: 这个是主账户,是代表了链上程序的账户。此账户存储可执行数据账户的地址
以及程序的更新权限
(即被授权对程序进行更改的地址)。
注意:可执行数据账户保存了已编译的程序代码,另外提醒初学者,要注意对比理解
可执行数据账户
和下一小节要讲的数据账户
,这是两个账户。
Program Executable Data Account
: 这个是可执行数据账户,一个包含程序可执行字节码的账户。
Buffer Account
: 这是一个临时账户,用作程序部署过程中使用的缓冲账户。当程序部署或升级时,字节码会被暂时保存到这个账户,直到部署或升级完成。之后,字节码数据会被转移到程序可执行数据账户,而该缓冲账户会被关闭。
下图展示了这个账户模型:
提示:
Program Account
的地址通常被称为Program ID
,它用于调用该程序。
Solana程序是“无状态”的,这意味着程序账户仅包含程序的可执行字节码。要存储和修改额外的数据,必须创建新的账户。这些账户通常被称为“数据账户”。
提示
在 Solana 中,程序代码 与 状态数据 是分开不同的账户存储的,这意味着 Solana 天生支持合约升级。这与以太坊的合约升级形成了鲜明的对比。
数据账户可以存储由其Owner程序
定义的任意数据。
注意,只有系统程序(System Program)可以创建新账户。一旦系统程序创建了一个账户,它就可以将该账户的所有权转移给另一个程序。
换句话说,为自定义程序创建数据账户,需要进行两个步骤:
1. 调用系统程序(System Program)来创建一个账户,并将账户的所有权转移给自定义程序。
2. 调用自定义程序(现在拥有该账户),然后初始化账户数据,这些数据由程序代码中定义。
这个数据账户创建过程通常被抽象为一个单独的步骤,但理解其中的底层流程是很有帮助的。
到这里,本文就讲完了。下一篇我们写代码来实际操作一下账户,帮助你巩固并理解这些理论。如果你想提前看到我的更新,可以关注我的公众号:认知那些事
。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!