Solana开发教程:搭建开发环境

Solong
9 min readNov 18, 2020

--

Solana的智能合约叫做”On-chain Program”,其可执行文件是一个ELF 文件格式的BPF 文件,这里的BPF 是由C或者Rust或者其他可以编译出BPF格式的高级语言编译生成的目标文件。当前Solana提供了Rust和 C的支持(都是通过LLVM来实现目标文件输出),并为其输出了单独SDK,我们将这些SDK和相关的编译 工具统称为Solana Onchain Program的开发工具链。

而使用这里的工具链编译出来的BPF的ELF文件(通常以.so为扩展名),需要部署到 solana validator 节点上,才能通过solana的runtime进行运行。

开发环境

开发环境首选还是和Solana官方的推荐环境保持一致,使用(Ubuntu 18.04)当然,这里也可以使用 MacOS,只是有些依赖需要自己手动按照以下。这里为了方便,我们以Ubuntu18.04为例。

对于国内的同学,为了节约生命时间,建议直接买个海外的云主机来操作,比如XX云的香港服务器。不要 问为什么,问就是好几天的时间换来的绿色上网的经验。

1. 安装Rust

如果已经安装了rust,则可以跳过这一小节,其实只要一个命令就可以了:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

安装后,需要source以下PATH:

source ~/.bash_profile

然后查看版本:

ubuntu@VM-0-12-ubuntu:~/solana/example-helloworld/src/program-rust$ rustc --version
rustc 1.47.0 (18bf6b4f0 2020-10-07)
ubuntu@VM-0-12-ubuntu:~/solana/example-helloworld/src/program-rust$ cargo --version
cargo 1.47.0 (f3c7e066a 2020-08-28)

2. 安装solana命令行工具

solana提供了编译好的命令行工具,包含了节点程序solana-validator, 私钥生成工具 solana-keygen等,当然也包含了合约开发工具 cargo-build-bpf(2020–10–22以后的1.4.x版本)。

去到solana的github下载最新编译 好的版本,这里我们选择了1.4.8版本的linux预编译版本:

wget https://github.com/solana-labs/solana/releases/download/v1.4.8/solana-release-x86_64-unknown-linux-gnu.tar.bz2

解压后设置好PATH路径,然后执行:

ubuntu@VM-0-12-ubuntu:~$ solana --version
solana-cli 1.4.8 (src:c8b3d0ba; feat:3582801427)

搭建本地测试节点

测试节点的搭建,solana已经准备好了docker镜像,因此先要保证你本机上已经可以运行docker。然后有 两种方法可以起镜像。

1.使用npm

这里主要借助npm对”@solana/web3.js”的包管理,将相关脚本通过node_modules拉下来,并提供启动 入口。使用npm主要是可以方便集成,不需要关心太多细节。

这里我们首先创建一个目录”localnet_test”,然后执行:

npm init
npm install @solana/web3.js

初始化好目录并安装好”@solana/web3.js”。然后添加启动脚本,编辑pacakge.json在”scripts” 里面增加:

"localnet:up": "set -x; solana-localnet down; set -e; solana-localnet up",
"localnet:down": "solana-localnet down",
"localnet:logs": "solana-localnet logs -f",

然后就可以执行:

npm run localnet:up

当看到:

+ curl -X POST -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":1, "method":"getTransactionCount"}' http://localhost:8899
{"jsonrpc":"2.0","result":0,"id":1}

表示本地的测试网已经搭好了,这里通过curl发送JSON-RPC的getTransactionCount 请求到 http://localhost:8899并得到正确返回。

然后设置我们的solana命令配置到本地测试网地址:

solana config set --url http://localhost:8899

执行:

solana cluster-version
1.3.21

这里可以看到docker镜像里面的版本是1.3.21。

此时如果希望查看节点日志,比如自己在写合约的时候,需要打印一些日志,可以通过:

npm run localnet:logs

打印出容器中节点的日志信息。

当需要停止节点时,使用:

npm run localnet:down

即可停止节点运行。

2.使用localnet.sh脚本

