以太坊测试区块链环境搭建

比特币吸金之道系列文章,由计算机黑客发明的网络货币,无国界,无政府,无中心。没有政府滥发货币,没有通货膨胀。在全球计算机网络中,自由的实现货币兑换和流通。
本系列文章只讲程序和策略,不谈挖矿…
关于作者:

  • 张丹(Conan), 程序员/Quant: Java,R,Nodejs
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com
转载请注明出处:
http://blog.fens.me/bitcoin-geth-testnet
以太坊测试区块链环境搭建
文章图片

前言
以太坊(ETH)的出现开启了区块链的2.0时代,要进行ETH的开发和测试,我们先要搭建起来ETH的测试区块链网络。在测试环境中,我们可以直接通过参数配置,生成创世区块,设置挖矿难度,设置gas消耗,执行转账交易,定义智能合约等的操作。
目录
  1. 搭建测试区块链
  2. 开发挖矿
  3. 第一笔转账
  4. 多节点网络
1. 搭建测试区块链 由于在以太坊公链上做任何操作,都需要消耗以太币(eth),对于开发者来说,很有必要在本地自行搭建一个测试区块链网络,进行智能合约的开发,最后再将开发好的合约部署到公链上。私有区块链不同于以太坊公链,给我们很多的自由度,直接可能通过参数配置,生成创世区块,设置挖矿难度,设置gas消耗,执行转账交易,定义智能合约等的操作,这些都需要我们手动进行设置。
私有区块链的搭建,也是基于geth客户端来完成的,geth的安装过程,请参考文章 geth以太坊节点安装。
下面,我们就用geth客户端,开始搭建测试区块链。创建测试节点的文件存储目录。
> mkdir /data0/eth-test/ > cd /data0/eth-test/

