这是区块链系列的第三篇,内容是在服务器上去搭建一条属于自己的以太坊私链,同时部署运行我们之前写好的demo,实现通信记录等等完整的操作,因为有过在Windows环境下搭建私链的经验,看起来并不难,但是,实际上,这里是让我消耗最多时间的地方!!!在这个过程中,真的是,大坑小坑不断,并且,我的目的是最终能真正跑起来,所以也需要去解决更多的问题
文章目录前言一:环境搭建搭建go环境geth的安装二:私有链搭建以及geth使用创建创世区块初始化创世块启动私有链三:控制台交互geth自动关闭问题解决方案挖矿返回null进入dev模式初始化时指定账户余额:项目启动前准备开放8545端口客户端的自动挖矿两种模式自动挖矿的比较geth的后台运行总结 一:环境搭建首先说一下我的环境,我的服务器是阿里云的,CentOS7.
还是一样,我用的是geth客户端
之前讲过,在不同环境搭建安装geth客户端方法是不一样的,是的不一样,CentOS只能先下载部署好go环境,然后再去github上clone下geth客户端
搭建go环境可以先在服务器上运行以下命令:
cd /usr/local/
mkdir go
cd go/
wget https://storage.googleapis.com/golang/go1.10.2.linux-amd64.tar.gz
tar -zxvf go1.10.2.linux-amd64.tar.gz
echo "export GOROOT=/usr/local/go" >> /etc/profile
echo "export PATH=/usr/local/go/bin:$PATH" >> /etc/profile
source /etc/profile
go version
最后执行完应该可以查询出go的版本,截图如下:
如果不能查询出正确的go版本,那么你直接打开/etc/profile配置文件,直接在文件尾部修改确认好你的路径没有问题,然后再重新source一下就可以了。
geth的安装接下来是geth的安装,先 git clone下go-ethereum项目,如果服务器上没git,那么先安装git
//正常情况
yum install git
//没有权限的话:
sudo yum install git
接着,执行以下指令:
mkdir /usr/local/apps/geth/
cd /usr/local/apps/geth/
git clone https://github.com/ethereum/go-ethereum.git
cd go-ethereum/
make all
echo "export PATH=$PATH:/usr/local/apps/geth/go-ethereum/build/bin" >> /etc/profile
source /etc/profile
geth version
正常的话能走到结尾会返回以下结果:
但是,大概率是不会正常的,因为在make过程中 可能会出现以下错误:
exec: “gcc”: executable file not found in $PATH
则是没有安装gcc的原因,执行
yum install gcc
还一定会出现无法进行clean all操作,具体信息大概是你缺了某个包某个文件,你进去它说的地方一看,还真的没有它说的缺的那个包;
实际上是因为我们clone下来的是整个master分支,所以我们需要切换分支,再进行clone即可,可以先去它的github上查看一下目前的分支信息,现在是19年12月份,现在是1.9;所以运行以下命令:
git checkout release/1.9
make geth
echo "export PATH=$PATH:/usr/local/apps/geth/go-ethereum/build/bin" >> /etc/profile
source /etc/profile
geth version
这样就能成功返回geth版本信息了。
最后,可以设置一下防火墙相关:
可以关闭防火墙:
systemctl stop firewalld
systemctl disable firewalld
也可以添加防火墙规则,允许geth使用某几个端口:
firewall-cmd --zone=public --add-port=8087/tcp --permanent
firewall-cmd --zone=public --add-port=30303/tcp --permanent
systemctl enable firewalld
systemctl start firewalld
区块链需要同步网络时间,所以需要启用网络时间同步,执行以下命令:
systemctl enable ntpd
systemctl start ntpd
二:私有链搭建以及geth使用
按照以前的感觉,我们可以先创建创世区块
创建创世区块首先,先创建一个文件夹,然后定义自己的创世区块,创世区块信息写在一个 JSON 格式的配置文件中。首先如下:genesis.json:
{
"nonce":"0xdeadbeefdeadbeef",
"mixhash":"0x0000000000000000000000000000000000000000000000000000000000000000",
"difficulty": "0x4000",
"alloc": {},
"coinbase":"0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x00000000",
"gasLimit":"0xffffffff",
"config":{
"chainId": 1024,
"homesteadBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0
}
}
初始化创世块
输入命令完成初始化:
geth --datadir data init genesis.json
启动私有链
初始化完成之后,输入以下命令即可启动私有链:
geth --identity "TestNode" --rpc --rpcport "8545" --datadir data --port "30303" --nodiscover --allow-insecure-unlock console
三:控制台交互
关于利用geth与控制台交互的各种指令和在Windows下无差别,可以看之前的博客,也可以看这个:Geth管理API文档 这个是geth客户端很完整的指令文档
geth自动关闭问题在这个过程中,如果你的服务器配置比较低,很可能会出现输入个命令没啥反应,并且geth这个进程随时可能会被杀掉退出,这是因为服务器内存不足触发Linux的OOM killer操作
解决方案1、设置 –cache,发现并不能解决问题。
2、升级内存,钱到位了就直接解决了。
3、用shell编程书写一个监控程序,发现问题重启即可。
4、设置swap分区。具体命令如下:
free -m
dd if=/dev/zero of=/swap bs=10M count=800
chmod 600 /swap
ll /swap
mkswap /swap
swapon /swap
swapon -s
free -m
这种方法是一个折中方法,但是够用。
挖矿返回null接着,当我们想在链上和在Windows一样先进行挖矿赚点钱的时候,发现输入miner.start()指令,会返回一个null,没其他任何反应,这里可能有几种情况,首先,可以确定的是geth高版本源码规定了不管挖没挖矿,都会返回Null.所以你首先确定一下你有没有矿工账户,其次看一下自己的区块数量有没有改变,如果都没有改变,那么你是正常模式下还是dev模式?因为在高版本geth里,–dev模式下新增了一个参数项:–dev.period value;value的默认值是0,这表示在默认情况下,只有发生交易才会进行挖矿(dev模式是回归测试模式,主要用来给开发人员提供一个方便的开发测试环境),如果你是dev模式的话,那么退出然后指定好–dev.period value的值重新进就可以了,如果不是dev模式,账号正常,但就是没有挖矿,那么你只能通过以下方法来解决这个问题了:
进入dev模式我们退出控制台,重新进,输入命令:
geth --identity "TestNode" --rpc --rpcport "8545" --dev --dev.period 1 --datadir data --port "30303" --nodiscover --allow-insecure-unlock console
然后会发现,报了这个Bug
Fatal: Failed to unlock developer account: could not decrypt key with given password
这是因为我们刚才自己创建了账号,而在 dev 模式下,启动节点后,系统默认提供一个开发者账号,并且这个账号密码是空;
所以加下来我们需要清除掉所有的信息,其实也就是吧data文件删除干净,然后不需要初始化创世块,直接输入上面的指令进入控制台就可以了,也就是直接输入:
geth --identity "TestNode" --rpc --rpcport "8545" --dev --dev.period 1 --datadir data --port "30303" --nodiscover --allow-insecure-unlock console
初始化时指定账户余额:
刚才因为账户没钱导致的没法交易所以要先挖矿,但是其实我们还可以在初始化时就指定余额。
在我们的 genesis.json里有这样一个参数: “alloc”: ,在这个参数可以指定某个账号的特定信息,包括账户余额。
那么我们修改我们的genesis文件,然后删掉相关数据,重新初始化即可。
修改的genesis文件的alloc配置如下:
"alloc": {"0x8df95cc3baed5d10d3a27c2705e3726c9aadf635":{"balance":"1000000000000000000000000000000"}},
怎么获得前面的账户地址呢,也有两种方法,一种是直接用geth指令创建账户(不用进入控制台模式就可以创建);第二就是把之前创建过的账户的地址记下来,然后把之前那个账户的keystore中对应的文件复制好重新放在你现在打算开启的私链地址的keystore中即可。
到了这里,我们在windows所做的在geth客户端的所有操作就基本都可以在服务器上去操作了,接下来就是结合我们的springBoot项目来实现了
项目启动前准备关于SpringBoot项目怎么在服务器上跑的一系列相关就不说了,记得修改我们的demo代码,主要是两个地方:
//修改连接地址
Web3j web3j = Web3j.build(new HttpService("http:// 你的服务器ip:8545"));
//新建链上账号时,修改保存核心文件路径
wallet = WalletUtils.generateBip39Wallet(walletPwd, new File("/usr/local/block/data/keystore/"));
//发起交易时,修改文件路径
String keyStoreKey = "/usr/local/block/data/keystore/";
大概就是这几个地方,修改完成之后打包部署上去即可。
可以把秘钥或者核心文件名等相关信息保存到你的数据库上,可以方便很多
开放8545端口项目部署完之后,这个时候直接请求对应接口你会发现访问会被拒绝,这个时候你需要先去阿里云控制台先设置好安全组,开发出8545端口,接着你要让你的客户端是可连接的
你可以通过以下命令查看你的客户端是否可连接:
wget 你的ip:8545
netstat -tnulp | grep 8545
netstat -all
ssh -v -p 8545 root@你的ip
如果不是可连接的,那么你运行这些命令会发现你会被拒绝。
通过netstat命令查看你的8545端口开放情况,一般默认是127.0.0.1或者localhost;这也意味着你只能在自身服务器上去相连接,但是跨服务器是不可以的,这种情况显然很不适合以后的开发,所以你可以退出geth客户端,重新进入,进入的时候指定你的客户端的开放情况
geth --identity "TestNode" --rpc --rpcaddr="0.0.0.0" --rpcport "8545" --dev --dev.period 1 --datadir data --port "30303" --nodiscover --allow-insecure-unlock console
这样的话就是任意联网的设备都可以请求你的8545端口,但是一般不要这样开放,因为很容易遭受攻击,我的开放了两天,一直有国外ip的机器在攻击,最好是在节点间设置 rpc 通信的白名单,这样也可以防止黑客暴力破解 keystore 的密码。
到这里就保证了你的项目和客户端是已经能互相连通的了
客户端的自动挖矿运行我们的项目,并且对客户端进行连接,我们接下来的需求是,怎么让它自动挖矿,而不是我们一直去运行miner.start()命令
一样的,geth客户端支持我们做这样的事情,这要分两种情况
首先是dev模式下的指令如下:
geth --identity "TestNode" --rpc --rpcaddr="0.0.0.0" --rpcport "8545" --dev --dev.period 1 --datadir data --port "30303" --nodiscover --allow-insecure-unlock --mine --etherbase 0 console 2
这个指令意思就是允许你一边启动一边自动挖矿,dev模式会简单许多
另外就是假设你不是dev模式,那么你应该这样启动:
首先创建一个password.json文件,里面直接保存你的矿工账户的密码;
接着,运行下面指令:
geth --rpc --rpcaddr="0.0.0.0" --rpcport "8545" --datadir data --allow-insecure-unlock --unlock 0x8df95cc3baed5d10d3a27c2705e3726c9aadf635 --password password.json --mine --etherbase 0 console 2
这样就实现了自动挖矿
两种模式自动挖矿的比较最大的差别就是dev模式下,挖矿速度更快,并且你可以设置为交易发生时再挖矿,资源消耗上更少,普通模式资只要开启了自动挖矿就会一直挖下去,不管有没有交易发生,源消耗更大;需要注意得一点是,dev模式下由于系统的默认账户密码是空,安全性比较不好,所以建议你自建账号,然后将其相关数据加密存储,并且将其设置为矿工行号即可,这样只需要在启动自动挖矿时去解锁账户即可
geth的后台运行到这里之前,你会发现你一退出客户端,服务就停了,这就很不符合实际情况了,还好你可以通过以下指令完成geth的后台启动并且自动挖矿,并且设置成交易提交再进行挖矿,减少资源损耗,并保证数据能准时准确快速上链:
nohup geth --rpc --rpcaddr="0.0.0.0" --rpcport "8545" --datadir data1 --allow-insecure-unlock --dev --dev.period 0 --mine --etherbase 0 2>> get.log &
这个时候会发现我们的8545端口是一直处于开启监听的状态
总结到了这里,基本就实现了我们在服务器搭建了一条私链,同时我们用代码实现了将数据上链的过程,同时,我们也可以把我们的挖矿服务器和跑服务的服务器分开来,比如本地跑项目,服务器挖矿等等的操作,这样就基本保证项目的落地性和可运行性,当然,关于安全等等方面的问题也是在真实环境中你需要考虑的。
最后,在附带一点智能合约的相关链接吧:
如何实现可升级的智能合约
开发编译智能合约
web3j教程:以太坊智能合约
智能合约初体验
你还可以去github上获取到很多相关资料,祝你好运!
如果中间有问题或者其他情况可以留言,我们一起交流学习