主页 > imtoken下载app > 6分钟以太坊实战系列-以太坊私链搭建与智能合约部署
6分钟以太坊实战系列-以太坊私链搭建与智能合约部署
本文是chainboard.io准备的6分钟以太坊实践的第三篇,从以太坊私链的搭建到智能合约的部署。 手把手带你在自己的私有链上部署自己的智能合约~
1. 建立私有以太坊
1.安装Geth(Go-Ethereum)客户端
(1) 在 Mac 上使用 Homebrew 安装
> brew tap ethereum/ethereum
> brew install ethereum
(2) 在Ubuntu上安装
sudo add-apt-repository -y ppa:ethereum/ethereum
sudo apt-get update
sudo apt-get install ethereum
(3) 直接下载
下载链接:
2. 初始化创世块
在初始化创世块时,首先创建一个包含以下内容的 genesis.json 文件:
{
"config": {
"chainId": 88,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"nonce": "0x0000000000000000",
"timestamp": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "",
"gasLimit": "0xffffffff",
"difficulty": "0x4000",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": { }
}
然后使用geth命令初始化:
> geth init ./genesis.json --datadir "./chain"
--datadir 后面是数据库文件目录的位置,可以自己指定
3.启动私有链
启动命令:
> geth --datadir "./chain" --nodediscover --networkid=88 console 2>>ouput.log
参数说明:
参数名称 参数说明
数据目录
设置当前区块链网络数据存放位置
没有发现
私链地址不会在线上看到
安慰
启动命令行模式,可以在Geth中执行命令
2.部署智能合约
部署前需要使用solc编译Solidity文件
1.编译Solidity文件
(一)安装npm
从nodejs官网下载对应版本并安装(安装nodejs即可)。 nodejs官网地址:
(2) 安装solc
> npm install -g solc
(3)编译Solidity文件
注意编译的命令不是solc而是solcjs
命令:
> solcjs .sol --bin --abi --optimize -o <输出文件夹路径>/
(4) 例子
这里我们以昨天课程中写的智能合约为例(示例合约见文末)。 进入合约所在目录:
> solcjs Compute.sol --bin --abi --optimize -o ./
生成四个文件,如下:
图片.png
因为合约中有 Compute 和 Owner 函数,所以会生成这两个函数的文件。 但是,由于Compute函数继承了Owner函数的方法,所以我们实际上只需要用到这两个文件,Compute_sol_Compute.abi Compute_sol_Compute.bin。
2.创建一个帐户和我的
在部署之前还需要执行几个步骤。
(1)启动私有链,进入geth的控制台
> geth --datadir "./chain" --nodiscover console 2>>ouput.log
(2) 创建账户
> personal.newAccount("passward")
"0x....." // 返回你新建的账户的地址
现在您可以查看您的帐户
> eth.accounts
["0x....."]
> eth.getBalabce(eth.accounts[0])
0
(3) 矿业
部署前需要先挖矿才能在账户里赚钱,因为部署需要gasERC20以太坊网络链项目官方,需要先赚点钱
// 在 miner.start() 的括号中可以填入挖矿的线程数,不填默认为一个线程
> miner.start()
可以在output.log中查看我们的日志信息:
INFO [03-04|22:48:14] Generating DAG in progress epoch=0 percentage=0 elapsed=2.518s
...
NFO [03-04|23:11:55] Commit new mining work number=1 txs=0 uncles=0 elapsed=129.456µs
INFO [03-04|23:11:55] Successfully sealed new block number=1 hash=729b9d…ea7aa5
INFO [03-04|23:11:55] mined potential block number=1 hash=729b9d…ea7aa5
注意:第一次挖矿会比较慢,以太坊节点会生成挖矿所需的数据,你会看到Generating DAG的进度,当进度达到100%时,就会正式开始挖矿,可以看到生成了开始块。
挖矿停止:
> miner.stop()
这时候账户里有钱了,可以再查一下
> eth.getBalabce(eth.accounts[0])
1.245e+21
3.部署合约
部署合约需要前面编译生成的Compute_sol_Compute.bin Compute_sol_Compute.abi文件
// 获取 .abi 文件内容
// 将Compute_sol_Compute.abi文件的内容复制出来,放到 web3.eth.contract() 中去
> var contractAbi = web3.eth.contract([{"constant":true,..}]);
// 获取 .bin 文件内容
// 将Compute_sol_Compute.bin文件的内容复制出来,注意在内容前面需要加上 '0x'
> var contractBin = '0x' + <.bin文件中的内容>
// 计算需要的 gas
> var gasValue = eth.estimateGas({data:contractBin})
// 部署合约
> var contract = contractAbi.new(
{
from: web3.eth.accounts[0],
data: contractBin,
gas: gasValue
}, function (e, contract){
console.log(e, contract);
if (typeof contract.address !== 'undefined') {
console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
}
})
可能会出现以下错误:
1.账户未解锁
Error: authentication needed: password or unlock undefined
解决办法:解锁账户
> personal.unlockAccount(eth.accounts[0])
Unlock account 0x32314e87346e13338fb11c0acc8e2d51ac4139eb
Passphrase: // 然后输入你账户的密码
2.账户余额不足
Error: insufficient funds for gas * price + value undefined
解决方案:挖矿
注意:需要先启动矿机,才能部署合约
> miner.start()
// 过一小会
Contract mined! address: 0x4289aec1d7cb79c8b181f37bb9fa5939b2c9e2bb transactionHash: 0x41f4dda5868d21f883fcf41ebeb2bddd3cac737ba2f5e005c2b573d19a9edf33
返回合约地址后,我们的智能合约就正式部署了。
3.在控制台调用智能合约
1、调用getLCM方法,传入我们需要计算最小公倍数的两个值:
> contract.getLCM(2, 3, {from:eth.coinbase, gas:200000})
"0xd52f4fa99f66052078564b123820b84083ede17da789ad8520410fb3c57ec739"
注意:
(1)因为getLCM方法会改变链上数据ERC20以太坊网络链项目官方,所以调用时一定要带上地址{from:eth.coinbase},否则会报Error: invalid address
(2) 在交易参数中,gas参数的默认值是90000,但是在这个方法中是不够的,需要自己设置一个更大的值。 交易完成后,可以使用eth.getTransactionReceipt('0x...')查看实际使用的gas量。如下图
图片.png
(三)交易参数详解
参数名称类型详细信息
从
数据,20 字节
发起交易的地址
到
数据,20 字节
可选,交易转账地址
气体
数字,默认为 90000
提供给交易的gas量,未使用的gas会返还到账户
汽油价格
数字
可选,gas单价
价值
数字
可选,交易转账金额
数据
数据
你的方法的参数
随机数
数字
可选,允许使用相同的随机数覆盖交易数据
2.调用getRecord方法:
> contract.getRecord(0)
[2, 3, 6]
从返回值可以看出我们的数据已经写入链中,计算出2和3的公倍数为6。
3.使用其他账户调用合约
在我们的合约中,权限是有限制的,只有部署的账户才能调用合约,其他账户在调用合约时将无法更改合约中的数据。
4. 示例合约
pragma solidity ^0.4.19;
contract Owner {
//合约拥有者
address public owner;
//构造函数,将合约的所有权给予发布者
function Owner() public {
owner = msg.sender;
}
//仅有合约的拥有者可以操作
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
//onlyOwner作为函数执行的前置条件,仅有合约拥有者可以更换所属权
function setOwner(address to) public onlyOwner {
if(to != address(0)) {
owner == to;
}
}
}
//通过is使Compute继承Owner合约
contract Compute is Owner {
//建立一个存储于区块链上的二维数组,存储每一次计算的输入以及结果
uint[3][] records;
//比较大小,solidity允许返回两个值
function compare(uint first, uint second) internal pure returns(uint bigOne, uint smallOne) {
if(first > second) {
return (first, second);
}
else {
return (second, first);
}
}
//建立事件去监听每一次计算并记录日志
event GetLCM(uint first, uint second, uint result);
function getLCM(uint first, uint second) external onlyOwner returns(uint) {
if (first == second) {
return first;
}
else {
uint bigOne;uint smallOne;
(bigOne, smallOne) = compare(first, second);
uint i = 1;
while(true) {
uint mul = i * bigOne;
if(mul % smallOne == 0) {
uint index = records.push([first, second, mul]) - 1;
//调用事件
GetLCM(first, second, mul);
return index;
}
i++;
}
}
}
//根据索引获取游戏记录
function getRecord(uint index) external onlyOwner view returns(uint[3]) {
return records[index];
}
}
系列文章地址:
第一篇:智能合约与Solidity高级语言(一)
第二部分:智能合约与Solidity高级语言(二)
第三部分:以太坊私链搭建与智能合约部署
第 4 部分:Web3j 调用智能合约
最后给大家介绍一下:
ChainBoard核心团队利用丰富的区块链技术研发经验,围绕项目需求持续创新,与合作伙伴携手共赢,深度融合,共同打造金融科技、游戏平台、众筹互助、医疗保健、物流等。 区块链在其他领域的应用。 主要输出智能合约开发、公链开发、联盟链开发、交互应用开发能力,帮助项目方快速获得先发优势。 目前,团队已与国内知名游戏运营商、海外金融机构在区块链+游戏、区块链+金融等方面展开深度合作。