IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    基于以太坊私有链搭建一个分布式应用【1】

    杜工发表于 2018-03-15 13:52:07
    love 0

    这几天不分白昼的看各种英文文档和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节点搭建完成。下一章我们来看怎么编写和执行一个合约。



沪ICP备19023445号-2号
友情链接