以太坊学习(二)
创建工作目录
mkdir EthereumNode-01
cd EthereumNode-01
创世块配置
-
在工作目录下配置创世快
genesis.json
内容如下{ "config": { "chainId": 666, "homesteadBlock": 0, "eip150Block": 0, "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "eip155Block": 0, "eip158Block": 0, "byzantiumBlock": 0, "constantinopleBlock": 0, "petersburgBlock": 0, "istanbulBlock": 0, "ethash": {} }, "nonce": "0x0", "timestamp": "0x5ddf8f3e", "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000", "gasLimit": "0x47b760", "difficulty": "0x00001", "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "coinbase": "0x0000000000000000000000000000000000000000", "alloc": { "0x1e82968C4624880FD1E8e818421841E6DB8D1Fa4" : {"balance" : "30000000000000000000"} }, "number": "0x0", "gasUsed": "0x0", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" }
-
如果用较短的创世块,可能会出现如下问题
Fatal: Failed to write genesis block: unsupported fork ordering: eip150Block not enabled, but eip155Block enabled at 0
-
初始化创世块
-
命令如下:
geth --datadir data init genesis.json
-
这会在当前目录下创建data 目录,用来保存区块数据及账户信息
启动以太坊
-
命令如下:
geth --rpc --nodiscover --datadir data --port 30303 --rpcapi "eth,net,web3,personal,admin,txpool,debug,miner" --rpccorsdomain "*" --networkid 666 --ipcdisable console 2>>node.log
控制台常见的参数如下:
--rpc 启用HTTP-RPC服务器 --rpcaddr value HTTP-RPC服务器接口地址(默认值:“localhost”) --rpcport value HTTP-RPC服务器监听端口(默认值:8545) --rpcapi value 基于HTTP-RPC接口提供的API --ws 启用WS-RPC服务器 --wsaddr value WS-RPC服务器监听接口地址(默认值:“localhost”) --wsport value WS-RPC服务器监听端口(默认值:8546) --wsapi value 基于WS-RPC的接口提供的API --wsorigins value websockets请求允许的源 --ipcdisable 禁用IPC-RPC服务器 --ipcpath 包含在datadir里的IPC socket/pipe文件名(转义过的显式路径) --rpccorsdomain value 允许跨域请求的域名列表(逗号分隔)(浏览器强制) --jspath loadScript JavaScript加载脚本的根路径(默认值:“.”) --exec value 执行JavaScript语句(只能结合console/attach使用) --preload value 预加载到控制台的JavaScript文件列表(逗号分隔)
2>>node.log
是将控制台输出写入日志node.log
tail -f node.log
新开一个命令行终端,实时显示日志
查看账户列表
> eth.accounts
[]
>
创建新账户
> personal.newAccount('123456')
123456
为新账户的密码,回车后,返回一个新账户
INFO [03-20|21:50:35.868] Your new key was generated address=0xaA94D19614bA0d84a2E5b6aefc9Ba6ef0bC0dc65
WARN [03-20|21:50:35.868] Please backup your key file! path=E:\\BlockChain\\EthereumNode-01\\data\\keystore\\UTC--2020-03-20T13-50-34.366456300Z--aa94d19614ba0d84a2e5b6aefc9ba6ef0bc0dc65
WARN [03-20|21:50:35.868] Please remember your password!
查询账户余额
-
方式一:
> eth.getBalance(eth.accounts[0])
-
方式二:
> eth.getBalance('0xd8bcf1324d566cbec5d3b67e6e14485b06a41d49'
0xd8bcf1324d566cbec5d3b67e6e14485b06a41d49
为账户地址
挖矿
-
启动挖矿
> miner.start(1)
其中 start 的参数表示挖矿使用的线程数。第一次启动挖矿会先生成挖矿所需的 DAG 文件,这个过程有点慢,等进度达到 100% 后,就会开始挖矿,此时屏幕会被挖矿信息刷屏。
挖矿日志如下:
INFO [03-20|22:03:47.245] Commit new mining work number=1 sealhash=8fbbe5…40027a uncles=0 txs=0 gas=0 fees=0 elapsed=0s INFO [03-20|22:04:03.460] Commit new mining work number=2 sealhash=995989…a76d80 uncles=0 txs=0 gas=0 fees=0 elapsed=0s INFO [03-20|22:04:03.460] Successfully sealed new block number=1 sealhash=8fbbe5…40027a hash=a5bba5…7718a6 elapsed=16.215s INFO [03-20|22:04:03.471] 🔨 mined potential block number=1 hash=a5bba5…7718a6
-
停止挖矿
> miner.stop()
挖到一个区块会奖励以太币,挖矿所得的奖励会进入矿工的账户,这个账户叫做
coinbase
,默认情况下coinbase
是本地账户中的第一个账户,可以通过miner.setEtherbase()
将其他账户设置成coinbase
。 -
可以使用以下命令,当新区块挖出后,挖矿即可结束。
> miner.start(1);admin.sleepBlocks(1);miner.stop();
交易
-
再创建一个账户
> personal.newAccount('666666')
-
目前,账户 0 已经挖到了 57 个块的奖励
> eth.getBalance(eth.accounts[0]) 114000000000000000000
-
账户 1 的余额还是0
> eth.getBalance(eth.accounts[1]) 0 >
-
我们要从账户 0 向账户 1 转账,先解锁账户 0,才能发起交易
> personal.unlockAccount(eth.accounts[0]) Unlock account 0xaa94d19614ba0d84a2e5b6aefc9ba6ef0bc0dc65 Passphrase: true >
-
使用最新版本geth客户,当执行personal.unlockAccount()或在程序中调用personal_unlockAccount接口时,会出现:account unlock with HTTP access is forbidden异常。
-
原因:新版本geth,出于安全考虑,默认禁止了HTTP通道解锁账户
-
解决方案: 启动命令中添加参数 --allow-insecure-unlock
-
发送交易,账户 0 -> 账户 1
> amount = web3.toWei(5,'ether') "5000000000000000000" > eth.sendTransaction({from:eth.accounts[0],to:eth.accounts[1],value:amount}) INFO [03-20|22:22:58.777] Submitted transaction fullhash=0x245245ffc8b14f6be66d963f29de353b78b7f3b2a32d9a11144971145eb0568e recipient=0xBCbB4d899288a6E708d59Ba5a5Bbd05e27B34389 "0x245245ffc8b14f6be66d963f29de353b78b7f3b2a32d9a11144971145eb0568e" >
-
此时如果没有挖矿,用
txpool.status
命令可以看到本地交易池中有一个待确认的交易> txpool.status { pending: 1, queued: 0 } >
-
可以使用
eth.getBlock("pending", true).transactions
查看当前待确认交易。> eth.getBlock("pending", true).transactions [{ blockHash: "0x65518f135a2c2098aed0b9a5d8befb39609ac0f8e7e4ba54420d9a43afa69d2f", blockNumber: 58, from: "0xaa94d19614ba0d84a2e5b6aefc9ba6ef0bc0dc65", gas: 21000, gasPrice: 1000000000, hash: "0x245245ffc8b14f6be66d963f29de353b78b7f3b2a32d9a11144971145eb0568e", input: "0x", nonce: 0, r: "0xb698786eee753f2920c5180393c498c364f0a9ebc7d62f6c385dd81cd8905df6", s: "0xb4bcd47f58420de3a48da859856e4ccd4ded904ec035102a4127d28fddddc50", to: "0xbcbb4d899288a6e708d59ba5a5bbd05e27b34389", transactionIndex: 0, v: "0x558", value: 5000000000000000000 }] >
-
启动挖矿
> miner.start(1);admin.sleepBlocks(1);miner.stop(); null INFO [03-20|22:29:27.542] Updated mining threads threads=1 INFO [03-20|22:29:27.542] Transaction pool price threshold updated price=1000000000 INFO [03-20|22:29:27.543] Commit new mining work number=58 sealhash=b8574d…d9c448 uncles=0 txs=0 gas=0 fees=0 elapsed=1.001ms INFO [03-20|22:29:27.543] Commit new mining work number=58 sealhash=766834…219caa uncles=0 txs=1 gas=21000 fees=2.1e-05 elapsed=1.001ms INFO [03-20|22:29:33.566] Successfully sealed new block number=58 sealhash=766834…219caa hash=ad8f2d…cdcb82 elapsed=6.022s INFO [03-20|22:29:33.566] 🔨 mined potential block number=58 hash=ad8f2d…cdcb82 INFO [03-20|22:29:33.566] Commit new mining work number=59 sealhash=d82776…c423ce uncles=0 txs=0 gas=0 fees=0 elapsed=0s INFO [03-20|22:29:34.527] Successfully sealed new block number=59 sealhash=d82776…c423ce hash=697373…36a59f elapsed=961.432ms
-
新区块挖出后,挖矿结束,查看账户 1 的余额,已经收到了账户 0 的以太币
> web3.fromWei(eth.getBalance(eth.accounts[1]),'ether') 5
添加区块链节点
- 查看节点数
> net.peerCount 0
- 查看节点信息
假如有两个节点,首先查看节点A信息> admin.nodeInfo.enode "enode://048157a0423689ba9f216835d6b47e63b730683e3eff95189a3b1dee5ab01c270a646be6a856a962b5e51bae31ec3294d9348523c0f30967249712e05f2b740d@127.0.0.1:30303?discport=0"
- 加入节点
将B节点加入到A区块链中,此时在B节点可以查看A节点中的账户信息,然而在A节点无法查询B节点账户信息> admin.addPeer("enode://048157a0423689ba9f216835d6b47e63b730683e3eff95189a3b1dee5ab01c270a646be6a856a962b5e51bae31ec3294d9348523c0f30967249712e05f2b740d@127.0.0.1:30303?discport=0") INFO tr[1ue0-2 2> |23:56:26.525] Looking for peers peercount=0 tried=0 static=1
- 再查看peerCount
> net.peerCount 1
- 查看详细信息
> admin.peers [{ caps: ["eth/63", "eth/64", "eth/65"], enode: "enode://048157a0423689ba9f216835d6b47e63b730683e3eff95189a3b1dee5ab01c270a646be6a856a962b5e51bae31ec3294d9348523c0f30967249712e05f2b740d@127.0.0.1:30303?discport=0", id: "ffc9100d70402c7ad9941a93c0387498c537b87b3be4d4e061b6ec95b155ffb7", name: "Geth/v1.9.11-stable-6a62fe39/windows-amd64/go1.13.8", network: { inbound: false, localAddress: "127.0.0.1:65414", remoteAddress: "127.0.0.1:30303", static: true, trusted: false }, protocols: { eth: { difficulty: 5258818, head: "0x6f7c741bf844a85a16e9a412e9c93d9fab300011cf647f9f2c4482903452578c", version: 65 } } }]