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:
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