Solana开发必备基本概念

Solana 开发者文档中有很多术语和解释,但我们不需要了解所有这些来开始开发。本文将介绍Solana的常见术语和开发涉及的关键数据结构。

Solana开发必备基本概念
一键发币: SOL | BNB | ETH | BASE | Blast | ARB | OP | POLYGON | AVAX | FTM | OK

Solana 开发者文档中有很多术语和解释,但我们不需要了解所有这些来开始开发。 Solana 智能合约也称为链上程序(on-chain program)。 与 EOS 等其他链运行的 WebAssembly 字节码不同,Solana 的可执行文件是 BPF 字节码,它将由 Solana 节点运行时加载并执行。

那么我们如何生成BPF字节码呢? 我们需要可以生成 BPF 字节码的编译器。 通常,LLVM 可以将 C 和 Rust 编译为 BPF 字节码。 由于 Solana 是建立在 Rust 之上的,所以这里我们也使用 Rust 作为示例。

1、基本术语

以下列出Solana模型中常见的基本术语:

  • 交易

交易(transaction)用于向 Solana 节点发送请求。 一个交易可能包含多个指令(instruction)。 节点收到交易后,会解析指令,并根据每条指令传递的program_id参数调用相关的链上程序。

  • 指令

指令(instruction)是Solana节点执行的最小单元:

Dapp 将序列化的程序参数和账户信息发送到 Solana 节点,Solana 节点找到相关的链上程序并将数据发送给程序,然后程序将其反序列化并使用参数执行命令。

  • 帐户

Solana 链上资源包括 RAM、文件、CPU(计算预算)等,与 EOS 的 RAM 和 CPU 不同。 Solana 定义了每个程序可以使用的最大数量,例如堆栈大小(4MB)、CPU 时间(200,000BPF)、栈深度(64)等。因此我们不会看到程序竞争资源。

链上保存的每条信息都是一个文件。在 Solana 中,人们总是对帐户(account)和文件(file)感到困惑,它们实际上是同一件事,就像在 Unix 中一样,一切都是文件。 所以人们需要为文件空间支付SOL。 如果你想关闭一个文件,只需将该文件的所有 SOL 转出即可,因为无需支付该文件的空间费用。

  • 运行时

正如我们之前提到的,Solana 运行时(runtime)运行 BPF 字节码,你可能想知道为什么它选择 BPF,而不是 WebAssembly,或者 Lua、python ?

我认为最主要的原因是性能,TPS始终是Solana的第一优先级,而BPF运行时消耗的资源较低。 程序内资源的限制可以在Solana SDK中找到。

pub struct BpfComputeBudget {
    /// Number of compute units that an instruction is allowed.  Compute units
    /// are consumed by program execution, resources they use, etc...
    pub max_units: u64,
    /// Number of compute units consumed by a log call
    pub log_units: u64,
    /// Number of compute units consumed by a log_u64 call
    pub log_64_units: u64,
    /// Number of compute units consumed by a create_program_address call
    pub create_program_address_units: u64,
    /// Number of compute units consumed by an invoke call (not including the cost incurred by
    /// the called program)
    pub invoke_units: u64,
    /// Maximum cross-program invocation depth allowed including the original caller
    pub max_invoke_depth: usize,
    /// Base number of compute units consumed to call SHA256
    pub sha256_base_cost: u64,
    /// Incremental number of units consumed by SHA256 (based on bytes)
    pub sha256_byte_cost: u64,
    /// Maximum BPF to BPF call depth
    pub max_call_depth: usize,
    /// Size of a stack frame in bytes, must match the size specified in the LLVM BPF backend
    pub stack_frame_size: usize,
    /// Number of compute units consumed by logging a `Pubkey`
    pub log_pubkey_units: u64,
}

2、关键数据结构

下面列出Solana开发中常见的关键数据结构:

  • Pubkey

Pubkey(公钥)代表一个Base58格式的账户地址,同样在指令中ProgramId也是同样的格式,就像我们之前说的链上程序是一个和账户一样的文件,唯一的区别是它是可执行的。

#[repr(transparent)]
#[derive(
    Serialize, Deserialize, Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd, Hash, AbiExample,
)]
pub struct Pubkey([u8; 32]);]
  • AccountInfo

AccountInfo(账户信息) 是我们在链上存储帐户的方式。 你还可以将这些属性视为文件属性:

/// Account information
#[derive(Clone)]
pub struct AccountInfo<'a> {
    /// Public key of the account
    pub key: &'a Pubkey,
    /// Was the transaction signed by this account's public key?
    pub is_signer: bool,
    /// Is the account writable?
    pub is_writable: bool,
    /// The lamports in the account.  Modifiable by programs.
    pub lamports: Rc<RefCell<&'a mut u64>>,
    /// The data held in this account.  Modifiable by programs.
    pub data: Rc<RefCell<&'a mut [u8]>>,
    /// Program that owns this account
    pub owner: &'a Pubkey,
    /// This account's data contains a loaded program (and is now read-only)
    pub executable: bool,
    /// The epoch at which this account will next owe rent
    pub rent_epoch: Epoch,
}

key是这个文件的id,是一个base58地址;lamports代表文件空间的租金费用,所以lamports不能为0,0表示文件被关闭;is_writable代表这是一个可执行文件(程序)或一个普通帐户;data存储文件的内容,是二进制数据的缓冲区。 每个文件/帐户都是由称为所有者(owner)的程序创建的。

  • ProgramResult

ProgramResult(程序结果) 是 ProgramError 类型的结果,它被定义为运行时抛出的错误的枚举。 如果程序运行良好,我们调用 Ok() 来得到正确的结果,如果出现问题,我们返回 ProgramError

/// Reasons the program may fail
#[derive(Clone, Debug, Deserialize, Eq, Error, PartialEq, Serialize)]
pub enum ProgramError {
    /// Allows on-chain programs to implement program-specific error types and see them returned
    /// by the Solana runtime. A program-specific error may be any type that is represented as
    /// or serialized to a u32 integer.
    #[error("Custom program error: {0:#x}")]
    Custom(u32)
    ...
}use std::{
    result::Result as ResultGeneric,
};
pub type ProgramResult = ResultGeneric<(), ProgramError>;
  • AccountMeta(账户元数据)

账户元数据(AccountMeta)主要用在指令中,传入账户地址、该账户是否是签名者、内容是否可写等信息。

/// Account metadata used to define Instructions
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct AccountMeta {
    /// An account's public key
    pub pubkey: Pubkey,
    /// True if an Instruction requires a Transaction signature matching `pubkey`.
    pub is_signer: bool,
    /// True if the `pubkey` can be loaded as a read-write account.
    pub is_writable: bool,
}

3、结束语

操作 Solana 程序更像是对文件进行 CRUD 操作。 在下一个教程中,我们将展示一些实现这些操作的常见方法。


原文链接:Solana Development Tutorial: Key Concepts

DefiPlot翻译整理,转载请标明出处

通过 NowPayments 打赏