区块链初探

内容摘要

  1. Geth的安装配置
  2. 搭建私有链以及加入私有节点
  3. 智能合约编写、部署与测试
  4. 日志分析

0. 实验环境

  • 虚拟机: ubuntu-17.10.1-desktop-amd64
  • go的版本: go1.11

1. 以太坊的安装,安装geth客户端

  • geth是用go语言写的,编译geth源码需要go语言和C语言编译器,因此需要先安装go语言,go语言版本推荐用go1.7及以上,go语言的安装配置教程。

  • 将github仓库克隆源文件:

    git clone https://github.com/ethereum/go-ethereum
    
  • 构建geth需要安装Go和C编译器:

    sudo apt-get install -y build-essential golang
    
  • 最后,使用以下命令构建程序生成geth

    cd go-ethereum
    make geth     
    
  • go-ethereum文件夹下可以运行build/bin/geth以启动节点,当然可以在/etc/profile配置一下geth的环境变量,然后就可以直接使用geth而不用具体指定路径了啦。

    vi /etc/profile
    

    在后面加入geth的文件具体路径,例如:

    export PATH=$PATH:/home/liuyt49/Desktop/go-ethereum/build/bin
    

2. 私有链创世区块搭建

  • 自定义创世区块,genesis.json

    {
        "config": {
                "chainId": 666,
                "homesteadBlock": 0,
                "eip155Block": 0,
                "eip158Block": 0
            },
        "alloc"      : {},
        "coinbase"   : "0x0000000000000000000000000000000000000000",
        "difficulty" : "0x00000001",
        "extraData"  : "",
        "gasLimit"   : "0xffffff",
        "nonce"      : "0x0000000000000042",
        "mixhash"    : "0x0000000000000000000000000000000000000000000000000000000000000000",
        "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
        "timestamp"  : "0x00"
    }
    

    参数解释:

    参数 解释
    alloc 用来预置账号以及账号的eth数量。私链挖矿比较容易,不需要预置有币的账号
    coinbase 矿工的账号
    difficulty 设置当前区块的难度
    extraData 附加信息
    gasLimit 该值设置对GAS的消耗总量限制,用来限制区块能包含的交易信息总和,因为我们是私有链,所以填最大
    nonce nonce值是一个64随机数,用于挖矿
    mixHash 与nonce配合用于挖矿,由上一个区块的一部分生成的hash
    parentHash 上一个区块的hash值,因为是创世区块,因此该值为0
  • 初始化区块链
    geth -datadir myData/00 init genesis.json
    参数解释:

    • datadir - 设置当前区块链网络数据存放的位置,区块链网络存储在myData/00文件夹下
    • init - 指定创世块文件的位置,并创建初始块
  • 启动私有链节点

    geth -datadir myData/00 -networkid 2018 -rpc --rpcport "8545" --port "30303" -rpcaddr 你的IP -rpccorsdomain "*" console 2>output.log
    参数解释:

    • rpc - 启动rpc通信,可以进行智能合约的部署和调试
    • rpcaddr – rpc接口的地址
    • networkid - 设置当前区块链的网络ID,用于区分不同的网络,是一个数字
    • console - 启动命令行模式,可以在Geth中执行命令
    • 输出重定向到output.log
  • 启动节点成功后,会进入Geth的命令行模式

    • 创建一个新用户,用户名为空

      personal.newAccount(password, [callback])
      

      preview

    • 解锁用户

      personal.unlockAccount(accountname, password);
      

      preview

    • 挖矿

      • 开始挖矿
        其中start的参数表示挖矿使用的线程数。第一次启动挖矿会先生成挖矿所需的DAG文件,这个过程有点慢,等进度达到100%后,就会开始挖矿,此时屏幕会被挖矿信息刷屏。
        miner.start(1)
        
      • 挖到第一个区块即停止挖矿
        admin.sleepBlocks(1) 
        
      • 停止挖矿
        miner.stop()
        

      preview

      • 返回null不代表没有开始挖矿,实际正在进行中,在日志文件中有输出,详细解释why did it returned null after call miner.start()
    • 查看余额

      eth.getBalance(eth.accounts[0])
      

      preview

    • 账号转账

      web3.eth.sendTransaction(transactionObject [, callback])
      

      区块链初探_第1张图片

    • 新手的一些小总结

      • 关于如何中断一个挖矿过程的具体操作
        输入miner.start()即启动挖矿,挖矿后,会不停刷屏,输入miner.stop()即停止,不用管刷屏导致的命令不全,命令会正常执行。
      • 正常退出Geth
        输入exit即可
      • 退出以后如何再次进入
        geth --datadir myData/00 console
        当然其中datadir需要对应自己区块链网络数据存放的位置
  • 创建并加入新的私有节点

    • 创建新节点与之前流程相似,切记使用同一个创世区块的配置genesis.json
    • 同一台主机创建两个节点需要注意使用的端口避免冲突
    • 设置的networkid需要相同
    • 新的终端输入
      geth -datadir myData/01 init genesis.json
      geth -datadir myData/01 -networkid 2018 -rpc  --rpcport "8546" --port "30304" -rpcaddr 你的IP -rpccorsdomain "*" console 2>output.log
      
    • 建立节点连接
      • 节点00,获取其节点信息

        区块链初探_第2张图片

      • 节点01连接节点00,使用到方法 admin.addPeer(节点00的enode)

        24

      • 查看连接情况。可能一开始没有显示,需要等一会。
        admin.peers
        区块链初探_第3张图片

