【区块链 | Solana】Solana链上程序开发入门【源码】

区块链开发工程师 2022-05-14 03:48:22 阅读数:612

程序区块开发solana

在这个教程里,我们将学习如何开发Solana链上程序,内容包括创建Solana账号、 从测试链获取免费的SOL、编译部署与测试流程,并开发一个简单的Solana链上程序。 在教程结束部分提供了完整源码的下载链接。

 

在深入学习本教程之前,请确保已按照这个教程中的步骤设置了环境并安装了工具套件。 可以访问这里查看Solana RPC API文档

1、连接到Solana开发网

如果你没有自己的节点也不要担心,Solana提供了与主网相同配置的devnet。所以在这里让我们首先将 API 端点 设置为开发链 - https://devnet.solana.com:

1
2
3
4
[email protected]:~$ solana config set --url https://devnet.solana.com
Config File: /home/ubuntu/.config/solana/cli/config.yml
RPC URL: https://devnet.solana.com
WebSocket URL: wss://devnet.solana.com/ (computed)

2、准备Solana帐户

每个链上程序实际上都是一个Account,但它被标记为“Executable: true”,这意味着它是一个可执行文件。 为了存储这个文件,我们需要创建另一个可以支付费用的 Solana 账户:

1
solana-keygen new

输入密码并确认后,新账号就保存在 /home/ubuntu/.config/solana/id.json 中,作为我们的默认密钥。 可以运行以下命令检查公钥:

1
2
[email protected]:~$ solana-keygen pubkey /home/ubuntu/.config/solana/id.json
7FqW6xXE4sMmZSeVxFsoTr83He4MhhePvA1vRAv9zgQf

在Solana测试链上,可以运行以下命令获得一些免费的 SOL以便执行后续的操作:

1
2
3
[email protected]:~$ solana airdrop 10 7FqW6xXE4sMmZSeVxFsoTr83He4MhhePvA1vRAv9zgQf
Requesting airdrop of 10 SOL from 34.82.57.86:9900
10 SOL

让我们检查一下我们的余额:

1
2
[email protected]:~$ solana balance 7FqW6xXE4sMmZSeVxFsoTr83He4MhhePvA1vRAv9zgQf
10 SOL

哇,有钱。

然后我们创建另一个帐户,用于存储程序文件:

1
solana-keygen new -o solana_memo_program.json

在这里,我们使用-o选项将新的密钥对输出到新文件solana_memo_program.json 。

3、编译程序

从 1.4.x 版本(2020-10-22 发布)开始,Solana 提供了cargo-build-bpf和cargo-test-bpf等工具, 帮助我们将 cargo 项目编译为 BPF 格式文件。

可以使用 Solana 官方团队提供的备忘录程序来试试这个。首先克隆仓库:

1
git clone https://github.com/solana-labs/solana-program-library.git

然后跳到文件夹solana-program-library/memo/program/并运行:

1
cargo build-bpf

这是我们上面提到的程序cargo-build-bpf的包装器。如果看到如下错误:

1
2
3
= note: /usr/bin/ld: cannot find Scrt1.o: No such file or directory
/usr/bin/ld: cannot find crti.o: No such file or directory
collect2: error: ld returned 1 exit status

那是因为你缺少一些32位的依赖包,让我们通过安装来修复它:

1
sudo apt install gcc-multilib

然后我们再次编译,得到:

1
2
To deploy this program:
$ solana deploy /home/ubuntu/solana/solana-program-library/target/deploy/spl_memo.so

好了,可以部署了,这里我们将它部署到我们创建的帐户并导出到文件solana_memo_program.json, 让我们先获取密钥:

1
2
solana-keygen pubkey ~/solana_memo_program.json
D8Cnv1UcThay2WijWP4SQ8G683UuVsKPaZEU7TNVKW1j

然后运行部署:

1
2
solana deploy /home/ubuntu/solana/solana-program-library/target/deploy/spl_memo.so ~/solana_memo_program.json
{"programId":"D8Cnv1UcThay2WijWP4SQ8G683UuVsKPaZEU7TNVKW1j"}

现在我们已经成功部署了一个程序到测试连,程序地址:D8Cnv1UcThay2WijWP4SQ8G683UuVsKPaZEU7TNVKW1j

为了验证命令行的结果,可以在 Solana explorer 上检查我们的程序,转到https://explorer.solana.com/ 并将网络更改为 Devnet,输入程序地址,可能会看到:

是的,我们的程序就在那里!

4、测试Solana程序

为了与我们的链上程序进行交互,这里我们需要老朋友@solana/web3.js。 让我们创建一个新的js项目并添加包@solana/web3.js:

1
2
yarn init
yarn add @solana/web3.js

