这篇博客演示的基本操作系统环境是CentOS 7,参考书籍:以太坊开发实战——以太坊关键技术与案例分析 第五章(吴寿鹤、冯翔、刘涛、周广益 著)。
文章结构:
一.geth客户端安装
二.搭建一个私有链
1.新建一个geth工作目录
2.创世区块配置文件
3.初始化
4.启动私有链
三.以太坊私有链上的基本操作
1.创建用户
2.查看余额
3.挖矿
4.解锁账户
5.交易
6.区块
7.账户管理
8.区块数据管理
9.远程节点连接
10.通过attach命令连接已启动节点
四.常见问题
1.执行miner.start()返回null
一.geth客户端安装
这篇博客演示的基本操作系统环境是CentOS 7,参考书籍:以太坊开发实战——以太坊关键技术与案例分析(吴寿鹤、冯翔、刘涛、周广益 著)。首先从github上获取go-ethereum源码,然后编译geth。获取源码命令:
[root@localhost opt]# git clone https://github.com/ethereum/go-ethereum.git
如果git未安装请自行百度安装。
如上图所示,由于之前在本目录中下载过go-ethereum,故显示其已存在。然后进入到go-ethereum目录,进行编译:
[root@localhost opt]# cd go-ethereum/
[root@localhost go-ethereum]# make geth
由于我的客户端编译过了,所以没有显示编译细节,但只要编译成功便会在末尾显示:Run "/opt/go-ethereum/build/bin/geth" to launch geth来提示启动geth,注意双引号之间的内容为你安装时的路径,会有所不同。
二.搭建一个私有链
1.新建一个geth工作目录
$ mkdir geth
$ cd geth
$ mkdir db
$ touch gensis.json //执行完成后目录结构
geth
├── db
└── gensis.json
2.创世区块配置文件
gensis. json文件内容如下:
{"config": {"chainId": 15,"homesteadBlock": 0,"eip155Block": 0,"eip158Block": 0},"coinbase" : "0x0000000000000000000000000000000000000000","difficulty" : "0x40000","extraData" : "","gasLimit" : "0xffffffff","nonce" : "0x0000000000000042","mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000","parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000","timestamp" : "0x00","alloc": { }}
相关参数作用表如下:
chainID | 指定了独立的区块链网络 ID。网络 ID 在连接到其他节点的时候会用到,以太坊公网的网络 ID 是 1,为了不与公有链网络冲突,运行私有链节点的时候要指定自己的网络 ID。不同 ID 网络的节点无法相互连接 |
homesteadBlock |
取值为0表示正在使用homesteadBlock版本。 以太坊的发展分成了四个阶段:(每个阶段进步到下一个阶段都是通过硬分叉的方式实现的) 1.Frontier(前沿):2015年7月30日,以太坊发布了Frontier阶段,此时的软件还不太成熟,但可以进行基本的挖矿测试去中心化应用(Dapps),该阶段参与者主要为开发者。 2.HomesteadBlock(家园):在2016年3月14日(圆周率节),以太坊发布了HomesteadBlock阶段。以太坊开始平稳运行,提供了图形界面的钱包,普通用户也可以体验和使用以太坊。 3.Metropolis(大都会):Metropolis被分成了两个阶段:Byzantium(拜占庭)和Constantinople (居士坦丁堡)。 2017.10.16,以太坊拜占庭硬分叉成功,引入了包括:zk-SNARKs(简明非交互零知识证明)、revert功能、return和抽象账户。 2019年2月底,以太坊区块链的第7,080,000区块作为激活点正式开启君士坦丁堡硬分叉,点在于将以太坊的共识机制由PoW向PoW+PoS混合机制过渡,从而使整个以太坊网络更加的轻盈、快捷与安全。按官方说法,具体在现有以太坊PoW主网上进行升级的有以下5个方面: (1).EIP 145:给EVM增加移位相关指令,包括左移SHL,逻辑右移SHR,算术右移SAR (2).EIP 1014:产生合约地址的一种新规则,与状态通道有关。规则为keccak256( 0xff ++ address ++ salt ++ keccak256(init_code)))[12:] (3).EIP 1052:为EVM增加EXTCODEHASH指令,这个指令可以获得一个合约bytecode的keccak256的hash值; (4).EIP 1283:修改EVM的SSTORE指令gas计算方式,预计会减少许多合约的gas消耗,需要硬分叉支持; (5).EIP 1234:将是潜在最有争议的提案,也需要硬分叉支持,它包括难度炸弹(Difficulty Bomb)协议推迟12个月和挖矿奖励调整,难度炸弹使挖矿难度随时间推移越来越高,挖矿奖励调整将挖矿奖励从3个降低到2个; 4.Serenity(宁静) |
eip155Block | eip是ethereum improvement proposal的缩写,你的链不会因为因为这些提议分叉,故设置为“0”即可 |
eip158Block | eip是ethereum improvement proposal的缩写,你的链不会因为因为这些提议分叉,故设置为“0”即可 |
mixhsah | 与nonce配合用于挖矿,由上一个区块的一部分生成的哈希。注意它和nonce的设置需要满足以太坊的Yellow paper, 4.3.4. Block Header Validity, (44)章节所描述的条件。 |
nonce | nonce就是一个64位随机数,用于挖矿,注意它和mixhash的设置需要满足以太坊的Yellow paper, 4.3.4. Block Header Validity, (44)章节所描述的条件。 |
difficulty | 设置设置当前区块难度,如果难度过大,CPU挖矿就很难 |
alloc | 给某个账户预分配以太币 |
coinbase | 矿工帐号 |
timestamp | 创世块的时间戳 |
parentHash | 上一个区块的哈希值,由于是创世区块,所以值为0 |
extraData | 可以写入32Byte大小的任意数据,每个block都会有,由挖出block的miner来决定要不要在里面写什么 |
gasLimit | 该值设置对GAS的消耗总量限制,用来限制区块能包含的交易信息总 |
3.初始化
//进入geth目录中,执行初始化命令:
$ geth --datadir "./db" init gensis.json
geth init命令用来初始化区块连,命令可以带有选项和参数,其中–datadir后面跟了一个目录名db,表示指定数据存放目录为db,gensis.json为init命令的参数。初始化成功后,会在db目录中生成geth和keystore两个文件夹,其中,geth/db/geth/chaindata中存放的是区块数据,geth/db/keystore中存放的是账户数据。geth目录结构如下:
[root@localhost geth]# tree ../geth/
../geth/
├── db
│ ├── geth
│ │ ├── chaindata
│ │ │ ├── 000001.log
│ │ │ ├── CURRENT
│ │ │ ├── LOCK
│ │ │ ├── LOG
│ │ │ └── MANIFEST-000000
│ │ └── lightchaindata
│ │ ├── 000001.log
│ │ ├── CURRENT
│ │ ├── LOCK
│ │ ├── LOG
│ │ └── MANIFEST-000000
│ └── keystore
└── gensis.json
4.启动私有链
//console 2>>geth.log 表示将日志输出到geth.log,打开另外一个控制台执行tail -f 查看日志
$ geth --datadir "./db" --nodiscover console 2>>geth.log
geth启动参数详解:
identity | 区块链的标识,用于标识目前网络的名字 |
datadir | 指明当前区块链私钥和网络数据存放的位置 |
port | 指定以太坊网络监听端口,默认为30303 |
rpc | 开启HTTP-RPC服务,可以进行智能合约的部署和调试 |
rpcaddr | 指定HTTP-RPC服务监听地址,默认为“localhost” |
rpcapi | 设置允许连接的rpc的客户端,一般为db、eth、net、web3 |
rpcport | 指定HTTP-RPC服务监听端口,默认为8545 |
networkid |
指定以太坊id,其实就是区块链网络的身份标识,共有链为1,测试链为3,默认启动id为1 |
etherbase | 指定矿工帐号,默认为keystory中首个帐号 |
mine |
开启挖矿,默认为CPU挖矿 |
minerthreads | 挖矿占用CPU线程数,默认为4 |
nodiscover | 关闭自动连接节点,但可以手动添加节点,在搭建私有链时,为避免其他节点连入私有链,可使用该命令 |
maxpeers | 设置允许最大节点数,默认为25 |
console | 启动命令行模式,可以在geth中执行命令 |
启动后进入javascript命令行控制台,显示结果如下:
[root@localhost geth]# geth --datadir "./db" --nodiscover console 2>>geth.log
Welcome to the Geth JavaScript console!instance: Geth/v1.8.20-unstable/linux-amd64/go1.11
coinbase: 0x1baed334cbf41a94daef7b247beebd6fdc45100c
at block: 112 (Mon, 25 Mar 2019 21:37:17 HKT)datadir: /opt/geth/dbmodules: admin:1.0 debug:1.0 eth:1.0 ethash:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0>
打开另一个终端,执行 tail -f geth.log可以时刻查看相关日志内容:
[root@localhost geth]# tail -f geth.log
INFO [03-26|10:20:55.418] Loaded most recent local header number=112 hash=842b42…2c27da td=28062821 age=12h43m38s
INFO [03-26|10:20:55.418] Loaded most recent local full block number=112 hash=842b42…2c27da td=28062821 age=12h43m38s
INFO [03-26|10:20:55.418] Loaded most recent local fast block number=112 hash=842b42…2c27da td=28062821 age=12h43m38s
INFO [03-26|10:20:55.419] Loaded local transaction journal transactions=0 dropped=0
INFO [03-26|10:20:55.419] Regenerated local transaction journal transactions=0 accounts=0
WARN [03-26|10:20:55.419] Blockchain not empty, fast sync disabled
INFO [03-26|10:20:55.584] New local node record seq=2 id=c9432d51b9f92fe1 ip=127.0.0.1 udp=0 tcp=30303
INFO [03-26|10:20:55.584] Started P2P networking self="enode://688e30b0fd748189b882fb54af5ddf5c2d11555fbf9fd869a96b0f59729cab43b7e6f4c02e59df5ee94a4c2890e54804fa7a2e9476d82e708a903b6b9cc5383a@127.0.0.1:30303?discport=0"
INFO [03-26|10:20:55.587] IPC endpoint opened url=/opt/geth/db/geth.ipc
INFO [03-26|10:20:55.786] Etherbase automatically configured address=0x1Baed334CbF41A94daEF7B247bEebD6fdC45100C
以太坊的javascript控制台中内置了一些以太坊对象,通过这些对象我们可以很方便的与以太坊交互:
- eth:提供了操作区块链相关的方法
- net:提供了查看p2p网络状态的方法
- admin:提供了管理节点相关的方法
- miner:提供启动和停止挖矿的方法
- personal:提供了管理账户的方法
- txpool:提供了查看交易内存池的方法
- web3:除了包含以上对象中有的方法,还包含了一些单位换算的方法
三.以太坊私有链上的基本操作
1.创建用户
//查看帐户,可以看到有我之前创建的三个账户,若没有创建过账户则显示: []
> eth.accounts
["0x1baed334cbf41a94daef7b247beebd6fdc45100c", "0xdb3d4ae8e3624d1ec75bba5c4da024c5984e3b17", "0x115b0ba0ffddb13cd513ec38679e1089c252c839"]
>
//建帐户的方式有两种,第一种创建帐户时直接初始化密码
//如下创建的账户为“0xeed50d745a67eaa2a2eaf9e08a2485d1c1145103”,密码为“444444”
> personal.newAccount("444444")
"0xeed50d745a67eaa2a2eaf9e08a2485d1c1145103"
>
//第二种方法是先创建账户,然后输入密码"555555"
> personal.newAccount()
Passphrase:
Repeat passphrase:
"0x6ccfd99b17da037d7f974aa9bd9bd65a04f514d1"
>
//此时查看已创建的用户,有5个
> eth.accounts
["0x1baed334cbf41a94daef7b247beebd6fdc45100c", "0xdb3d4ae8e3624d1ec75bba5c4da024c5984e3b17", "0x115b0ba0ffddb13cd513ec38679e1089c252c839", "0xeed50d745a67eaa2a2eaf9e08a2485d1c1145103", "0x6ccfd99b17da037d7f974aa9bd9bd65a04f514d1"]
>
//账户创建成功后会返回账户地公钥,生成的账户文件在keystore文件夹下:
db/keystore/
├── UTC--2019-03-25T13-11-16.002140069Z--1baed334cbf41a94daef7b247beebd6fdc45100c
├── UTC--2019-03-25T13-15-38.206845483Z--db3d4ae8e3624d1ec75bba5c4da024c5984e3b17
├── UTC--2019-03-25T13-28-30.957174224Z--115b0ba0ffddb13cd513ec38679e1089c252c839
├── UTC--2019-03-26T02-47-59.331021277Z--eed50d745a67eaa2a2eaf9e08a2485d1c1145103
└── UTC--2019-03-26T02-52-31.434967091Z--6ccfd99b17da037d7f974aa9bd9bd65a04f514d1
2.查看余额
以太币的最小单位为wei,1 ether = wei
//由于我的账户挖过矿,且发生过交易,故前三个账户有余额,单位为wei
//而新创建的两个账户未发生过交易,故余额为0
> eth.getBalance(eth.accounts[0])
557000021000000000000
> eth.getBalance(eth.accounts[1])
999979000000000000
> eth.getBalance(eth.accounts[2])
2000000000000000000
> eth.getBalance(eth.accounts[3])
0
> eth.getBalance(eth.accounts[4])
0
>
3.挖矿
//在挖矿之前要先设置挖矿奖励地址,默认为创建的第一个账户地址,即eth.accounts[0]
> miner.setEtherbase(eth.accounts[0])
true
>
//设置完成后,查看是否设置成功,返回结果为设置后的挖矿奖励地址
> eth.coinbase
"0x1baed334cbf41a94daef7b247beebd6fdc45100c"
>
//开始挖矿
> miner.start()
null
//在之前打开的另一个终端中可以看到挖矿日志记录
INFO [03-26|13:05:36.057] Updated mining threads threads=4
INFO [03-26|13:05:36.057] Transaction pool price threshold updated price=1000000000
INFO [03-26|13:05:36.059] Commit new mining work number=113 sealhash=527c2b…95e338 uncles=0 txs=0 gas=0 fees=0 elapsed=746.685µs
INFO [03-26|13:06:55.500] Successfully sealed new block number=113 sealhash=527c2b…95e338 hash=0b5a7f…5202bb elapsed=1m19.441s
INFO [03-26|13:06:55.500] ? mined potential block number=113 hash=0b5a7f…5202bb
INFO [03-26|13:06:55.501] Commit new mining work number=114 sealhash=20a5a4…07fb8c uncles=0 txs=0 gas=0 fees=0 elapsed=137.993µs
INFO [03-26|13:06:56.895] Successfully sealed new block number=114 sealhash=20a5a4…07fb8c hash=5bae51…cca193 elapsed=1.394s
INFO [03-26|13:06:56.895] ? mined potential block number=114 hash=5bae51…cca193
INFO [03-26|13:06:56.895] Commit new mining work number=115 sealhash=75cdcb…42129c uncles=0 txs=0 gas=0 fees=0 elapsed=187.946µs
INFO [03-26|13:07:00.470] Successfully sealed new block number=115 sealhash=75cdcb…42129c hash=52352a…4e6153 elapsed=3.574s
INFO [03-26|13:07:00.470] ? mined potential block number=115 hash=52352a…4e6153
INFO [03-26|13:07:00.470] Commit new mining work number=116 sealhash=8590f9…10690f uncles=0 txs=0 gas=0 fees=0 elapsed=138.993µs
INFO [03-26|13:07:01.796] Successfully sealed new block number=116 sealhash=8590f9…10690f hash=2bc9b7…1d7a1c elapsed=1.326s
INFO [03-26|13:07:01.796] ? mined potential block number=116 hash=2bc9b7…1d7a1c
INFO [03-26|13:07:01.797] Commit new mining work number=117 sealhash=4f171e…976b8e uncles=0 txs=0 gas=0 fees=0 elapsed=208.115µs
INFO [03-26|13:07:02.863] Successfully sealed new block number=117 sealhash=4f171e…976b8e hash=89b748…8abebc elapsed=1.066s
INFO [03-26|13:07:02.864] ? mined potential block number=117 hash=89b748…8abebc
INFO [03-26|13:07:02.864] Commit new mining work number=118 sealhash=d23ff5…1ee086 uncles=0 txs=0 gas=0 fees=0 elapsed=173.425µs
INFO [03-26|13:07:06.387] Successfully sealed new block number=118 sealhash=d23ff5…1ee086 hash=573e64…31050e elapsed=3.522s
INFO [03-26|13:07:06.387] ? mined potential block number=118 hash=573e64…31050e
INFO [03-26|13:07:06.387] Commit new mining work number=119 sealhash=c8840a…c9c0af uncles=0 txs=0 gas=0 fees=0 elapsed=228.028µs
INFO [03-26|13:07:12.455] Successfully sealed new block number=119 sealhash=c8840a…c9c0af hash=dae780…86c027 elapsed=6.068s
INFO [03-26|13:07:12.455] ? mined potential block number=119 hash=dae780…86c027
INFO [03-26|13:07:12.455] Commit new mining work number=120 sealhash=f89e85…f46780 uncles=0 txs=0 gas=0 fees=0 elapsed=134.293µs
INFO [03-26|13:07:12.851] Successfully sealed new block number=120 sealhash=f89e85…f46780 hash=b034c6…e2c5fc elapsed=395.460ms
INFO [03-26|13:07:12.851] ? block reached canonical chain number=113 hash=0b5a7f…5202bb
INFO [03-26|13:07:12.851] ? mined potential block number=120 hash=b034c6…e2c5fc
4.解锁账户
//方式一,参数中只传入要解锁的账户地址,控制台提示输入密码时请输入密码,成功后返回true
> personal.unlockAccount(eth.accounts[2])
Unlock account 0x115b0ba0ffddb13cd513ec38679e1089c252c839
Passphrase:
true
> //方式二,参数中传入账户地址和密码
> personal.unlockAccount(eth.accounts[2],"333333")
true
> //方式三,参数中传入账户地址、密码、账户解锁状态持续时间
> personal.unlockAccount(eth.accounts[2],"333333",300)
true
>
5.交易
//发起交易,内容为accounts[2]账户向accounts[3]账户发送1 ether以太币,返回值为交易hash
//此时的交易正在矿工的交易池中等待被打包
> eth.sendTransaction({from: eth.accounts[2], to: eth.accounts[3],value: web3.toWei(1,"ether")})
"0x28f7e6989893d6e8b1cd26d5d7a285654f5a3c8eff7d6b2029817496deb8bda0"//查看accounts[2]用户和accounts[3]用户的余额如下:
> eth.getBalance(eth.accounts[2])
2000000000000000000
> eth.getBalance(eth.accounts[3])
0//查看交易池等待被打包的交易,其中有一条pending的交易,表示已提交但还未被处理的交易
> txpool.status
{pending: 1,queued: 0
}//查看pending交易详情
> txpool.inspect.pending
{0x115B0ba0ffDdB13Cd513ec38679E1089C252C839: {0: "0xeed50D745A67EaA2A2EAf9e08A2485D1c1145103: 1000000000000000000 wei + 90000 gas × 1000000000 wei"}
}
//要使交易被处理,必须要挖矿,启动挖矿后,等待挖到一个区块之后就可以停止挖矿了
> miner.start(1);admin.sleepBlocks(1);miner.stop();
null
>
//在日志显示终端可以看到正常执行后的挖矿日志
INFO [03-26|14:37:06.377] Updated mining threads threads=1
INFO [03-26|14:37:06.377] Transaction pool price threshold updated price=1000000000
INFO [03-26|14:37:06.378] Commit new mining work number=418 sealhash=14f834…2c37a4 uncles=0 txs=0 gas=0 fees=0 elapsed=376.473µs
INFO [03-26|14:37:06.381] Commit new mining work number=418 sealhash=f1a1e0…13c185 uncles=0 txs=1 gas=21000 fees=2.1e-05 elapsed=3.129ms
INFO [03-26|14:37:06.537] Successfully sealed new block number=418 sealhash=f1a1e0…13c185 hash=a79ae1…4cce3e elapsed=158.086ms
INFO [03-26|14:37:06.537] ? block reached canonical chain number=411 hash=8de5b1…25b9e2
INFO [03-26|14:37:06.537] ? mined potential block number=418 hash=a79ae1…4cce3e
INFO [03-26|14:37:06.537] Commit new mining work number=419 sealhash=58dcdb…adddbf uncles=0 txs=0 gas=0 fees=0 elapsed=217.251µs
//此时交易已经成功打包,并且加入区块链中了,此时查看余额:
> eth.getBalance(eth.accounts[2])
999979000000000000
> eth.getBalance(eth.accounts[3])
1000000000000000000
>
accounts[3]余额正确为1 ether,而accounts[2]似乎应该由2 ether变为1 ether,但结果并不是,这其中的原由便需要好好解释一下。
在以太坊中一个比较重要的概念就是gas,当你调用一个智能合约的时候,整个网络中的每个矿工会分别执行你调用的合约程序,这会消耗矿工的CPU、内存、与硬盘空间,在合约中执行每个命令的消耗会用单位gas计数。
gasPrice是你愿意为单位gas支付的费用,以gwei为单位表示。1 gwei = 1 000 000 000 wei,在交易中gasPrice是由发起交易的人规定的,每个矿工接收到交易请求时,会根据gasPrice的高低来决定是否要打包进区块中。
如果你希望矿工运行你的合约,你最好提供高一点的gasPrice。在某种程度上,这是一场基于合约运行,有多意愿付费驱动下的竞价。
在每个交易中必须包含gasLimit和gasPrice的值。gasLimit代表这个交易在执行过程中最多被允许消耗的gas数量。gasLimit和gasPrice就代表了交易发送者愿意为执行交易支付的wei的最大值。其最多可能付款金额 = gasLimit X gasPrice (wei)。
在交易完成后,如果实际消耗的gas小于gasLimit,那么剩余的gas会返回给交易发起者,交易实际法非金额计算方式:
实际交易费 = gasUsed X gasPrice
回到本例子中,通过查看下文中本交易被发起时的交易详情可以知道,本例子的转账交易发起时的gas = 90000,gasPrice = 1 000 000 000。而交易完成后被打包进区块后,该交易的详细信息中gasUsed: = 21 000 。
故这次交易的花费了:21 000 X 1 000 000 000 = 21 000 000 000 000 wei
accounts[2]向accounts[3]转账了1 ether后剩余1 ether = 1 000 000 000 000 000 000 wei,但还要承担交易费,故:
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
— 2 1 0 0 0 0 0 0 0 0 0 0 0 0
——————————————————————
9 9 9 9 7 9 0 0 0 0 0 0 0 0 0 0 0 0
所以accounts[2]账户的余额为999 979 000 000 000 000
6.区块
//查看指定交易哈希值 所对应交易 被发起时的交易详情:
> eth.getTransaction("0x28f7e6989893d6e8b1cd26d5d7a285654f5a3c8eff7d6b2029817496deb8bda0")
{blockHash: "0xa79ae173965c379d7fd75e865faf955e65d55feb1b3afe840a18fbe8f04cce3e",blockNumber: 418,from: "0x115b0ba0ffddb13cd513ec38679e1089c252c839",gas: 90000,gasPrice: 1000000000,hash: "0x28f7e6989893d6e8b1cd26d5d7a285654f5a3c8eff7d6b2029817496deb8bda0",input: "0x",nonce: 0,r: "0xb7579b66aa0e051b7ec7e8dad8f4d07454d415df6d7a2497a76f76b7e4bb0b62",s: "0x53357a3b80e1e478012b89df718be16613f4f3a20141393acb16538dd3b02d23",to: "0xeed50d745a67eaa2a2eaf9e08a2485d1c1145103",transactionIndex: 0,v: "0x42",value: 1000000000000000000
}
>
其中参数详情 :
blockHash | 交易所在区块的哈希值。当这个区块处于pending时将会返回null |
blockNumber | 交易所在区块的区号。当这个区块处于pending时将会返回null |
from | 交易发起的地址 |
gas | 交易发起者提供的gas数量 |
gasPrice | 交易发起者提供的gasPrice,单位为wei |
hash | 交易的哈希值 |
input | 交易附带的数据 |
nonce | 交易的发起者在之前发起过的交易数量 |
transactionIndex | 交易在区块中的序号。当这个区块处于pending时将会返回null |
value | 交易附带的货币量,单位为wei |
to | 交易接受者的地址 |
//查看指定交易哈希值 所对应交易 被打包进区块时的详细信息:
> eth.getTransactionReceipt("0x28f7e6989893d6e8b1cd26d5d7a285654f5a3c8eff7d6b2029817496deb8bda0")
{blockHash: "0xa79ae173965c379d7fd75e865faf955e65d55feb1b3afe840a18fbe8f04cce3e",blockNumber: 418,contractAddress: null,cumulativeGasUsed: 21000,from: "0x115b0ba0ffddb13cd513ec38679e1089c252c839",gasUsed: 21000,logs: [],logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",root: "0x45ddc0ef9a33a1e97acdd4b966ad631278f15a5744699ff7672f13f07d60e2e3",to: "0xeed50d745a67eaa2a2eaf9e08a2485d1c1145103",transactionHash: "0x28f7e6989893d6e8b1cd26d5d7a285654f5a3c8eff7d6b2029817496deb8bda0",transactionIndex: 0
}
>
其中参数详情 :
blockHash | 交易所在区块的哈希值。 |
blockNumber | 交易所在区块的区号。 |
contractAddress | 创建的合约地址。如果是一个合约创建交易,则返回合约地址,其他情况返回null |
cumulativeGasUsed | 当前交易执行后累计花费的gas总值 |
from | 交易发送者的地址 |
gasUsed | 执行当前这个交易单独花费的gas |
logs | 这个交易产生的日志对象数组 |
logsBloom | logsBloom由logs中的address与topics共同决定,详细请看以太坊黄皮书,作用是便于快速查找监听的事件是否在该交易中产生 |
root | 交易执行后的stateroot |
to | 交易接收者的地址。如果是一个合约创建的交易,返回null |
transactionHash | 交易的哈希值 |
transationIndex | 交易在区块里面的序号 |
常用查询区块命令:
- 查看当前区块总数:eth.blockNumber
- 查询最新区块:eth.getBlock("latest") 返回该区块的详细信息,eth.getBlock(blockNumber/blockHash)根据区块 Number或Hash查询区块
//查看当前区块链节点中第Number为1的区块详情 > eth.getBlock(1) {difficulty: 249472,extraData: "0xd683010814846765746886676f312e3131856c696e7578",gasLimit: 4290772993,gasUsed: 0,hash: "0xc18e6263be514c9c79b822d1d1fa9c17f25c148f4e71fb876da2c676eb19df2a",logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",miner: "0x1baed334cbf41a94daef7b247beebd6fdc45100c",mixHash: "0xf67374106da53196fe47cd9002ea0e18415d209efae336619c8fa4fab1359455",nonce: "0x1f7390e1d36e28fd",number: 1,parentHash: "0xa0e580c6769ac3dd80894b2a256164a76b796839d2eb7f799ef6b9850ea5e82e",receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",size: 535,stateRoot: "0xbb491beccc4865b5728c8cec43bc46846591d54ba2a87dbd86aa03af18bcdbfd",timestamp: 1553519563,totalDifficulty: 511616,transactions: [],transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",uncles: [] } >
参数含义如下:
difficulty 挖矿难度,后面区块难度会随着区块高度升高而提高 extraData 当前区块链附加信息,若创世区块该值为空,则在第二个区块中会保存创建该私有链时的geth、go,以及操作系统版本,保存的信息为第一个挖到该区块的矿工信息 gasLimit 该区块允许的最大gas数 GasUsed gas花费,在以太坊中交易和部署智能合约会消耗gas hash 当前区块哈希值 logsBloom logsBloom由logs中的address与topics共同决定,详细请看以太坊黄皮书,作用是便于快速查找监听的事件是否在该交易中产生 miner
挖到该区块的矿工地址 mixHash 与nonce配合用于挖矿,由上一个区块的一部分生成的hash nonce 工作量证明 number 当前区块链高度 parentHash 上一个区块链哈希值 receiptsRoot 区块receipt trie的根 sha3Uncles 对叔区块进行hash运算的结果 size 区块大小,以字节为单位 stateRoot 块的状态树根结果 timestamp 时间戳 totalDifficulty 达到该区块的难度综总数 transactions 以数组的形式保存交易的tx值 transactionsRoot 交易的默尔克树根 uncles 当前区块引用的束缚区块的哈希值
7.账户管理
(1).创建新帐号
[root@localhost geth]# geth --datadir "./db1" account new
INFO [03-29|20:39:53.169] Maximum peer count ETH=25 LES=0 total=25
Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase:
Repeat passphrase:
Address: {b1d70e94ffcba142fd024ece374e0be3cd9c08ad}
(2).列举已存在帐号
[root@localhost geth]# geth --datadir "./db1" account list
INFO [03-29|20:46:02.607] Maximum peer count ETH=25 LES=0 total=25
Account #0: {c4e87bb87064c40ecc07ed8955f35533c92a82f0} keystore:///opt/geth/db1/keystore/UTC--2019-03-28T13-07-34.305959164Z--c4e87bb87064c40ecc07ed8955f35533c92a82f0
Account #1: {70083e2f06da81015c1ee24b60a53fde4f30bddb} keystore:///opt/geth/db1/keystore/UTC--2019-03-28T14-08-09.815911074Z--70083e2f06da81015c1ee24b60a53fde4f30bddb
Account #2: {da66a23edbec03deef9eea953c1a2d865bf3acb3} keystore:///opt/geth/db1/keystore/UTC--2019-03-28T14-21-37.216641721Z--da66a23edbec03deef9eea953c1a2d865bf3acb3
Account #3: {b1d70e94ffcba142fd024ece374e0be3cd9c08ad} keystore:///opt/geth/db1/keystore/UTC--2019-03-29T12-40-09.120020587Z--b1d70e94ffcba142fd024ece374e0be3cd9c08ad
(3).修改账户密码
[root@localhost geth]# geth --datadir "./db1" account update b1d70e94ffcba142fd024ece374e0be3cd9c08ad
INFO [03-29|20:48:53.009] Maximum peer count ETH=25 LES=0 total=25
Unlocking account b1d70e94ffcba142fd024ece374e0be3cd9c08ad | Attempt 1/3
Passphrase:
INFO [03-29|20:48:58.466] Unlocked account address=0xB1d70e94FfCBa142FD024ecE374e0bE3Cd9C08ad
Please give a new password. Do not forget this password.
Passphrase:
Repeat passphrase:
(4).导入密钥文件
[root@localhost geth]# geth --datadir "./db1" account import ecc.key
INFO [03-29|21:06:10.906] Maximum peer count ETH=25 LES=0 total=25
Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase:
Repeat passphrase:
Address: {fc563cb4086c1c9621c72b1a9f8d3b487fe438e9}
//其中ecc.key是ECDSA[椭圆曲线数字签名算法(ECDSA)是使用椭圆曲线密码(ECC)对数字签名算法(DSA)的模拟]的私钥
[root@localhost geth]# cat ecc.key
25066ae7675c08bdafded1c1403cc5d1431597149eac21261c5a3002339a007b
8.区块数据管理
(1).导出区块数据
//将db1目录中的区块数据导入到bak文件中:
[root@localhost geth]# geth --datadir "./db1" export ./bak
INFO [03-29|21:14:53.492] Maximum peer count ETH=25 LES=0 total=25
INFO [03-29|21:14:53.496] Allocated cache and file handles database=/opt/geth/db1/geth/chaindata cache=512 handles=1024
INFO [03-29|21:14:53.810] Disk storage enabled for ethash caches dir=/opt/geth/db1/geth/ethash count=3
INFO [03-29|21:14:53.810] Disk storage enabled for ethash DAGs dir=/root/.ethash count=2
INFO [03-29|21:14:53.870] Loaded most recent local header number=35 hash=7f2f97…73ba58 td=4603649 age=23h9m8s
INFO [03-29|21:14:53.870] Loaded most recent local full block number=35 hash=7f2f97…73ba58 td=4603649 age=23h9m8s
INFO [03-29|21:14:53.870] Loaded most recent local fast block number=35 hash=7f2f97…73ba58 td=4603649 age=23h9m8s
INFO [03-29|21:14:53.870] Exporting blockchain file=./bak
INFO [03-29|21:14:53.870] Exporting batch of blocks count=36
INFO [03-29|21:14:53.873] Exported blockchain file=./bak
Export done in 3.070252ms
//导入成功好会在当前目录下生成一个bak文件
[root@localhost geth]# ll
total 48
-rwxr-xr-x. 1 root root 19230 Mar 29 21:14 bak
drwx------. 4 root root 49 Mar 28 22:06 db1
-rw-r--r--. 1 root root 65 Mar 29 21:06 ecc.key
-rw-r--r--. 1 root root 605 Mar 28 20:11 gensis.json
-rw-r--r--. 1 root root 20377 Mar 28 22:06 geth.log
(2).移除区块数据
[root@localhost geth]# geth --datadir "./db1" removedb
INFO [03-29|21:18:16.562] Maximum peer count ETH=25 LES=0 total=25
/opt/geth/db1/geth/chaindata
Remove this database? [y/N] y
Remove this database? [y/N] y
INFO [03-29|21:18:23.975] Database successfully deleted database=chaindata elapsed=1.166ms
/opt/geth/db1/geth/lightchaindata
Remove this database? [y/N] y
Remove this database? [y/N] y
INFO [03-29|21:18:26.355] Database successfully deleted database=lightchaindata elapsed=1.276ms
(3).导入区块数据
//导入区块数据之前要用gensis.json文件执行初始化
[root@localhost geth]# geth --datadir "./db1" init gensis.json
INFO [03-29|21:19:30.372] Maximum peer count ETH=25 LES=0 total=25
INFO [03-29|21:19:30.374] Allocated cache and file handles database=/opt/geth/db/geth/chaindata cache=16 handles=16
INFO [03-29|21:19:30.464] Writing custom genesis block
INFO [03-29|21:19:30.464] Persisted trie from memory database nodes=0 size=0.00B time=21.737µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [03-29|21:19:30.464] Successfully wrote genesis state database=chaindata hash=1ef75f…d1799a
INFO [03-29|21:19:30.464] Allocated cache and file handles database=/opt/geth/db/geth/lightchaindata cache=16 handles=16
INFO [03-29|21:19:30.548] Writing custom genesis block
INFO [03-29|21:19:30.548] Persisted trie from memory database nodes=0 size=0.00B time=6.821µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [03-29|21:19:30.549] Successfully wrote genesis state database=lightchaindata hash=1ef75f…d1799a
//初始化完成后就可以导入区块数据le
[root@localhost geth]# geth --datadir "./db1" import ./bak
INFO [03-29|21:21:32.802] Maximum peer count ETH=25 LES=0 total=25
INFO [03-29|21:21:32.805] Allocated cache and file handles database=/opt/geth/db1/geth/chaindata cache=512 handles=1024
INFO [03-29|21:21:32.990] Writing default main-net genesis block
INFO [03-29|21:21:33.440] Persisted trie from memory database nodes=12356 size=1.88mB time=72.102914ms gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [03-29|21:21:33.440] Disk storage enabled for ethash caches dir=/opt/geth/db1/geth/ethash count=3
INFO [03-29|21:21:33.440] Disk storage enabled for ethash DAGs dir=/root/.ethash count=2
INFO [03-29|21:21:33.468] Loaded most recent local header number=0 hash=d4e567…cb8fa3 td=17179869184 age=49y11mo2w
INFO [03-29|21:21:33.468] Loaded most recent local full block number=0 hash=d4e567…cb8fa3 td=17179869184 age=49y11mo2w
INFO [03-29|21:21:33.468] Loaded most recent local fast block number=0 hash=d4e567…cb8fa3 td=17179869184 age=49y11mo2w
INFO [03-29|21:21:33.469] Importing blockchain file=./bak
ERROR[03-29|21:21:33.471]
########## BAD BLOCK #########
Chain config: {ChainID: 1 Homestead: 1150000 DAO: 1920000 DAOSupport: true EIP150: 2463000 EIP155: 2675000 EIP158: 2675000 Byzantium: 4370000 Constantinople: <nil> Engine: ethash}Number: 1
Hash: 0xa5144c4a46a7047492371bdee8459785d09ae44e32d06a8a96c7409dfd35013aError: unknown ancestor
##############################ERROR[03-29|21:21:33.471] Import error err="invalid block 35: unknown ancestor"
INFO [03-29|21:21:33.471] Blockchain manager stopped
Import done in 2.573417ms.CompactionsLevel | Tables | Size(MB) | Time(sec) | Read(MB) | Write(MB)
-------+------------+---------------+---------------+---------------+---------------Read(MB):0.00000 Write(MB):2.38956
Trie cache misses: 0
Trie cache unloads: 0Object memory: 268.085 MB current, 267.908 MB peak
System memory: 334.967 MB current, 334.967 MB peak
Allocations: 1.118 million
GC pause: 396.612µsCompacting entire database...
Compaction done in 786.903722ms.CompactionsLevel | Tables | Size(MB) | Time(sec) | Read(MB) | Write(MB)
-------+------------+---------------+---------------+---------------+---------------0 | 0 | 0.00000 | 0.59842 | 0.00000 | 1.915271 | 1 | 1.91526 | 0.13436 | 1.91527 | 1.91526Read(MB):1.88542 Write(MB):6.22033
INFO [03-29|21:21:34.304] Database closed database=/opt/geth/db1/geth/chaindata
(4).dump
//从区块链中dump制定区块数据,geth命令后可以传入区块编号或区块hash值
$ geth --datadir "./db1" dump 0
9.远程节点连接
(1).查看节点信息
> admin.nodeInfo
{enode: "enode://4b13086b294f1b7b0801ff78eb62cd9b1bf2991819ccc2b69df9a0371a031c0d8f25e84aa92781cb590a20b4ed25d4c67184c44470e008a77dfbe9ec4fedfe20@127.0.0.1:38690?discport=0",enr: "0xf895b8407a227a916f7016b5dec567b0ecb41d6452fb41130b69bf861fae9ed271ff9c46607ae835137bf7b5508dfdd86a8df8ce859c61d044513ed707d72f5a58e272a50183636170ccc5836574683fc58373686806826964827634826970847f00000189736563703235366b31a1024b13086b294f1b7b0801ff78eb62cd9b1bf2991819ccc2b69df9a0371a031c0d83746370829722",id: "d0bd4223d5c476927e34787e99179c27da96f4e1dee7913a345d445c89a164dd",ip: "127.0.0.1",listenAddr: "[::]:38690",name: "Geth/v1.8.20-unstable/linux-amd64/go1.11",ports: {discovery: 0,listener: 38690},protocols: {eth: {config: {byzantiumBlock: 0,chainId: 1337,clique: {...},constantinopleBlock: 0,eip150Block: 0,eip150Hash: "0x0000000000000000000000000000000000000000000000000000000000000000",eip155Block: 0,eip158Block: 0,homesteadBlock: 0},difficulty: 37,genesis: "0x004680c14f64dd409489eb632569fb1440bffbfbbc4996263e3f3cadb10e37a1",head: "0x782e496b3110c566136549d7dfbc2cf7700b6414fcc3aa9d74eb5984ab076f39",network: 1337},shh: {maxMessageSize: 1048576,minimumPoW: 0.2,version: "6.0"}}
}
(2).添加其他节点
可以通过admin.addPeer()方法连接到其他节点,两个接节点想要联通,必须保证网络时相通的,并且要指定相同的networkid。我的第一个节点时我的本机节点,另一个节点时远程服务器节点,两个节点的gensis.json文件相同。
首先通过在远程服务器节点获取其encode信息,注意要把encode中的[::]替换成该机器的IP地址。
> admin.nodeInfo.enode
"enode://e5b417b09f971fc06a4a413ed4ed2d431cd303e286e44b01cf6c126c51708bde44cf6f692f611e441ba22f0ebce1b384d3f418af338589358daacd322f9df966@207.246.103.126:30303"
//在本机连接远程服务器节点
> admin.addPeer("enode://e5b417b09f971fc06a4a413ed4ed2d431cd303e286e44b01cf6c126c51708bde44cf6f692f611e441ba22f0ebce1b384d3f418af338589358daacd322f9df966@207.246.103.126:30303")
true
(3).查看已连接的远程节点
> admin.peers
[{caps: ["eth/63"],enode: "enode://e5b417b09f971fc06a4a413ed4ed2d431cd303e286e44b01cf6c126c51708bde44cf6f692f611e441ba22f0ebce1b384d3f418af338589358daacd322f9df966@207.246.103.126:30303",id: "f40c748606f81f3d600584b70e4425165ed68ed47484d20afe5051655e509719",name: "Geth/v1.8.23-stable/linux-amd64/go1.10.3",network: {inbound: false,localAddress: "192.168.124.48:48550",remoteAddress: "207.246.103.126:30303",static: true,trusted: false},protocols: {eth: {difficulty: 1,head: "0x1ef75f7ced81aa0ff14865c59117439c6ae6760468d64e46e06311190dd1799a",version: 63}}
}]
10.通过attach命令连接已启动节点
当通过geth命令启动了一个以太坊私有链时,会在数据目录下生成一个geth.ipc文件,在本例子中即为“./db/geth.ipc”。通过attach命令可以连接这个已经启动的节点,来启动一个Js命令环境:
[root@localhost geth]# geth --datadir "./db" attach ipc:./db/geth.ipc
Welcome to the Geth JavaScript console!instance: Geth/v1.9.0-unstable-acbb8a14/linux-amd64/go1.11
coinbase: 0x8c7ae59ab7e5d510ae3f09a9544978f50315b5f5
at block: 107 (Sat, 06 Apr 2019 15:27:50 HKT)datadir: /opt/geth/dbmodules: admin:1.0 debug:1.0 eth:1.0 ethash:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0>
四.常见问题
1.执行miner.start()返回null
解决方案借鉴自:https://blog.csdn.net/billwzf/article/details/83145111
geth版本更新之后,–dev模式(回归测试模式)下新增了一个参数项:
--dev Ephemeral proof-of-authority network with a pre-funded developer account, mining enabled
--dev.period value Block period to use in developer mode (0 = mine only if transaction pending) (default: 0)
–dev是我们常用的参数,之前版本中我们只用使用–dev然后执行miner.start()就可以挖矿,但是在后面的版本中,当我们会发现只有发送交易了才会挖一个块。引起此问题的原因就是新增了–dev.period value配置项。此配置默认值为0,也就是说只有pending中存在交易才会挖矿。所以–dev参数依旧使用,然后再在后面添加–dev.period 1,即设置dev.period的参数为1。
由于此参数的存在,使得存在两种启动模式:
1.dev模式
//该模式下需要在pending中先存在交易才可以挖矿
geth --networkid 15 --dev console 2>>geth.log
2.dev自动挖矿模式
geth --networkid 15 --dev --dev.period 1 console 2>>geth.log