3. 对getBlock中所得区块的各个字段进行解释

  • web3.eth.getBlock()方法返回指定块编号或块哈希对应的块。
  • 调用:
    eth.getBlock(blockHashOrBlockNumber [, returnTransactionObjects] [, callback])
  • 参数:
    • blockHashOrBlockNumber:String|Number - 块编号或块哈希值,或者使用以下字符串:“genesis”、“latest” 或 “pending” 。
    • returnTransactionObjects:Boolean - 可选,默认值为false。当设置为true时,返回块中将包括所有交易详情,否则仅返回交易哈希。
    • callback:Function - 可选的回调函数,其第一个参数为错误对象,第二个参数为结果。
  • eth.getBlock(0)
    区块链初探_第4张图片
  • 返回值字段解释
    • difficulty: 该块的难度值
    • extraData: 块中的"extra data"字段
    • gasLimit: 该块允许的最大的gas值
    • gasUsed: 该块中所有交易使用的gas的总量
    • hash: 块的哈希值,处于pending状态的块的hash值为null
    • logsBloom: 块中日志的bloom filter,处于pending状态的块为null
    • miner: 接收奖励的矿工地址
    • mixHash: 与nonce配合用于挖矿,由上一个区块的一部分生成的hash
    • nonce: nonce就是一个64位随机数,用于挖矿,用于计算生成的proof-of-work的哈希,处于pending状态的块为null
    • number: 块编号,处于pending状态的块为null
    • parentHash: 父块的哈希值(hash)
    • receiptsRoot: 收款字典树的根节点哈希值
    • sha3Uncles: 块中叔伯数据的SHA3值
    • size: 字节为单位的块大小
    • stateRoot: 块中的最终状态树根节点,存储整个系统状态的专用Merkle树的根哈希
    • timestamp: 块创建的Unix时间戳
    • totalDifficulty: 截至该块的全链总难度值
    • transactions: 该块交易集合
    • transactionsRoot: 交易树根节点
    • uncles: 叔伯块哈希值数组

