这几天不分白昼的看各种英文文档和stackoverflow,终于把区块链这套基本的框架和流程搞通了,感觉十分不容易,故做个分享。不过,如果你时间充裕,请直接阅读英文官方文档:http://www.ethdocs.org/en/latest/,不要看我们这些囫囵吞枣的内容。如果阅读有困难,可以从本文先找找感觉。
名词解释
Ethereum–以太坊,是一个开源的有智能合约功能的公共区块链平台
公有链、私有链、联盟链–公有链不解释;私有链是指其写入权限由某个组织和机构控制的区块链,参与节点的资格会被严格限制;联盟链是指有若干个机构共同参与管理的区块链,每个机构都运行着一个或多个节点,其中的数据只允许系统内不同的机构进行读写和发送交易,并且共同来记录交易数据。
Geth–对应软件包ethereum,又名Go Ethereum,是以太坊协议的三种实现之一,由Go语言开发,完全开源的项目。Geth 可以被安装在很多操作系统上,包括Windows、Linux、Mac的OSX、Android或者IOS系统
Solidity–对应软件包solc,是一种语法类似JavaScript的高级语言。它被设计成以编译的方式生成以太坊虚拟机代码。
gas— cost = gasPrice * gasUsed, gaslimit是由发起者设置的,gasPrice是双方博弈的。
truffle:合约编译、测试、发布框架工具
以太坊中的数据单位:
* ether
* finney
* szabo
* wei
* 1 ether = 1 * 10^18 wei;
* 1 ether = 1 * 10^6 szabo;
* 1 ehter = 1* 10^3 finney;
程序在处理交易的时候用的单位都是wei
系统准备
两台同网段的linux云虚机,内存必须>=2G
系统建议使用最新的ubuntu版本,可以省却很多编译的麻烦。如果是centos>7.0。
本问采用两台ubuntu系统:
10.120.113.245—简称node1服务器
10.120.113.246—简称node2服务器
node1服务器搭建
安装geth:
sudo apt-get install software-properties-common sudo add-apt-repository -y ppa:ethereum/ethereum sudo add-apt-repository -y ppa:ethereum/ethereum-dev sudo apt-get update sudo apt-get install ethereum
安装solc编译器
sudo apt-get install solc
先创建3个账号,作为创世大神用的。以下代码运行三次。
appadmin@ubuntu:~$ geth account new
INFO [03-06|17:39:52] Maximum peer count ETH=25 LES=0 total=25
Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase:
Repeat passphrase:
Address: {e2b44335459830c43aaede94a6c748b40f5bfb26}
开始创造世界,先编辑个genesis.json文件:
{
“nonce”: “0x0000000000000042”, //Number once
“difficulty”: “0x1”,//挖矿的难度
“alloc”: {//给三个创世大神初始化钱
“f4182f0dc92313f8e106fc033641c3351703911f”: {
“balance”: “20000009800000000000000000000”
},
“899a969874bec249e4ef439c75adb0c358913b95”: {
“balance”: “20000009800000000000000000000”
},
“6797c39109ec4676d3b5dbb4dc76f1143a0f633a”: {
“balance”: “20000009800000000000000000000”
}
},
“config”: {
“chainId”: 12,//1-8不能用,详情https://ethereum.stackexchange.com/questions/17051/how-to-select-a-network-id-or-is-there-a-list-of-network-ids
“homesteadBlock”: 0,
“eip155Block”: 0,
“eip158Block”: 0
},
“mixhash”: “0x0000000000000000000000000000000000000000000000000000000000000000”, “coinbase”: “0x0000000000000000000000000000000000000000”,
“timestamp”: “0x00”,
“parentHash”: “0x0000000000000000000000000000000000000000000000000000000000000000”,
“extraData”: “0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa”,//传啥都行,但必须符合这格式
“gasLimit”: “0xb2d05e00”
}
好,把上面这个json文件放到eth目录中,执行如下代码:
geth –datadir “/home/appadmin/.ethereum” init eth/genesis.json
创建成功后,编写个启动脚本start.sh:
#!/bin/sh
geth –ipcdisable –rpc –rpcaddr “10.120.113.245” –port 30303 –rpcport 8101 –rpccorsdomain “*” –unlock ‘0,1,2’ –password ~/eth/password –networkid 12 –datadir ‘~/.ethereum’ console 2>>log
rpc是对外通信用的, ipc是内部通信用的,如果ipcdisable会无法在新的会话中attach到这个节点中,保证安全性(相反,可以geth attach新开一个控制台)
命令中会用password密码文件解锁以上三个账号,下文会解释为何要解锁。
保存,chmod +x start.sh 让其可执行
然后运行./start.sh其中控制台,稍后片刻就进入了。
查看节点下的创世大神们都有谁:
> eth.accounts
[“0xe2b44335459830c43aaede94a6c748b40f5bfb26”, “0x83817fa106fee9cfe149c9548e3656bffda90987”, “0x58a87b6080a226750f1e9e6d0f999ddfbc1bf914”]
开始挖矿钱,先看看矿机在谁的控制下:
eth.coinbase
可以通过这个命令设置所有者:
miner.setEtherbase(eth.accounts[2])
开始挖矿
> miner.start()
null
查看账户有多少钱了,上面说过,单位都是wei
> eth.getBalance('0xe2b44335459830c43aaede94a6c748b40f5bfb26') 2.0000019635e+28 > eth.getBalance('0x83817fa106fee9cfe149c9548e3656bffda90987') 2.00000098e+28 > eth.getBalance('0xbcf5b841303bc08026ce2d3b8f83498ffe42c12f') 0
可以使用eth.blockNumber查看一下区块高度是否增加。
> eth.blockNumber
1982
> eth.blockNumber
1985
> miner.stop()
true
> eth.blockNumber
1991
> eth.blockNumber
1991
> eth.blockNumber
1991
再创建个新账号:
> personal.newAccount()
Passphrase:
Repeat passphrase:
“0xdc23fc95dc3d452a210652be55195f5f743167ed”
> eth.accounts
[“0xe2b44335459830c43aaede94a6c748b40f5bfb26”, “0x83817fa106fee9cfe149c9548e3656bffda90987”, “0x58a87b6080a226750f1e9e6d0f999ddfbc1bf914”, “0xdc23fc95dc3d452a210652be55195f5f743167ed”]
> eth.getBalance(‘0xdc23fc95dc3d452a210652be55195f5f743167ed’)
0
执行转账命令,看看好不好使,结果发现报错:
> eth.sendTransaction({from: eth.accounts[3], to: eth.accounts[0], value: 120000000000000000000})
Error: authentication needed: password or unlock
at web3.js:3143:20
at web3.js:6347:15
at web3.js:5081:36
at <anonymous>:1:1
这个是以太坊的一个保护机制,每隔一段时间账户就会自动锁定,这个时候任何以太币在账户之间的转换都会被拒绝,除非把该账户解锁.
这个时候我们就需要执行 personal.unlockAccount(eth.accounts[3]) 并输入密码来解锁eth.accounts[3]才可。
> personal.unlockAccount(eth.accounts[3])
Unlock account 0xdc23fc95dc3d452a210652be55195f5f743167ed
Passphrase:
true
> eth.sendTransaction({from: eth.accounts[3], to: eth.accounts[0], value: 120000000000000000000})
Error: insufficient funds for gas * price + value
at web3.js:3143:20
at web3.js:6347:15
at web3.js:5081:36
at <anonymous>:1:1
> eth.gasPrice
18000000000
> eth.estimateGas({from: eth.accounts[2], to: eth.accounts[0], value: 120000000000000000000})
21000
由 于cost = gas * gasPrice , ( 账户3减少的资产 – 账户0增加的资产)/ gasPrice = 消耗的gas
> personal.unlockAccount(eth.accounts[2])
Unlock account 0xdc23fc95dc3d452a210652be55195f5f743167ed
Passphrase:
true
> eth.sendTransaction({from: eth.accounts[2], to: eth.accounts[0], value: 110000000000000000000})
“0xc27f031a26c80db62e959a00fe17325bed32820d6497076eedfd50fd51e5330a”
这时候可以看到矿池里面有未打包的交易,需要等矿工打包完成。
> txpool.status
{
pending: 1,
queued: 0
}
通过getTransation查看交易详情。
> eth.getTransaction(‘0xc27f031a26c80db62e959a00fe17325bed32820d6497076eedfd50fd51e5330a’)
{
blockHash: “0x0000000000000000000000000000000000000000000000000000000000000000”,
blockNumber: null,
from: “0x58a87b6080a226750f1e9e6d0f999ddfbc1bf914”,
gas: 90000,
gasPrice: 18000000000,
hash: “0xc27f031a26c80db62e959a00fe17325bed32820d6497076eedfd50fd51e5330a”,
input: “0x”,
nonce: 0,
r: “0x37114e0086c08a33cca996ba3a0ac3b263bf974e539f7a4c2136a2dca0bfe67a”,
s: “0x2b88f2a5abc23e8a21759589e4a7565fbfe61768e5b00b4e0b0056d4824087ca”,
to: “0xe2b44335459830c43aaede94a6c748b40f5bfb26”,
transactionIndex: 0,
v: “0x3b”,
value: 110000000000000000000
}
至此,node1节点搭建完成。下一章我们来看怎么编写和执行一个合约。