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

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

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

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

一、命令行客户端
1、克隆仓库
brew tap ethereum/ethereum
2、安装go 客户端
brew install ethereum
3、运行
geth

二、图形化客户端
https://github.com/ethereum/mist/releases/


说明:

安装目录:/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: DAOSupport: false EIP150: EIP155: 0 EIP158: 0 Byzantium: Constantinople: 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
logs logsBloom由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数
gasUsed gas花费,在以太坊中交易和部署智能合约会消耗gas,暂时可理解为以太币
hash 当前区块hash值
logsBloom logsBloom由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

 

你可能感兴趣的:(区块链)