Skip to main content

程序

任何开发者都可以在Solana链上编写以及部署程序。Solana程序(在其他链上叫做智能合约),是所有链上活动的基础。 链上的一切活动,从去中心化金融(DeFi),到非同质化代币(NFT),再到社交媒体,链上游戏,都由Solana程序所驱动。

info

tip 要点

  • 程序可以处理来自用户和其他程序的指令
  • 所有的程序都是无状态的:所有的和程序交互的数据都是存储在独立的账户中。执行时,这些账户借由指令传入程序
  • 程序本身存储在标记为executable(可执行)的账户中。
  • 任何程序的所有者都是BPF Loader and executed by the Solana Runtime
  • 开发者通常使用Rust或C++来编写程序,也可以采用任何其他可以编译为LLVMBPF后端的语言
  • 所有的程序都有一个单独的入口点,指令的执行就是从这里开始的(亦即process_instruction)。参数须包括:
    • program_id: pubkey (公钥)
    • accounts: array (数组)
    • instruction_data: byte array (字节数组)

深入

与其他链不同,Solana将代码与数据完全分开。 程序需要访问的全部数据都存储在独立的账户中,在指令中这些账户需要以引用的方式传入。 这种模式使得一个通用的程序可以在不同的账户上运行,而不用为此额外部署程序。 这种模式的例子很常见,包括了"原生程序"以及"SPL程序"等。

原生程序和Solana程序库(SPL)

Solana自带一系列程序,这些程序是链上交互的核心构成要素。 这些程序分为原生程序Solana程序库(SPL程序)

原生程序提供了运行验证节点(validator)所需的功能。原生程序中最广为人知的是System Program。 这个程序负责管理建立新账户以及在两个账户之间转账SOL。

SPL程序定义了一系列的链上活动,其中包括针对代币的创建,交换,借贷,以及创建质押池,维护链上域名解析服务等。 SPL Token Program(SPL代币程序)可以直接在命令行调用,其他的一些,如 Associated Token Account Program(关联代币账户程序), 则常被用于编写其他定制程序。

编写程序

编写Solana程序常用的是Rust和C++,但是也可以使用其他可以编译为LLVM的BPF后端的语言。 最近Neon LabsSolang发起了一个项目, 旨在建立Solana的EVM兼容性,进而让开发者可以使用Solidity编写程序。

大部分Rust编写的程序遵循以下架构:

文件描述
lib.rs注册模块
entrypoint.rs程序的入口点
instruction.rs程序的API, 对指令的数据进行序列化与反序列化
processor.rs程序的业务逻辑
state.rs程序对象,对状态进行反序列化
error.rs程序中制定的错误

最近,Anchor逐渐成为了一个广受欢迎的Solana程序开发框架。 Anchor是一个有态度的框架,与Ruby on Rails相似,这个框架旨在减少模式化的代码,将Rust开发流程中的序列化与反序列化过程流水线化。

在部署到Testnet(测试网)和Mainnet(主网)之前,程序在开发和测试阶段经常使用Localhost和Devnet(开发网)环境。 Solana支持以下的几个环境:

集群环境RPC连接URL
Mainnet-betahttps://api.mainnet-beta.solana.com
Testnethttps://api.testnet.solana.com
Devnethttps://api.devnet.solana.com
Localhost默认端口:8899(例如,http://localhost:8899,http://192.168.1.88:8899)

部署到一个环境之后,客户端就可以通过对应集群的RPC连接与链上程序进行交互。

部署程序

开发者可以使用命令行部署程序:

solana program deploy <PROGRAM_FILEPATH>

部署程序的时候,程序会被编译为包含BPF字节码的ELF共享对象,并上传到Solana集群上。 和Solana上其他的任何东西一样,程序储存在账户当中。唯一的特殊之处是,这些账户标记为executable(可执行),并且其所有者是"BPF Loader(BPF加载器)"。 这个账户的地址被称为program_id,在后面的一切交易当中,用于指代这个程序。

Solana支持多种BPF加载器,最新的是Upgradable BPF Loader。 BPF加载器负责管理程序账户,让客户端可以通过其program_id对程序进行访问。每个程序都只有一个入口点,这里对指令进行处理。这里的参数须包括:

  • program_id: pubkey(公钥)
  • accounts: array(数组)
  • instruction_data: byte array(字节数组)

当程序被调用时,会在Solana运行库中被执行。

其他资料