基于以太坊搭建私有链

简介

本文主要学习以太坊的底层操作,环境搭建,查看系统信息,账号创建,挖矿,交易,智能合约部署等操作

安装

机器:Mac

源码:https://github.com/ethereum/go-ethereum 本文以go版本的ethereum为例

如果是其它机型请参照 官方安装文档

brew tap ethereum/ethereum
brew install ethereum

# 如果希望基于ethereum的develop分支安装,执行 brew install ethereum --devel
brew install ethereum

初始化

以默认方式启动会连接以太坊主链,同步数据到本地,占用本地磁盘空间,所以不建议这么做。我们以私链的方式运行即可。运行私有链那么就必须定义自己的创世区块

默认方式启动,单机环境不建议使用,命令供参考

> geth

或dev模式运行
> get --dev console 2>> geth-log

# 如果这种方式启动,进入控制台需要使用 geth attach 命令

初始化

在指定目录下新建一个目录用于保存生成的数据

cd /tmp && mkdir blockchain && cd blockchain
mkdir data
touch genesis.json

目录结构如下
.
├── data
└── genesis.json

genesis.json:初始化私有链的配置文件,配置创世区块信息

data:存放区块链数据的目录。

genesis.json内容如下

{
  "config": {
    "chainId": 15,
    "homesteadBlock": 0,
    "eip155Block": 0,
    "eip158Block": 0
  },
  "alloc": {},
  "nonce": "0x0000000000000042",
  "difficulty": "0x020000",
  "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "coinbase": "0x0000000000000000000000000000000000000000",
  "timestamp": "0x00",
  "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
  "gasLimit": "0x4c4b40"
}

参数解释:

alloc:用来预设置账号以及账号的 ether 数量。因为私有链挖矿比较容易,所以我们不需要预设置账号。比如,{"0x880004bb64282fb01a3a2500ddf1f4bb5ad4b64a":{"balance":"100000000000000000000000000000"}}
nonce:一个64位随机数,用于挖矿。
mixhash:和 nonce 配合用于挖矿,由上一个区块的一部分生成的 hash。
difficulty:设置当前区块的难度,如果难度过大,cpu挖矿就很难,所以这边设置的很小,不要跟自己过不去嘛。
coinbase:默认挖矿的矿工账号。
timestamp:设置创世块的时间戳。
parentHash:上一个区块的hash值,因为是创世块,所以值是0。
extraData:附加信息,随便填。
gasLimit:设置对GAS的消耗总量限制,用来限制区块能包含的交易信息总和。因为我们是私有链,所以可以写的大一些,方便开发测试。

接下来我们就需要将创世区块的初始信息写入区块链中,使用geth init命令

cd /tmp/blockchain
geth --datadir "./data" --networkid 31415926 --rpc --rpccorsdomain "*" init ./genesis.json

大致会输出如下信息:

INFO [03-12|19:36:02] Allocated cache and file handles
INFO [03-12|19:36:02] Writing custom genesis block
INFO [03-12|19:36:02] Persisted trie from memory database
INFO [03-12|19:36:02] Successfully wrote genesis state

此时的目录结构就变成如下:

.
├── data
│  ├── geth
│  │  ├── chaindata
│  │  │  ├── 000001.log
│  │  │  ├── CURRENT
│  │  │  ├── LOCK
│  │  │  ├── LOG
│  │  │  └── MANIFEST-000000
│  │  └── lightchaindata
│  │      ├── 000001.log
│  │      ├── CURRENT
│  │      ├── LOCK
│  │      ├── LOG
│  │      └── MANIFEST-000000
│  └── keystore
└── genesis.json

其中keystore目录用来保存账户信息,geth目录用来保存区块信息。

启动私有链

geth --datadir data --networkid 31415926 --rpc --rpccorsdomain "*" --nodiscover console

输出如下即表示成功进入 geth 的控制台:

Welcome to the Geth JavaScript console!

instance: Geth/v1.8.2-stable/darwin-amd64/go1.10
 modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0

>

基本操作

  1. 创建账号# 查看一下系统有的用户eth.accounts

[]

查看详细的用户信息

personal

创建两个账号用于转账,或者使用 personal.newAccount() 也会提示输入密码

personal.newAccount('123456') personal.newAccount('123456')

