暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

【以太坊实战】windows下基于geth的以太坊DApp私链开发环境搭建

知否Tech 2020-09-25
1363


一、安装DApp开发环境

1.1 安装Node.js

https://nodejs.org/en/download/

我们使用官方长期支持的 Latest LTS Version: 12.18.4 (includes npm 6.14.6)版本,点击这个链接下载32位安装包,32位安装包即可用于32位系统,也可用于64位系统。如果你确认你的系统是64位,也可以下载64位包装包。下载后直接安装即可。安装完毕,打开一个控制台窗口,可以使用node了:

C:\Users\Administrator>node -v

v12.18.4


1.2 安装Geth

https://geth.ethereum.org/downloads/

https://gethstore.blob.core.windows.net/builds/geth-windows-amd64-1.9.21-0287d548.exe

下载64位或32位Geth安装程序,然后进行安装。安装完毕后打开一个控制台,执行命令验证安装成功:

C:\Users\Administrator>geth version

Geth

Version: 1.9.21-stable

Git Commit: 0287d54847d3297f3ced62cd83a4c95ccbe0045b

Git Commit Date: 20200909

Architecture: amd64

Protocol Versions: [65 64 63]

Go Version: go1.15

Operating System: windows

GOPATH=

GOROOT=go

C:\Users\Administrator>



1.3 安装solidity编译器

C:\Users\Administrator>npm install -g solc


安装完毕后,执行命令验证安装成功

C:\Users\Administrator>solcjs --version

0.7.1+commit.f4a555be.Emscripten.clang


1.4安装web3

web3.js是一组用来和本地或远程以太坊节点进行交互的js库,它可以使用HTTP或IPC建立与以太坊节点旳连接。

Web3的安装过程使用了git,因此需要先安装windows版的git命令行。下载64位或32位的git安装程序,本地安装后在继续安装web3。

C:\Users\Administrator>npm install -g web3

npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142

npm WARN deprecated har-validator@5.1.5: this

npm WARN deprecated multicodec@0.5.7: stable api reached

> keccak@3.0.1 install C:\Users\Administrator\AppData\Roaming\npm\node_modules\web3\node_modules\keccak

> node-gyp-build || exit 0

> bufferutil@4.0.1 install C:\Users\Administrator\AppData\Roaming\npm\node_modules\web3\node_modules\bufferutil

> node-gyp-build

> secp256k1@4.0.2 install C:\Users\Administrator\AppData\Roaming\npm\node_modules\web3\node_modules\secp256k1

> node-gyp-build || exit 0

> utf-8-validate@5.0.2 install C:\Users\Administrator\AppData\Roaming\npm\node_modules\web3\node_modules\utf-8-validate

> node-gyp-build

> web3@1.3.0 postinstall C:\Users\Administrator\AppData\Roaming\npm\node_modules\web3

> node angular-patch.js

+ web3@1.3.0

added 322 packages from 318 contributors in 85.036s



安装验证:

C:\Users\guow> node –p 'require("web3")'

{[Function: Web3]

providers:{…}}

1.5安装truffle框架

Truffle是什么?

Truffle是针对基于以太坊的Solidity语言的一套开发框架。本身基于Javascript。

执行以下命令安装truffle开发框架:

C:\Users\Administrator>npm install -g truffle


验证安装:

C:\Users\Administrator>truffle.cmd version

Truffle v5.1.45 (core: 5.1.45)

Solidity v0.5.16 (solc-js)

Node v12.18.4

Web3.js v1.2.1


1.6安装webpack

本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle

执行以下命令安装webpack:

C:\Users\Administrator>npm install -g webpack


验证安装

C:\Users\Administrator>webpack -v

4.44.2


三、运行私链节点

2.1创世块配置

创建一个节点目录node1,并在其中创建私链的创世块配置文件:

C:\Users\guow> mkdir node1

C:\Users\guow> cd node1

C:\Users\guow\node1> notepad private.json

然后编辑内容如下:

{

  "config": {

     "chainId": 7878

  },

  "difficulty" : "0x2000",

  "gasLimit"   : "0xffffffff",

  "nonce"      : "0x0000000000000042",

  "mixhash"    : "0x0000000000000000000000000000000000000000000000000000000000000000",

  "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",

  "timestamp"  : "0x00",

  "alloc": {

     "0x5fc5cEce9458b3977Df2217507b45745Ce7Ec5B0": {

         "balance": "0x200000000000000000000000000000000000000000000000000000000000000"

     }

  }

}



  • config.chainId用来声明以太坊网络编号,选择一个大于10的数字即可。

  • difficulty用来声明挖矿难度,越小的值难度越低,也就能更快速地出块。

2.2初始化私链节点

执行geth的init命令初始化私链节点:

C:\Users\Administrator\node1>geth --datadir .\data init private.json

C:\Users\Administrator\node1>geth --datadir .\data init private.json

INFO [09-24|22:37:48.025] Maximum peer count                       ETH=50 LES=0 total=50

INFO [09-24|22:37:48.287] Set global gas cap                       cap=25000000

INFO [09-24|22:37:48.292] Allocated cache and file handles         database=C:\Users\Administrator\node1\data\geth\chaindata cache=16.00MiB handles=16

INFO [09-24|22:37:48.498] Writing custom genesis block

INFO [09-24|22:37:48.509] Persisted trie from memory database      nodes=1 size=171.00B time=0s gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B

INFO [09-24|22:37:48.542] Successfully wrote genesis state         database=chaindata hash="64cc5d…a0d013"

INFO [09-24|22:37:48.553] Allocated cache and file handles         database=C:\Users\Administrator\node1\data\geth\lightchaindata cache=16.00MiB handles=16

INFO [09-24|22:37:48.706] Writing custom genesis block

INFO [09-24|22:37:48.709] Persisted trie from memory database      nodes=1 size=171.00B time=0s gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B

INFO [09-24|22:37:48.724] Successfully wrote genesis state         database=lightchaindata hash="64cc5d…a0d013"


这会在当前目录下创建data目录,用来保存区块数据及账户信息:

C:\Users\Administrator\node1>dir

驱动器 C 中的卷没有标签。

卷的序列号是 2C83-78AB

C:\Users\Administrator\node1 的目录

2020/09/24  22:32    <DIR>          .

2020/09/24  22:32    <DIR>          ..

2020/09/24  22:37    <DIR>          data

2020/09/24  22:36               521 private.json

               1 个文件            521 字节

               3 个目录 10,227,728,384 可用字节

C:\Users\Administrator\node1>


可以上述命令写到一个脚本init.cmd里,这样避免每次都输入那么多记不住的东西。文件内容如下:

geth --datadir .\data init private.json

在部署下一个节点时,就可以直接执行这个脚本进行初始化了。例如,在另一台机器上:

C:\Users\guow\node1> init.cmd

2.3启动私链节点

从指定的私链数据目录启动并设定一个不同的网络编号来启动节点:

C:\Users\Administrator\node1>geth --rpc --datadir .\data --networkid 7878 console


#增加--nodiscover  关闭p2p网络的自动发现,解决问题:INFO [09-24|17:44:47.158] Looking for peers                        peercount=0 tried=81  static=0

#待验证,win 加上--rpc参数后增加--nodiscover 参数无效

C:\Users\Administrator\node1>geth --rpc --datadir .\data  --nodiscover  --networkid 7878 console


同样,你可以用一个脚本console.cmd来简化启动节点时的输入,文件内容如下:

geth --rpc \

--rpcaddr 0.0.0.0 \

--rpccorsdomain "*" \

--datadir ./data \

--networkid 7878 \

console

  • rpcaddr参数用来声明节点RPC API的监听地址,设为0.0.0.0就可以从其他机器访问API了;

  • rpccorsdomain参数是为了解决web3从浏览器中跨域调用的安全限制问题。以后启动节点,只要直接执行这个脚本即可:

C:\Users\guow\node1> console.cmd

2.4 账户管理

2.4.1 查看账户列表

在geth控制台,使用eth对象的accounts属性查看目前的账户列表:

> eth.accounts

[]

