区块链开发之搭建以太坊私有链

(一)区块链开发之搭建以太坊私有链

本文链接:https://blog.csdn.net/rwdxll/article/details/82929417

1、安装ethereum/Go client(以太坊客户端)

https://github.com/ethereum/go-ethereum/wiki/Installation-Instructions-for-Mac

https://github.com/ethereum/homebrew-ethereum

 
  1. 一、命令行客户端

  2. 1、克隆仓库

  3. brew tap ethereum/ethereum

  4. 2、安装go 客户端

  5. brew install ethereum

  6. 3、运行

  7. geth

  8.  
  9. 二、图形化客户端

  10. https://github.com/ethereum/mist/releases/

  11.  

说明:

安装目录:/usr/local/Cellar/ethereum/1.8.14,将bin目录添加到环境变量里.

2、创建私有链

i.新建一个geth工作目录

mkdir geth

cd geth

touch gensis.json

ii.创世区块配置文件

创世(gensis)区块是区块链的起点,是区块链的第一块区块--------0号区块,唯一一个没有前任的区块。这个协议确保了没有其他节点会和你的节点的区块链版本一致,除非它们的创世区块和你的一模一样,通过这个方法可以创建多个私有区块链。

文件:gensis.json

{
  "config": {
        "chainId": 15,
        "homesteadBlock": 0,
        "eip155Block": 0,
        "eip158Block": 0
    },
  "alloc"      : {"0x6e1d19B1D713E39fD77Db95ff2929db78dB4ad34":{"balance":"100000"}

  },
  "coinbase"   : "0x0000000000000000000000000000000000000000",
  "difficulty" : "0x01",
  "extraData"  : "0x",
  "gasLimit"   : "0xfffffff",
  "nonce"      : "0x0000000000000001",
  "mixhash"    : "0x0000000000000000000000000000000000000000000000000000000000000000",
  "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
  "timestamp"  : "0x00"
}

 

参数

描述

mixhash

与nonce配合用于挖矿,由上一个区块的一部分生成的hash。注意他和nonce的设置需要满足以太坊的Yellow paper, 4.3.4. Block Header Validity, (44)章节所描述的条件。

nonce

nonce就是一个64位随机数,用于挖矿,注意他和mixhash的设置需要满足以太坊的Yellow paper, 4.3.4. Block Header Validity, (44)章节所描述的条件。

difficulty

设置当前区块的难度,如果难度过大,cpu挖矿就很难,这里设置较小难度

alloc

用来预置账号以及账号的以太币数量,因为私有链挖矿比较容易,所以我们不需要预置有币的账号,需要的时候自己创建即可以。可以使用MetaMask创建地址。

coinbase

矿工的账号,随便填

timestamp

设置创世块的时间戳

parentHash

上一个区块的hash值,因为是创世块,所以这个值是0

extraData

附加信息,随便填,可以填你的个性信息

gasLimit

该值设置对GAS的消耗总量限制,用来限制区块能包含的交易信息总和,因为我们是私有

iii.初始化

cd geth

mkdir db

geth --datadir "./db" init gensis.json

geth init 命令用来初始化区块链,命令可以带有选项和参数,其中--datadir选项后面跟一个文件夹名db,gensis.json是init命令行参数。初始成功后会在数据目录db下生产geth和keystore两个文件夹。此时目录结构如下:

其中,geth/db/chaindata中存放的是区块链数据,geth/db/keystore中存放的是账户数据。

iv.启动节点

geth geth --datadir "./db" --rpc --rpcaddr=0.0.0.0 --rpcport 8545 --rpccorsdomain "*" --rpcapi "eth,net,web3,personal,admin,shh,txpool,debug,miner" --nodiscover --maxpeers 30 --networkid 1981 --port 30303 --mine --minerthreads 1 --etherbase "0x6e1d19B1D713E39fD77Db95ff2929db78dB4ad34" console

参数说明:

 

identity

区块链的标示,随便填写,用于标示目前网络的名字

 

init

指定创世块文件的位置,并创建初始块

 

datadir

设置当前区块链网络数据存放的位置

 

port

网络监听端口

 

rpc

启动rpc通信,可以进行智能合约的部署和调试

 rpcaddr指定HTTP-RPC服务监听地址,默认为“localhost”
 

rpcapi

设置允许连接的rpc的客户端,一般为db,eth,net,web3

 rpcport指定允许连接的rpc服务监听端口,默认为8545
 

networkid

设置当前区块链的网络ID,用于区分不同的网络,是一个数字

 etherbase指定旷工账号,默认为keystore中的首个账号
 

mine

开启挖矿,默认为CPU挖矿

 minerthreads挖矿占用CPU的线程数,默认为4
 nodiscover关闭自动连接节点,但是可以手动添加节点,在搭建私有链时,为避免其他节点连入私有链,可以使用该命令
 maxpeers设置允许最大连接节点数目,默认为25
 console启动命令行模式,可以在Geth中执行命令 

log:

