合约的自动编译和一键部署
合约的自动编译和一键部署在开发智能合约时,有时候儿需要对合约自动化部署,通过一条指令或者调用一个文件来完成,下面给出一个思路,供借鉴:环境的安装1、安装 相关软件 [root@k7762v /home]# yum install git[root@k7762v /home]# yum install openssl-devel [root@k7762v /home]# n...
合约的自动编译和一键部署
在开发智能合约时,有时候儿需要对合约自动化部署,通过一条指令或者调用一个文件来完成,下面给出一个思路,供借鉴:
- 环境的安装
1、安装 相关软件
[root@k7762v /home]# yum install git
[root@k7762v /home]# yum install openssl-devel
[root@k7762v /home]# npm install -g ethereumjs-testrpc
[root@k7762v /home]# npm install -g truffle
[root@k7762v /home]# yum install -y curl golang
如果在安装web3时,警告找不到package.json,下面是解决这个警告或者错误的一种方法:
npm init -f
然后再次运行
# npm install web3
2、创建工作目录并配置环境变量
mkdir ~/go
echo "export GOPATH=$HOME/go" >> /etc/profile
source /etc/profile
3、创建Truffles
1)、空项目:truffle init
2)、复杂WEB
[root@k7762v /home/testmy]# truffle unbox webpack
4、如果tesrpc出现错误端口情况:
说明:testrpc已被废弃,现已更名为Ganache CLI
lsof -i:8545 找到pid 然后 kill -9 pid
但是本次安装这个进程是DOCKER进程 ID,暂时还不能杀。
5、安装CMAKE3.9,编译SOLC
wget https://cmake.org/files/v3.9/cmake-3.9.2.tar.gz
tar xvf cmake-3.9.2.tar.gz && cd cmake-3.9.2
./configure && make && make install
6、安装SOLC
编译安装:
git clone --recursive https://github.com/ethereum/solidity.git
cd solidity
mkdir build
cd build
cmake .. && make
但是这里编译需要boost库,要提前安装。不过有简单的方法:
命令安装:
sudo npm install -g solc solc-cli --save-dev
如果在使用时仍然报缺少哪个,就再安装一次就好了。
7、安装solcjs
如果安装了第六步的命令安装,本步可省略。
npm install -g solc
npm install solc //遇到找不到SOLC模块,再来一次
8、数据库客户端安装访问
安装方法:
npm install mysql
如果有错误缺少json文件,可按照上面web3安装时的方法init或者手动创建:
package.json
{
"name": "mysqltest",
"description": "test project",
"version": "0.0.1",
"private": true,
"devDependencies":{
"mysql":"2.6.2"
}
}
访问:
mysql -h110.212.41.17 -P3306 -p –u用户名 数据库名
提示输入密码,输入密码即可。
根据需要来创建一个表,例如:
CREATE TABLE `contract` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NULL DEFAULT NULL,
`abi` TEXT NOT NULL,
`addr` VARCHAR(200) NOT NULL DEFAULT '0x',
PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
- 合约的编译
此处采用多文件遍历:
const fs = require('fs');
const path = require('path');
const solc = require('solc');
//const CONTRACTS_DIR = path.resolve(__dirname, 'contracts');
const CONTRACTS_DIR = path.resolve(__dirname);
function findContract(pathName) {
const contractPath = path.resolve(CONTRACTS_DIR, pathName);
if (isContract(contractPath)) {
return fs.readFileSync(contractPath, 'utf8');
} else {
throw new Error(`File ${contractPath} not found`);
}
}
function isContract(path) {
return fs.existsSync(path);
}
function findImports (pathName) {
try {
return { contents: findContract(pathName) };
} catch(e) {
return { error: e.message };
}
}
const source = findContract('xxx.sol');//主要的 sol
const compiled = solc.compile({
sources: {
'xxx' : source
}
}, 1, findImports);//1表示编译最优,findImports会自动传入依赖的sol,可以在此函数内打印路径显示依赖
for (var cn in compiled.contracts){
console.log(JSON.parse(compiled.contracts[cn].interface));
console.log(compiled.contracts[cn].bytecode);
}
~
- 合约的自动部署和保存
var Web3 = require('web3');
var fs = require('fs');
const solc = require('solc');
var web3;
var id = 0;//默认值
var clientid ='';
var serviceid = '';
var dbip ='110.212.41.17';
var dbport=3306;
var usename ='test';
var pwd ='123456';
var dbname = 'my_baas';
var count = getConfig();
if (count < 3){
return;
}
console.log('create web3 instance');
if (typeof web3 !== 'undefined'){
web3 = new Web3(web3.currentProvider);
console.log("new currenprovider");
}
else
{
console.log("http remote rpc create");
web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:8089"));
console.log("isok http");
}
//初始化数据库模块
var maxid = 0;
console.log("init mysql ....");
var mysql = require('mysql');
var connection = mysql.createConnection({
host:dbip,
user:'root',
password:'123456',
port:dbport,
database:'test'
});
//var id0 = selectID();
console.log('Reading Contract xxxx...');
var input = {
'xxx0.sol':fs.readFileSync("./xxx0.sol","utf-8"),
'xxx.sol':fs.readFileSync("./xxx.sol","utf-8")
};
console.log('start compile.....');
const output = solc.compile({sources:input},1);
let abi = JSON.parse(output.contracts['xxx.sol:xxx'].interface);
let bytecode = output.contracts['xxx.sol:xxx'].bytecode;
//save db
console.log("save abi and bytecode ......");
insertTable(id,'',abi,bytecode);
//获得Gas
function getGas(){
let gasEstimate = web3.eth.estimateGas({data: '0x' + bytecode});
console.log(gasEstimate);
}
//处理参数
function getConfig(){
//处理输入参数
var args = process.argv.splice(2);
console.log(args);
//获得参数个数
var num = args.length;
if (num < 3){
console.log("params count is too small!");
return num;
}
id = args[0];
clientid = args[1];
serviceid = args[2];
if ("" == args[3] || null == args[3] ){
console.log('err value is: ' + args[3]);
return num;
}
dbip = args[3];
console.log('dbip value is: '+dbip);
dbport = args[4];
console.log(id,clientid,serviceid);
}
//部署--应该使用原始签名,此处不再使用
function deployContract(){
var adTokenContract=new web3.eth.Contract(abi).deploy({
data:'0x'+bytecode, //以0x开头
arguments:[10000000000,"TAG",2], //传递构造函数的参数
}).send({
//from:account,
from:"0xcb4f30359dae96e70c30e3e1cdf76e3ef8b3bb4f",
//gas:4700000,
gas:4700000,
//gasPrice:'30000000000000'
},function(error,transactionHash){
console.log("send回调");
console.log("error:"+error);
console.log("send transactionHash:"+transactionHash);
})
.on('error', function(error){ console.error(error) })
.then(function(newContractInstance){
var newContractAddress=newContractInstance.options.address
console.log("新合约地址:"+newContractAddress);
insertTable(id,'',abi,newContractAddress);
});
}
//选择数据库
function selectID(){
connection.connect();
var sel = "select max(id) as id from contract";
connection.query(sel,function(error, results, fields){
if (error) {
console.log("error:",error.message);
throw error;
}
if (results) {
console.log("maxid is:",results[0].id + 1);
id = parseInt( results[0].id) + 1;
}
});
//connection.end();
}
//插入数据库ABI及地址
function insertTable(id,name,abi,addr){
connection.connect(function(err){
if(err){
console.log('[query] - :'+err);
return;
}
console.log('[connection connect] succeed!');
});
var abistr = JSON.stringify(abi);
id = 33;
var insertSql =
"insert into contract(id,name,abi,addr)values("+id+",'"+name+"','"+abistr+"','"+addr+"')";
console.log(insertSql);
connection.query(insertSql,function(err,result){
if (err){
console.log('[insert error]-',err.message);
return;
}
console.log('insert id:',result);
});
}
//关闭数据库连接
function Close(){
connection.end(function(err){
if(err){
return;
}
console.log('[connection end] succeed!');
});
}
- 签名交易自动管理方式处理发送合约
需要安装ethereumjs-tx
var Tx = require('ethereumjs-tx');
var privateKey = new Buffer('e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', 'hex')
var rawTx = {
nonce: '0x00',
gasPrice: '0x09184e72a000',
gasLimit: '0x2710',
to: '0x0000000000000000000000000000000000000000',
value: '0x00',
data: '0x7f7465737432000000000000000000000000000000000000000000000000000000600057'
}
var tx = new Tx(rawTx);
tx.sign(privateKey);
var serializedTx = tx.serialize();//序列化???
//console.log(serializedTx.toString('hex'));
//f889808609184e72a00082271094000000000000000000000000000000000000000080a47f74657374320000000000000000000000000000000000000000000000000000006000571ca08a8bbf888cfa37bbf0bb965423625641fc956967b81d12e23709cead01446075a01ce999b56a8a88504be365442ea61239198e23d1fce7d00fcfc5cd3b44b7215f
web3.eth.sendRawTransaction('0x' + serializedTx.toString('hex'), function(err, hash) {
if (!err)
console.log(hash); // "0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385"
});
只需要把编译智能合约的bytecode部分放到data中,签名发送即可。交易完成后调用:
web3.eth.getTransactionReceipt(交易哈希)获取合约的地址。
- 总结
通过上述的一系列工作,就可以编译部署一个智能合约了,如果你想自动化部署可以考虑这么做,更方便。
如果你对c++和区块链感兴趣,欢迎关注:
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)