最近开始了解区块链,并开始学习以太坊。以太坊并不是我们单纯了解的可以对以太币进行交易的平台,它是是一个开源的有智能合约功能的公共区块链平台。在这个平台上,借助它专用的加密货币--以太币(ETH)提供了去中心化的以太虚拟机环境处理点对点的合约。

作为一个初学者,想要快速进入以太坊的学习门槛,搭建一个以太坊的私有链,不失为一个很好的途径。通过在私有链上创建账户、部署合约并进行交易,完成这一系列操作后,对于了解以太坊以及基于以太坊进行开发,就可以初窥门径了。

一、环境准备

为了以后更深入的学习区块链相关技术,以及避免在搭建私链的过程中出现各种莫名其妙的问题,当然,也为了看起来逼格高一些:),我选择在Linux系统下完成私有链的搭建。具体环境如下:

      宿主系统:Windows 10专业版

      虚拟机:   VMware Workstation Pro 12.5.4

      操作系统:Ubuntu 18.4.1 64位

二、安装Geth

Geth是以太坊的客户端,其全称是go-ethereum。以太坊的客户端用于接入以太坊网络,进行账户管理、交易、挖矿、智能合约部署开发等相关的操作。目前有多种语言实现的客户端,Geth是用Go语言编写的,支持接入以太坊网络并成为一个完整节点。也可作为一个 HTTP-RPC 服务器对外提供 JSON-RPC 接口。其他常用的以太坊客户端如下:

  • Parity:Rust 语言实现
  • cpp-ethereum:C++ 语言实现
  • ethereumjs-lib:JavaScript 语言实现
  • Ethereum(J):Java 语言实现
  • ethereumH:Haskell 语言实现
  • pyethapp: Python 语言实现
  • ruby-ethereum:Ruby 语言实现

Geth的安装有两种方式,一种是直接下载程序进行安装,另一种是通过编译源码安装。这里我选择的是通过下载程序安装。

打开命令行窗口,依次执行以下命令:

sudo apt-get install software-properties-common
sudo add-apt-repository -y ppa:ethereum/ethereum
sudo add-apt-repository -y ppa:ethereum/ethereum-dev
sudo apt-get update
sudo apt-get install ethereum

执行完 以上命令后,执行如下命令:

geth --help

会显示Geth的版本和命令参数等信息

 

附上Geth的Git项目地址和wiki地址 

Git:https://github.com/ethereum/Go-ethereum

wiki:https://github.com/ethereum/Go-ethereum/wiki/Building-Ethereum

三、定义创世区块

1、创建工作目录

## 尽量不要在需要管理员权限的路径下创建工作目录,避免出现因权限问题引起的麻烦
mkdir ~/privatechain
## data目录用于存放账户信息和区块数据
mkdir ~/privatechain/data

2、创建创世区块配置文件

在privatechain目录下新建genesis.json文件,文件内容如下:

{
  "config": {
     "chainId": 10,
     "homesteadBlock": 0,
     "eip155Block": 0,
     "eip158Block": 0
  },
  "coinbase"   : "0x0000000000000000000000000000000000000000",
  "difficulty" : "0x2000",
  "extraData"  : "",
  "gasLimit"   : "0xffffffff",
  "nonce"      : "0x0000000000000042",
  "mixhash"    : "0x0000000000000000000000000000000000000000000000000000000000000000",
  "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
  "timestamp"  : "0x00",
  "alloc": {
     "08a58f09194e403d02a1928a7bf78646cfc260b0": {
         "balance": "0x200000000000000000000000000000000000000000000000000000000000000"
     },
     "87366ef81db496edd0ea2055ca605e8686eec1e6": {
         "balance": "0x200000000000000000000000000000000000000000000000000000000000000"
     }
  }
}

如果是初次接触以太坊,对文件的内容不了解没有关系。等我们完成了整个私有链的创建,并在链上完成了和账户、合约及交易的相关操作,就会理解其中大部分的含义了。下面的表格对配置文件做简要说明:

        参数名                                                                                      描      述