INFO [10-09|11:25:34.522] Maximum peer count                       ETH=30 LES=0 total=30
INFO [10-09|11:25:34.552] Starting peer-to-peer node               instance=Geth/v1.8.14-stable/darwin-amd64/go1.10.3
INFO [10-09|11:25:34.552] Allocated cache and file handles         database=/Users/xxx/Desktop/nasnano/ethereum/geth/db/geth/chaindata cache=768 handles=1024
INFO [10-09|11:25:34.662] Initialised chain configuration          config="{ChainID: 15 Homestead: 0 DAO: <nil> DAOSupport: false EIP150: <nil> EIP155: 0 EIP158: 0 Byzantium: <nil> Constantinople: <nil> Engine: unknown}"
INFO [10-09|11:25:34.663] Disk storage enabled for ethash caches   dir=/Users/xxx/Desktop/nasnano/ethereum/geth/db/geth/ethash count=3
INFO [10-09|11:25:34.663] Disk storage enabled for ethash DAGs     dir=/Users/xxx/.ethash                                      count=2
INFO [10-09|11:25:34.663] Initialising Ethereum protocol           versions="[63 62]" network=1981
INFO [10-09|11:25:34.664] Loaded most recent local header          number=0 hash=f62ece…c00ca7 td=1
INFO [10-09|11:25:34.664] Loaded most recent local full block      number=0 hash=f62ece…c00ca7 td=1
INFO [10-09|11:25:34.664] Loaded most recent local fast block      number=0 hash=f62ece…c00ca7 td=1
INFO [10-09|11:25:34.665] Regenerated local transaction journal    transactions=0 accounts=0
INFO [10-09|11:25:34.666] Starting P2P networking
INFO [10-09|11:25:34.667] RLPx listener up                         self="enode://576e857437aba95e59cfee3570a0fdd0d00dc9c4656ef9e48b47649cdc9b56f86bbf54081a5e38cec85fa150b4b088e22ccd93978e3de0c52aeed6b43471ee79@[::]:30303?discport=0"
INFO [10-09|11:25:34.669] IPC endpoint opened                      url=/Users/xxx/Desktop/nasnano/ethereum/geth/db/geth.ipc
INFO [10-09|11:25:34.697] HTTP endpoint opened                     url=http://0.0.0.0:8545                                      cors=* vhosts=localhost
INFO [10-09|11:25:34.697] Transaction pool price threshold updated price=18000000000
INFO [10-09|11:25:34.698] Commit new mining work                   number=1 uncles=0 txs=0 gas=0 fees=0 elapsed=514.993µs
Welcome to the Geth JavaScript console!

instance: Geth/v1.8.14-stable/darwin-amd64/go1.10.3
coinbase: 0x6e1d19b1d713e39fd77db95ff2929db78db4ad34
at block: 0 (Thu, 01 Jan 1970 08:00:00 CST)
 datadir: /Users/xxx/Desktop/nasnano/ethereum/geth/db
 modules: admin:1.0 debug:1.0 eth:1.0 ethash:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0

> INFO [10-09|11:25:37.341] Generating DAG in progress               epoch=0 percentage=0 elapsed=1.492s
INFO [10-09|11:25:38.962] Generating DAG in progress               epoch=0 percentage=1 elapsed=3.113s

v.进入JavaScript控制台

通过attach命令,连接到iv启动的节点(会在db下生成geth.ipc),启动js命令环境

geth --datadir "./db" attach ipc:./db/geth.ipc

Welcome to the Geth JavaScript console!

instance: Geth/v1.8.14-stable/darwin-amd64/go1.10.3
coinbase: 0x6e1d19b1d713e39fd77db95ff2929db78db4ad34
at block: 0 (Thu, 01 Jan 1970 08:00:00 CST)
 datadir: /Users/liliang/Desktop/nasnano/ethereum/geth/db
 modules: admin:1.0 debug:1.0 eth:1.0 ethash:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0

>

vi.以太坊JavaScript控制台命令

js控制台内置了一些对象,通过这些对象可以很方便的与以太坊交互,这些内置对象包括:

eth:提供操作区块链相关的方法

net:提供了查看p2p网络状态的的方法

admin:提供了管理节点相关的方法

miner:提供启动和停止挖矿的方法

personal:提供了管理账户的方法

txpool:提供了查看交易内存池的方法

web3:除了包含以上对象中有的方法,还包含一些单位换算的方法

1、新建账户

> personal.newAccount("123456")
"0x98d03a20eb02fc526534cabbda6dc2e6b43de214"

personal.newAccount("password"),传入的参数是账户的密码。执行成功后会返回账户的公钥,生成的账户文件在keystor目录下.

查看账户:

eth.accounts
["0x2dd6b2362d6351b18bd3af9519b8e5b2e44d0339", "0x98d03a20eb02fc526534cabbda6dc2e6b43de214"]

2、查看余额

> balance=web3.fromWei(eth.getBalance(eth.accounts[0]),"ether")
0
> balance=web3.fromWei(eth.getBalance(eth.accounts[1]),"ether")
0

eth.accouts[index]会按传入的索引返回已有的账户,eth.getBalance(address)会返回账户的余额,余额为wei为单位,传入的参数是账户的公钥。web3.fromWei单位转换,在这个例子中是将wei转换成ether。

创建的账户都是0,怎样获得以太币呢,答案是挖矿。

3、挖矿

为了获取以太币,我们需要开始挖矿,不过在开启挖矿之前,我们要先设置挖矿奖励的地址

> miner.setEtherbase(eth.accounts[0])
true

查看设置是否成功:

> eth.coinbase
"0x2dd6b2362d6351b18bd3af9519b8e5b2e44d0339"