4. 编写简单的智能合约,在remix下进行调试,并部署在链上进行调用

  • 编写简单的智能合约,并在remix下进行调试
    • 智能合约
      pragma solidity ^0.4.0;
      
      contract SimpleContract {
          string message;
          
          function setMessage(string x) public{
              
              message = x;
          }
          
          function getMessage() constant public returns (string) {
              
              return message;
          }
      }
      
    • 编译合约
      • 选择合适的编译器版本
      • 点击右侧栏的Compile模块下的Start to compile按钮进行编译,同时编译成功可以在Run中模拟运行。
        区块链初探_第5张图片
    • 部署合约
      部署合约就是将编译好的合约字节码通过外部账号发送交易的形式部署到以太坊区块链上。
      步骤:
      • compile页面编译成功后点击Details按钮,出现浮层页面在浮层中找到WEB3DEPLOY , 将WEB3DEPLOY中的内容复制。

      • 将智能合约直接粘贴到命令行(console)

        var simplecontractContract = web3.eth.contract([{"constant":false,"inputs":[{"name":"x","type":"string"}],"name":"setMessage","outputs":[],"payable":false,"type":"function","stateMutability":"nonpayable"},{"constant":true,"inputs":[],"name":"getMessage","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function","stateMutability":"view"}]);
        var simplecontract = simplecontractContract.new(
        {
            from: web3.eth.accounts[0], 
            data: '0x606060405261028f806100126000396000f360606040526000357c010000000000000000000000000000000000000000000000000000000090048063368b877214610047578063ce6d41de146100a257610042565b610002565b34610002576100a06004808035906020019082018035906020019191908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050909091905050610122565b005b34610002576100b460048050506101d3565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156101145780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b8060006000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017157805160ff19168380011785556101a2565b828001600101855582156101a2579182015b828111156101a1578251826000505591602001919060010190610183565b5b5090506101cd91906101af565b808211156101c957600081815060009055506001016101af565b5090565b50505b50565b602060405190810160405280600081526020015060006000508054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102805780601f1061025557610100808354040283529160200191610280565b820191906000526020600020905b81548152906001019060200180831161026357829003601f168201915b5050505050905061028c565b9056', 
            gas: '4700000'
        }, function (e, contract){
            console.log(e, contract);
            if (typeof contract.address !== 'undefined') {
                console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
            }
        })
        

        区块链初探_第6张图片

        • 出现报错,进行部署之前,先将交易的账号进行解锁,不然会出现错误

          personal.unlockAccount(eth.accounts[0])
          

          8

      • 再次进行粘贴,没有报错了

        区块链初探_第7张图片

      • 检查一下交易池,查看当前交易的待处理状况:

        txpool.status
        

        12
        看到当前的交易池中有一个交易正在等待确认。然后,我们查看待确认交易的详细内容:

        eth.getBlock("pending",true).transactions
        

        区块链初探_第8张图片
        查看区块信息与我们之前所设置的相同。

        • from数据项就是我们发送交易的地址
        • input就是合约编译完成的字节码
        • 新的交易创建在第3号区块中
      • 查看日志

        INFO [11-03|02:52:58.543] Submitted contract creation              fullhash=0x16acefe5b61cff177b3cc65d21237594913bdd7e0c71d97200a42db22147f55d contract=0xE87619e16Aa3d2fd7BeA8A18Bb770b8B1Fd808b8
        

        说明交易已经发送到区块链中了,正在等待矿工的确认,确认后才真正完成智能合约的部署

        • 注意:接下来要开始挖矿(miner.start(1))
    • 调用智能合约
      • 关于 web3.eth.contract
      • 使用一个在某个地址上已经存在的合约
        • simplecontract是合约对象,通过创建合约的交易来部署合约,是第一个合约
        • simplecontract.address 得到之前部署了的合约的合约地址
        • testcontract为合约对象,通过交易修改合约的数据。
        // instantiate by address
        testcontract = simplecontractcontract.at(simplecontract.address)
        
        区块链初探_第9张图片
      • 调用
        如果调用的智能合约函数需要合约中的数据, 则需要消耗以太坊gas,否则不需要消耗。由于需要修改合约中的数据, 调用setMessage()时需要使用sendTransaction()发起交易, 并附加发起者的账号. 以上操作只是发起了交易, 但交易并不一定会被处理. 交易被处理还必须要有节点处于挖矿模式。想要获取到修改后的数据,必须等到交易完成后,getMessage才可以获取到修改后的数据。
        • 调用setMessage方法

          testcontract.setMessage.sendTransaction("sysu", {from:eth.accounts[0]})
          

          区块链初探_第10张图片
          解决方法与之前一样,只需要解锁一下账号就可以了
          16
          17
          返回的值发送的交易的hash值
          查看交易池信息以及详细的交易信息
          区块链初探_第11张图片
          然后开始挖矿 - miner.start(1)

        • 调用getMessage方法

          19

