本篇文章简单介绍使用go-ethereum链接以太坊的主网和测试网以及一些基础开发须知,着重介绍如何搭建一个私网的以太坊,至于以太坊应用开发,有机会的话,将在后面的文章中重点介绍。node
本篇文章中包含笔者花费大量心血理解并整理的配置和参数说明资料,望能够为诸位道友提供一些帮助。git
Go Ethereum能够安装的操做系统平台有Mac OS X,Windows以及Linux/Unix。详情请看Installation Instructions。github
这里介绍在Linux上,从go-ethereum源码构建的安装流程。官方提到的Linux/Unix平台包括Ubuntu,Arch和FreeBSD。这里以Ubuntu为例。golang
编译环境要求有 Go 和 C编译程序。安装方法以下:web
apt-get install -y build-essential golang
复制代码
切换到你准备编译go-ethereum源码的目录,执行命令:算法
git clone https://github.com/ethereum/go-ethereum
复制代码
上述命令会clone go-ethereum的主干分支代码,该分支代码是持续开发代码,若是想要使用发布代码,参见go-ethereum release。这里以当时最新的发布代码 v1.8.7 为例:docker
wget https://github.com/ethereum/go-ethereum/archive/v1.8.7.tar.gz
复制代码
tar zxvf v1.8.7.tar.gz
复制代码
将解压后的代码移动到你准备编译go-ethereum源码的目录。编程
当你准备好go-ethereum的源码后,进入go-ethereum源码工程顶级目录,执行命令:json
make geth
复制代码
(推荐)若是你想要编译出全部工具,执行:bootstrap
make all
复制代码
编译完成后,全部工具能够在 build/bin 目录下找到,将这些二进制文件取出来放到你选好的安装目录,或者就在原来的位置放着,这里我放到 /opt/xingweidong/eth/bin 目录下,接下来根据你的喜爱设置系统环境变量,添加以下内容:
export ETH_HOME=/opt/xingweidong/eth
export PATH=$PATH:$ETH_HOME/bin
复制代码
别忘了使用 source /etc/profile 或者其余你喜欢的方法更新你的环境变量信息。
geth命令,主要的Ethereum CLI客户端,是Ethereum网(main-, test- 或 private网)的入口,有能力做为一个full node(默认)存档节点(保留全部历史数据)或者一个light node(现场检索数据)节点运行。经由暴露在HTTP, WebSocket 或 IPC传输的顶部的JSON RPC端点,它能够被其余过程用做Ethereum网的网关。
提示:查看 geth 全部命令行选项使用 geth --help 或者查看 CLI Wiki page。
目前为止,大多数状况是人们想要简单地与Ethereum网进行交互:建立帐户;转移资金;部署并与合约交互。对于这种特殊的使用状况,用户不关心之前的历史数据,因此咱们能快速的同步当前的Ethereum网状态。执行命令:
geth console
复制代码
命令做用:
向开发者过渡,若是你想要创造合约,你几乎确定想要在没有任何真实资金的状况下作到这一点,直到你掌握整个系统。换句话说,代替链接到Ethereum main网,你会想要加入到一个 test网,它是和 main网彻底等价的,只须要:
geth --testnet console
复制代码
console子命令与上面的含义彻底相同而且它们在一个测试网上也一样有用。若是你跳到这一步,请看上面对它们的解释。
然而,指定 --testnet 将从新配置你的 Geth 实例一小部分:
注意:尽管有一些内部安全措施防止main网和test网的交易互换,你也应该确认老是为测试资产和真实资产使用分开的帐户。除非你手动移动帐户,Geth将默认正确分开两个网络,而且在它们之间将不会有任何帐户可用。
上述测试网络是基于ethash工做证实共识算法的跨客户端网络。所以,因为网络的低难度/安全性,它有必定的额外开销,而且更容易受到重组攻击。Go Ethereum还支持链接到称为Rinkeby的权威证实测试网络(由社区成员运营)。这个网络更轻,更安全,但只受到go-ethereum的支持。
geth --rinkeby console
复制代码
代替传递大量选项给 geth 二进制,你能传递一个配置文件经由:
geth --config /path/to/your_config.toml
复制代码
为了理解这个文件的写法,你能使用 dumpconfig 子命令export你的现有配置:
geth --your-favourite-flags dumpconfig
eg:geth --testnet dumpconfig
复制代码
注意:这个只在 geth v1.6.0以及以上版本有效。
经过使用Docker,你能够在你的机器上快速启动Ethereum并运行:
docker run -d --name ethereum-node -v /Users/alice/ethereum:/root \
-p 8545:8545 -p 30303:30303 \
ethereum/client-go
复制代码
上述命令将以快速同步模式启动geth,并具备1GB的DB内存容量。它也将在你的home目录下建立一个永久卷来储存你的区块链和映射的默认端口。还有一个 alpine 标签可用于image的精简版本。
若是你想要从其余容器或主机访问RPC,不要忘了 --rpcaddr 0.0.0.0。默认状况下,geth 绑定本地接口而且不可从外访问RPC端点。
做为一个开发者,你将想要及早开始经由你本身的程序而不是手动控制台与Geth和Ethereum网交互。为此,Geth已经内置支持一个基于APIs(standard APIs 和 Geth specific APIs)的JSON-RPC。它可以经由HTTP, WebSockets 和 IPC (unix sockets on unix based platforms, and named pipes on Windows)暴露。
IPC接口默认是激活的并暴露全部Geth支持的APIs,然而HTTP 和 WS接口须要手动激活而且因为安全缘由只能暴露一个APIs子集。这些能够根据你的须要打开或关闭并被配置。
详情请看 Programatically interfacing Geth nodes
维护你本身的私网是十分复杂的,由于在一个正规的网络中,大量配置的获取和受权须要手动设置。下面,咱们创建一个简单的私网以太坊。
说明:为了使下面建立私网以太坊的步骤更加直白,笔者将默认使用如下的geth选项值(请自行查看选项含义):
在开始以前,笔者先介绍一下如何建立以太坊帐户:
geth account new
复制代码
geth --datadir /root/privatenet/.ethereum account new
复制代码
按照提示输入帐户密码便可。
注意:建立私网以太坊帐户时,务必指定 --datadir 选项,不然会默认建立主网以太坊帐户。
首先,你须要创造你的网络的全部节点须要意识到并赞成的创世状态。这个由一个小JSON文件组成(例如,称它为 genesis.json):
{
"config": {
"chainId": 15,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"alloc" : {},
"coinbase" : "0x0000000000000000000000000000000000000000",
"difficulty" : "0x20000",
"extraData" : "",
"gasLimit" : "0x2fefd8",
"nonce" : "0x0000000000001993",
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp" : "0x00"
}
复制代码
参数说明(下表是笔者参考go-ethereum源码README和ethereum_yellow_paper整理所得,若有错误,请帮忙指正):
参数 | 描述 |
---|---|
alloc | 能够预置帐号以及帐号的以太币数量 |
coinbase | 区块受益者地址,能够设置成已存在的帐户。后面挖出的区块的受益者将是挖掘出那个区块的帐户(矿工) |
difficulty | 表明当前区块的难度等级(十六进制),这里定义创世区块的难度等级,难度等级越高,挖矿越难。后面生成的区块难度等级根据前一个区块的难度等级和时间戳计算获得 |
extraData | 一个包含这个区块相关数据的字节数组,任意填写。必须是32位之内 |
gasLimit | 执行这个事务应该被使用的gas的最大量。这个在任何计算被作以前是预付的,而且在以后不会增长 |
nonce | 表明从这个地址发送的事务数目,或者在关联代码的帐户状况下,这表明这个帐户创造的合约数目。(在Yellow Paper中对nonce有多处描述,这里选择了4.1章节的描述,) |
mixhash | 一个256位的hash,由nonce合并,证实在这个区块上已经执行足够量的计算 |
parentHash | 前一个(父级)区块的header的keccak256算法hash |
timestamp | 这个区块开始的Unix的time()和合理输出 |
上面这些域应该能够知足大多数需求,不过咱们建议改变 nonce 为一些随机值,这样你就能阻止不知名的远程节点访问你。若是你想要为了更早测试,预储备一些帐户,你能在 alloc 域进行帐户配置:
"alloc": {
"0x0000000000000000000000000000000000000001": {"balance": "111111111"},
"0x0000000000000000000000000000000000000002": {"balance": "222222222"}
}
复制代码
随着创世状态定义在上面的JSON文件,你应该在启动每一个节点以前,优先初始化它,以确认全部区块链参数被正确设置:
geth --datadir /root/privatenet/.ethereum init genesis.json
复制代码
当全部你想要运行的节点初始化到指望的创世状态,你将须要开始一个bootstrap节点,其余节点可使用它在你的网络或因特网中找到彼此。干净的方式是配置并运行一个独立的bootnode:
bootnode -genkey bootnode.key
复制代码
bootnode -nodekey bootnode.key
复制代码
当bootnode上线,它将展现一个 enode URL,例如:
INFO [05-09|01:47:05] UDP listener up self=enode://75535ebac1f5b2a644edb134dbe91c6c288353be1a5301864edae529630b35c5ff0c0ae9e07b2bcdef578c3ac1b72b2cda105c061c2c77067f1fd8ec54d852b7@[::]:30301
复制代码
其余节点可使用这个 enode URL 链接它并交换对等信息。确认用你的外部访问IP替换展现的IP地址信息(极可能是 [::])去获得真正的 enode URL。例如:
enode://75535ebac1f5b2a644edb134dbe91c6c288353be1a5301864edae529630b35c5ff0c0ae9e07b2bcdef578c3ac1b72b2cda105c061c2c77067f1fd8ec54d852b7@192.168.1.214:30301
复制代码
保存这个准确的 enode URL 到你的一个文本中或者其余什么地方,下面须要用到。
注意:你也可使用彻底成熟的Geth节点做为引导节点,但这是不太推荐的方式。
为了成员节点启动时使用的配置一致,须要写一个配置文件,例如 privatenet.toml(参考自 testnet 的配置, 执行命令 geth --testnet dumpconfig 可见):
# Note: this config doesn't contain the genesis block.
[Eth]
NetworkId = 3369
DatabaseCache = 768
GasPrice = 18000000000
[Eth.Ethash]
CacheDir = "ethash"
CachesInMem = 2
CachesOnDisk = 3
DatasetDir = "/root/privatenet/.ethash"
DatasetsInMem = 1
DatasetsOnDisk = 2
[Eth.TxPool]
NoLocals = false
Journal = "transactions.rlp"
Rejournal = 3600000000000
PriceLimit = 1
PriceBump = 10
AccountSlots = 16
GlobalSlots = 4096
AccountQueue = 64
GlobalQueue = 1024
Lifetime = 10800000000000
[Eth.GPO]
Blocks = 20
Percentile = 60
[Shh]
MaxMessageSize = 1048576
MinimumAcceptedPOW = 2e-01
[Node]
DataDir = "/root/privatenet/.ethereum"
IPCPath = "geth.ipc"
HTTPPort = 8545
HTTPVirtualHosts = ["localhost"]
HTTPModules = ["net", "web3", "eth", "shh"]
WSPort = 8546
WSModules = ["net", "web3", "eth", "shh"]
[Node.P2P]
MaxPeers = 25
NoDiscovery = false
BootstrapNodes = ["enode://75535ebac1f5b2a644edb134dbe91c6c288353be1a5301864edae529630b35c5ff0c0ae9e07b2bcdef578c3ac1b72b2cda105c061c2c77067f1fd8ec54d852b7@1 92.168.1.214:30301"]StaticNodes = []
TrustedNodes = []
ListenAddr = ":30303"
EnableMsgEvents = false
[Dashboard]
Host = "localhost"
Port = 8080
Refresh = 5000000000
复制代码
配置说明(下表是笔者参考geth参数说明和go-ethereum相关配置项代码整理所得,若有错误,请帮忙指正):
域 | 配置项 | 对应参数 | 说明 |
---|---|---|---|
Eth | NetworkId | --networkid value | Network标识符(integer类型,1=Frontier,2=Morden(disused),3=Ropsten,4=Rinkeby),默认为1。若是创建在私网上,使用另外的任意值,好比:3369 |
Eth | DatabaseCache | null | (我的理解)为database申请的系统内存,单位为MB,最小值和默认值是16MB |
Eth | GasPrice | --gasprice “18000000000” | 接受挖掘事务的最低gas价格。可能指miner的报酬 |
Eth.Ethash | CacheDir | --ethash.cachedir | 存储ethash证实缓存的目录(默认在 datadir 目录里) |
Eth.Ethash | CachesInMem | --ethash.cachesinmem value | 保留在内存中的最新ethash缓存的数目(每16MB)(默认:2)。 |
Eth.Ethash | CachesOnDisk | --ethash.cachesondisk value | 保留在磁盘中的最新ethash缓存的数目(每16MB)(默认:3)。 |
Eth.Ethash | DatasetDir | --ethash.dagdir "/home/karalabe/.ethash" | 存储ethash挖掘DAGs的目录(默认在home目录里) |
Eth.Ethash | DatasetsInMem | --ethash.dagsinmem value | 保留在内存中的最新ethash挖掘DAGs(每1+GB)(默认:1)。 |
Eth.Ethash | DatasetsOnDisk | --ethash.dagsondisk value | 保留在磁盘中的最新ethash挖掘DAGs(每1+GB)(默认:2)。 |
Eth.TxPool | NoLocals | --txpool.nolocals | 免除本地提交事务的费用 |
Eth.TxPool | Journal | --txpool.journal value | 用于节点重启的本地事务磁盘日志(默认:"transactions.rlp") |
Eth.TxPool | Rejournal | --txpool.rejournal value | 从新生成本地事务日志的时间间隔(默认:1h0m0s) |
Eth.TxPool | PriceLimit | --txpool.pricelimit value | 强制接归入池的最小gas价格限制(默认:1) |
Eth.TxPool | PriceBump | --txpool.pricebump value | 替代一个已经存在的事务的价格碰撞百分比(默认:10) |
Eth.TxPool | AccountSlots | --txpool.accountslots value | 每一个帐户担保的可执行事务时隙的最小数目(默认:16) |
Eth.TxPool | GlobalSlots | --txpool.globalslots value | 全部帐户的可执行事务时隙的最大数目(默认:4096) |
Eth.TxPool | AccountQueue | --txpool.accountqueue value | 每一个帐户许可的非可执行事务时隙的最大数目(默认:64) |
Eth.TxPool | GlobalQueue | --txpool.globalqueue | 全部帐户的非可执行事务时隙的最大数目(默认:1024) |
Eth.TxPool | Lifetime | --txpool.lifetime value | 非可执行事务的排队最大时间(默认:3h0m0s) |
Eth.GPO | Blocks | --gpoblocks value | 检查gas价格的最新区块的数目(默认:10) |
Eth.GPO | Percentile | --gpopercentile value | 建议的gas价格是一组最新事务gas价格的百分位(默认:50) |
Shh | MaxMessageSize | --shh.maxmessagesize value | 可接受的最大信息大小(默认:1048576) |
Shh | MinimumAcceptedPOW | --shh.pow value | 可接受的最小POW(默认:0.2) |
Node | DataDir | --datadir "/home/karalabe/.ethereum" | databases和keystore的数据目录 |
Node | IPCPath | --ipcpath | datadir里的IPC socket/pipe的文件名 |
Node | HTTPPort | --rpcport value | HTTP-RPC服务监听端口(默认:8545) |
Node | HTTPVirtualHosts | --rpcaddr value | HTTP-RPC服务监听接口(默认:"localhost") |
Node | HTTPModules | null | 经由HTTP RPC接口暴露的API modules列表 |
Node | WSPort | --wsport value | WS-RPC 服务监听端口(默认:8546) |
Node | WSModules | null | 经由websocket RPC接口暴露的API modules列表,若是modules是空的,全部指向public的RPC API端点将会被暴露 |
Node.P2P | MaxPeers | --maxpeers value | network peers的最大数目(若是设置为0,network失效)(默认:25) |
Node.P2P | NoDiscovery | --nodiscover | 使peer发现机制无效(手动peer添加)。这里设置为false,以便使用这个配置文件的新节点能够被发现。 |
Node.P2P | BootstrapNodes | --bootnodes value | 逗号分割的P2P discovery bootstrap enode URLs(对于 light servers,设置 v4+v5 代替)。将上面启动bootnodes时获取的enode URL替换IP后添加到这里。 |
Node.P2P | BootstrapNodesV5 | --bootnodesv5 value | 逗号分割的P2P v5 discovery bootstrap enode URLs(light server,light nodes) |
Node.P2P | StaticNodes | null | 配置做为static nodes的节点enode URLs列表 |
Node.P2P | TrustedNodes | null | 配置做为trusted nodes的节点enode URLs列表 |
Node.P2P | ListenAddr | --port | network监听端口(默认:30303) |
Node.P2P | EnableMsgEvents | null | 若是EnableMsgEvents被设置,服务器将发出PeerEvents,不管一个peer什么时候发送或接收一条信息 |
Dashboard | Host | null | 启动dashboard服务的主机接口,若是这个域为空,则没有dashboard将被启动 |
Dashboard | Port | null | 启动dashboard服务的TCP端口数字。默认0值是有效的,并将使用一个随机端口数字(用于临时节点) |
Dashboard | Refresh | null | 数据更新的刷新速率,chartEntry将被常常收集 |
在你的操做目录建立config文件夹,将写好的配置文件privatenet.toml移动到config目录里。
以太坊的成员节点,之间是彻底对等的,每一个节点均可以有多个帐户。
启动私网以太坊的成员节点:
geth --config config/privatenet.toml
复制代码
链接到刚刚启动的或者已经在运行的node,开始一个交互式JavaScript环境:
geth attach privatenet/.ethereum/geth.ipc
复制代码
官方说明: 当bootnode运转起来而且外部可达(你能尝试 telnet 去确认它的确可达),开始随后的Geth节点,为了对等发现,经由 --bootnodes 选项指向bootnode。保持你的私网的数据目录单独将极可能是明智的选择,因此也指定一个自定义的 --datadir 选项。
geth --datadir=path/to/custom/data/folder --bootnodes=<bootnode-enode-url-from-above>
复制代码
注意:由于你的网络将被从main和test网彻底切除,因此你将须要配置一个 miner 去处理交易并为你创造新块。
公共Ethereum网的mining是一个复杂的任务,由于它惟一可行的是使用GPUs,要求一个OpenCL 或 CUDA激活 ethminer 实例。更多信息请查阅 EtherMining subreddit和 Genoil miner 仓库。
然而在一个私网的设置,一个单一的 CPU miner实例是足够知足实际需求的,由于它不须要沉重的资源(考虑到运行在一个单一的线程上,也不须要多个)就能在一个正确的间隔内生产一个稳定的区块流(stable stream of blocks)。为mining开始一个Geth实例,指定你一般使用的选项运行它,经过如下方法扩展:
geth --config config/privatenet.toml --mine --minerthreads=1 --etherbase=0x0000000000000000000000000000000000000000
复制代码
这将开始mining区块并在一个单一CPU线程上交易,存入全部事件到一个 --etherbase 选项指定的帐户,若是不指定帐户,则会默认指定当前节点上的第一个帐户。你能进一步调节mining,经过(--targetgaslimit)改变默认gas限制区块而且在(--gasprice)处接受价格交易。
另外,也能够在交互式JavaScript环境中控制mining实例:
miner.start(4)
复制代码
miner.stop()
复制代码
更多Mining相关信息,请参看Mining
至此,私网以太坊搭建完成,感谢阅读!
原创不易,与君共勉!