chainId指定了独立的区块链网络 ID。网络 ID 在连接到其他节点的时候会用到,以太坊公网的网络 ID 是 1,为了不与公有链网络冲突,运行私有链节点的时候要指定自己的网络 ID。不同 ID 网络的节点无法相互连接
homesteadBlock当设置为0表示使用homestead发布该链
noncenonce就是一个64位随机数,用于挖矿,注意它和mixhash的设置需要满足以太坊的Yellow paper, 4.3.4. Block Header Validity, (44)章节所描述的条件
mixhash与nonce配合用于挖矿,由上一个区块的一部分生成的hash。注意它和nonce的设置需要满足以太坊的Yellow paper, 4.3.4. Block Header Validity, (44)章节所描述的条件
difficulty设置设置当前区块的难度,越大挖矿就越难
alloc用来预置账号以及账号的以太币数量,因为私有链挖矿比较容易,所以我们也可以不需要预置有币的账号,需要的时候自己创建即可以
coinbase矿工账号,可以随便写
timestamp设置创世块的时间戳
parentHash上一个区块的hash,创世区块的该项参数就为0
extraData附加信息,可以随便写
gasLimit该值设置对GAS的消耗总量限制,用来限制区块能包含的交易信息总和。我们创建的是私有链,可以填最大

3、创建创世区块

cd ~/privatechain
geth --datadir ./data init genesis.json

执行完以上命令,在privatechain下的data目录中会生成两个目录,结构如下:

其中:

geth目录用于保存我们所建私有链的区块数据

keystore目录用于保存用户的账户数据

四、启动私有链

执行如下命令,启动私有链:

## --datadir 表示当前区块链网络数据存放的位置
## --nodiscover 表示该链禁止被其他节点发现
## console 2>>geth.log 表示将日志输出到geth.log。可以打开另外一个控制台执行 tail -f 查看日志
geth --datadir ./data --nodiscover console 2>>geth.log

启动成功后如下图所示:

还有一种启动方式,其作用是启动PRC通信,启动命令如下:

geth --nodiscover --identity "my etherum" --rpc --rpccorsdomain "*" --datadir ./data --port "30303" --rpcapi "db,eth,net,web3" --networkid 10 --allow-insecure-unlock console 2>>geth.log

PRC启动命令的参数含义如下表所示: 

         参数名                                                                                描             述 
identity区块链的标识,用于标示目前网络的名字
nodiscover关闭p2p网络的自动发现,需要手动添加节点,这样有利于我们隐藏私有网络
init指定创世块文件的位置,并创建创世块
datadir当前区块数据存放的位置
port网络监听端口,默认30303
rpc启动rpc通信
rpcapi设置允许连接rpc的客户端,一般为db,eth,net,web3
rpccorsdomain指定什么url能连接到你的节点执行rpc定制端任务,如果输入的是“*”,则任何url都可以连接到你的rpc实例
rpcaddr连接rpc的地址,默认为localhost
rpcport连接rpc的端口,默认为8545
networkid设置当前区块链的网络ID,用于区分不同的网络,是一个数字
console启动命令行模式,可以在Geth中执行命令

如果在创建创世区块之前已经启动了私有链,在创建了创世区块配置文件后,可以通过以下命令重新进入geth控制台,并使用配置文件更新区块:

geth --datadir data --networkid 10 console

提示:--networkid参数即为创世区块配置文件中的chainId

 五、创建账户

为了后期测试方便,我们创建两个账户,用于演示账户之间的转账操作。

启动私有链后,在控制台输入如下命令:

## newAccount的参数为账号密码,这里新账户的密码分别是123456和000000
> personal.newAccount("123456")
> personal.newAccount("000000")

创建账户后会返回遗传hash码,代表的是新建账户的地址

 此时查询私链上的账户及账户的余额信息,会返回相应的结果。

下面显示私链上的账户信息

由于还没有开始挖矿,账户中的余额为0

 六、挖矿

新创建的账户都是没有余额的,只有通过挖矿赚钱,才能让账户有收入,下面介绍如何开始挖矿。

1、开始挖矿

## start的参数表示挖矿使用的线程数,若不写表示使用最大线程数。返回true或null表示执行成功
> miner.start()

当percentage = 100时,就会开始挖矿

提示:

  • 第一次启动挖矿会先生成挖矿所需的 DAG 文件,这个过程有点慢,等进度达到 100% 后,就会开始挖矿
  • 如果第一次挖矿遇到一直卡在Commit new mining work,可能是因为创世区块初始化失败,检查初始化genesis.json的指令,排查原因并解决
  • 还有一种挖矿失败可能是因为之前存在的链,把~/.ethash删除即可

 2、停止挖矿

执行如下命令停止挖矿

> miner.stop()

挖矿结束后再次查看账户余额

挖到一个区块会奖励5个以太币,挖矿所得的奖励会进入矿工的账户,这个账户叫做 coinbase,默认情况下 coinbase 是本地账户中的第一个账户。

