以太坊(Ethereum)是一个建立在区块链技术之上,去中心化应用平台。它允许任何人在平台中建立和使用通过区块链技术运行的去中心化应用。
以太坊区块链的基础是参与节点的点对点网络,以太坊节点加入到以太坊网络形成去中心化的共识系统。以太坊网络有以下几种:
生产环境网络对应的是以太坊共有链,私有网络对应的是以太坊私有链或联盟链,
Geth是Go Ethereum开源项目的简称,它是使用Go语言编写且实现了Ethereum协议的客户端软件,也是目前用户最多,使用最广泛的客户端。通过Geth客户端与以太坊网络进行连接和交互可以实现账户管理、合约部署、挖矿等众多有趣且实用的功能。
Geth的安装方法:
$ gitclone https://github.com/ethereum/go-ethereum.git $ cd go-ethereum $ git checkout v1.7.2 $ make geth $ make all $ cp ./build/bin/geth/usr/bin |
安装成功后执行:
$ geth version Geth Version: 1.7.2-stable Git Commit: 1db4ecdc0b9e828ff65777fb466fc7c1d04e0de9 Architecture: amd64 Protocol Versions: [63 62] Network Id: 1 |
1.初始化一个创世区块
初始化创世区块时,要先创建一个genesis.json
文件,
genesis.json:
{ "config": { "chainId": 10, "homesteadBlock": 0, "eip155Block": 0, "eip158Block": 0 }, "coinbase": "0x0000000000000000000000000000000000000000", "difficulty": "0x20000", "extraData": "", "gasLimit": "0x2fefd8", "nonce": "0x0000000000000042", "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "timestamp": "0x00", "alloc": {} } |
然后进行创世区块的初始化:
$ geth init ./genesis.json --datadir ./chain WARN [05-22|11:16:36] No etherbase set and no accounts found as default INFO [05-22|11:16:36] Allocated cache and file handles database=/home/geth/chain/geth/chaindata cache=16 handles=16 INFO [05-22|11:16:36] Writing custom genesis block INFO [05-22|11:16:36] Successfully wrote genesis state database=chaindata hash=5e1fc7…d790e0 INFO [05-22|11:16:36] Allocated cache and file handles database=/home/geth/chain/geth/lightchaindata cache=16 handles=16 INFO [05-22|11:16:36] Writing custom genesis block INFO [05-22|11:16:36] Successfully wrote genesis state database=lightchaindata hash=5e1fc7…d790e0 |
2.启动私有网络
执行命令,其中参数nodiscover表示私有链地址,不会被网上看到,命令congsole表示同时会启动Geth的JavaScript控制台
$ geth --datadir ./chain --nodiscover console 2>>eth_output.log Welcome to the Geth JavaScript console!
instance: Geth/v1.7.2-stable-1db4ecdc/linux-amd64/go1.9.2 modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0
> |
启动Geth的控制台后就可以进行操作,Geth的控制台是JavaScript开发的,实现了web3.jsAPI。web3.js 是一个通过RPC 调用 和本地以太坊节点进行通信的js库。web3.js可以与任何暴露了RPC接口的以太坊节点连接。web3中提供了eth对象 - web3.eth来与以太坊区块链进行交互。
备注:
web3 API =》 http://web3js.readthedocs.io/en/1.0/index.html
中文版:http://web3.tryblockchain.org/Web3.js-api-refrence.html#toc_22
创建帐户:
> web3.personal.newAccount("password") "0xb518124a8e586b18cb16bf4a6a74b376f48db2cd" |
返回的字符串就是账户
查询账户:
> web3.eth.accounts ["0xb518124a8e586b18cb16bf4a6a74b376f48db2cd"] |
挖矿执行以下命令:
> miner.start(1) null |
执行成功后,控制台范围null,通过日志可以看到已经在进行挖矿:
$ tailf eth_output.log INFO [05-22|13:17:36] Successfully sealed new block number=4 hash=4c2ded…26ee60 INFO [05-22|13:17:36] mined potential block number=4 hash=4c2ded…26ee60 INFO [05-22|13:17:36] Commit new mining work number=5 txs=0 uncles=0 elapsed=163.749µs INFO [05-22|13:17:37] Successfully sealed new block number=5 hash=f30c33…e14fb3 INFO [05-22|13:17:37] mined potential block number=5 hash=f30c33…e14fb3 INFO [05-22|13:17:37] Commit new mining work number=6 txs=0 uncles=0 elapsed=241.586µs INFO [05-22|13:17:39] Successfully sealed new block number=6 hash=76363f…460004 INFO [05-22|13:17:39] block reached canonical chain number=1 hash=377d55…8d0308 INFO [05-22|13:17:39] mined potential block number=6 hash=76363f…460004 INFO [05-22|13:17:39] Commit new mining work number=7 txs=0 uncles=0 elapsed=155.252µs |
如果要停止挖矿的话,可以执行命令:
> miner.stop() null |
备注:停止挖矿后,以太币则不会产生,同样智能合约、转帐等操作也不会起作用。
执行挖矿后,挖矿产生的以太币会默认保持到创建的第一个账户(也就是0xb518124a8e586b18cb16bf4a6a74b376f48db2cd),我们可以查询账户余额:
> web3.eth.getBalance("0xb518124a8e586b18cb16bf4a6a74b376f48db2cd") 555000000000000000000
#查看格式化的以太币 > web3.fromWei(web3.eth.getBalance("0xb518124a8e586b18cb16bf4a6a74b376f48db2cd")) 555 |
因为GethJavascript Console是基于Javascript的,所以也可以创建js函数,查看所有帐户余额:
> function checkAllBalances() { ... var totalBal = 0; ... for (var acctNum in eth.accounts) { ...... var acct = eth.accounts[acctNum]; ...... var acctBal = web3.fromWei(eth.getBalance(acct), "ether"); ...... totalBal += parseFloat(acctBal); ...... console.log(" eth.accounts[" + acctNum + "]: \t" + acct + " \tbalance: " + acctBal + " ether"); ...... } ... console.log(" Total balance: " + totalBal + " ether"); ... }; > checkAllBalances() eth.accounts[0]: 0xb518124a8e586b18cb16bf4a6a74b376f48db2cd balance: 715 ether Total balance: 715 ether |
转账至少需要2个账户,所以首先再创建一个账户:
> web3.personal.newAccount("password") "0xbd4a62c2832b3ef2205c23cfec8ba3dacc875b75" > web3.eth.accounts ["0xb518124a8e586b18cb16bf4a6a74b376f48db2cd", "0xbd4a62c2832b3ef2205c23cfec8ba3dacc875b75"] |
支持操作账户字符串比较麻烦,可以复制给变量:
> account0 = web3.eth.accounts[0] "0xb518124a8e586b18cb16bf4a6a74b376f48db2cd" > account1 = web3.eth.accounts[1] "0xbd4a62c2832b3ef2205c23cfec8ba3dacc875b75" |
然后从账户1转账给账户2,注意转账前需要先解锁被转账的账户:
> web3.personal.unlockAccount(account0,"password") true
> web3.eth.sendTransaction({from:account0,to:account1,value:web3.toWei(3,"ether")}) "0xd9f95d44de1f4858f23f9e326859713a527922498955cf84eb8bb75296b35fd6" |
查询账户余额:
> checkAllBalances() eth.accounts[0]: 0xb518124a8e586b18cb16bf4a6a74b376f48db2cd balance: 1832 ether eth.accounts[1]: 0xbd4a62c2832b3ef2205c23cfec8ba3dacc875b75 balance: 3 ether Total balance: 1835 ether |
可以到账户2的余额正是3 ether,说明转账成功。如果把挖矿命令停了以后,再进行转账的话将不会成功。
以太坊是一个去中心化的平台,往往需要较多节点共同运作才能得到理想的测试效果,搭建私有网络比较难构建多节点,所以可以连接以太网提供的测试网络,以太坊公开的测试网络共有4个,目前仍在运行的有3个。每个网络都有自己的创世区块和名字,按开始运行时间的早晚,依次为:
Morden是以太坊官方提供的测试网络,自2015年7月开始运行。到2016年11月时,由于难度炸弹已经严重影响出块速度,不得不退役,重新开启一条新的区块链。Morden的共识机制为PoW。
https://ropsten.etherscan.io/
Ropsten也是以太坊官方提供的测试网络,是为了解决Morden难度炸弹问题而重新启动的一条区块链,目前仍在运行,共识机制为PoW。测试网络上的以太币并无实际价值,因此Ropsten的挖矿难度很低,目前在755M左右,仅仅只有主网络的0.07%。这样低的难度一方面使一台普通笔记本电脑的CPU也可以挖出区块,获得测试网络上的以太币,方便开发人员测试软件,但是却不能阻止攻击。
https://kovan.etherscan.io/
为了解决测试网络中PoW共识机制的问题,以太坊钱包Parity的开发团队发起了一个新的测试网络Kovan。Kovan使用了权威证明(Proof-of-Authority)的共识机制,简称PoA。
Kovan目前仍在运行,但仅有Parity钱包客户端可以使用这个测试网络。
https://rinkeby.etherscan.io/
Rinkeby也是以太坊官方提供的测试网络,使用PoA共识机制。与Kovan不同,以太坊团队提供了Rinkeby的PoA共识机制说明文档,理论上任何以太坊钱包都可以根据这个说明文档,支持Rinkeby测试网络,目前Rinkeby已经开始运行。
目前开发人员最常用的测试网络是Rinkeby,本文说明连接到Rinkeby
使用Geth连接到Rinkeby测试网络,加上参数--rinkeby,或者指定--networkid=4(1=Frontier, 2=Morden (disused),3=Ropsten, 4=Rinkeby)。
因为连接测试网络就需要同步区块链数据,Geth的参数可以指定--syncmode来设置同步模块:
本文采用ligth模式进行同步Rinkeyby测试网络:
$ geth --datadir ./rinkeby_light \ --rinkeby \ --syncmode light \ --rpc console 2>eth_rinkeby_out.log |
同步需要花点时间,同步情况可以通过web3.eth.syncing查询:
> web3.eth.syncing { currentBlock: 168256, //已经同步的区块数 highestBlock: 2331548, //总共的区块数 knownStates: 0, pulledStates: 0, startingBlock: 74688 } |
当web3.eth.syncing返回false说明同步完成,要等同步完成后才能进行账户余额查询和转账的操作
使用以太坊测试网络同样需要创建账号:
> web3.personal.newAccount("password") "0xb2e149dc56c65bd0ee10c76fb7a92b140cec1adf" |
Rinkeby测试网络使用的是PoA共识机制,我们不能通过挖矿来获取以太币。想获取Rinkeby测试网络中的以太币,需要去申请,这个申请Rinkeby以太币的功能被称为水龙头(Faucet),水龙头会源源不断的产生以太币,并且受到权威节点控制,以确保不会被滥用。
水龙头网站:https://www.rinkeby.io/#faucet
获取方法:有三种在推特、脸书、google+等上发布消息,并将消息的网址粘贴到上面截图的输入框中选个获取就可以。本文采用google+的方式,在google+发布一条消息,消息内容就是你的账号:
然后将这个消息的连接输入到水龙头网站的输入框,并点击“Give me Ether”,有三种选项,前面是获得的以太币数量,后面是冷却时间,在冷却时间过后才能进行下一次以太币申请。例如第一项是生成3个以太币,8小时后才能再次申请。本文选择的就是第一项3个以太币。
申请成功后,可以在https://rinkeby.etherscan.io查到转账记录:
https://rinkeby.etherscan.io/tx/0x2caf8eb8e6b90a4577c80ff17165e36cdf3a9f8d71bba25539a2fc5af5814144
然后我们查询账户余额,可以查询到是3000000000000000000Wei=3以太币
> web3.eth.getBalance("0xb2e149dc56c65bd0ee10c76fb7a92b140cec1adf") 3000000000000000000 |