开启挖矿:

miner.start(1),参数是线程数,表示可以开启几个线程来挖矿,本例中设置的是一个线程。当出现小锤子表示开始挖矿了。当挖矿时会有大量的输入填满终端,为了方便操作,你可以重现打开一个新的控制台,执行attach命令,进入一个新的JavaScript环境。

关闭挖矿,等需要的时候在开:

>miner.stop()

true

查看下余额:

>  balance=web3.fromWei(eth.getBalance(eth.accounts[0]),"ether")
6330

在以太坊上任何操作都需要借助交易来完成,如转账、部署合约、用用只能合约

4、解锁账户

在发送交易之前,要先解锁账户,否则会报错,执行以下命令解锁账户

> personal.unlockAccount(eth.accounts[0],"123456")
true

> personal.unlockAccount(eth.accounts[0],"123456",300)
true

personal.unlockAccount(addr,passwd,duration)命令用来解锁账户,第一个参数解锁地址,第二个参数是密码,第三个参数传入解锁状态持续时间,其中duration单位为秒。

5、交易

> eth.sendTransaction({from: eth.accounts[0],to: eth.accounts[1],value:web3.toWei(1,"ether")})
"0x590f47c8d2aac75460c08cd761fa81559e2053ce608f9f4fb68c27a73cb86379"

查看交易池等待被打币的交易。

> txpool.status
{
  pending: 1,
  queued: 0
}

pending表示已提交,但未被处理的交易。

查看pending交易的详情。

> txpool.inspect.pending
{
  0x2dd6b2362D6351B18BD3af9519b8E5B2e44d0339: {
    0: "0x98D03a20EB02Fc526534CaBbdA6Dc2e6b43DE214: 1000000000000000000 wei + 90000 gas × 18000000000 wei"
  }
}

要使交易被处理,必须要挖矿。这里我们启动挖矿,然后等待挖到一个区块之后就停止挖矿:

miner.start(1);admin.sleepBlocks(1);miner.stop();

交易被打包,并且加入到区块链中了,查下余额

> balance=web3.fromWei(eth.getBalance(eth.accounts[1]),"ether")
1

vii.区块

查询发起转账交易的详情,参数为交易hash:

> eth.getTransaction("0x590f47c8d2aac75460c08cd761fa81559e2053ce608f9f4fb68c27a73cb86379")
{
  blockHash: "0x5e5cf36663b967ed1c1bb26018fbe5df8af645dc6d9abced0eb317697a220722",
  blockNumber: 1423,
  from: "0x2dd6b2362d6351b18bd3af9519b8e5b2e44d0339",
  gas: 90000,
  gasPrice: 18000000000,
  hash: "0x590f47c8d2aac75460c08cd761fa81559e2053ce608f9f4fb68c27a73cb86379",
  input: "0x",
  nonce: 0,
  r: "0x3a562af2294afae7116c0ae2f4ba09da53f9fab8ca74d7e6ace0d22562f93636",
  s: "0x5bf7b3df00558695dd315c049c238021b60b6d0fd05a06b2b9c5cf5a169c87c2",
  to: "0x98d03a20eb02fc526534cabbda6dc2e6b43de214",
  transactionIndex: 0,
  v: "0x42",
  value: 1000000000000000000
}

交易参数:

blockHash交易所在区块的哈希值。当这个区块处于pending时将会返回null
blockNumber交易所在区块号。当这个区块处于pending时将会返回null
from交易发起者的地址
gas交易发起者提供的gas数量
gasprice交易发起者提供的gas数量
hash交易的哈希值
input交易附带的数据
nonce交易的发起者在之前发起过的交易数量
transactionIndex交易在区块中的序号。当这个区块处于pending时将会返回null
value交易附带货币量,单位为Wei
to交易接收者的地址

查看发起交易在区块中的详细信息:

> eth.getTransactionReceipt("0x590f47c8d2aac75460c08cd761fa81559e2053ce608f9f4fb68c27a73cb86379")
{
  blockHash: "0x5e5cf36663b967ed1c1bb26018fbe5df8af645dc6d9abced0eb317697a220722",
  blockNumber: 1423,
  contractAddress: null,
  cumulativeGasUsed: 21000,
  from: "0x2dd6b2362d6351b18bd3af9519b8e5b2e44d0339",
  gasUsed: 21000,
  logs: [],
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  root: "0xf977149c1937aa24648e0225c7626a2e3b3a8446baa1e60fc9d210ea395f7861",
  to: "0x98d03a20eb02fc526534cabbda6dc2e6b43de214",
  transactionHash: "0x590f47c8d2aac75460c08cd761fa81559e2053ce608f9f4fb68c27a73cb86379",
  transactionIndex: 0
}

TransactionReceipt参数详解

blockHash交易所在区块哈希
blockNumber交易所在去考的块号
contractAddress创建的合约地址。如果是一个合约创建交易,则返回合约地址,其他情况返回null
cumulativeGasUsed当前交易执行后累计话费的gas总值
from交易发送者的地址
gasUsed执行当前这个交易单独花费的gas
logslogsBloom由logs中的address与topics共同决定,详细请查看以太坊黄皮书
root交易执行后的stateroot
to交易接受者的地址。如果是一个合约创建的交易,返回null
transactionHash交易哈希值
transactionIndex交易在区块里面的序号