然后在根文件夹和测试代码中创建一个类似index.js的入口 js 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var solana_web3 = require('@solana/web3.js');
function testMemo(connection, account){
const instruction = new solana_web3.TransactionInstruction({
keys: [],
programId:new solana_web3.PublicKey('D8Cnv1UcThay2WijWP4SQ8G683UuVsKPaZEU7TNVKW1j'),
data: Buffer.from('cztest'),
});
console.log("account:", account.publicKey.toBase58())
solana_web3.sendAndConfirmTransaction(
connection,
new solana_web3.Transaction().add(instruction),
[account],
{
skipPreflight: true,
commitment: "singleGossip",
},
).then(()=>{console.log("done")}).catch((e)=>{console.log("error",e)});
}function main() {
connection = new solana_web3.Connection("https://devnet.solana.com", 'singleGossip');
const account = new solana_web3.Account()
const lamports = 10*1000000000
connection.requestAirdrop(account.publicKey, lamports).then(()=>{
console.log("airdrop done")
testMemo(connection, account)
});
}
main()

让我们看看这里发生了什么。

首先连接到 devnet 端点,然后我们使用 solana_web3 提供的solana_web3.Account() 函数创建 一个新帐户,该帐户将用于稍后与我们的程序交互。

然后我们从 devnet 得到一些免费的SOL ,然后调用了这个testMemo函数,该函数向我们的程序发送一个交易, 参数作为数据流传入(这里我们传递一个字符串“ cztest ”)

现在,让我们再次使用资源管理器检查我们的Solana程序:

如上所示的交易,我们可以看到十六进制格式的数据,可以使用binascii 之类的工具来解码这些数据:

1
2
3
>>> import binascii
>>> binascii.a2b_hex('637a74657374')
b'cztest'

在这里我们可以看到结果与我们发送给程序的字符串相同

5、编写自己的Solana程序

我们刚刚尝试了一个从 Solana 官方 repo 中提取的程序,那么我们应该怎么做才能从头开始编写 一个Solana链上程序呢?作为一个普通的 Rust 项目,Solana 链上程序也是由 cargo 管理的。

首先,让我们使用 cargo 来启动我们的新项目:

1
cargo new onchain_program

然后使用喜欢的编辑器打开onchain_program/Cargo.toml并为项目添加一些基本信息:

1
2
3
4
5
6
7
8
9
10
[dependencies]
arrayref = "0.3.6"
num-derive = "0.3"
num-traits = "0.2"
num_enum = "0.5.1"
solana-program = "1.4.8"
thiserror = "1.0"[dev-dependencies]
solana-sdk = "1.4.8"[lib]
crate-type = ["cdylib", "lib"][package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

我们还添加了一个Xargo.toml文件,用于在编译 bpf 文件时支持跨平台。 然后是时候自己动手了,让我们编写一些 Rust 代码。首先我们在src/lib.rs中添加一个入口点:

1
2
3
#![deny(missing_docs)]//! A simple program that return success.#[cfg(not(feature = "no-entrypoint"))]
mod entrypoint;// Export current sdk types for downstream users building with a different sdk version
pub use solana_program;

然后在入口文件entrypoint.rs 中添加一些代码:

1
2
3
4
5
6
7
8
9
10
11
12
//! Program entrypointuse solana_program::{
account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, program_error::ProgramError,
pubkey::Pubkey,
};
use std::str::from_utf8;entrypoint!(process_instruction);
fn process_instruction(
_program_id: &Pubkey,
_accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
Ok(())
}

这是一个非常简单的程序,我们这里什么都没做,只是返回成功

函数process_instruction是我们在指令结构中传递的整个入口函数。它包含执行该指令所需的所有信息: _program_id表示程序,_accounts表示该指令中需要的所有帐户,instruction_data表示我们用来传递 其他参数的序列化数据流。当程序运行良好时,我们使用Ok(())返回成功,或者使用Err(error)返回失败。

如果你已经准备好,接下来就可以按之前所做的那样部署此程序:

1
2
cargo build-bpf...To deploy this program:
$ solana deploy /home/ubuntu/solana/memo_test/onchain_program/target/deploy/onchain_program.so

6、结束语

借助 Solana 提供的所有工具和 SDK,我们可以使用 cargo 轻松获取目标文件。一旦你了解了整个过程, 会发现它只是一个 Rust 项目,它使用rustrc提供的 LLVM 编译成 BPF 格式文件,然后我们将它部署在链上。 我想提一提的是,在开发 Solana 链上程序时,并不是所有的 Rust 特性都可以使用,详细信息可以 在这里找到。如果你使用 1.3.x 版本的工具套件,那么还需要xargo-build.sh。

教程代码可以从这里下载: example-helloworldicon-default.png?t=M3K6https://github.com/solana-labs/example-helloworld#rust-limitations
solana-program-libraryicon-default.png?t=M3K6https://github.com/solana-labs/solana-program-library cargo-build-bpficon-default.png?t=M3K6https://github.com/solana-labs/solana/tree/master/sdk/cargo-build-bpf

版权声明:本文为[区块链开发工程师]所创,转载请带上原文链接,感谢。 https://blog.csdn.net/qq_28505809/article/details/124662107