作为区块链, 链子总要有个头,所以需要创建一个创世块作为头部,才好往下添加,也可以说,创世块是链的基础。创世文件名称命名为genesis.json,内容如下,为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": "0x00002",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": { },
"number": "0x0",
"gasUsed": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
各参数说明
mixhash | 与nonce配合用于挖矿,由上一个区块的一部分生成的hash。注意他和nonce的设置需要满足以太坊的Yellow paper, 4.3.4. Block Header Validity。. |
nonce | nonce就是一个64位随机数,用于挖矿,注意他和mixhash的设置需要满足以太坊的Yellow paper, 4.3.4. Block Header Validity, (44)章节所描述的条件。 |
difficulty | 设置当前区块的难度,如果难度过大,cpu挖矿就很难,这里设置较小难度 |
alloc | 用来预置账号以及账号的以太币数量,因为私有链挖矿比较容易,所以我们不需要预置有币的账号,需要的时候自己创建即可以。 |
coinbase | 矿工的账号,随便填 |
timestamp | 设置创世块的时间戳 |
parentHash | 上一个区块的hash值,因为是创世块,所以这个值是0 |
extraData | 附加信息,随便填,可以填你的个性信息 |
gasLimit | 该值设置对GAS的消耗总量限制,用来限制区块能包含的交易信息总和,因为我们是私有链,所以填最大。 |
#创建一个genesis.json的文件夹
sudo gedit genesis.json
#创建一个privateChain的文件夹
mkdir privateChain
#移动genesis.json到privateChain文件夹里
mv genesis.json privateChain/
#进入privateChain目录下
cd privateChain
#data为新建文件夹
geth --datadir data --networkid 20200107 --rpc --rpccorsdomain "*" init genesis.json
因为每一个节点都是从创世块开始,为保证创建节点在同一条链上,在初始化创世块时,为他指定一个networkid。
--networkid 20140628,为私链id,可以任意修改为自己的id,以太坊主网id为1,后续要搭建私链下的其他节点,networkid必须相同
--datadir data 中data是文件夹的名称,私链数据会存储在这个文件夹内(也就是说在privateChain目录下新建一个data文件)。当要在同一计算机中创建其他私链节点时,可创建另外的文件夹,例如data2,然后通过--datadir data2区分不同的私链节点,如果未设置--datadir,则会读取以太坊主网的数据,默认位置在/root/.ethereum中。
init初始化genesis.json,创建创世区块(创建区块时也就创建好了第一个节点)。如果执行成功,在终端大致会是这个样子
如果创建成功privateChain下会出现以下文件
geth文件夹下用来存放私链的相关数据,keystore文件夹下存放的是该链的用户信息。在围绕私链的一系列动作完成后。
(如果不想跳坑,此步请参考第八步下的错误提示:HTTP通道解锁账户解决方法)
#退到privateChain目录
cd ..
#启动以太坊私有链客户端
geth --datadir data --networkid 20200107 --rpc --rpccorsdomain "*" --nodiscover --port 16333 --rpcport 8546 console
rpccorsdomain是允许chrome插件MetaMask,remix等跨域访问web3接口。
console即可开启geth客户端,需要说明的是,需设置端口
--port 16333 系统默认是30303
--rpcport 8546 系统默认是8545
如果启用第二个测试节点,port以及rpcport应与第一个节点不同
每次启动该条私有链时都要执行此命令,且进入相同目录下
也可以如下这样写(经供参考,按需索取推荐——最好一步就写全一点,省的后来要改,呜呜~)
#退到privateChain目录
cd ..
#启动以太坊私有链客户端rpcaddr 本机IP(私有链ip)地址
geth --identity "myblockchain" –rpc --rpcaddr 127.0.0.1 --rpccorsdomain "*" --datadir data --port"16333" --rpcport 8546 --rpcapi "db,eth,net,web3" --allow-insecure-unlock --networkid 20200107 console
命令解释:
参数名称 | 参数描述 |
identity | 区块链的标示,随便填写,用于标示目前网络的名字 |
init | 指定创世块文件的位置,并创建初始块 |
datadir | 设置当前区块链网络数据存放的位置 |
port | 网络监听端口,默认监听30303 |
rpc | 启动rpc通信,可以进行智能合约的部署和调试 |
rpcapi | 设置允许连接的rpc的客户端,一般为db,eth,net,web3默认开启 |
networkid | 设置当前区块链的网络ID,用于区分不同的网络,是一个数字 |
console | 启动命令行模式,可以在Geth中执行命令 |
rpcaddr | 本机IP地址或公链服务器地址(默认为127.0.0.1,只能本地访问) |
--allow-insecure-unlock | 解锁HTTP |
--nodiscover | 关闭p2p网络的自动发现,需要手动添加节点,这样有利于我们隐藏私有网络 |
rpcport | ipc服务端口,默认端口号8545 |
到此步以太坊私有链就启动成功了。
为什么要创建账户?
因为接下去旷工要挖矿,没有账户是挖不了矿的,因为挖矿成功后,系统会奖励ETH,需要有账户接受奖励。
#账户查询1通用
personal.listAccounts
#矿工账户查询2,只有在创建好用户才可以查询,没有用户查询会报错
eth.coinbase
#创建账,注意“123456”就是密码了,可以更改为其他的字符串。
personal.newAccount("123456")
#括号里的1表示表示仅以一个线程挖矿,为空的话表示全部进程进行挖矿
miner.start(1)
首次会初始化,耐心等待,待进度(比例)到达100时会开始挖矿。
表示挖矿成功。
#查看账户
eth.accounts
#查看区块高度
eth.blockNumber
#查看创世区块
eth.getBlock(0)
#拿到挖到最后一个区块的矿工的名字
eth.getBlock(eth.blockNumber).miner
#将第一个账户设置为矿工
miner.setEtherbase(eth.accounts[0])
#查看当前节点信息
admin.nodeInfo
#自己节点的URL,在其他的客户端上执行admin.addPeer("自己节点的URL")告诉它们添加自己的节点
admin.nodeInfo.enode
#查看第一个账户余额
eth.getBalance(eth.accounts[0])
转账交易,要有两个或两个以上账户才能够开始转账,接下来我们要再创建建一个账户。
#创建第二个账户注意“654321”就是密码了,请自行更改为其他的字符串
personal.newAccount("654321")
#以太坊挖矿默认是第一个账户,因此只有第一个账户有余额,输入
#查询第一个账户余额(注意web3.fromWei的意思是将wei单位转换成ether,应为默认挖到矿的是wei)
web3.fromWei(web3.eth.getBalance(web3.eth.accounts[0]),"ether")
#查询第二个账户余额
web3.fromWei(web3.eth.getBalance(web3.eth.accounts[1]),"ether")
#开始转账第一个账户转账给第二个账户5个以太币
web3.eth.sendTransaction({from:web3.eth.accounts[0] , to: web3.eth.accounts[1],value: web3.toWei(5, "ether")})
#会提示需要密码或者解锁,那么我们需要解锁第一个账户,因为是用一个账户转出ether的personal.unlockAccount(web3.eth.accounts[0])
##注意解锁失败,请参看下述教程##
先查询
可以看到第一个账户余额是126eth,这是挖矿所得,第二个账户余额为0eth。
小提示:
备注eth单位解释:
kwei (1000 Wei)
mwei (1000 KWei)
gwei (1000 mwei)
szabo (1000 gwei)
finney (1000 szabo)
ether (1000 finney)
也就是说ether =wei * 10^18,也就是说精度可以达到18位。
开始转账
出现上述错误分析
出于安全考虑,默认禁止了HTTP通道解锁账户
解决方法
如果已经了解打开此功能的风险,可通启动命令中添加参数:
--allow -insecure -unlock
操作:先退出geth客户端加参数后重新进入geth客户端
#退出geth客户端
exit
#--allow-insecure-unlock解锁HTTP
geth --datadir data --networkid 20200107 --rpc --rpccorsdomain "*" --nodiscover --port 16333 --rpcport 8546 --allow-insecure-unlock console
#以太坊挖矿默认是第一个账户,因此只有第一个账户有余额,
#查询第一个账户余额(注意web3.fromWei的意思是将wei单位转换成ether,应为默认挖到矿的是wei)
web3.fromWei(web3.eth.getBalance(web3.eth.accounts[0]),"ether")
#查询第二个账户余额
web3.fromWei(web3.eth.getBalance(web3.eth.accounts[1]),"ether")
#开始转账第一个账户转账给第二个账户5个以太币
web3.eth.sendTransaction({from:web3.eth.accounts[0] , to: web3.eth.accounts[1],value: web3.toWei(5, "ether")})
#会提示需要密码或者解锁,那么我们需要解锁第一个账户,因为是用一个账户转出ether的
personal.unlockAccount(web3.eth.accounts[0])
上步已经解锁成功了,我们现在可以开始转账了
#开始转账,账户1转给账户2五个以太币
web3.eth.sendTransaction({from:web3.eth.accounts[0] , to: web3.eth.accounts[1],value: web3.toWei(5, "ether")})
注意:
解锁后有时间限制,如果你在这时间段无任何相关操作转账,再进行转账操作时将要重新输入账户密码。
此时说明转账已经提交成功,但是交易并未完成,还需要矿工挖矿提交新的区块,在区块中加入这次转账交易,提交新的区块全网的节点(按百分比算)确认完成后,交易才正式生效。
开始再次挖矿,同步交易
#开始挖矿,无论指定那个用户挖矿同步交易都可以,这里默认挖矿账户是第一个
miner.start()
挖矿成功后停止挖矿,再次查看账户余额
#产生矿标志时停止挖矿
miner.stop()
#查看账户1
web3.fromWei(web3.eth.getBalance(web3.eth.accounts[0]),"ether")
#查看账户2
web3.fromWei(web3.eth.getBalance(web3.eth.accounts[1]),"ether")
为什么账户1的比特币会比我们第一次查询时多呢?
那是因为再次执行挖矿同步交易的工程中,也会挖到新的币。
此时说明转账成功了。
到此步一条简单的私有链就搭建成功了。==》》下章节会讲述如何创建新节点。