常用的一些查询区块的命令:

查看当前区块总数:

> eth.blockNumber
1433

查询最新的区块(参数为区块数或Hash)
> eth.getBlock('latest')
{
  difficulty: 235650,
  extraData: "0xd98301080e846765746888676f312e31302e338664617277696e",
  gasLimit: 66190083,
  gasUsed: 0,
  hash: "0xd6a6e5da6ef0c5127363c468570c7f9a679b2d33dc14570ea751b916c0e17087",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0x6e1d19b1d713e39fd77db95ff2929db78db4ad34",
  mixHash: "0xbf6a2bdde494f66921a763829a3d3d8ecc65bdbfbc4feba4ee9f99a599dec4a3",
  nonce: "0x0df18fb718d8ab3c",
  number: 1433,
  parentHash: "0xf631a736994fc3e9bd2772cbbcb092b2f8f58b49f0f7607deed83006d8500b61",
  receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 540,
  stateRoot: "0xd604935e26d44991888489c6412a6f4cf04bbd25913a6eeda0b5920b8d0cef51",
  timestamp: 1539072197,
  totalDifficulty: 264521090,
  transactions: [],
  transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  uncles: []
}

> eth.getBlock(0)
{
  difficulty: 1,
  extraData: "0x",
  gasLimit: 268435455,
  gasUsed: 0,
  hash: "0xf62ece4906c7cadd848274fc800e0d881f9d296db67c9641121ea5315ec00ca7",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0x0000000000000000000000000000000000000000",
  mixHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  nonce: "0x0000000000000001",
  number: 0,
  parentHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 505,
  stateRoot: "0x19ef3cc3d7fdd74a91b4fcdcb8b18f6d151a74a6aa6dbab57ba0314152dadd2d",
  timestamp: 0,
  totalDifficulty: 1,
  transactions: [],
  transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  uncles: []
}

区块参数详解

diffculty挖矿难度,后面区块难度会随着区块高度升高而提高
extraData当前区块附件信息,若创世区块该值为空,则在第二个区块中会保存创建该私有链时的geth、go,以及操作系统版本,保存的信息为第一个挖到该区块的矿工信息
gasLimit该区块允许的最大gas数
gasUsedgas花费,在以太坊中交易和部署智能合约会消耗gas,暂时可理解为以太币
hash当前区块hash值
logsBloomlogsBloom由logs中的address与topics共同决定,详细请看以太坊黄皮书。作用是便于快速查找监听的事件是否在该交易中产生
miner挖到该区块的矿工地址
mixHash与nonce配合用于挖矿,由上一个区块的一部分生成的hash
nonce工作量证明
number当前的区块高度
parentHash上一个区块hash值
receiptsRoot区块receipt trie的根
sha3Uncles对叔区块进行的hash运算的结果
size区块大小,以字节为单位
stateRoot块的状态树根结果
timestamp时间戳
totalDifficulty达到该区块的难度总数
transactions以数组的形式保存交易的tx值
transactionsRoot交易的默克尔树根
uncles当前区块引用的叔父区块的哈希值

viii.远程节点管理

之前是单机上的操作,需要和其他节点醉成一个以太坊网络,需要获取其他节点的信息。

查看节点信息:

> admin.nodeInfo
{
  enode: "enode://576e857437aba95e59cfee3570a0fdd0d00dc9c4656ef9e48b47649cdc9b56f86bbf54081a5e38cec85fa150b4b088e22ccd93978e3de0c52aeed6b43471ee79@[::]:30303?discport=0",
  id: "576e857437aba95e59cfee3570a0fdd0d00dc9c4656ef9e48b47649cdc9b56f86bbf54081a5e38cec85fa150b4b088e22ccd93978e3de0c52aeed6b43471ee79",
  ip: "::",
  listenAddr: "[::]:30303",
  name: "Geth/v1.8.14-stable/darwin-amd64/go1.10.3",
  ports: {
    discovery: 0,
    listener: 30303
  },
  protocols: {
    eth: {
      config: {
        chainId: 15,
        eip150Hash: "0x0000000000000000000000000000000000000000000000000000000000000000",
        eip155Block: 0,
        eip158Block: 0,
        homesteadBlock: 0
      },
      difficulty: 264521090,
      genesis: "0xf62ece4906c7cadd848274fc800e0d881f9d296db67c9641121ea5315ec00ca7",
      head: "0xd6a6e5da6ef0c5127363c468570c7f9a679b2d33dc14570ea751b916c0e17087",
      network: 1981
    }
  }
}

添加其他节点:

获取另一个节点的encode的信息,将enode中的[::]替换成节点二的IP地址:

> admin.nodeInfo.enode
"enode://576e857437aba95e59cfee3570a0fdd0d00dc9c4656ef9e48b47649cdc9b56f86bbf54081a5e38cec85fa150b4b088e22ccd93978e3de0c52aeed6b43471ee79@[::]:30303?discport=0"

> admin.addpeer("enode://576e857437aba95e59cfee3570a0fdd0d00dc9c4656ef9e48b47649cdc9b56f86bbf54081a5e38cec85fa150b4b088e22ccd93978e3de0c52aeed6b43471ee79@172.16.15.145:30303")

true

查看远程节点:

> admin.peers

 

-------------------

