近期在区块链的热潮推动下,我开始研究区块链技术,尤其是智能合约。可编程式的智能合约龙头老大非以太坊莫属了,其他的合约平台如 hyperledger,EOS 相对来说没以太坊成熟,以后陆续在研究。好了,废话不多说了,开始以太坊私有链搭建。
一.geth,mist 客户端下载
1.这里我给大家介绍下,以太坊客户端,以太坊客户端主要分成两类。一个是后台命令行客户端,如:geth(go语言),parity(Rust语言),他们是一个与以太坊网络交互的命令行客户端。
其余的命令行客户还有 ethereumjs-lib(javascript),pyethapp(python),ruby-ethereum(ruby) ....主要 geth 使用的比较普遍,这里我就使用geth作为命令行客户端。
2.mist 是属于可视化钱包,这么说吧,你在geth 客户端中生成的用户,以太坊币数量可以通过mist 钱包可视化展示。当然mist 不只有这些简单的功能,最重要的是能部署智能合约,发布,调用。其他还有很多轻钱包,如 lightWallet,metamask...
下面是geth和mist下载地址,这里我使用的是windows系统安装。
二.创建以太坊初始区块文件 genesis.json
{"config": {"chainId": 101,"homesteadBlock": 0,"eip155Block": 0,"eip158Block": 0},"alloc": {},"coinbase": "0x0000000000000000000000000000000000000000","difficulty": "0x400","extraData": "","gasLimit": "0xffffffff","nonce": "0x0000000000000042","mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000","parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000","timestamp": "0x00"}
chainId : 以太坊区块链网络Id,ethereum主链是1,私有链只用不要与主链冲突即可。
alloc : 预留账户,如下
"alloc":{
"0x0000000000000000000000000000000000000001":{"balance":"121312321"},
"0x0000000000000000000000000000000000000002":{"balance":"121312321"},
}
Coinbase: 旷工账户
Difficulty: 挖矿难度,0x400,这个是简单。
extraData:相当于备注
gasLimit:最小消耗gas
nonce : 64位随机数,用于挖矿,注意他和mixhash的设置需要满足以太坊黄皮书中的要求
parentHash : 上一个区块的Hash值,因为是创世块,石头里蹦出来的,没有在它前面的,所以是0
Timestamp : 时间戳
三.初始化区块节点
geth --datadir data0 init genesis.json
data0 是当前文件夹存储节点数据,注意:不要使用其他文章介绍的“%cd%\chain”目录
四.启动geth客户端节点
注意:在geth安装目录下执行
geth --identity "TestNode1" --datadir "data0" --rpc --rpcapi "db,eth,net,web3" --rpcaddr "127.0.0.1" --rpcport "8486" --port "30304" --networkid "29382" console
使用命令 geth -h 可以查看geth 相关的帮助文档。这里我说几个常用的属性。
--Identity : 节点身份标识,起个名字
--datadir : 指定节点存在位置,“data0”
--rpc : 启用http-rpc服务器
--rpcapi : 基于http-rpc提供的api接口。eth,net,web3,db...
--rpcaddr : http-rpc服务器接口地址:默认“127.0.0.1”
--rpcport : http-rpc 端口(多节点时,不要重复)
--port : 节点端口号(多节点时,不要重复)
--networkid : 网络标识符 随便指定一个id(确保多节点是统一网络,保持一致)
下图启动配置信息说明:
五. geth 常用命令
#创建账户
personal.newAccount("123456")
#获取账户数组
eth.accounts
#解锁账户,转账时可使用
personal.unlockAccount(eth.accounts[0], "123456")
#节点主账户
eth.coinbase
#查看账户余额
eth.getBalance(eth.accounts[0])
#启动,结束挖矿,写区块
miner.start(), miner.stop()
下面是运行miner.start() 开始挖矿的运行示意图。
六.配置多节点服务
单个节点运行太霸道,不能成为中心化,咱们给私有的以太坊网络在添加一个节点
1.再初始化一个节点
geth --datadir data1 init genesis.json
“data1”作为新节点的存储目录,同样使用genesis.json作为初始化文件
2. 启动新节点
geth --identity "TestNode2" --datadir "data1" --rpc --rpcapi "db,eth,net,web3" --rpcaddr "127.0.0.1" --ipcpath "data1\geth\geth.ipc" --rpcport "8487" --port "30305" --networkid "29382" console
3. 给新节点创建一个账户,否则无法启动挖矿
personal.newAccout(“123”)
4.查看:新节点enode信息,使用你本机ip替换[::]
5.重要:主节点添加新节点,使两节点连上同一个私有链上
admin.addpeer("enode://d4f64272de882d2e2ccefc6466c6580ddecd253f5c9d87f977ac3881cbea7b141c07681ea605c53af5815cbfc25b5138b9ddb07be61b757850a55b7197939ba4@192.168.1.175:30304")
这里"enode://......." 填写你节点 admin.nodeInfo.enode 的信息
6. 如何确保两节点已连接
首先使用命令admin.nodeInfo,查看结果是否为空[],另外在其中一个节点启动挖矿命令 miner.start()
如果出现如下图所示,则两节点则已经连通
至此我们的节点钱包里有不少eth,可惜是私有链上的。下面就用可视化工具mist钱包查看,并使用mist钱包发布合约。
七. 启动mist钱包
首先默认启动主节点钱包,若是mist钱包不能打开。用命令启动,进入mist钱包目录,用git Bash 在此启动。使用windows powershell启动很卡,没有安装git 客户端的,请先安装git 客户端。
启动mist 你可以看到右上脚有个net-private 说明启动的是私链钱包
2. 打开第二个节点钱包
由于我使用的mist钱包,不能导入第二个节点钱包数据,所以我打算启动第二个节点的钱包,这里有个大坑!!!
mist.exe --rpc ipc http://127.0.0.1:8545 ## 带ipc都是错的,很多网站,包括Ethereum github issue问答区都给出的错误要加ipc (注意:这是错误的打开方式)
有两种方式打开多个节点钱包方式
(1)只读的http 方式打开钱包。不能转账,不能部署合约
mist.exe --rpc http://127.0.0.1:8545
(2)以rpc方式打开访问ipc接口方式打开mist钱包
mist.exe --rpc \\\\.\\pipe\\data1\\geth\\geth.ipc ##这是节点二指定的ipcpath路径, 可以看下我启动节点二的配置 --ipcpath
至此,我们可以将第二个节点的钱包打开,进行节点可视化转账交易。
八. mist钱包部署合约
下面是写的简单的合约案例
pragma solidity ^0.4.18;
contract Token {
mapping (address=>uint) public balancesOf;
address public owner;
event LogownerWitidras(address addr,uint amount);functionToken() public {
owner=msg.sender;
balancesOf[msg.sender]= 10000;
}functiontransfer(address _to, uint _value) public {if(balancesOf[msg.sender] < _value) revert(); //避免转移出去的代币超过当前的存货
if(balancesOf[_to] + _value < balancesOf[_to]) revert();//避免自己调用自己,或者递归调用
balancesOf[msg.sender] -=_value;
balancesOf[_to]+=_value;
}functionmint(uint _amount) public {
balancesOf[owner]+=_amount;
}//向当前合约存款
functiondeposit() payable public returns(address addr, uint amount){//msg.sender 全局变量,调用合约的发起方
//msg.value 全局变量,调用合约的发起方转发的货币量,以wei为单位。
return (msg.sender, msg.value * 1ether);
}
modifier onlyOwner{if(msg.sender!=owner){
revert();
}
_;
}functiongetContractAddrees() public constant returns (address){return this;
}functionwithdrawFromContract(address _toAddr,uint amount) public onlyOwner{
_toAddr.transfer(amount* 1ether);
emit LogownerWitidras(_toAddr,amount* 1ether);
}//获取合约账户余额
functiongetContractBalance() public constant returns (uint){returngetContractAddrees().balance;
}functiongetAddressBalance(address addr) public constant returns(uint){returnaddr.balance;
}
}
View Code
点击部署,在矿池中产生一个待开采区块。启动miner.start() 挖矿。
待确认完毕,则合约部署完毕。具体的合约调用,我就不在本篇文章赘述了。
好了初步的以太坊客户端应用搭建完毕,之后还会陆续更新solidity 合约代码类文章,欢迎小伙伴们继续关注。
~~~转载请注明出处~~~
----------------------------------------请关注微信公众号“刻意链习”,持续带你理解更多的区块链技术------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------------
更多参考文案