parity 合约
parity 是 rust 语言实现的以太坊客户端,现改名为 openethereum,目标是成为最快、最轻和最安全的以太坊客户端。它和 go 版本的 geth 功能差不多,支持 wasm 虚拟机,但不自带 cpu 挖矿。
一、环境构建
创建并运行 debian:10 镜像
docker run --name parity --restart always -p 8545 -itd debian:10
连接 debian 终端
docker exec -it parity /bin/bash
换源(加速下载包)和更新
/bin/bash -c 'echo -e "\
deb http://mirrors.163.com/debian/ buster main non-free contrib\n\
deb http://mirrors.163.com/debian/ buster-updates main non-free contrib\n\
deb http://mirrors.163.com/debian/ buster-backports main non-free contrib\n\
deb http://mirrors.163.com/debian-security/ buster/updates main non-free contrib" > /etc/apt/sources.list;\
apt update;\
apt upgrade -y;'
安装所需的包
apt install -y curl cmake g++ clang npm git nano
安装 rustup 来安装 rust
curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain nightly
把 rustup 添加到环境变量 path 并生效
echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> ~/.bashrc && source ~/.bashrc
rustup 换源 ,加速下载
/bin/bash -c 'echo -e "\
[source.crates-io]\n\
replace-with = "tuna"\n\
\n\
[source.tuna]\n\
registry = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git"" > $HOME/.cargo/config;'
下载 openethereum 代码
git clone https://github.com/openethereum/openethereum.git -b v3.0.1 ~/openethereum
编译并安装 openethereum
cd ~/openethereum && cargo install --path . --features final
安装 wasm 工具 ,添加 wasm32-unknown-unknown 和安装 wasm-build
rustup target add wasm32-unknown-unknown && cargo install pwasm-utils-cli --bin wasm-build
二、合约
下载 wasm 实例项目 pwasm-tutorial
git clone https://github.com/openethereum/pwasm-tutorial.git --depth 1 ~/pwasm-tutorial
编译项目中的 token 合约 , 编译成功后,可以在目录~/pwasm-tutorial/step-5/target 及其子目录 json 下分别找到 wasm 和 abi 文件
cd ~/pwasm-tutorial/step-5 && ./build.sh
启动测试节点和导入测试账户 ,测试账户在创世时已经分配一些余额用于合约测试
openethereum --chain ~/pwasm-tutorial/wasm-dev-chain.json --jsonrpc-apis=all &
curl --data '{"jsonrpc":"2.0","method":"parity_newAccountFromPhrase","params":["user", "user"],"id":0}' -H "Content-Type: application/json" -X POST localhost:8545
安装 web3 和进入 node 交互控制台
cd ~/pwasm-tutorial && npm install web3 && node
部署调用流程 ,进入 node 交互控制台,参考https://github.com/openethereum/pwasm-tutorial#deploy
操作
var Web3 = require("web3");
var fs = require("fs");
// 连接本地节点
var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
// 设置默认账户为测试账户
web3.eth.defaultAccount = "0x004ec07d2329997267ec62b4166639513386f32e";
// 读取合约abi
var abi = JSON.parse(fs.readFileSync("./step-5/target/json/TokenInterface.json"));
// 读取16进制的合约代码
var codeHex = '0x' + fs.readFileSync("./step-5/target/pwasm_tutorial_contract.wasm").toString('hex');
var TokenContract = new web3.eth.Contract(abi, { data: codeHex, from: web3.eth.defaultAccount });
var TokenDeployTransaction = TokenContract.deploy({data: codeHex, arguments: [10000000]});
// 部署合约,可能提示gaslimit不够,再次执行此句部署
web3.eth.personal.unlockAccount(web3.eth.defaultAccount, "user").then(() => TokenDeployTransaction.estimateGas()).then(gas => TokenDeployTransaction.send({gasLimit: gas, from: web3.eth.defaultAccount})).then(contract => { console.log("Address of new contract: " + contract.options.address); TokenContract = contract; }).catch(err => console.log(err));
// token转账
web3.eth.personal.unlockAccount(web3.eth.defaultAccount, "user").then(() => TokenContract.methods.transfer("0x7BA4324585CB5597adC283024819254345CD7C62", 200).send()).then(console.log).catch(console.log);
// 余额查询
TokenContract.methods.balanceOf("0x7BA4324585CB5597adC283024819254345CD7C62").call().then(console.log);
TokenContract.methods.balanceOf(web3.eth.defaultAccount).call().then(console.log);
一键部署调用测试
编辑 js 文件
cd ~/pwasm-tutorial && nano wasm-5.js
输入以下内容保存,ctrl+o
保存,ctrl+x
关闭编辑器
const Web3 = require('web3')
const fs = require("fs")
const web3 = new Web3(new Web3.providers.HttpProvider('http://127.0.0.1:8545'))
web3.eth.defaultAccount = "0x004ec07d2329997267ec62b4166639513386f32e"
var testAccount = "0x7BA4324585CB5597adC283024819254345CD7C62"
var abi = require("./step-5/target/json/TokenInterface")
var code = '0x' + fs.readFileSync("./step-5/target/pwasm_tutorial_contract.wasm").toString('hex')
var TokenContract = new web3.eth.Contract(abi, { from: web3.eth.defaultAccount })
var TokenDeployTransaction = TokenContract.deploy({
data: code,
arguments: [10000000000000]
});
(async () => {
await web3.eth.personal.unlockAccount(web3.eth.defaultAccount, "user")
gas = await TokenDeployTransaction.estimateGas()
TokenContract = await TokenDeployTransaction.send({ gasLimit: gas })
console.log("Address of new contract: " + TokenContract.options.address);
await web3.eth.personal.unlockAccount(web3.eth.defaultAccount, "user")
console.log(await TokenContract.methods.balanceOf(web3.eth.defaultAccount).call())
await TokenContract.methods.transfer(testAccount, 2000).send(console.log)
console.log(await TokenContract.methods.balanceOf(testAccount).call())
console.log(await TokenContract.methods.balanceOf(web3.eth.defaultAccount).call())
})().catch(err => console.log(err));
执行 js 文件
node wasm-5.js