文章详细介绍了 Solana 中的系统变量(sysvars),包括如何通过 Anchor 框架访问这些变量,以及它们的功能和使用场景。
在 Solana 中,sysvar 是只读系统账户,它们使 Solana 程序能够访问区块链状态和网络信息。它们类似于 Ethereum 的全局变量,这些变量也使智能合约能够访问网络或区块链状态信息,但它们具有类似于 Ethereum 预编译的唯一公共地址。
在 Anchor 程序中,你可以通过两种方式访问 sysvars:要么使用 anchor 的 get 方法包装,或者将其视为你的 #[Derive(Accounts)]
中的账户,使用其公共地址。
并非所有 sysvars 都支持 get
方法,并且其中一些已被弃用(关于弃用的信息将在本指南中指定)。对于没有 get
方法的 sysvars,我们将使用其公共地址进行访问。
slot 是一个时间窗口(大约 400 毫秒),在该窗口中,指定的领导者可以生成一个区块。一个 slot 包含一个区块(与 Ethereum 上相同类型的区块,即交易列表)。然而,如果区块领导者未能在该 slot 产生区块,则该 slot 可能不包含区块。其关系如下图所示:
尽管每个区块映射到恰好一个 slot,但区块哈希与 slot 哈希并不相同。当你在浏览器中单击一个 slot 编号时,则会打开带有不同哈希的区块详细信息,这一区别是显而易见的。
让我们看下图中来自 Solana 区块浏览器的一个例子:
图片中高亮的绿色数字是 slot 编号 237240962 ,而高亮的黄色文本是 slot 哈希 DYFtWxEdLbos9E6SjZQCMq8z242Yv2bVoj6dzwskd5vZ。下面高亮的红色的区块哈希是 FzHwFHDAXJBc55rpjShznGCBnC7DsTCjxf3KKAk6hk9T。
(其他区块详细信息已被裁剪):
我们可以通过它们独特的哈希来区分区块和 slot,即使它们具有相同的数字。
作为测试,点击浏览器中的任何 slot 编号 在这里,你会注意到将打开一个区块页面。此区块的哈希将与 slot 哈希不同。
如前所述,并非所有 sysvars 都可以使用 Anchor 的 get
方法进行访问。诸如 Clock、EpochSchedule 和 Rent 之类的 sysvars 可以通过此方法访问。
虽然 Solana 文档将 Fees 和 EpochRewards 列为可以通过 get
方法访问的 sysvars,但在最新版本的 Anchor 中这些已被弃用。因此,无法通过 get
方法在 Anchor 中调用它们。
我们将使用 get
方法访问并记录所有当前支持的 sysvars 的内容。首先,我们创建一个新的 Anchor 项目:
anchor init sysvars
cd sysvars
anchor build
要利用 Clock sysvar,我们可以调用 Clock::get()
(我们在之前的教程中做过类似的事情)方法,如下所示。
在我们项目的初始化函数中添加以下代码:
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
// 获取 Clock sysvar
let clock = Clock::get()?;
msg!(
"clock: {:?}",
// 获取 Clock sysvar 的所有详细信息
clock
);
Ok(())
}
现在,运行对本地方的 Solana 节点的测试并检查日志:
在 Solana 中,纪元是大约两天的时间段。SOL 只能在纪元开始时质押或解除质押。如果你在纪元结束之前质押(或解除质押)SOL,则该 SOL 被标记为“激活”或“停用”,同时等待纪元结束。
Solana 在其关于 委托 SOL 的描述中详细说明了这一点。
我们可以使用 get
方法访问 EpochSchedule sysvar,类似于 Clock sysvar。
更新初始化函数,添加以下代码:
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
// 获取 EpochSchedule sysvar
let epoch_schedule = EpochSchedule::get()?;
msg!(
"epoch schedule: {:?}",
// 获取 EpochSchedule sysvar 的所有详细信息
epoch_schedule
);
Ok(())
}
再次运行测试,将生成以下日志:
从日志中,我们可以观察到 EpochSchedule sysvar 包含以下字段:
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!