此时查看第二个账户的余额仍然为0

 我们可以通过miner.setEtherbase() 将其他账户设置成coinbase

重新开始挖矿,过一段时间后,查看第二个账户下的余额,此时账户已经有余额了。

此时显示的账户余额的单位是Wei,如果要转成以太币,可进行如下操作:

 

可以看出第一个账户和第二个账户的以太币余额分别为5和15,这表明他们分别挖到了1个区块和3个区块。

 提示:Wei是以太币的最小单位,1Eth(以太币)= 1,000,000,000,000,000,000 Wei  (10的18次方)。通常,大家也使用Gwei作为展示单位。比较常用的就是Eth,Gwei和Wei。以太坊还有其他的单位,他们的换算关系如下:

  • Kwei(Babbage) = 1,000 Wei
  • Mwei(Lovelace) = 1,000,000 Wei
  • Gwei(Shannon) = 1,000,000,000 Wei
  • Microether(Szabo) = 1,000,000,000,000 Wei
  • Milliether(Finney) = 1,000,000,000,000,000 Wei
  • Ether = 1,000,000,000,000,000,000 Wei

 七、转账

这一节我们演示转账操作。转账前我们再看一下两个账户的余额:

 执行以下转账命令,将第一个账户的2个以太币转到第二个账户下:

> amount = web3.toWei(2,'ether')
> eth.sendTransaction({from:eth.accounts[0], to:eth.accounts[1], value:amount})

 执行后显示如下:

从提示可以看出是账户没有解锁,需要先解锁才能执行转账操作。解锁命令如下:

## 第一个参数为解锁的账户,第二个参数是账户密码
personal.unlockAccount(eth.accounts[0],‘123456’)

返回 true 表示解锁成功

下面重新执行上面的转账操作,返回结果如下:

转账成功后输出的是此次交易的 hash 码。

此时查看账户信息,发现账户余额并没有发生变化。

 这是因为当前没有处于挖矿状态,只有处于挖矿的状态才能确认打包交易。但此时我们可以在交易池中看到有一笔待确认的交易。执行一下命令查看交易池信息:

> txpool.status

从返回结果中我们可以看到有一个待确认的交易。

 执行如下命令查看待确认交易的详细信息:

> eth.getBlock("pending", true).transactions

 返回交易信息如下:

此时我们重新启动挖矿,稍后再查看账户信息如下所示:

可以看到第二个账户多了2个ETH,如果挖矿时间段,此时查看第一个账户,应该比之前少了2个ETH。如果挖矿时间长,则账户余额应该会有较大变化,相比之前会更多。

八、查看区块和交易信息

1、查看区块信息

  • 查看区块总数
> eth.blockNumber

  •  根据区块编号查看区块信息
> eth.getBlock(1)

 2、查看交易信息

查看上面转账交易成功后输出的交易hash,通过该hash我们可以查看交易详细信息

> eth.getTransaction("0x5372d5d4580c5cd2055e13e31d81079ffe64fa151930cc5c70f8c1659d527249
")

返回结果如下:

九、 Geth控制台常用对象及命令

Geth控制台内置了一些用来操作以太坊的Javascript对象,用户可以直接使用这些对象。主要包括:

  • eth:操作区块链相关的方法
  • net:查看p2p网络状态的方法
  • admin:与管理节点相关的方法
  • miner:启动&停止挖矿的方法
  • personal:管理账户的方法
  • txpool:查看交易内存池的方法
  • web3:包含了以上对象,还包含一些单位换算的方法

这些对象的常用命令有:

  •  personal.newAccount():创建账户
  • personal.unlockAccount():解锁账户
  • eth.accounts:枚举系统中的账户
  • eth.getBalance():查看账户余额,返回值的单位是 Wei(Wei 是以太坊中最小单位,类似比特币中的聪,1 ether = 10^18 Wei)
  • eth.blockNumber:列出区块总数
  • eth.getBlock():根据区块编码获取区块详细信息
  • eth.getTransaction():根据交易hash获取交易详细信息
  • miner.start():开始挖矿
  • miner.stop():停止挖矿
  • eth.coinbase:挖矿奖励的账户
  • web3.fromWei():Wei 换算成以太币
  • web3.toWei():以太币换算成 Wei
  • txpool.status:交易池中的状态
  • admin.addPeer():连接到其他节点

 到这里,在本机搭建以太坊私有链的步骤就全部完成了。后面我会继续介绍在《CentOS下搭建Geth环境》以及《Geth私链的多节点运行》。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