npm的本质其实是调用localnet.sh 脚本,所以我们也可以直接将这个脚本copy下来,然后根据自己的需求进行定制,比如上面的本地集群运行 镜像的版本。

首先将脚本保存到本地,假设在目录下localnet.sh_test的localnet.sh文件。

mkdir localnet.sh_test
cd localnet.sh_test
curl https://raw.githubusercontent.com/solana-labs/solana-web3.js/master/bin/localnet.sh -o localnet.sh

然后添加执行权限:

chmod a+x localnet.sh

然后首先修改:

channel="edge"

设置默认channel,因为原来的脚本依赖了package.json文件。channle表示容器中运行的集群的版本, 这里我们可以指定其为1.4.8:

channel="v1.4.7"

然后就可以通过这个脚本来启动/停止本地集群了。比如:

./localnet.sh up

按照之前的,将solana的配置中链接的节点地址改为localnet:

solana config set --url http://localhost:8899

这个时候来看下集群版本:

ubuntu@VM-0-12-ubuntu:~/solana/localnet.sh_test$ solana cluster-version
1.4.7

已经切换成指定的v1.4.7了。

同样的这里可以通过./localnet.sh logs查看日志,./localnet.sh down停止节点。

3.发生了什么?

来看下localnet.sh的逻辑。

首先确定”channel”表示哪个solana镜像,完整的镜像列表可以在docker hub 查询到。如果是”up” 命令。最终会执行:

docker run "${ARGS[@]}" solanalabs/solana:"$channel"

实际上就是配置了一些参数后,其一个docker镜像。

那么这个docker镜像是怎么构成的呢?来看Solana SDK

FROM debian:buster# JSON RPC port
EXPOSE 8899/tcp
RUN apt update && \
apt-get install -y bzip2 libssl-dev && \
rm -rf /var/lib/apt/lists/*
COPY usr/bin /usr/bin/
ENTRYPOINT [ "/usr/bin/solana-run.sh" ]
CMD [""]

就是在”debian:buster”的镜像上,按照了bzip2 libbsl-dev等依赖后, 然后通过CI的docker镜像构建好solana的命令行程序,然后将这些命令行程序和 solana-run.sh,fetch-spl.sh等工具脚本复制到/usr/bin, 并设置为ENTRYPOINT为/usr/bin/solana-run.sh, 参数就是上面localnet.sh提供的”${ARGS[@]}”。

而这里的 solana-run.sh 就是构建本地测试节点的要做的具体逻辑。

主要流程包含了

ledgerDir=$PWD/config/ledger // 设置ledger目录
solana-keygen new --no-passphrase //生成默认钱包
validator_identity="$dataDir/validator-identity.json" // 设置validator账户
validator_vote_account="$dataDir/validator-vote-account.json" // 设置vote账户
validator_stake_account="$dataDir/validator-stake-account.json" // 设置stake账户
[[ -e "$ledgerDir"/genesis.bin || -e "$ledgerDir"/genesis.tar.bz2 ]] // 配置genesis文件
./fetch-spl.sh // 配置SPL Token合约
solana-genesis // 设置genesis
solana-validator "${args[@]}" & // 启动validator

如果希望在自己的机器上搭建,那么可以直接执行这个脚本中, 比如希望调试solana validator程序的时候,只要自己先编译好solana,设置好PATH变量,然后运行 这个脚本,就会以本机编译的程序来启动validator了。

总结

如果是简单的测试合约,那么通过发布到devnet环境就可以了,但是如果想调试合约,在合约里面打个日志, 此时如果没有个运行的节点,就没法看到合约的日志内容。为此 solana项目已经提供了可运行的本地测试集群docker 镜像,并提供了操作脚本,以便操作。当然你可以按照脚本里面的配置,自行在自己的真机上跑一个节点。 如果只是出于调试合约打日志的目的,使用docker容器,会更加方便。如果调试solana validator 则 搭建自己搭建更合适一点。

英文版看这里

参考

  1. localnet.sh
  2. docker-solana

--

--