使用最新版本geth客户,当执行personal.unlockAccount()或在程序中调用personal_unlockAccount接口时,会出现:account unlock with HTTP access is forbidden异常。

异常原因

新版本geth,出于安全考虑,默认禁止了HTTP通道解锁账户,相关issue:https://github.com/ethereum/go-ethereum/pull/17037

解决方案

如果已经了解打开此功能的风险,可通启动命令中添加参数:

--allow-insecure-unlock

来进行打开操作。

示例:

geth --rpc --rpcapi eth,web3,personal --allow-insecure-unlock

 

以太坊测试区块链环境搭建

比特币吸金之道系列文章,由计算机黑客发明的网络货币,无国界,无政府,无中心。没有政府滥发货币,没有通货膨胀。在全球计算机网络中,自由的实现货币兑换和流通。

本系列文章只讲程序和策略,不谈挖矿…

关于作者:

  • 张丹(Conan), 程序员/Quant: Java,R,Nodejs
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/bitcoin-geth-testnet

前言

以太坊(ETH)的出现开启了区块链的2.0时代,要进行ETH的开发和测试,我们先要搭建起来ETH的测试区块链网络。在测试环境中,我们可以直接通过参数配置,生成创世区块,设置挖矿难度,设置gas消耗,执行转账交易,定义智能合约等的操作。

目录

  1. 搭建测试区块链
  2. 开发挖矿
  3. 第一笔转账
  4. 多节点网络

1. 搭建测试区块链

由于在以太坊公链上做任何操作,都需要消耗以太币(eth),对于开发者来说,很有必要在本地自行搭建一个测试区块链网络,进行智能合约的开发,最后再将开发好的合约部署到公链上。私有区块链不同于以太坊公链,给我们很多的自由度,直接可能通过参数配置,生成创世区块,设置挖矿难度,设置gas消耗,执行转账交易,定义智能合约等的操作,这些都需要我们手动进行设置。

私有区块链的搭建,也是基于geth客户端来完成的,geth的安装过程,请参考文章 geth以太坊节点安装

下面,我们就用geth客户端,开始搭建测试区块链。创建测试节点的文件存储目录。


> mkdir /data0/eth-test/
> cd /data0/eth-test/

新建配置文件genesis.json


> vi genesis.json
{
 "nonce": "0x0000000000000042",
 "timestamp": "0x0",
 "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
 "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
 "extraData": "0x",
 "gasLimit": "0x80000000",
 "difficulty": "0x3",
 "coinbase": "0x3333333333333333333333333333333333333333",
 "config":{
    "chainId": 55,
    "homesteadBlock": 0,
    "eip155Block": 0
 },
 "alloc": {}
}

参数设置:

  • nonce:64位随机数,用于挖矿
  • timestamp:创世块的时间戳
  • parentHash:上一个区块的hash值,因为是创世块,所以这个值是0
  • mixhash:与 nonce 配合用于挖矿,由上一个区块的一部分生成的 hash。
  • extraData:附加信息,任意填写
  • gasLimit :对GAS的消耗总量限制,用来限制区块能包含的交易信息总和,因为我们就测试链,所以随意填写。
  • difficulty:难度值,越大越难
  • coinbase:矿工账号,第一个区块挖出后将给这个矿工账号发送奖励的以太币。
  • alloc: 预设账号以及账号的以太币数量,测试链挖矿比较容易可以不配置
  • chainId 指定了独立的区块链网络 ID,不同 ID 网络的节点无法互相连接。

初始化区块链,生成创世区块和初始状态。


> geth --datadir=/data0/eth-test init /data0/eth-test/genesis.json
INFO [06-26|08:10:32.943749] Maximum peer count                       ETH=25 LES=0 total=25
INFO [06-26|08:10:32.944172] Allocated cache and file handles         database=/data0/eth-test/geth/chaindata cache=16 handles=16
INFO [06-26|08:10:32.989586] Persisted trie from memory database      nodes=0 size=0.00B time=3.877µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [06-26|08:10:32.989983] Successfully wrote genesis state         database=chaindata                      hash=4a306e…543a63
INFO [06-26|08:10:32.990028] Allocated cache and file handles         database=/data0/eth-test/geth/lightchaindata cache=16 handles=16
INFO [06-26|08:10:33.036685] Persisted trie from memory database      nodes=0 size=0.00B time=3.258µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [06-26|08:10:33.037027] Successfully wrote genesis state         database=lightchaindata                      hash=4a306e…543a63

运行日志,包括了允许最大点对点连接当前节点数为total=25,普通节点连接数ETH=25,LES轻节点连接数0。数据库存储的目录在 /data0/eth-test/geth/chaindata ,当前存活的节点 livenodes=1。

参数说明

  • datadir, 设置当前区块链网络数据存放的位置
  • init,初始化,生成创世区块

接下来,启动测试节点,并进入 geth 命令行界面。