eth.accounts "0x18a6581a285f40ac3faaa646e13d7c6dd87276f4", "0x2455572ef500cf8634a4090d6d6096c588013e2a"

此时可以看下 keystore 目录,多出了两个文件,也就是我们刚才创建的两个账户密钥(丢了它,你就等于丢了币)

  1. 挖矿

账号创建好了,但是一开始账号都没有 ether,这时就需要挖矿获取币了。

使用miner.start()命令开启挖矿,默认挖出的 ether 是存到 eth.coinbase 账户中的,也就是第一个账户。

# 查看账号1下的余额
> eth.getBalance(eth.accounts[0])

# 查看coinbase账号
> eth.coinbase
0x18a6581a285f40ac3faaa646e13d7c6dd87276f4

# 如果想要把挖到的矿存入其他账户,可以使用
> miner.setEtherbase(eth.accounts[1])
true

开始挖矿,我们先把coinbase改成账号1
> miner.setEtherbase(eth.accounts[0])
true

# 如果出现 miner.start() 直接返回 null 的情况,请先查看是否还未创建过账户。
> miner.start(1)
INFO [05-31|19:57:17] Updated mining threads                   threads=0
INFO [05-31|19:57:17] Transaction pool price threshold updated price=18000000000
INFO [05-31|19:57:17] Starting mining operation
INFO [05-31|19:57:17] Commit new mining work                   number=12 txs=0 uncles=0 elapsed=194.667µs
INFO [05-31|19:57:19] Successfully sealed new block            number=12 hash=82d29d…65290c
INFO [05-31|19:57:19] 🔨 mined potential block                  number=12 hash=82d29d…65290c
INFO [05-31|19:57:19] Commit new mining work                   number=13 txs=0 uncles=0 elapsed=159.066µs
INFO [05-31|19:57:19] Successfully sealed new block            number=13 hash=e91844…e962a6
INFO [05-31|19:57:19] 🔨 mined potential block                  number=13 hash=e91844…e962a6
等到 percentage 达到100就能挖出来了,请耐心等待~,出现小锤头的时候意味着你挖到了!

# 已经挖到了,我们先暂停挖矿,注意:输入的字符会被挖矿刷屏信息冲掉,没有关系,只要输入完整的miner.stop()之后回车,即可停止挖矿。正在执行的挖矿进程不会立即暂停,仍然会等到当前完整快写完后才会暂停
> miner.stop()
true

然后查看账户余额
> eth.getBalance(eth.accounts[0])
112000000000000000000
# 不要被这个零的个数吓到,这里默认显示的以 wei 为单位的,而 1 ether = 10^18 wei,所以我们转换一下单位立马就清晰了,

> web3.fromWei(eth.getBalance(eth.accounts[0]), 'ether')
112
# 嗯,其实我们目前就挖了112个ether

转账

在转账前,我们需要先解锁账号

> personal.unlockAccount(eth.accounts[0])

# 我们先转8个ether给账号2
> eth.sendTransaction({from:eth.accounts[0],to:eth.accounts[1],value:web3.toWei(8,'ether')})

INFO [03-12|20:24:15] Submitted transaction      fullhash=0x996a3037b75585415ece5b1dc28181833691760176b3f24066c93e7093a967e5 recipient=0x29a079BdbC6D4d122178FBe01558E5DF2D008523

我们可以看到目前只是向区块链提交了这笔转账交易,谁来执行这笔交易呢?矿工。我们还是得开启挖矿模式,把这笔转账交易执行掉。然后我们再来看看好朋友的账户里面有多少 ether 了,

> miner.start(1)
# 持续几秒
> miner.stop()

# 然后查看账号2的余额,已经有余额
> eth.getBalance(eth.accounts[1])
8000000000000000000

连接到其它节点

连接到其它节点的前提条件:

  1. 网络必须是互通的,不能一个在局域网,一个在公网
  2. 端口开放,8545和30303
  3. 指定相同的networkid

方法一:

首先我们要知道节点二的enode信息,在节点二上执行:

> admin.nodeInfo.enode
"enode://9e86289ea859ca041f235aed87a091d0cd594b377cbe13e1c5f5a08a8a280e62d4019ac54063ed6a1d0e3c3eaedad0b73c40b99a16a176993f0373ffe92be672@[::]:30303"

然后在节点一上执行:

