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