> geth --identity "TestNode" --rpc --rpcport "8545" --datadir=/data0/eth-test --port "30303" --nodiscover console
INFO [06-26|08:14:00.916738] Maximum peer count                       ETH=25 LES=0 total=25
INFO [06-26|08:14:00.918148] Starting peer-to-peer node               instance=Geth/TestNode/v1.8.12-unstable-f1986f86/linux-amd64/go1.10.3
INFO [06-26|08:14:00.918235] Allocated cache and file handles         database=/data0/eth-test/geth/chaindata cache=768 handles=512
INFO [06-26|08:14:00.979836] Initialised chain configuration          config="{ChainID: 55 Homestead: 0 DAO:  DAOSupport: false EIP150:  EIP155: 0 EIP158:  Byzantium:  Constantinople:  Engine: unknown}"
INFO [06-26|08:14:00.979915] Disk storage enabled for ethash caches   dir=/data0/eth-test/geth/ethash count=3
INFO [06-26|08:14:00.979943] Disk storage enabled for ethash DAGs     dir=/root/.ethash               count=2
INFO [06-26|08:14:00.980023] Initialising Ethereum protocol           versions="[63 62]" network=1
INFO [06-26|08:14:00.980566] Loaded most recent local header          number=0 hash=4a306e…543a63 td=3
INFO [06-26|08:14:00.980634] Loaded most recent local full block      number=0 hash=4a306e…543a63 td=3
INFO [06-26|08:14:00.980662] Loaded most recent local fast block      number=0 hash=4a306e…543a63 td=3
INFO [06-26|08:14:00.980842] Regenerated local transaction journal    transactions=0 accounts=0
INFO [06-26|08:14:00.981818] Starting P2P networking 
INFO [06-26|08:14:00.982303] RLPx listener up                         self="enode://15653a443e91b04040fe2731e0a0fa556a1d050580fa587110b17460cf471a8c3b42ac08dbc3d84a404f8c102ae35b28d9e2c1b9f2eae4c828a0dfa21c1f2117@[::]:30303?discport=0"
INFO [06-26|08:14:00.985029] IPC endpoint opened                      url=/data0/eth-test/geth.ipc
INFO [06-26|08:14:00.985503] HTTP endpoint opened                     url=http://127.0.0.1:8545    cors= vhosts=localhost
Welcome to the Geth JavaScript console!

instance: Geth/TestNode/v1.8.12-unstable-f1986f86/linux-amd64/go1.10.3
 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

> 
  • identity, 自定义的节点名字
  • rpc , 允许 HTTP-RPC 访问
  • rpcport , HTTP_RPC的访问端口,默认为8545
  • port , 网络监听端口,默认为30303
  • datadir, 设置当前区块链网络数据存放的位置
  • console, 启动命令行模式,可以在Geth中执行命令
  • nodiscover, 私有链地址,不会被网上看到

这样我们就把一个测试网络启动起来了,由于是单节点,网络没有其他的节点,所以并没有直接的数据输出。

2. 开始挖矿

接下来,我们在自己搭建的私有网络中,开始做常规ETH的操作。

2.1 创建账号

创建一个新账号,密码为123456,账号的地址为:0x9cac40f650e2cbe459dcb32c7c23103497134467。


> personal.newAccount("123456")
"0x9cac40f650e2cbe459dcb32c7c23103497134467"

另一种方式,生成一个新账号。


> personal.newAccount()
Passphrase: 
Repeat passphrase: 
"0x762a2e28c5dbab9cd31369db5f3cbb48f421c0e3"

查看所有账号


> eth.accounts
["0x9cac40f650e2cbe459dcb32c7c23103497134467", "0x762a2e28c5dbab9cd31369db5f3cbb48f421c0e3"]

2.2 挖矿

接下来,我们开始挖矿。挖矿,就是产生以太币的过程。之前在genesis.json文件中,设置的difficulty=3,挖矿难比较低,很快就是挖出以太币来。


# 开始挖矿
> miner.start(1)
INFO [06-26|08:19:58.086688] Updated mining threads                   threads=1
INFO [06-26|08:19:58.086828] Transaction pool price threshold updated price=18000000000

# 矿工账号:如果有多个账户的情况下,挖矿获得的eth,会自动计入第一账户中。
INFO [06-26|08:19:58.086887] Etherbase automatically configured       address=0x9cac40F650E2CBE459dcb32c7c23103497134467   
INFO [06-26|08:19:58.087015] Starting mining operation 

# 开始探索新区块,没有交易内容
INFO [06-26|08:19:58.087793] Commit new mining work                   number=1 txs=0 uncles=0 elapsed=659.441µs            

# 成功发现新区块
INFO [06-26|08:19:58.451612] Successfully sealed new block            number=1 hash=c120d3…23dad2                          

#  确认挖到新区块
INFO [06-26|08:19:58.452182]  mined potential block                  number=1 hash=c120d3…23dad2                      
INFO [06-26|08:19:58.45237] Commit new mining work                   number=2 txs=0 uncles=0 elapsed=165.519µs
INFO [06-26|08:20:00.683558] Successfully sealed new block            number=2 hash=011b1c…100594
INFO [06-26|08:20:00.68399]  mined potential block                  number=2 hash=011b1c…100594
INFO [06-26|08:20:00.684181] Commit new mining work                   number=3 txs=0 uncles=0 elapsed=111.601µs
INFO [06-26|08:20:09.965339] Successfully sealed new block            number=3 hash=173ea5…c059ef
INFO [06-26|08:20:09.965789]  mined potential block                  number=3 hash=173ea5…c059ef
INFO [06-26|08:20:09.966091] Commit new mining work                   number=4 txs=0 uncles=0 elapsed=246.371µs
INFO [06-26|08:20:11.622999] Successfully sealed new block            number=4 hash=56240d…0910a3

