Solana 60 天课程

2025年02月27日更新 66 人订阅
原价: ¥ 28 限时优惠
专栏简介 开始 Solana - 安装与故障排除 Solana 和 Rust 中的算术与基本类型 Solana Anchor 程序 IDL Solana中的Require、Revert和自定义错误 Solana程序是可升级的,并且没有构造函数 Solidity开发者的Rust基础 Rust不寻常的语法 Rust 函数式过程宏 Rust 结构体与属性式和自定义派生宏 Rust 和 Solana 中的可见性与“继承” Solana时钟及其他“区块”变量 Solana 系统变量详解 Solana 日志、“事件”与交易历史 Tx.origin、msg.sender 和 onlyOwner 在 Solana 中:识别调用者 Solana 计算单元与交易费用介绍 在 Solana 和 Anchor 中初始化账户 Solana 计数器教程:在账户中读写数据 使用 Solana web3 js 和 Anchor 读取账户数据 在Solana中创建“映射”和“嵌套映射” Solana中的存储成本、最大存储容量和账户调整 在 Solana 中读取账户余额的 Anchor 方法:address(account).balance 功能修饰符(view、pure、payable)和回退函数在 Solana 中不存在的原因 在 Solana 上实现 SOL 转账及构建支付分配器 使用不同签名者修改账户 PDA(程序派生地址)与 Solana 中的密钥对账户 理解 Solana 中的账户所有权:从PDA中转移SOL Anchor 中的 Init if needed 与重初始化攻击 Solana 中的多重调用:批量交易与交易大小限制 Solana 中的所有者与权限 在Solana中删除和关闭账户与程序 在 Anchor 中:不同类型的账户 在链上读取另一个锚点程序账户数据 在 Anchor 中的跨程序调用(CPI)

Solana 计算单元与交易费用介绍

  • RareSkills
  • 发布于 2024-02-25 17:25
  • 阅读 1078

文章详细介绍了Solana区块链中的计算单元(Compute Units)概念,与以太坊的gas机制进行了对比,并探讨了计算单元的优化策略及其对交易费用的影响。

Solana 计算单元

在以太坊中,交易的价格计算为 $\text{gasUsed} \times \text{gasPrice}$。这告诉我们,将交易包含在区块链中将花费多少 Ether。在发送交易之前,会指定并预付 gasLimit。如果交易用尽了 gas,它将被回滚。

与 EVM 链不同,Solana 的操作码/指令消耗的是“计算单元”(可以说是一个更好的名称),而不是 gas,每笔交易的软上限为 200,000 个计算单元。如果交易消耗的计算单元超过 200,000,它将被回滚。

在以太坊中,计算所需的 gas 成本与存储相关的 gas 成本是相同的。在 Solana 中,存储的处理方式不同,因此 Solana 中持久化数据的定价是一个不同的讨论话题。

然而,从运行操作码的定价角度来看,以太坊和 Solana 的行为是相似的。

两条链都执行编译后的字节码,并对每条执行的指令收取费用。以太坊使用 EVM 字节码,但 Solana 运行的是 Berkeley Packet Filter 的修改版本,称为 Solana Packet Filter。

以太坊根据执行时间的长短对不同操作码收取不同的费用,范围从 1 gas 到数千 gas。在 Solana 中,每个操作码消耗 1 个计算单元。

当计算单元不足时该怎么办

在执行无法在限制内完成的重计算操作时,传统策略是“保存你的工作”并在多个交易中完成。

“保存你的工作”部分需要放入永久存储中,这是我们尚未涉及的内容。这类似于在以太坊中尝试遍历一个巨大的循环;你会有一个存储变量来保存你离开时的索引,以及一个存储变量来保存到该点为止的计算结果。

计算单元优化

正如我们所知,Solana 使用计算单元来防止停机问题,并防止运行永远执行的代码。每笔交易的计算单元限制为 200,000 CU(可以以额外成本增加到 1.4m CU),如果超过(选择的限制),程序将终止,所有更改的状态将回滚,费用不会退还给调用者。这可以防止攻击者意图在节点上运行永不结束或计算密集型的程序以减慢或停止链。

然而,与 EVM 链不同,交易中使用的计算资源不会影响为该交易支付的费用。无论你使用了整个限制还是只使用了很少的一部分,你都将被收取相同的费用。例如,400 计算单元的交易与 200,000 计算单元的交易费用相同。

除了计算单元之外,Solana 交易的签名者数量也会影响计算单元成本。根据 Solana 文档

“目前,交易费用仅由交易中需要验证的签名数量决定。交易中签名数量的唯一限制是交易本身的最大大小。交易中的每个签名(64 字节)(最大 1232 字节)必须引用一个唯一的公钥(32 字节),因此单个交易最多可以包含 12 个签名(不确定为什么要这样做)。”

我们可以通过这个小例子看到这一点。从一个空的 Solana 程序开始:

use anchor_lang::prelude::*;

declare_id!("6CCLqLGeyExCFegJDjRDirWQRRSbM5XNq3yKvmaWS2ZC");

##[program]
pub mod compute_unit {
    use super::*;

    pub fn initialize(_ctx: Context<Initialize>) -> Result<()> {
        Ok(())
    }
}

##[derive(Accounts)]
pub struct Initialize {}

更新测试文件:


import * as anchor from "@coral-xyz/anchor";
import { Program } from "@coral-xyz/anchor";
import { ComputeUnit } from "../target/types/compute_unit";

describe("compute_unit", () => {
  // 配置客户端以使用本地集群。
  anchor.setProvider(anchor.AnchorProvider.env());
  const program = anchor.workspace.ComputeUnit as Program<ComputeUnit>;
  const defaultKeyPair = new anchor.web3.PublicKey(
    // 将此替换为你的默认提供者密钥对,你可以通过在终端中运行 `solana address` 来获取它
    "EXJupeVMqDbHk7xY4XP4TVXq22L3ZJxJ9Gm68hJccpLp"
  );

  it("Is initialized!", async () => {
    // 记录密钥对的初始余额
    let bal_before = await program.provider.connection.getBalance(
      defaultKeyPair
    );
    console.log("before:", bal_before);

    // 调用我们程序的初始化函数
    const tx = await program.methods.initialize().rpc();

    // 记录密钥对的余额之后
    let bal_after = a...

剩余50%的内容订阅专栏后可查看

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论