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

发布时间:2023-09-15 12:30

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

\"【区块链

 

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

1、连接到Solana开发网

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

1
2
3
4
ubuntu@VM-0-12-ubuntu:~$ 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
ubuntu@VM-0-12-ubuntu:~$ solana-keygen pubkey /home/ubuntu/.config/solana/id.json
7FqW6xXE4sMmZSeVxFsoTr83He4MhhePvA1vRAv9zgQf

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

1
2
3
ubuntu@VM-0-12-ubuntu:~$ solana airdrop 10 7FqW6xXE4sMmZSeVxFsoTr83He4MhhePvA1vRAv9zgQf
Requesting airdrop of 10 SOL from 34.82.57.86:9900
10 SOL

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

1
2
ubuntu@VM-0-12-ubuntu:~$ 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-helloworld\"icon-default.png?t=M3K6\"https://github.com/solana-labs/example-helloworld#rust-limitations
solana-program-library\"icon-default.png?t=M3K6\"https://github.com/solana-labs/solana-program-library cargo-build-bpf\"icon-default.png?t=M3K6\"https://github.com/solana-labs/solana/tree/master/sdk/cargo-build-bpf

\0\0\0\0\0\0\0\0\0\0\0\0

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号