// 省略

INFO [06-26|08:20:16.264066] Commit new mining work                   number=10 txs=0 uncles=0 elapsed=155.89µs
INFO [06-26|08:20:16.466436] Successfully sealed new block            number=10 hash=819037…fbcd88
INFO [06-26|08:20:16.466774]  block reached canonical chain          number=5  hash=7f1015…f53c57
INFO [06-26|08:20:16.466794]  mined potential block                  number=10 hash=819037…fbcd88
INFO [06-26|08:20:16.466965] Commit new mining work                   number=11 txs=0 uncles=0 elapsed=92.726µs

# 停止挖矿
> miner.stop()
true

开始挖了几秒,就产生了10个区块。查看账户资金为50000000000000000000 wei。第一个账户为矿工账号,第二个账户是一个普通账号。


> eth.getBalance(eth.accounts[0])
50000000000000000000
> eth.getBalance(eth.accounts[1])
0

由于Wei是最小的单位,我们把Wei转换为ether为单位,比较好看,就是为 50 ether = 50000000000000000000/10^18


> web3.fromWei(eth.getBalance(eth.accounts[0]), "ether")
50

转换单位

  • Wei = 10^0 Wei
  • Ada = 10^3 Wei
  • Babbage = 10^6 Wei
  • Shannon = 10^9 Weiv
  • Szabo = 10^12 Wei
  • Finney = 10^15 Wei
  • Ether = 10^18 Wei
  • Einstein = 10^21 Wei
  • Douglas = 10^42 Wei

2.3 查看区块高度

下一步,我们查看一下区块高度,并分析一下区块的细节。


# 查看区块高度
> eth.blockNumber
10

# 查看第10个区块的细节
> eth.getBlock(10)
{
  difficulty: 131648,
  extraData: "0xd88301080c846765746888676f312e31302e33856c696e7578",
  gasLimit: 2126604064,
  gasUsed: 0,
  hash: "0x819037bcc65eb789eca82fcc3d6c686852ab8297df6396cffa6cfffeaffbcd88",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0x9cac40f650e2cbe459dcb32c7c23103497134467",
  mixHash: "0x311cd5ef45d9295d8c1b1b8778fb05b0e49dc6cae5971763c2e2d7e3d20bd895",
  nonce: "0x0b1aae8070cdff77",
  number: 10,
  parentHash: "0x1c5609a70d36a460234b95116fcc391e49890c5082af41d8cba3b5b366aa0028",
  receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 537,
  stateRoot: "0x0917e990c98b3daf316d0d38a4a2eefd0ad30436bab8ae61adb1ca24723eea81",
  timestamp: 1529972416,
  totalDifficulty: 1313603,
  transactions: [],
  transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  uncles: []
}

第10个区块为当前的最后一个区块,挖矿难度difficulty=131648,没有交易gasUsed=0,当前块的hash值hash: “0x819037bcc65eb789eca82fcc3d6c686852ab8297df6396cffa6cfffeaffbcd88”,,上一个块的地址parentHash: “0x819037bcc65eb789eca82fcc3d6c686852ab8297df6396cffa6cfffeaffbcd88”,矿工账号miner: “0x9cac40f650e2cbe459dcb32c7c23103497134467”,区块高度number=10。

3. 第一笔转账

接下来,让我完成第一笔转账。从矿工账号转账30ether到第二个账号。


> eth.sendTransaction({from:eth.accounts[0],to:eth.accounts[1],value:web3.toWei(30,"ether")})
Error: authentication needed: password or unlock
    at web3.js:3143:20
    at web3.js:6347:15
    at web3.js:5081:36
    at :1:1

第一次,执行转账操作时,出现错误。需要把转输eth的账号进行解锁,才能转账。


# 解锁账号
> personal.unlockAccount(eth.accounts[0])
Unlock account 0x9cac40f650e2cbe459dcb32c7c23103497134467
Passphrase: 
true

# 再次转账
> eth.sendTransaction({from:eth.accounts[0],to:eth.accounts[1],value:web3.toWei(30,"ether")})
INFO [06-26|08:26:44.060461] Submitted transaction                    fullhash=0x8d6d1eb3c1c82be1f419d8f772048644361c41362fd8de27f8252470f975d6bb recipient=0x762A2e28C5DbaB9cD31369DB5f3CBB48f421C0E3
"0x8d6d1eb3c1c82be1f419d8f772048644361c41362fd8de27f8252470f975d6bb"

交易日志,交易的hash值fullhash=0x8d6d1eb3c1c82be1f419d8f772048644361c41362fd8de27f8252470f975d6bb,收款账号recipient=0x762A2e28C5DbaB9cD31369DB5f3CBB48f421C0E3。

我们提交了第一笔的转账,查看2个账户的余额。


> eth.getBalance(eth.accounts[0])
50000000000000000000
> eth.getBalance(eth.accounts[1])
0

账户的余额并没有发生变化,这是因为基于区块链的转账操作需要矿工确认才能完成,矿工确认的过程是要经过挖矿的。我们的转账的操作的任务已经提交,但是交易并未完成,还需要矿工挖矿提交新的区块,在区块中加入这次转账交易,提交新的区块全网的节点(按百分比算,具体还没细看源代码)确认完成后,交易才正式生效。