5. 对交易的字段进行解释

获取一个交易信息,使用到eth.getTransaction(hash)方法,返回具有指定哈希值hash的交易对象。

  • 已确认交易
    区块链初探_第12张图片
  • 未确认交易
    区块链初探_第13张图片
  • 字段解释
    • blockHash: 交易所在块的哈希值,如果交易处于pending状态,该值为null
    • blockNumber: 交易所在块的编号,如果交易处于pending状态,该值为null
    • from: 交易发起者的地址
    • gas: 发送方提供的gas用量
    • gasPrice: 发送方承诺的gas的价格,以wei为单位
    • hash: 交易的哈希值
    • input: 随交易发送的数据
    • nonce: 交易发起者(from账户)发出交易的次数
    • r: ECDSA签名值,交易的签名数据
    • s: ECDSA签名值,交易的签名数据
    • to: 交易接收方的地址。对于创建合约的交易,该值为null
    • transactionIndex: 交易在块中的索引位置
    • v: ECDSA签名值,交易的签名数据
    • value: 以wei为单位的转账金额

6. 对日志输出进行解释

  • 启动本地节点self=enode://XXX

    INFO [10-31|19:57:55.038] Started P2P networking                   self=enode://63b1fc80da8edeaa22bc873c6263e4a6f3c4b5dbd73b66042aed71691671daab52ed3c819ec113311221a3e68b2c8e994cf3c45dcbc2eadb4f1a94624985f798@127.0.0.1:30303
    
  • 从本地database=/home/liuyt49/Desktop/Blockchain/data/00/geth/chaindata读取区块数据

    INFO [10-31|19:57:54.880] Allocated cache and file handles         database=/home/liuyt49/Desktop/Blockchain/data/00/geth/chaindata cache=492 handles=512
    
  • 初始化区块链配置

    INFO [10-31|19:57:54.904] Initialised chain configuration          config="{ChainID: 666 Homestead: 0 DAO:  DAOSupport: false EIP150:  EIP155: 0 EIP158: 0 Byzantium:  Constantinople:  Engine: unknown}"
    
  • 允许硬盘存储 ethash 相关caches、DAGs

    INFO [10-31|19:57:54.904] Disk storage enabled for ethash caches   dir=/home/liuyt49/Desktop/Blockchain/data/00/geth/ethash count=3
    INFO [10-31|19:57:54.904] Disk storage enabled for ethash DAGs     dir=/home/liuyt49/.ethash                                count=2
    
    • ethash介绍
  • 初始化以太坊协议

    INFO [10-31|19:57:54.904] Initialising Ethereum protocol           versions="[63 62]" network=2018
    
  • 第一次启动挖矿会先生成挖矿所需的 DAG 文件,这个过程有点慢,等进度达到 100% 后,就会开始挖矿

    INFO [10-31|19:59:04.873] Generating DAG in progress               epoch=0 percentage=0 elapsed=10.269s
    INFO [10-31|19:59:13.702] Generating DAG in progress               epoch=0 percentage=1 elapsed=19.099s
    INFO [10-31|19:59:22.337] Generating DAG in progress               epoch=0 percentage=2 elapsed=27.734s
    INFO [10-31|19:59:32.276] Generating DAG in progress               epoch=0 percentage=3 elapsed=37.672s
    INFO [10-31|19:59:40.475] Generating DAG in progress               epoch=0 percentage=4 elapsed=45.871s
    INFO [10-31|19:59:48.898] Generating DAG in progress               epoch=0 percentage=5 elapsed=54.294s
    INFO [10-31|19:59:57.013] Generating DAG in progress               epoch=0 percentage=6 elapsed=1m2.410s
    INFO [10-31|20:00:05.233] Generating DAG in progress               epoch=0 percentage=7 elapsed=1m10.630s
    INFO [10-31|20:00:13.440] Generating DAG in progress               epoch=0 percentage=8 elapsed=1m18.837s
    INFO [10-31|20:00:21.584] Generating DAG in progress               epoch=0 percentage=9 elapsed=1m26.980s
    INFO [10-31|20:00:30.118] Generating DAG in progress               epoch=0 percentage=10 elapsed=1m35.514s
    INFO [10-31|20:00:38.132] Generating DAG in progress               epoch=0 percentage=11 elapsed=1m43.529s
    INFO [10-31|20:00:46.207] Generating DAG in progress               epoch=0 percentage=12 elapsed=1m51.603s
    INFO [10-31|20:00:54.200] Generating DAG in progress               epoch=0 percentage=13 elapsed=1m59.597s
    INFO [10-31|20:01:02.389] Generating DAG in progress               epoch=0 percentage=14 elapsed=2m7.785s
    INFO [10-31|20:01:10.538] Generating DAG in progress               epoch=0 percentage=15 elapsed=2m15.934s
    INFO [10-31|20:01:18.506] Generating DAG in progress               epoch=0 percentage=16 elapsed=2m23.902s
                                                        .......
    INFO [10-31|20:13:42.967] Generating DAG in progress               epoch=1 percentage=2  elapsed=1m6.364s
    
  • 挖到新的区块

    INFO [10-31|20:13:43.441] Successfully sealed new block            number=1 sealhash=737470…ef7f65 hash=ed8040…934883 elapsed=14m50.215s
    INFO [10-31|20:13:43.441]  mined potential block                  number=1 hash=ed8040…934883
    
  • 提交交易,但是交易还未被确认,处于pending,其中fullhash是该交易的哈希值,recipient是该交易接收者的地址

    INFO [11-03|05:43:22.270] Submitted transaction                    fullhash=0x361469a6b9e6cddf8e9c69ca9ab256c2a7be730b9a97ebc3b1e36dd580a7eddc recipient=0xE87619e16Aa3d2fd7BeA8A18Bb770b8B1Fd808b8
    
  • 添加新的节点01,并与之建立连接

    DEBUG[11-03|04:33:03.972] Adding p2p peer                          name=Geth/01/v1.8.18-unst... addr=127.0.0.1:33534 peers=1
    DEBUG[11-03|04:33:03.972] Ethereum peer connected                  id=663bef20db32f8c5 conn=inbound name=Geth/01/v1.8.18-unstable-3e1cfbae/linux-amd64/go1.11.1
    
  • 部署合约,其中fullhash是部署合约的交易的哈希值,contract是合约地址

    INFO [11-03|02:52:58.543] Submitted contract creation              fullhash=0x16acefe5b61cff177b3cc65d21237594913bdd7e0c71d97200a42db22147f55d contract=0xE87619e16Aa3d2fd7BeA8A18Bb770b8B1Fd808b8
    
  • 退出

    INFO [11-04:14:22.449] HTTP endpoint closed                     url=http://127.0.0.1:8545
    INFO [11-04:14:22.952] IPC endpoint closed                      endpoint=/home/liuyt49/Desktop/Blockchain/data/00/geth.ipc
    INFO [11-04:14:23.416] Writing cached state to disk             block=1 hash=ed8040…934883 root=f09abd…6b0e95
    INFO [11-04:14:23.959] Persisted trie from memory database      nodes=1 size=148.00B time=542.494034ms gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
    INFO [11-04:14:24.449] Blockchain manager stopped 
    INFO [11-04:14:24.449] Stopping Ethereum protocol 
    INFO [11-04:14:24.449] Ethereum protocol stopped 
    INFO [11-04:14:24.449] Transaction pool stopped 
    INFO [11-04:14:26.085] Database closed                          database=/home/liuyt49/Desktop/Blockchain/data/00/geth/chaindata
    

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