区块链学习(一)Mac系统下搭建基于以太坊的区块链开发环境

区块链的相关知识后补,先从实际的上手,从实例中学习

知识点

分布式数据库并且只能插入和查找

任何人都可以成为节点,保存整个数据库,且数据同步

工作量产生价值,成为币

软件安装

brew tap ethereum/ethereum
brew install ethereum

执行时间较长,需要耐心等待或者梯子

也可以编译安装,请自行百度

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

检查是否安装成功

geth -h

搭建私有链

需要给一个数据存储的文件夹,我们使用

cd ~
mkdir ethereum
cd ethereum

初始化一个创世区块,新建文件

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

有没有一种普罗米修斯里面造物主的感觉

下面是对这个创世区块的一些解释

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: 用来预置账号以及账号的以太币数量,因为私有链挖矿比较容易,所以我们不需要预置有币的账号,需要的时候自己创建即可以。
coinbase: 矿工的账号,随便填
timestamp: 设置创世块的时间戳
parentHash: 上一个区块的hash值,因为是创世块,所以这个值是0
extraData: 附加信息,随便填,可以填你的个性信息
gasLimit: 该值设置对GAS的消耗总量限制,用来限制区块能包含的交易信息总和,因为我们是私有链,所以填最大。

然后我们可以准备启动我们的私链

geth --datadir data init genesis.json

运行上面的命令,会读取genesis.json文件,根据其中的内容,将创世区块写入到区块链中。如果看到log信息中含有Successfully wrote genesis state字样,说明初始化成功。其中的数据信息等会保存在我们设置的data目录中。

启动私有链

初始化完成后,就可以通过输入以下命令启动私有链,并打开console了

geth –-datadir data console 2>> geth.log

指定数据目录是data,启动console,并且把console的输出重定向到geth.log文件

这样你可以另外启动一个控制台,使用命令查看console的输出

启动了区块链节点并进入了Javascript Console

这是一个交互式的Javascript执行环境,在这里面可以执行Javascript代码,其中>是命令提示符。在这个环境里也内置了一些用来操作以太坊的Javascript对象,可以直接使用这些对象。这些对象主要包括:

eth:包含一些跟操作区块链相关的方法 
net:包含以下查看p2p网络状态的方法 
admin:包含一些与管理节点相关的方法 
miner:包含启动&停止挖矿的一些方法 
personal:主要包含一些管理账户的方法 
txpool:包含一些查看交易内存池的方法 
web3:包含了以上对象,还包含一些单位换算的方法

基本玩法

查看&创建账户

>eth.accounts
[ ]

目前还没有账户,下面开始创建,参数即是密钥

>personal.newAccount('password')
"0x2b661b5b692de27578e6fb199b4ae2714ff24047"

查询余额

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

注意在console里也是可以用tab键自动补全的

启动&停止挖矿

miner.start(10)

其中参数表示挖矿使用的线程数。

第一次启动挖矿会先生成挖矿所需的DAG文件,这个过程有点慢,等进度达到100%后,就会开始挖矿,此时屏幕会被挖矿信息刷屏。

如果想停止挖矿,并且进度已经达到100%之后,可以在js console中输入

miner.stop()

挖到的区块会奖励币,是按wei的单位,wei是以太币的最小单位,1个以太币=10的18次方个wei。要查看有多少个以太币,可以用web3.fromWei()将返回值换算成以太币

>eth.getBalance(eth.accounts[0])
2.31e+21
>web3.fromWei(eth.getBalance(eth.accounts[0]),'ether') 
2310

可以设置矿工的账户

>miner.setEtherbase(eth.accounts[1])
true
>eth.coinbase

返回矿工的账户

转账

#为账户设置别名,方便命令输入
user1=eth.accounts[0]
user2=eth.accounts[1]
#查看区块高度,现在为0
eth.blockNumber
#转账测试,首先解锁账号user1
#命令运行后要求输入解锁密码,直接回车,默认账号锁定密码为空
也就是调用newAccount时候传的参数
返回true成功
personal.unlockAccount(user1)
#从user1向user2转账3个以太币
#命令运行后,提交交易立马回出发挖矿
eth.sendTransaction({from:user1,to:user2,value:web3.toWei(3,"ether")})

 

发现还没转过去,此时交易已经提交到区块链,但还未被处理,这可以通过查看txpool来验证:

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

#挖矿测试
#geth启动后,自动启动挖矿,这时运行miner.start(),返回为null 无交易的时候#不挖矿,当有交易时自动会触发挖矿流程

#我们可以先停止挖矿
miner.stop()

然后发现交易已经完成

查看交易和区块

可以通过区块号查看区块

> eth.getBlock(66)
{
 difficulty: 135266,
 extraData: "0xd783010802846765746886676f312e31308664617277696e",
 gasLimit: 3350537,
 gasUsed: 0,
 hash: "0x265dfcc0649bf6240812256b2b9b4e3ae48d51fd8e43e25329ac111556eacdc8",
 logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
 miner: "0x4a3b0216e1644c1bbabda527a6da7fc5d178b58f",
 mixHash: "0xaf755722f62cac9b483d3437dbc795f2d3a02e28ec03d39d8ecbb6012906263c",
 nonce: "0x3cd80f6ec5c2f3e9",
 number: 66,
 parentHash: "0x099776a52223b892d13266bb3aec3cc04c455dc797185f0b3300d39f9fc0a8ec",
 receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
 sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
 size: 535,
 stateRoot: "0x0c9feec5a201c8c98618331aecbfd2d4d93da1c6064abd0c41ae649fc08d8d06",
 timestamp: 1520391527,
 totalDifficulty: 8919666,
 transactions: [],
 transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
 uncles: []
}

或者通过交易hash查看交易,交易hash就是在sendTransaction的时候,会返回的一串

> amount = web3.toWei(10,'ether')
"10000000000000000000"
> eth.sendTransaction({from:eth.accounts[0],to:eth.accounts[1],value:amount})
INFO [03-07|11:13:11] Submitted transaction fullhash=0x1b21bba16dd79b659c83594b0c41de42debb2738b447f6b24e133d51149ae2a6 recipient=0x46B24d04105551498587e3C6CE2c3341d5988938
"0x1b21bba16dd79b659c83594b0c41de42debb2738b447f6b24e133d51149ae2a6"
>eth.getTransaction("0x1b21bba16dd79b659c83594b0c41de42debb2738b447f6b24e133d51149ae2a6")
{
 blockHash: "0x1cb368a27cc23c786ff5cdf7cd4351d48f4c8e8aea2e084a5e9d7c480449c79a",
 blockNumber: 463,
 from: "0x4a3b0216e1644c1bbabda527a6da7fc5d178b58f",
 gas: 90000,
 gasPrice: 18000000000,
 hash: "0x1b21bba16dd79b659c83594b0c41de42debb2738b447f6b24e133d51149ae2a6",
 input: "0x",
 nonce: 0,
 r: "0x31d22686e0d408a16497becf6d47fbfdffe6692d91727e5b7ed3d73ede9e66ea",
 s: "0x7ff7c14a20991e2dfdb813c2237b08a5611c8c8cb3c2dcb03a55ed282ce4d9c3",
 to: "0x46b24d04105551498587e3c6ce2c3341d5988938",
 transactionIndex: 0,
 v: "0x38",
 value: 10000000000000000000
}