> admin.addPeer("enode://9e86289ea859ca041f235aed87a091d0cd594b377cbe13e1c5f5a08a8a280e62d4019ac54063ed6a1d0e3c3eaedad0b73c40b99a16a176993f0373ffe92be672@remote_ip:30303")
remote_ip需要替换成节点2的IP

返回true就说明执行成功,我们可以通过admin.peers查看新增的节点信息,同步操作是异步的,可能不能立马看到节点2的信息

addPeer()的参数就是节点二的enode信息,连接成功后,节点二就会开始同步节点一的区块,同步完成后,任意一个节点开始挖矿,另一个节点会自动同步区块,向任意一个节点发送交易,另一个节点也会收到该笔交易。

方法二:

除了上面的方法,也可以在启动节点的时候指定--bootnodes选项连接到其他节点。

示例:指定两个节点

geth --bootnodes enode://pubkey1@ip1:port1,enode://pubkey2@ip2:port2

以太坊钱包

关于以几种客户端的介绍请参考 以太坊客户端介绍

我们现在以Ethereum Wallet为例来连接本地私有链,下载Ethereum Wallet后,直接点图标启动默认会链接以太坊共链。所以我们需要在命令行启动,并指定私有链地址

cd /Applications
./Ethereum\ Wallet.app/Contents/MacOS/Ethereum\ Wallet --rpc "私有链ipc地址"

私有链地址在私有链启动时,日志的第16行可以找到,以本机为例,启动命令就是

./Ethereum\ Wallet.app/Contents/MacOS/Ethereum\ Wallet --rpc /Users/moon/geth/data/geth.ipc

如果需要连接远程节点,请参考 以太坊客户端连接远程节点

欢迎订阅「K叔区块链」 - 专注于区块链技术学习

博客地址:http://www.jouypub.com

简书主页:https://www.jianshu.com/u/756c9c8ae984

segmentfault主页:https://segmentfault.com/blog/jouypub

腾讯云主页:https://cloud.tencent.com/developer/column/72548

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏区块链

以太坊开发实战(第 2 章: Truffle, Ganache, Geth, 和 Mist)

见识了智能合约以及以太坊的工作方式,现在我们就尝试将它部署到两种测试网络里面。

1.9K15
来自专栏芋道源码1024

分布式事务 TCC-Transaction 源码分析 —— 项目实战

1. 概述 本文分享 TCC 项目实战。以官方 Maven项目 tcc-transaction-http-sample 为例子( tcc-transaction...

6557
来自专栏WebDeveloper

以太坊go-ethereum(第一讲)

转账完成后,eth.getBalance(eth.accounts[1])查询余额,发现余额没有增加。

1482
来自专栏区块链入门

【财务安全】如何使用imToken钱包进行离线签名

注: 使用你的联网手机是热钱包, 用来观察钱包, 未联网手机作为冷钱包用作离线签名授权

932
来自专栏极客编程

如何用Python和Flask框架开发以太坊智能合约

将数据存储在数据库中是任何软件应用程序不可或缺的一部分。无论如何控制该数据库都有一个该数据的主控。区块链技术将数据存储到区块链网络内的区块中。因此,只要某个节点...

1633
来自专栏CDA数据分析师

你的第一个智能合约「Hello World」,好像也不是很智能

在看过 我花了 99 个以太坊(Ethereum)来学智能合约开发(http://davidfnck.com/blockchain/ethereum-smart...

1482
来自专栏极客编程

比特币钱包隔离认证开发指南 原

本文件的大部分内容可以在与隔离认证相关的BIP中找到,包括BIP141,BIP143,BIP144和BIP145。请将此视为阅读其他相关文件的第一个参考点,并作...

1051
来自专栏申龙斌的程序人生

同时给200多人发送比特币,程序员是这样做到的

在币圈中,使用自己的钱包给他人发币时,就跟平常的微信、支付宝扫码付款类似,输入BTC地址和金额,再输入支付密码,不管对方是否在地球的另一端,不需要任何银行的中介...

1692
来自专栏区块链源码分析

比特币源码分析之一:总览

本文主要讲解比特币源码,下一篇文章会介绍比特币交易是如何通过非对称加密机制来完成安全交易的,欢迎大家互动留下问题和希望讲解的题目。

91517
来自专栏汇智网教程

原 EOS智能合约开发入门

4296

扫码关注云+社区

领取腾讯云代金券