新建配置文件genesis.json
> vi genesis.json { "nonce": "0x0000000000000042", "timestamp": "0x0", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", "extraData": "0x", "gasLimit": "0x80000000", "difficulty": "0x3", "coinbase": "0x3333333333333333333333333333333333333333", "config":{ "chainId": 55, "homesteadBlock": 0, "eip155Block": 0 }, "alloc": {} }

参数设置:
  • nonce:64位随机数,用于挖矿
  • timestamp:创世块的时间戳
  • parentHash:上一个区块的hash值,因为是创世块,所以这个值是0
  • mixhash:与 nonce 配合用于挖矿,由上一个区块的一部分生成的 hash。
  • extraData:附加信息,任意填写
  • gasLimit :对GAS的消耗总量限制,用来限制区块能包含的交易信息总和,因为我们就测试链,所以随意填写。
  • difficulty:难度值,越大越难
  • coinbase:矿工账号,第一个区块挖出后将给这个矿工账号发送奖励的以太币。
  • alloc: 预设账号以及账号的以太币数量,测试链挖矿比较容易可以不配置
  • chainId 指定了独立的区块链网络 ID,不同 ID 网络的节点无法互相连接。
初始化区块链,生成创世区块和初始状态。
> geth --datadir=/data0/eth-test init /data0/eth-test/genesis.json INFO [06-26|08:10:32.943749] Maximum peer countETH=25 LES=0 total=25 INFO [06-26|08:10:32.944172] Allocated cache and file handlesdatabase=/data0/eth-test/geth/chaindata cache=16 handles=16 INFO [06-26|08:10:32.989586] Persisted trie from memory databasenodes=0 size=0.00B time=3.877μs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B INFO [06-26|08:10:32.989983] Successfully wrote genesis statedatabase=chaindatahash=4a306e…543a63 INFO [06-26|08:10:32.990028] Allocated cache and file handlesdatabase=/data0/eth-test/geth/lightchaindata cache=16 handles=16 INFO [06-26|08:10:33.036685] Persisted trie from memory databasenodes=0 size=0.00B time=3.258μs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B INFO [06-26|08:10:33.037027] Successfully wrote genesis statedatabase=lightchaindatahash=4a306e…543a63

运行日志,包括了允许最大点对点连接当前节点数为total=25,普通节点连接数ETH=25,LES轻节点连接数0。数据库存储的目录在 /data0/eth-test/geth/chaindata ,当前存活的节点 livenodes=1。
参数说明
  • datadir, 设置当前区块链网络数据存放的位置
  • init,初始化,生成创世区块
接下来,启动测试节点,并进入 geth 命令行界面。
> geth --identity "TestNode" --rpc --rpcport "8545" --datadir=/data0/eth-test --port "30303" --nodiscover console INFO [06-26|08:14:00.916738] Maximum peer countETH=25 LES=0 total=25 INFO [06-26|08:14:00.918148] Starting peer-to-peer nodeinstance=Geth/TestNode/v1.8.12-unstable-f1986f86/linux-amd64/go1.10.3 INFO [06-26|08:14:00.918235] Allocated cache and file handlesdatabase=/data0/eth-test/geth/chaindata cache=768 handles=512 INFO [06-26|08:14:00.979836] Initialised chain configurationconfig="{ChainID: 55 Homestead: 0 DAO:DAOSupport: false EIP150:EIP155: 0 EIP158:Byzantium:Constantinople:Engine: unknown}" INFO [06-26|08:14:00.979915] Disk storage enabled for ethash cachesdir=/data0/eth-test/geth/ethash count=3 INFO [06-26|08:14:00.979943] Disk storage enabled for ethash DAGsdir=/root/.ethashcount=2 INFO [06-26|08:14:00.980023] Initialising Ethereum protocolversions="[63 62]" network=1 INFO [06-26|08:14:00.980566] Loaded most recent local headernumber=0 hash=4a306e…543a63 td=3 INFO [06-26|08:14:00.980634] Loaded most recent local full blocknumber=0 hash=4a306e…543a63 td=3 INFO [06-26|08:14:00.980662] Loaded most recent local fast blocknumber=0 hash=4a306e…543a63 td=3 INFO [06-26|08:14:00.980842] Regenerated local transaction journaltransactions=0 accounts=0 INFO [06-26|08:14:00.981818] Starting P2P networking INFO [06-26|08:14:00.982303] RLPx listener upself="enode://15653a443e91b04040fe2731e0a0fa556a1d050580fa587110b17460cf471a8c3b42ac08dbc3d84a404f8c102ae35b28d9e2c1b9f2eae4c828a0dfa21c1f2117@[::]:30303?discport=0" INFO [06-26|08:14:00.985029] IPC endpoint openedurl=/data0/eth-test/geth.ipc INFO [06-26|08:14:00.985503] HTTP endpoint openedurl=http://127.0.0.1:8545cors= vhosts=localhost Welcome to the Geth JavaScript console!instance: Geth/TestNode/v1.8.12-unstable-f1986f86/linux-amd64/go1.10.3 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>

  • identity, 自定义的节点名字
  • rpc , 允许 HTTP-RPC 访问
  • rpcport , HTTP_RPC的访问端口,默认为8545
  • port , 网络监听端口,默认为30303
  • datadir, 设置当前区块链网络数据存放的位置
  • console, 启动命令行模式,可以在Geth中执行命令
  • nodiscover, 私有链地址,不会被网上看到
这样我们就把一个测试网络启动起来了,由于是单节点,网络没有其他的节点,所以并没有直接的数据输出。
2. 开始挖矿 接下来,我们在自己搭建的私有网络中,开始做常规ETH的操作。
2.1 创建账号
创建一个新账号,密码为123456,账号的地址为:0x9cac40f650e2cbe459dcb32c7c23103497134467。
> personal.newAccount("123456") "0x9cac40f650e2cbe459dcb32c7c23103497134467"

另一种方式,生成一个新账号。
> personal.newAccount() Passphrase: Repeat passphrase: "0x762a2e28c5dbab9cd31369db5f3cbb48f421c0e3"

查看所有账号
> eth.accounts ["0x9cac40f650e2cbe459dcb32c7c23103497134467", "0x762a2e28c5dbab9cd31369db5f3cbb48f421c0e3"]

2.2 挖矿
接下来,我们开始挖矿。挖矿,就是产生以太币的过程。之前在genesis.json文件中,设置的difficulty=3,挖矿难比较低,很快就是挖出以太币来。
# 开始挖矿 > miner.start(1) INFO [06-26|08:19:58.086688] Updated mining threadsthreads=1 INFO [06-26|08:19:58.086828] Transaction pool price threshold updated price=18000000000# 矿工账号:如果有多个账户的情况下,挖矿获得的eth,会自动计入第一账户中。 INFO [06-26|08:19:58.086887] Etherbase automatically configuredaddress=0x9cac40F650E2CBE459dcb32c7c23103497134467 INFO [06-26|08:19:58.087015] Starting mining operation # 开始探索新区块,没有交易内容 INFO [06-26|08:19:58.087793] Commit new mining worknumber=1 txs=0 uncles=0 elapsed=659.441μs# 成功发现新区块 INFO [06-26|08:19:58.451612] Successfully sealed new blocknumber=1 hash=c120d3…23dad2#确认挖到新区块 INFO [06-26|08:19:58.452182] ? mined potential blocknumber=1 hash=c120d3…23dad2 INFO [06-26|08:19:58.45237] Commit new mining worknumber=2 txs=0 uncles=0 elapsed=165.519μs INFO [06-26|08:20:00.683558] Successfully sealed new blocknumber=2 hash=011b1c…100594 INFO [06-26|08:20:00.68399] ? mined potential blocknumber=2 hash=011b1c…100594 INFO [06-26|08:20:00.684181] Commit new mining worknumber=3 txs=0 uncles=0 elapsed=111.601μs INFO [06-26|08:20:09.965339] Successfully sealed new blocknumber=3 hash=173ea5…c059ef INFO [06-26|08:20:09.965789] ? mined potential blocknumber=3 hash=173ea5…c059ef INFO [06-26|08:20:09.966091] Commit new mining worknumber=4 txs=0 uncles=0 elapsed=246.371μs INFO [06-26|08:20:11.622999] Successfully sealed new blocknumber=4 hash=56240d…0910a3// 省略INFO [06-26|08:20:16.264066] Commit new mining worknumber=10 txs=0 uncles=0 elapsed=155.89μs INFO [06-26|08:20:16.466436] Successfully sealed new blocknumber=10 hash=819037…fbcd88 INFO [06-26|08:20:16.466774] ? block reached canonical chainnumber=5hash=7f1015…f53c57 INFO [06-26|08:20:16.466794] ? mined potential blocknumber=10 hash=819037…fbcd88 INFO [06-26|08:20:16.466965] Commit new mining worknumber=11 txs=0 uncles=0 elapsed=92.726μs# 停止挖矿 > miner.stop() true

开始挖了几秒,就产生了10个区块。查看账户资金为50000000000000000000 wei。第一个账户为矿工账号,第二个账户是一个普通账号。
> eth.getBalance(eth.accounts[0]) 50000000000000000000 > eth.getBalance(eth.accounts[1]) 0

由于Wei是最小的单位,我们把Wei转换为ether为单位,比较好看,就是为 50 ether = 50000000000000000000/10^18
> web3.fromWei(eth.getBalance(eth.accounts[0]), "ether") 50

转换单位
  • Wei = 10^0 Wei
  • Ada = 10^3 Wei
  • Babbage = 10^6 Wei
  • Shannon = 10^9 Weiv
  • Szabo = 10^12 Wei
  • Finney = 10^15 Wei
  • Ether = 10^18 Wei
  • Einstein = 10^21 Wei
  • Douglas = 10^42 Wei
2.3 查看区块高度
下一步,我们查看一下区块高度,并分析一下区块的细节。
# 查看区块高度 > eth.blockNumber 10# 查看第10个区块的细节 > eth.getBlock(10) { difficulty: 131648, extraData: "0xd88301080c846765746888676f312e31302e33856c696e7578", gasLimit: 2126604064, gasUsed: 0, hash: "0x819037bcc65eb789eca82fcc3d6c686852ab8297df6396cffa6cfffeaffbcd88", logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", miner: "0x9cac40f650e2cbe459dcb32c7c23103497134467", mixHash: "0x311cd5ef45d9295d8c1b1b8778fb05b0e49dc6cae5971763c2e2d7e3d20bd895", nonce: "0x0b1aae8070cdff77", number: 10, parentHash: "0x1c5609a70d36a460234b95116fcc391e49890c5082af41d8cba3b5b366aa0028", receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", size: 537, stateRoot: "0x0917e990c98b3daf316d0d38a4a2eefd0ad30436bab8ae61adb1ca24723eea81", timestamp: 1529972416, totalDifficulty: 1313603, transactions: [], transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", uncles: [] }

第10个区块为当前的最后一个区块,挖矿难度difficulty=131648,没有交易gasUsed=0,当前块的hash值hash: “0x819037bcc65eb789eca82fcc3d6c686852ab8297df6396cffa6cfffeaffbcd88”,,上一个块的地址parentHash: “0x819037bcc65eb789eca82fcc3d6c686852ab8297df6396cffa6cfffeaffbcd88”,矿工账号miner: “0x9cac40f650e2cbe459dcb32c7c23103497134467”,区块高度number=10。
3. 第一笔转账 接下来,让我完成第一笔转账。从矿工账号转账30ether到第二个账号。
> eth.sendTransaction({from:eth.accounts[0],to:eth.accounts[1],value:web3.toWei(30,"ether")}) Error: authentication needed: password or unlock at web3.js:3143:20 at web3.js:6347:15 at web3.js:5081:36 at :1:1

【以太坊测试区块链环境搭建】第一次,执行转账操作时,出现错误。需要把转输eth的账号进行解锁,才能转账。
# 解锁账号 > personal.unlockAccount(eth.accounts[0]) Unlock account 0x9cac40f650e2cbe459dcb32c7c23103497134467 Passphrase: true# 再次转账 > eth.sendTransaction({from:eth.accounts[0],to:eth.accounts[1],value:web3.toWei(30,"ether")}) INFO [06-26|08:26:44.060461] Submitted transactionfullhash=0x8d6d1eb3c1c82be1f419d8f772048644361c41362fd8de27f8252470f975d6bb recipient=0x762A2e28C5DbaB9cD31369DB5f3CBB48f421C0E3 "0x8d6d1eb3c1c82be1f419d8f772048644361c41362fd8de27f8252470f975d6bb"

交易日志,交易的hash值fullhash=0x8d6d1eb3c1c82be1f419d8f772048644361c41362fd8de27f8252470f975d6bb,收款账号recipient=0x762A2e28C5DbaB9cD31369DB5f3CBB48f421C0E3。
我们提交了第一笔的转账,查看2个账户的余额。
> eth.getBalance(eth.accounts[0]) 50000000000000000000 > eth.getBalance(eth.accounts[1]) 0

账户的余额并没有发生变化,这是因为基于区块链的转账操作需要矿工确认才能完成,矿工确认的过程是要经过挖矿的。我们的转账的操作的任务已经提交,但是交易并未完成,还需要矿工挖矿提交新的区块,在区块中加入这次转账交易,提交新的区块全网的节点(按百分比算,具体还没细看源代码)确认完成后,交易才正式生效。
由于链上只有我们自己,我们要重新开起挖矿程序。
# 开始挖矿 > miner.start(1) INFO [06-26|08:27:24.712255] Updated mining threadsthreads=1 INFO [06-26|08:27:24.712434] Transaction pool price threshold updated price=18000000000 INFO [06-26|08:27:24.712617] Starting mining operation # 探索新的区块,包含一个操作信息txs=1 INFO [06-26|08:27:24.713512] Commit new mining worknumber=11 txs=1 uncles=0 elapsed=808.72μs INFO [06-26|08:27:27.638518] Successfully sealed new blocknumber=11 hash=68495b…35d4fe INFO [06-26|08:27:27.638986] ? block reached canonical chainnumber=6hash=3617e8…0dd7f5 INFO [06-26|08:27:27.639006] ? mined potential blocknumber=11 hash=68495b…35d4fe INFO [06-26|08:27:27.639245] Commit new mining worknumber=12 txs=0 uncles=0 elapsed=227.705μs INFO [06-26|08:27:28.199602] Successfully sealed new blocknumber=12 hash=96fd37…37c016 INFO [06-26|08:27:28.199963] ? block reached canonical chainnumber=7hash=a8d6d5…e6036d INFO [06-26|08:27:28.19998] ? mined potential blocknumber=12 hash=96fd37…37c016 INFO [06-26|08:27:28.200427] Commit new mining worknumber=13 txs=0 uncles=0 elapsed=276.033μs INFO [06-26|08:27:29.766971] Successfully sealed new blocknumber=13 hash=a13201…c051c8 INFO [06-26|08:27:29.767429] ? block reached canonical chainnumber=8hash=16222d…7a9445 INFO [06-26|08:27:29.767447] ? mined potential blocknumber=13 hash=a13201…c051c8 INFO [06-26|08:27:29.767572] Commit new mining worknumber=14 txs=0 uncles=0 elapsed=110.439μs INFO [06-26|08:27:30.302882] Successfully sealed new blocknumber=14 hash=e1ab15…e44665 INFO [06-26|08:27:30.303213] ? block reached canonical chainnumber=9hash=1c5609…aa0028 INFO [06-26|08:27:30.303243] ? mined potential blocknumber=14 hash=e1ab15…e44665 INFO [06-26|08:27:30.303471] Commit new mining worknumber=15 txs=0 uncles=0 elapsed=114.85μs INFO [06-26|08:27:35.685475] Successfully sealed new blocknumber=15 hash=e1b5a4…1bab9e INFO [06-26|08:27:35.686032] ? block reached canonical chainnumber=10 hash=819037…fbcd88 INFO [06-26|08:27:35.686146] ? mined potential blocknumber=15 hash=e1b5a4…1bab9e INFO [06-26|08:27:35.686523] Commit new mining worknumber=16 txs=0 uncles=0 elapsed=294.263μs# 停止挖矿 > miner.stop() true

在高度number=11的区块上,我们发现了有一笔转账信息。再次,查看账户余额,发现账户余额发生了变化。
> eth.getBalance(eth.accounts[0]) 45000000000000000000 > eth.getBalance(eth.accounts[1]) 30000000000000000000

第一个账户变成了 45 ether,第二个账号变成了30 ether。第二个账户余额,正是我们之前设定的转账金额。
# 查看当前块的高度 > eth.blockNumber 15# 第11个区块的细节 > eth.getBlock(11) difficulty: 131072, extraData: "0xd88301080c846765746888676f312e31302e33856c696e7578", gasLimit: 2124527304, gasUsed: 21000, hash: "0x68495bf329e886a8043d1af74d145a870ae6aa2d4e42134499b3730e5c35d4fe", logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", miner: "0x9cac40f650e2cbe459dcb32c7c23103497134467", mixHash: "0xbbf5053e0409cded11f0c8f1059cad389d366723cb2f6c077d6c71c36d31a254", nonce: "0x3cc35610dc92f143", number: 11, parentHash: "0x819037bcc65eb789eca82fcc3d6c686852ab8297df6396cffa6cfffeaffbcd88", receiptsRoot: "0x170861bbc9f17f29b4c8ef046f44fa7435c3ad3a54e752591c87050345c29d31", sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", size: 653, stateRoot: "0x6e44fbe836ebf62523a37bbbb1beaad0c0802be9ff5c4e7b19c16a1eb4c50112", timestamp: 1529972844, totalDifficulty: 1444675, transactions: ["0x8d6d1eb3c1c82be1f419d8f772048644361c41362fd8de27f8252470f975d6bb"], transactionsRoot: "0x98881bb99ed82df9a69726705fb2ac2d1371e9ba992c52ed3b4cd3ee50762d38", uncles: [] }

第11个区块发生了交易,消耗的gas手续费为gasUsed=21000 Wei,交易一共发生1笔transactions=0x8d6d1eb3c1c82be1f419d8f772048644361c41362fd8de27f8252470f975d6bb,矿工账号miner: “0x9cac40f650e2cbe459dcb32c7c23103497134467″。
总结一下,本文介绍了如何搭建以太坊的私有节点,实现了挖矿的过程,并完了2个账户的第一笔转账操作。下一篇文章,找我了解智能合约的编写。
转载请注明出处:
http://blog.fens.me/bitcoin-geth-testnet
以太坊测试区块链环境搭建
文章图片

This entry was posted in 数字货币

    推荐阅读