zoukankan      html  css  js  c++  java
  • 第一行代码:以太坊(1)-创建自己的私有区块链

    本文会利用以太坊客户端(geth)搭建一个私有区块链,并在这个私有区块链上挖矿,通过本文的案例,读者可以更深入理解区块链、以太坊、挖矿的理论。

    通过阅读本文,您可以:

    • 掌握搭建以太坊开发环境的方法
    • 掌握geth的基本使用方法
    • 了解如何启动JavaScript控制台
    • 掌握建立一个私有区块链的步骤
    • 掌握如何在私有区块链上挖矿

    1. 以太坊(Ethereum)开发环境搭建

    在玩以太坊之前,首先要搭建以太坊的开发环境。第一步就是安装geth。那么geth是什么呢?geth(或称为go-ethereum)是以太坊节点的一个实现。也就是说,geth是一个客户端,用于连接以太坊网络。从geth的名 字可以看出,geth是用go语言实现的一个以太坊节点。那么为什么需要这个节点呢?

    这是因为以太坊网络由多个节点组成,这些节点可能是用不同技术实现的。如geth就是官方的以太坊节点。通过这些节点可以用命令行方式直接访问区块链网络,如广播交易,发布智能合约等,但对于大多数用户来说,都是非程序员出身,让他们通过命令行方式去操作以太坊网络是不可能的,所以就要求有图形化的操作界面来操作以太坊网络。但geth这样的节点是做不到的,因此,就需要像web3.js,web3.py这样的程序库,再配合JavaScript、Python实现可视化的以太坊客户端,但这些库是无法直接连接进以太坊网络的,他们只能连接像geth这样的以太坊节点,然后通过一塔发节点访问以太坊网络,所以geth其实同时起到客户端和服务端的作用。也就是说,geth是以太坊网络的客户端,是web3.js的服务端。

    安装geth也非常容易,可以直接到下面的官网下载不同平台的geth安装程序。

    https://ethereum.github.io/go-ethereum/downloads

    访问上面的Url,会看到页面上面显示如下图所示的下载按钮。

    image.png

    目前geth的最新版本是1.8.3,支持Linux、Mac OS X和Windows平台,读者可以根据实际情况下载相应平台的geth安装程序,也可以直接下载源代码(最后一个按钮),然后编译和安装geth,不过这种方式只适合于专业人员,对于初学者,并不推荐使用这种方式。

    (1)安装Windows版geth

    Windows版安装程序是一个exe文件(geth-windows-amd64-1.8.3-329ac18e.exe或类似的文件名),直接双击安装即可。双击该文件会显示如下图所示的安装界面。

    image.png

    单击“I Agree”按钮会显示如下图所示的选择组件界面。

    image.png

    建议读者将Geth和Development tools都选上,否则在用到相关工具时还需要安装。然后单击“Next”按钮进入下一个安装界面。该界面主要用于指定geth的安装目录,默认安装目录是“C:Program FilesGeth”,如果读者不想将geth安装到这个目录,可以修改成其他目录,如“D:geth”效果如下图所示。

    image.png

    接下来单击“Install”按钮开始安装geth。安装的过程会显示当前安装进度的百分比,直到最后显示“Completed”,表示已经安装成功,如下图所示。最后单击“Close”按钮关闭安装界面。

    image.png

    Windows版的geth其实就是一些exe文件,如下图所示。其中geth.exe是本书主要使用的工具。

    image.png

    安装完geth后,最好将geth.exe文件所在的目录加到PATH环境变量中,这样在任何目录下就都可以使用geth.exe文件。

    (2)安装Mac OS X版geth

    Mac OS X版安装程序是一个压缩文件(geth-darwin-amd64-1.8.3-329ac18e.tar.gz或类似的名字),将该压缩文件解压,会发现只有一个geth可执行文件,如下图所示。

    image.png

    如果要想下载Mac OS X版的geth相关工具,可以到图2-1所示页面下方选择相应的操作系统,下载Tools压缩包或安装程序(点击Geth&Tools 1.8.3即可下载相应操作系统的Tools),如下图所示。为了使用方便,可以将geth所在的路径加到/etc/profile文件的PATH变量中,然后执行source /etc/profile命令,让配置立即生效。这样在任何目录下都可以使用geth。

    image.png

    在Mac OS X下还可以使用brew命令安装以太坊开发环境。

    brew tap ethereum/ethereum
    brew install ethereum
    

    读者可以选择自己喜欢的方式在Mac OS X下安装以太坊开发环境。

    (3)安装Linux版geth

    Linux版的geth与Mac OS X版的geth差不多,安装程序同样是一个压缩文件(geth-linux-amd64-1.8.3-329ac18e.tar.gz或类似的文件名),将该压缩文件复制到Linux的某个目录,然后在Console中进入该目录,执行如下的命令对该文件解压。

    tar zxvf geth-linux-amd64-1.8.3-329ac18e.tar.gz

    解压后,仍然只有一个geth可执行文件,这个可执行文件是静态编译的,在任何Linux发行版上都可以独立执行。

    在Linux下安装完geth后,最好将geth文件所在的路径添加到PATH变量中,设置的方法与Mac OS X类似。

    2. 使用geth命令创建以太坊账户

    安装完geth,需要测试一下,可以在控制台输入geth version命令(用于查看geth的版本信息),如果输出类似下图所示的信息,表示geth已经安装成功。

    image.png

    在Windows下执行geth version命令,也会得到与图2-9类似的版本信息,只是部分信息稍有差异,如下图所示。

    image.png

    使用geth的第一步就是创建账户。以太坊的账户用40位十六进制的地址表示,如下面的十六进制数就是一个标准的以太坊账户地址(前面的0x表示十六进制)。

    0x24924f33a9c49d312a8d885ade76ece76b315982

    第一次使用geth时,geth中没有任何账户,所以首先需要使用geth命令创建以太坊账户。在创建以太坊账户之前,可以使用下面的命令查看以太坊当前的账户。

    geth account list

    执行上面的命令,会显示如下图所示的信息,很明显,没有任何账户。

    image.png

    现在使用geth account new命令创建以太坊账户,在创建的过程中要求输入账户的密码。如果最后输出了一个以太坊地址,就说明账户创建成功了,如下图所示。该地址就是以太坊账户。

    image.png

    可以使用同样的方法多创建几个以太坊账户。然后使用geth account list命令查看以太坊当前的账户,会得到如下图所示的查询结果。根据查询结果显示,以太坊当前有3个账户。

    image.png

    3. 删除以太坊账户

    geth并没有直接提供删除以太坊账户的命令,不过可以通过删除账户本地文件的方式删除以太坊账户(因为每一个以太坊账户对应一个文件)。根据上图所示的以太坊账户信息,可以得知账户文件的存储路径如下:

    /Users/lining/Library/Ethereum/keystore

    进入该目录,会看到如下图所示的3个文件,分别对应上一节建立的3个以太坊账户。如果要删除某个以太坊账户,只需要删除对应的文件即可,然后再次执行geth account
    list命令,会发现与文件对应的以太坊账户消失了。

    image.png

    在Windows中的操作与Mac OS X相同,只是保存账户文件的路径不同。在Windows下使用同样的方式创建3个以太坊账户,然后使用geth account list命令列出所有的账户,如下图所示。

    image.png

    从上图所示的账户信息可知,保存账户文件的路径如下:

    C:UsersandroidguyAppDataRoamingEthereumkeystore

    其中androidguy是Windows用户名,请将其改成自己机器的用户名。

    4. geth JavaScript控制台

    geth可以通过JavaScript控制台和JavaScript代码访问以太坊网络。只需要执行geth console命令,就可以启动JavaScript控制台,在该控制台可以直接输入JavaScript代码,按Enter键会执行输入的JavaScript代码,不过有一个问题,就是geth命令同时也负责同步区块,以及其他工作,这样会产生大量的日志信息,这些日志信息会与JavaScript代码交替出现,非常烦人。效果如下图所示。

    image.png

    为了不让日志信息在JavaScript控制台输出,可以使用下面的命令启动JavaScript控制台,其中2表示日志管道,也就是将日志信息直接输出到geth.log文件。

    geth console 2>>geth.log

    执行上面的命令,会进入JavaScript控制台,在控制台中,除了输入的JavaScript代码和执行结果外,什么都不会输出,效果如下图所示。

    image.png

    在Windows下使用同样的操作会得到与Mac OS X下完全一样的效果,如下图所示。

    image.png

    JavaScript控制台并不是简简单单用来执行JavaScript代码的,其实这个控制台可以通过web3.js API直接访问以太坊网络。web3.js就是一套API,支持Web和Node.js。可能很多读者看到这些估计有些懵,一下抛出这么多概念,又是web3.js,又是Node.js。这些技术会在本书后面详细介绍,本节只要知道在JavaScript控制台可以使用JavaScript代码访问以太坊网络就可以了。如果使用geth console命令进入JavaScript控制台,并不需要单独安装web3.js,直接就可以使用web3.js的API。

    在JavaScript控制台中内置了很多JavaScript对象,其中web3就是其中最重要的对象。当启动JavaScript控制台后,这些对象会自动创建,可以直接使用。例如,可以直接在JavaScript控制台中执行下面的JavaScript代码。

    str = web3.fromAscii('ethereum')   //  将'ethereum'按ASCII转换为十六进制数
    web3.toDecimal('0xa')           //  将十六进制数(0xa)转换为十进制数
    //  判断地址是否有效
    isAddress = web3.isAddress("0x8888f1f195afa192cfee860698584c030f4c9db1");

    这些命令执行的效果如下图所示。在Windows中的JavaScript控制台也会得到完全相同的效果。

    image.png

    使用web3.js API的方式有很多,除了在JavaScript控制台中使用web3.js API外,至少还可以在下面的环境中使用web3.js。

    • 浏览器

    • Node.js

    • IPython

    • Jupyter Notebook

    5. 建立私有区块链与挖矿

    本节会利用geth命令创建一个私有区块链,然后自己挖矿,可以通过这个操作过程更深入理解以太坊和区块链的概念。

    创建私有区块链的步骤如下:

    (1)建立创世块

    区块链是由若干个区块组成的。在私有链启动后,需要为区块链创建第一个区块(创世块),相当于数据结构中链表的头节点。不过以太坊并不知道如何创建这个创世块,需要我们告诉以太坊如何创建,因此,首先需要建立一个创世块的描述文件,这个描述文件是JSON格式的,本例起名为block.json,代码如下:

    block.json文件

    文件位置:src/chapter2/block.json

    
    {
        "config":
        {
            "chainId":15,
            "homesteadBlock":0
        },
        "difficulty":"20",
        "gasLimit":"2100000",
        "alloc":{
            "7df9a875a174b3bc565e6424a0050ebc1b2d1d82":{"balance":"300000"},
            "f41c74c9ae680c1aa78f42e5647a62f353b7bdde":{"balance":"400000"}
        }
    }

    一个完整的区块描述文件非常复杂,本例只对区块进行了一些基本设置,这些设置项的描述如下:

    • chainId:指定了独立的区块链网络 ID。网络 ID
    在连接到其他节点的时候会用到,以太坊公网的网络 ID 是 1,为了不与公有链网络冲突,运行私有链节点的时候要指定自己的网络 ID。不同 ID 网络的节点无法相互连接。

    • homesteadBlock:以太坊推出的第2个主要的区块发行版本,Frontier是第1个推出的区块发行版本(也是测试版本)。建议使用homesteadBlock,这里的0表示有效。

    • difficulty:挖矿的难易程度,该值越小,挖矿越容易。也就是说,该值越小,挖矿需要的算力越小,在测试时,建议设置一个比较小的值,否则挖矿会需要很长时间。

    • gasLimit:挖每个区块需要消耗资源的上限,gas与以太币(ether)一样,都是以太坊中的单位。之所以将gas与ether分开,是为了防止ether的波动对挖每个区块消耗资源的影响。

    • alloc:为了测试挖矿,临时分配的账户,其中balance表示当前账户的余额,单位是Wei。

    (2)初始化区块链

    这一步需要使用如下的命令对区块链进行初始化。

    geth init block.json --datadir test

    其中test表示与区块链相关数据保存的目录,本例test与block.json文件在同一个目录下。执行上面的命令后,会在当前block.json文件所在的目录生成一个test子目录。test子目录的结构如下图所示。

    image.png

    很明显,在test目录下面还有两个子目录:geth和keystore。其中geth目录保存了同步区块链以及相关的数据,keystore目录保存了账户文件。由于私有链刚创建,还没有创建账户,所以keystore目录为空。
    如果在Windows下执行前面初始化区块链的命令,会得到与Mac OS X下完全一样的结果。读者可以自己在Windows做实验。

    (3)启动以太坊客户端(geth)

    在这一步使用下面的命令启动以太坊客户端(进入JavaScript控制台)。其中datadir命令行参数表示geth会使用test目录保存相关文件。

    geth --datadir test console

    (4) 将账户与矿工绑定

    负责挖矿的账户称为矿工。miner是JavaScript控制台中内置的矿工对象,在Java可以使用下面的命令将block.json文件中的两个地址中的一个与miner对象绑定。

    miner.setEtherbase("0x7df9a875a174b3bc565e6424a0050ebc1b2d1d82")
    

    (5)开始挖矿

    在开始挖矿之前,可以使用下面的命令查一下两个临时账号的余额。

    eth.getBalance("0x7df9a875a174b3bc565e6424a0050ebc1b2d1d82")
    eth.getBalance("0xf41c74c9ae680c1aa78f42e5647a62f353b7bdde")
    

    查询结果分别是300000和400000。现在矿工(miner)已经和余额为300000的账户绑定,接下来在JavaScript控制台执行如下的代码开始挖矿。

    miner.start()

    执行这行代码后,就会开始挖矿,如果要停止挖矿,需要在JavaScript控制台执行如下的代码。

    miner.stop()

    停止挖矿后,可以执行下面的代码查询当前区块链中的区块数,其中eth是JavaScript控制台内建的对象。在本例中一共挖了36个区块,也就是目前在网络中有一条由36个区块组成的区块链。

    eth.blockNumber

    再次使用下面的代码查询两个临时账户的余额。

    eth.getBalance("0x7df9a875a174b3bc565e6424a0050ebc1b2d1d82")
    eth.getBalance("0xf41c74c9ae680c1aa78f42e5647a62f353b7bdde")

    我们会发现与矿工(miner)绑定的账户的余额变多了,多出的余额就是挖矿的奖励(以太币),如下图所示。

    image.png

    在Windows下执行同样的命令会获得相同的结果(挖了30个区块),如下图所示。

    image.png

    (6)控制挖矿数量

    有时需要控制挖矿数量,也就是说,挖到指定数量的区块后自动终止挖矿,要达到这个目的,需要在JavaScript控制台执行下面的命令。

    miner.start(3);
    admin.sleepBlocks(10);
    miner.stop();

    其中start方法的参数表示挖矿使用的线程,默认值是CPU内核的数量,如CPU是双核的,那么线程数就是2。sleepBlocks方法的参数表示要挖的区块数,本例是10个区块。如果还没有挖完10个区块,那么sleepBlocks方法会处于阻塞状态,直到挖完10个区块,会继续执行下面的代码,也就是miner.stop(),这时挖矿就会结束。

  • 相关阅读:
    hdu 1028 Ignatius and the Princess III (n的划分)
    CodeForces
    poj 3254 Corn Fields (状压DP入门)
    HYSBZ 1040 骑士 (基环外向树DP)
    PAT 1071 Speech Patterns (25)
    PAT 1077 Kuchiguse (20)
    PAT 1043 Is It a Binary Search Tree (25)
    PAT 1053 Path of Equal Weight (30)
    c++ 常用标准库
    常见数学问题
  • 原文地址:https://www.cnblogs.com/nokiaguy/p/9697725.html
Copyright © 2011-2022 走看看