因为我们还没有创建账户,所以这个列表还是空的。

2.4.2创建新账户

在geth控制台,使用personal对象的newAccount()方法创建一个新账户,参数为你自己选择的密码:

> personal.newAccount('78787878')

INFO [09-24|22:48:28.324] Your new key was generated               address=0xF9E7eCf50f36117a905B27489199220F30900515

WARN [09-24|22:48:28.329] Please backup your key file!             path=C:\Users\Administrator\node1\data\keystore\UTC--2020-09-24T14-48-25.811601100Z--f9e7ecf50f36117a905b27489199220f30900515

WARN [09-24|22:48:28.338] Please remember your password!

"0xf9e7ecf50f36117a905b27489199220f30900515"


输出就是新创建的账户地址(公钥),你的输出不会和上面的示例相同。geth会保存到数据目录下的keystore文件中。密码要自己记住,以后还需要用到。

2.4.3查询账户余额

在geth控制台,使用personal对象的getBalance()方法获取指定账户的余额,参数为账户地址:

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

0

>



或者直接输入账户地址:

> eth.getBalance('0xf9e7ecf50f36117a905b27489199220f30900515')

0

新创建的账户,余额果然为0。

2.4.4挖矿

没钱的账户什么也干不了,需要挖矿来挣点钱。在geth控制台执行miner对象的start()方法来启动挖矿:

> miner.start(1)

等几分钟以后,检查账户余额:

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

15000000000000000000


钱不少了,15ETH了。执行miner对象的stop()方法停止挖矿:

> miner.stop()

2.4.5解锁账户

在部署合约时需要一个解锁的账户。在geth控制台使用personal对象的unlockAccount()方法来解锁指定的账户,参数为账户地址和账户密码(在创建账户时指定的那个密码):

> eth.unlockAccount(eth.accounts[0],'78787878')

> personal.unlockAccount(eth.accounts[0],'78787878')

true

三、构建示例项目

3.1 新建DApp项目

执行以下命令创建项目目录并进入该目录:

C:\Users\guow> mkdir demo

C:\Users\guow> cd demo

然后用webpack模版初始化项目骨架结构:

C:\Users\Administrator\demo>truffle.cmd unbox webpack

Starting unbox...

=================

√ Preparing to download box

× Downloading

Unbox failed!

× Downloading

Unbox failed!

RequestError: Error: connect ETIMEDOUT 151.101.108.133:443

    at new RequestError (C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\node_modules\request-promise-core\lib\errors.js:14:1)

    at Request.plumbing.callback (C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\node_modules\request-promise-core\lib\plumbing.js:87:1)

    at Request.RP$callback [as _callback] (C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\node_modules\request-promise-core\lib\plumbing.js:46:1)

    at self.callback (C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\node_modules\request\request.js:185:1)

    at Request.emit (events.js:315:20)

    at Request.onRequestError (C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\node_modules\request\request.js:881:1)

    at ClientRequest.emit (events.js:315:20)

    at TLSSocket.socketErrorListener (_http_client.js:426:9)

    at TLSSocket.emit (events.js:315:20)

    at emitErrorNT (internal/streams/destroy.js:92:8)

    at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)

    at processTicksAndRejections (internal/process/task_queues.js:84:21)

Truffle v5.1.45 (core: 5.1.45)

Node v12.18.4


解决方案:hosts方案,将以下连接的hosts文件追加至本机hosts文件之后,报错,再次执行成功,喵啊~

https://github.com/googlehosts/hosts/blob/master/hosts-files/hosts



C:\Users\guow\demo> truffle.cmd unbox webpack

Downloading…

Unpacking…

Setting up…

Unbox successful. Sweet!

3.2 安装项目依赖的NPM包

执行以下命令安装nmp包:

C:\Users\guow\demo$ npm install


#报错

C:\Users\Administrator\demo>npm install

npm WARN saveError ENOENT: no such file or directory, open 'C:\Users\Administrator\package.json'

npm WARN enoent ENOENT: no such file or directory, open 'C:\Users\Administrator\package.json'

npm WARN Administrator No description

npm WARN Administrator No repository field.

