Solana/账户模型/租赁与租赁豁免机制

在 solana 上, 每个账户都要消耗存储空间, 而这些空间背后是集群中的节点在为您存数据. 所以, solana 设计了一个租赁机制: 您要为您在链上存的每一字节数据付租金. 但又因为频繁续租太麻烦, 也设计了租赁豁免制度.

租赁

Solana 的账户不是免费的, 它占用存储资源, 而节点们要保存这些数据. 因此, solana 要求每个账户必须有一部分 sol 用作数据存储租金.

这套机制的核心规则是:

  • 账户存储数据越多, 占用的空间越大, 所需的租金也越多.
  • 租金是预付的, 按照一定周期定时从您的账户中扣款.
  • 如果账户余额不足, 或者长期空着不用, 系统可以把它回收掉.

这笔租金实际上是您存在账户余额里的一部分 sol, solana 运行时会根据当前租金费率计算出租期.

设计租赁机制的根本原因是为了防止账户垃圾, 这些垃圾账户可能被有意或无意的创建:

  • 用户创建大量空账户, 从不清理.
  • 合约部署后遗留无用数据.
  • 程序错误导致堆积大量临时账户.

如果账户没有成本, 链上的状态会无限膨胀, 最终影响性能和稳定性. 通过租赁机制, solana 迫使用户对链上状态负责, 用经济手段做资源管理.

租赁豁免

Solana 也知道频繁续租会很麻烦, 所以它设计了租赁豁免机制: 只要您账户里的 sol 足够多, 超过一个阈值, 系统就默认您预付了永久租金, 您的账户就不会被回收了.

假设您创建了一个数据账户, 占用了 100 字节. 系统会根据当前的租金费率算出一笔豁免租金, 比如 0.002 sol. 您只要在账户里放进去这 0.002 SOL, 系统就视作豁免, 系统永远不会向您再收租, 您的账户也永远不会被删掉.

这套机制设计得非常实用, 带来了几个好处:

  • 开发者不需要给账户设置租期, 续租逻辑.
  • 用户不需要关心账户什么时候过期.
  • 合约运行更加稳定.

Solana 从一开始就采用了租赁和租赁豁免并存的机制. 但在 simd-0084 提案中, 开发团队提出移除周期性租金收取机制. 根据 solana stack exchange 上的讨论, 这一变更于 2023 年 12 月 6 日前部署完成.

因此, solana 已经彻底移除了对租金收取的实际处理逻辑. 也就是说: 租金仍然作为一个概念存在于 solana 网络中, 但系统已经不会再周期性地收取租金或因为账户余额不足而删除账户. 实际上, 现在所有账户都相当于租赁豁免, 只要创建出来了就不会被删.

事实上, 我花了很多时间确认了这一修改的真实性. 请注意, solana 官方文档以及他人的博客文章可能仍包含部分过时信息, 建议结合上述社区讨论和提案确认最新状态.

租赁周期

从技术上讲, 每个账户都会记录自己的上次租金计费时间和余额. Solana 每个 epoch(大概两天)会进行一次租金结算. 如果某个账户没达到豁免门槛, 长期没有被访问, 且余额又不足以继续支付租金, 那它就可能被标记为"可清除", 节点会对账户数据进行清理, 释放状态空间.

如果您是程序开发者, 一般只要给数据账户设置成"租赁豁免", 后续就不用管它了.

请注意, 周期性租金收取的实际处理逻辑已经从 solana 网络里彻底移除.

租赁豁免资金计算

账户初始化时就要考虑豁免金额. 您需要提前估算账户空间大小, 并把足够的 sol 存进去. 租赁费率由 solana 网络实时计算, 您可以通过 get_minimum_balance_for_rent_exemption rpc 接口来获取当前存储指定大小的数据时需要的租赁豁免资金数量.

例: 如果小明要在账户中存储 100 字节的数据, 他需要的租赁豁免资金是多少?

答: 当前需要 1586880 lamport. 注意这个值可能会随着时间而发生变动.

import pxsol

print(pxsol.rpc.get_minimum_balance_for_rent_exemption(100, {}))
# 1586880

开发者要注意的细节

Solana 的账户租赁机制是为了控制状态存储成本, 让链上的数据有代价的存储. 同时, 为了开发方便, 又引入了租赁豁免机制, 只要您存够了钱, 就可以让账户永久保留.

对开发者来说, 最重要的是在初始化账户时正确设置余额, 以达成租赁豁免.