parity 合约

admin
admin 2020年06月11日
  • 在其它设备中阅读本文章

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