由于链上只有我们自己,我们要重新开起挖矿程序。


# 开始挖矿
> miner.start(1)
INFO [06-26|08:27:24.712255] Updated mining threads                   threads=1
INFO [06-26|08:27:24.712434] Transaction pool price threshold updated price=18000000000
INFO [06-26|08:27:24.712617] Starting mining operation 

# 探索新的区块,包含一个操作信息txs=1
INFO [06-26|08:27:24.713512] Commit new mining work                   number=11 txs=1 uncles=0 elapsed=808.72µs
INFO [06-26|08:27:27.638518] Successfully sealed new block            number=11 hash=68495b…35d4fe
INFO [06-26|08:27:27.638986]  block reached canonical chain          number=6  hash=3617e8…0dd7f5
INFO [06-26|08:27:27.639006]  mined potential block                  number=11 hash=68495b…35d4fe
INFO [06-26|08:27:27.639245] Commit new mining work                   number=12 txs=0 uncles=0 elapsed=227.705µs
INFO [06-26|08:27:28.199602] Successfully sealed new block            number=12 hash=96fd37…37c016
INFO [06-26|08:27:28.199963]  block reached canonical chain          number=7  hash=a8d6d5…e6036d
INFO [06-26|08:27:28.19998]  mined potential block                  number=12 hash=96fd37…37c016
INFO [06-26|08:27:28.200427] Commit new mining work                   number=13 txs=0 uncles=0 elapsed=276.033µs
INFO [06-26|08:27:29.766971] Successfully sealed new block            number=13 hash=a13201…c051c8
INFO [06-26|08:27:29.767429]  block reached canonical chain          number=8  hash=16222d…7a9445
INFO [06-26|08:27:29.767447]  mined potential block                  number=13 hash=a13201…c051c8
INFO [06-26|08:27:29.767572] Commit new mining work                   number=14 txs=0 uncles=0 elapsed=110.439µs
INFO [06-26|08:27:30.302882] Successfully sealed new block            number=14 hash=e1ab15…e44665
INFO [06-26|08:27:30.303213]  block reached canonical chain          number=9  hash=1c5609…aa0028
INFO [06-26|08:27:30.303243]  mined potential block                  number=14 hash=e1ab15…e44665
INFO [06-26|08:27:30.303471] Commit new mining work                   number=15 txs=0 uncles=0 elapsed=114.85µs
INFO [06-26|08:27:35.685475] Successfully sealed new block            number=15 hash=e1b5a4…1bab9e
INFO [06-26|08:27:35.686032]  block reached canonical chain          number=10 hash=819037…fbcd88
INFO [06-26|08:27:35.686146]  mined potential block                  number=15 hash=e1b5a4…1bab9e
INFO [06-26|08:27:35.686523] Commit new mining work                   number=16 txs=0 uncles=0 elapsed=294.263µs

# 停止挖矿
> miner.stop()
true

在高度number=11的区块上,我们发现了有一笔转账信息。再次,查看账户余额,发现账户余额发生了变化。


> eth.getBalance(eth.accounts[0])
45000000000000000000
> eth.getBalance(eth.accounts[1])
30000000000000000000

第一个账户变成了 45 ether,第二个账号变成了30 ether。第二个账户余额,正是我们之前设定的转账金额。


# 查看当前块的高度
> eth.blockNumber
15

# 第11个区块的细节
> eth.getBlock(11)
  difficulty: 131072,
  extraData: "0xd88301080c846765746888676f312e31302e33856c696e7578",
  gasLimit: 2124527304,
  gasUsed: 21000,
  hash: "0x68495bf329e886a8043d1af74d145a870ae6aa2d4e42134499b3730e5c35d4fe",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0x9cac40f650e2cbe459dcb32c7c23103497134467",
  mixHash: "0xbbf5053e0409cded11f0c8f1059cad389d366723cb2f6c077d6c71c36d31a254",
  nonce: "0x3cc35610dc92f143",
  number: 11,
  parentHash: "0x819037bcc65eb789eca82fcc3d6c686852ab8297df6396cffa6cfffeaffbcd88",
  receiptsRoot: "0x170861bbc9f17f29b4c8ef046f44fa7435c3ad3a54e752591c87050345c29d31",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 653,
  stateRoot: "0x6e44fbe836ebf62523a37bbbb1beaad0c0802be9ff5c4e7b19c16a1eb4c50112",
  timestamp: 1529972844,
  totalDifficulty: 1444675,
  transactions: ["0x8d6d1eb3c1c82be1f419d8f772048644361c41362fd8de27f8252470f975d6bb"],
  transactionsRoot: "0x98881bb99ed82df9a69726705fb2ac2d1371e9ba992c52ed3b4cd3ee50762d38",
  uncles: []
}

第11个区块发生了交易,消耗的gas手续费为gasUsed=21000 Wei,交易一共发生1笔transactions=0x8d6d1eb3c1c82be1f419d8f772048644361c41362fd8de27f8252470f975d6bb,矿工账号miner: “0x9cac40f650e2cbe459dcb32c7c23103497134467″。

总结一下,本文介绍了如何搭建以太坊的私有节点,实现了挖矿的过程,并完了2个账户的第一笔转账操作。下一篇文章,找我了解智能合约的编写。

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI周红伟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值