npm WARN Administrator No README data

npm WARN Administrator No license field.

npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.1.3 (node_modules\fsevents):

npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules\watchpack-chokidar2\node_modules\fsevents):

npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

up to date in 5.784s


#解决方案

C:\Users\Administrator>npm init -y


3.3 修改truffle配置

如果你使用图形版的ganache,不需要修改truffle.js配置文件。否则,需要在truffle.js中,修改port为8545,因为ganache-cli在8545端口监听:

module.exports = {

networks:{

development: {

port: 8545

}

}

}

3.4 启动节点

执行以下命令启动节点仿真器,以便部署合约并执行交易:

C:\Users\guow\node1> console.cmd

注意:为了在节点上部署合约,别忘了启动geth后先解锁账户:

> personal.unlockAcount(eth.accounts[0],'78787878')

true

3.5 编译合约

执行以下命令编译项目合约:

C:\Users\guow\demo> truffle.cmd compile

3.6 部署合约

执行以下命令来部署合约:

C:\Users\guow\demo> truffle.cmd migrate

#错误

C:\Users\Administrator\demo1>truffle.cmd migrate

Compiling your contracts...

===========================

> Compiling .\contracts\ConvertLib.sol

> Artifacts written to C:\Users\Administrator\demo1\build\contracts

> Compiled successfully using:

   - solc: 0.5.16+commit.9c3226ce.Emscripten.clang

> Something went wrong while attempting to connect to the network. Check your network configuration.

ProviderError:

Could not connect to your Ethereum client with the following parameters:

    - host       > 127.0.0.1

    - port       > 7545

    - network_id > 5777

Please check that your Ethereum client:

    - is running

    - is accepting RPC connections (i.e., "--rpc" option is used in geth)

    - is accessible over the network

    - is properly configured in your Truffle configuration file (truffle-config.js)

    at C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\provider\wrapper.js:75:1

    at C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\provider\wrapper.js:107:1

    at XMLHttpRequest.request.onreadystatechange (C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\node_modules\web3-providers-http\src\index.js:96:1)

    at XMLHttpRequestEventTarget.dispatchEvent (C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\node_modules\xhr2-cookies\dist\xml-http-request-event-target.js:34:1)

    at XMLHttpRequest._setReadyState (C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\node_modules\xhr2-cookies\dist\xml-http-request.js:208:1)

    at XMLHttpRequest._onHttpRequestError (C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\node_modules\xhr2-cookies\dist\xml-http-request.js:349:1)

    at ClientRequest.<anonymous> (C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\node_modules\xhr2-cookies\dist\xml-http-request.js:252:47)

    at ClientRequest.emit (events.js:315:20)

    at Socket.socketErrorListener (_http_client.js:426:9)

    at Socket.emit (events.js:315:20)

    at emitErrorNT (internal/streams/destroy.js:92:8)

    at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)

    at processTicksAndRejections (internal/process/task_queues.js:84:21)

Truffle v5.1.45 (core: 5.1.45)

Node v12.18.4


#解决方案,修改C:\Users\Administrator\demo1\truffle-config.js


  networks: {

    // Useful for testing. The `development` name is special - truffle uses it by default

    // if it's defined here and no other network is specified at the command line.

    // You should run a client (like ganache-cli, geth or parity) in a separate terminal

    // tab if you use this network and you must also set the `host`, `port` and `network_id`

    // options below to some value.

    //

     development: {

      host: "127.0.0.1",     // Localhost (default: none)

      port: 8545,            // Standard Ethereum port (default: none)

      network_id: "*",       // Any network (default: none)

     },




如果你之前忘了在geth控制台解锁账户,会看到如下错误,参考前面说明进行解锁即可:

Error: authentication needed: password or unlock

C:\Users\Administrator\demo1>truffle.cmd migrate

Compiling your contracts...

===========================

> Compiling .\contracts\ConvertLib.sol

> Artifacts written to C:\Users\Administrator\demo1\build\contracts

> Compiled successfully using:

   - solc: 0.5.16+commit.9c3226ce.Emscripten.clang

Starting migrations...

======================

> Network name:    'development'

> Network id:      7878

> Block gas limit: 4282396671 (0xff402fff)

1_initial_migration.js

======================

   Deploying 'Migrations'

   ----------------------

Error:  *** Deployment Failed ***

"Migrations" -- Returned error: authentication needed: password or unlock.

    at C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\deployer\src\deployment.js:364:1

    at processTicksAndRejections (internal/process/task_queues.js:97:5)

    at Migration._deploy (C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\Migration.js:68:1)

    at Migration._load (C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\Migration.js:55:1)

    at Migration.run (C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\Migration.js:171:1)

    at Object.runMigrations (C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\index.js:150:1)

    at Object.runFrom (C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\index.js:110:1)

    at Object.run (C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\index.js:87:1)

    at runMigrations (C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\core\lib\commands\migrate.js:269:1)

    at C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\core\lib\commands\migrate.js:231:1

Truffle v5.1.45 (core: 5.1.45)

Node v12.18.4

C:\Users\Administrator\demo1>


geth --unlock 0xf9e7ecf50f36117a905b27489199220f30900515 --password 78787878


or


personal.unlockAccount('0xf9e7ecf50f36117a905b27489199220f30900515', '78787878')



错误原因:异常原因:新版本geth,出于安全考虑,默认禁止了HTTP通道解锁账户

解决方式:启动节点命令添加

--allow-insecure-unlock


geth --rpc --datadir .\data --allow-insecure-unlock --networkid 7878 console



> personal.unlockAccount('0xf9e7ecf50f36117a905b27489199220f30900515', '78787878')

true


#再次部署,仍然报错

C:\Users\Administrator\demo1>truffle.cmd migrate

Compiling your contracts...

===========================

> Compiling .\contracts\ConvertLib.sol

> Artifacts written to C:\Users\Administrator\demo1\build\contracts

> Compiled successfully using:

   - solc: 0.5.16+commit.9c3226ce.Emscripten.clang

Starting migrations...

======================

> Network name:    'development'

> Network id:      7878

> Block gas limit: 4282396671 (0xff402fff)

1_initial_migration.js

======================

   Deploying 'Migrations'

   ----------------------

Error:  *** Deployment Failed ***

"Migrations" -- Returned error: invalid transaction v, r, s values.

    at C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\deployer\src\deployment.js:364:1

    at processTicksAndRejections (internal/process/task_queues.js:97:5)

    at Migration._deploy (C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\Migration.js:68:1)

    at Migration._load (C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\Migration.js:55:1)

    at Migration.run (C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\Migration.js:171:1)

    at Object.runMigrations (C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\index.js:150:1)

    at Object.runFrom (C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\index.js:110:1)

    at Object.run (C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\index.js:87:1)

    at runMigrations (C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\core\lib\commands\migrate.js:269:1)

    at C:\Users\Administrator\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\core\lib\commands\migrate.js:231:1

Truffle v5.1.45 (core: 5.1.45)

Node v12.18.4

C:\Users\Administrator\demo1>



如果已经正确地解锁了账户,你会看到部署过程停止在如下状态:

Replacing Migrations…

… 0x3088762a5bc9…

这是因为truffle在等待部署交易提交,但是我们在私链中还没有启动挖矿。现在切换回geth终端窗口,查看交易池的状态:

> txpool.status

{

pending:1,

queued:0

}

果然有一个挂起的交易!启动挖矿就是了:

> miner.start(1)

稍等小会儿,再查看交易池的状态:

> txpool.status

{

pending:0,

queued:0

}

交易已经成功提交了。我们可以停止挖矿了,因为它太占CPU了:

> miner.stop()

现在切换回truffle那个终端,部署过程也正确地执行完了。

3.7 启动DApp

执行以下命令来启动DApp:

C:\Users\guow\demo> npm run dev

在浏览器里访问http://localhost:8080即可

如果你希望从别的机器也可以访问你的DApp应用,修改一下package.json:

{

scripts:{

"dev": "webpack-dev-server –-host 0.0.0.0"

}

}












文章转载自知否Tech,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论