Mac安装以太坊、remix-ide和智能合约初步

Mac安装以太坊、remix-ide和智能合约初步

前提条件

  • 安装好brew
    brew类似apt-get一样,在mac方便的安装各种软件。
  • 安装golang
    我以前是下载代码编译的,一段时间没用,估计版本升级的比较厉害。不能用。直接从新用brew安装了golang。

安装geth踩坑

先开始按照网上提示,直接用brew安装以太坊环境。

brew tap ethereum/ethereum
brew install ethereum 

安装过程没问题,悲伤的故事是,安装完成执行:

geth version

来测试的时候,被告知可执行文件非法,不能执行。google了一下,没结果,但不止我一个人碰到,看来这个版本有问题。
卸载掉刚刚装的东西:

brew uninstall ethereum

然后重头再来,直接到git上clone代码编译:

git clone https://github.com/ethereum/go-ethereum.git
cd go-ethereum
make geth

没有问题。编译完成之后,执行

./build/bin/geth version

Geth
Version: 1.9.7-unstable
Git Commit: 0ce5e113be8c54c7c30a3a797827114adb0df19c
Git Commit Date: 20191102
Architecture: amd64
Protocol Versions: [64 63]
Network Id: 1
Go Version: go1.13.4
Operating System: darwin
GOPATH=/Users/xxxxx
GOROOT=/usr/local/Cellar/go/1.13.4/libexec

说明没问题,把geth link到环境可执行的目录下,比如/user/local/bin:

ln -s /xxxx/build/bin/geth /user/local/bin/geth

就可以在任意地方都执行geth启动以太坊了。

初始化创世区

先要初始化创世区块。新建一个目录作为项目目录,然后在目录中创建一个名为:genesis.json的文件,内容如下:

{
    "nonce": "0x0000000000000042",
    "difficulty": "0x020000",
    "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "coinbase": "0x0000000000000000000000000000000000000000",
    "timestamp": "0x00",
    "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
    "gasLimit": "0x4c4b40",
    "config": {
        "chainId": 15,
        "homesteadBlock": 0,
        "eip155Block": 0,
        "eip158Block": 0
    },
    "alloc": {}
}

具体啥意思我也不知道。都是网上找的,几乎某度找出来的,都是这个一样的文件。我就直接用了。
使用此文件初始化创世区块:

geth init ./genesis.json --datadir ./mychain
WARN [03-21|09:54:38] No etherbase set and no accounts found as default
INFO [03-21|09:54:38] Allocated cache and file handles         database=/Users/jianjiangwang/Desktop/mychain/chain/geth/chaindata cache=16 handles=16
INFO [03-21|09:54:38] Successfully wrote genesis state         database=chaindata                                                 hash=ee3898…ae7194
INFO [03-21|09:54:38] Allocated cache and file handles         database=/Users/jianjiangwang/Desktop/mychain/chain/geth/lightchaindata cache=16 handles=16
INFO [03-21|09:54:38] Successfully wrote genesis state         database=lightchaindata

参数--datadir ./mychain用来指定区块数据存放的目录。打开mychain目录,可以看到geth目录和keystore目录。可以认为创世区初始化成功了。

启动私链

网上所言,有两种启动方式:

  • 方式一
geth --datadir ./mychain --nodiscover console 2>>eth_output.log

参数说明:

  • –datadir : 指定区块链网络数据的存放位置
  • console : 启动命令行模式,可以在geth中执行命令
  • –nodiscover : 指定为私有链,不会被网上看到
  • >>eth_output.log:表示在当前文件夹下用eth_output.log文件来记录输出

执行tail -f eth_output.log, 可以看到输出日志。
这个方法启动,只能在命令行来执行命令测试。

  • 方式二
    执行:
geth --networkid 10 --datadir ./mychain --rpc --rpcapi "admin,debug,eth,miner,net,personal,shh,txpool,web3" --rpcaddr "0.0.0.0" --rpccorsdomain "*" --nodiscover --dev console>>eth.log

然后打开另一个终端,输入:

geth attach "http://127.0.0.1:8545"

进入以太坊的操作终端。
这种方式启动,打开了网络连接的入口,在后面安装了remix-ide之后,在线发布合约的话,需要这种模式。

上述两种都是正常启动方式。启动起来之后,你会发现,这个链,不挖矿。不挖矿就很多东西没法测试了。毕竟以太坊做任何交易都需要消耗gas。
不挖矿的原因,据说是只有发送交易的时候才会挖矿。
继续找资料,找到一个说法:新版本-dev模式增加了新的参数项:

--dev               Ephemeral proof-of-authority network with a pre-funded developer account, mining enabled
--dev.period value  Block period to use in developer mode (0 = mine only if transaction pending) (default: 0)

据说以前的版本只要加上--dev就可以通过执行miner.start()挖矿。反正我直接下载最新版本是不行的,执行都返回null,根据这个说明是只有交易发生时候才会挖矿。但我发送交易,就直接告诉我没有gas不让做。所以我始终没有得到以太币。不知道别人实际操作,可能需要在配置创世区的json文件中的alloc参数来设置一个默认账号的初始的以太币吧。

我为了尽快测试,所以修改启动参数,让他自己开始挖矿了。

geth --datadir ./mychain --nodiscover --dev --dev.period 1 console 2>>eth_output.log

启动起来之后,会发现已经内置了一个测试账号,密码是空。并且已经内置了巨量的以太币。其实如果不管挖矿,只有有–dev参数,就会测试模式启动,就有一个带有海量以太币的默认账户。但每次关闭重新启动都会服务到初始状态。

几个常用命令测试

启动geth之后,在控制台输入命令测试验证。
查看当前账户:

> web3.eth.accounts

创建账户,创建时需要设置密码:

> web3.personal.newAccount('123456')
"0xdaa65af5d348c25266a5588148a9c0e9e4c056f8"

输入的是密码,返回的一长串是账号。
再执行web3.eth.accounts命令,可以看到多了一个账户。
开始挖矿:
先设置挖矿的账户:

> miner.setEtherbase("0xdaa65af5d348c25266a5588148a9c0e9e4c056f8")

里面的长串是已经存在的账号。
也可以:

miner.setEtherbase(eth.accounts[0])

获取账号列表中的第一个。
可以执行:

>eth.coinbase

看当前设置的挖矿账户是哪个。
开始挖矿:

>miner.start()

停止挖矿:

>miner.stop()

查看账户余额:

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

eth的最小单位是wei, 1 ether = 1e18 wei

发起转账。转账前需要先解锁账户:

personal.unlockAccount(eth.accounts[0])
personal.unlockAccount(eth.accounts[1])

解锁之后,进行转账:

amount = web3.toWei(5,'ether')
eth.sendTransaction({from:eth.accounts[0],to:eth.accounts[1],value:amount})

从0账户给1账户转5个以太币。
锁上账户:

personal.lockAccount(eth.accounts[0])
personal.lockAccount(eth.accounts[1])

到这里,以太坊测试环境基本就安装完成了。

智能合约Remix Solidity IDE安装

这东西也是满满的坑。这东西需要nodejs环境。先用brew把nodejs装好,但根据我的尝试,版本号有要求,反复踩坑之后,找了无数页面。最后才安装起来。
基本的环境要求:

$ node -v
v7.10.1
$ npm -v
4.2.0

有说node用8也行的,我没尝试。npm版本感觉影响不大,但有人说也有关系。我原来是6.x,一起给降了。
node的版本太复杂,还好提供了版本管理工具n。先装上:

npm install -g n

然后通过n可以指定需要的node版本。

sudo n 7.10.1

可以随便指定node的版本号,把电脑中的node版本调整到所需要的。
npm的版本直接用npm自己指定就行:

npm install npm@4 -g

其他版本的node,尝试了很多次,不管是直接npm安装还是从git下载代码编译,都失败,主要都是[email protected]这个东西装不上。更新node版本之后,源代码编译也不成功。大家可以试试,下载源码编译:

git clone https://github.com/ethereum/remix-ide.git
cd remix-ide
npm install
npm start

我直接通过npm安装。但安装过程报错,找不到npx的执行路径。
先执行:

npm install npx

然后把npx link到可执行目录中,比如/user/local/bin:

ln -s /usr/local/Cellar/node/12.7.0/bin/npx npx

可能是由于我最初是的node是12.7,虽然我后来通过n更换了版本,但是我看了通过npm安装的新的包,仍然在12.7.0的目录中。scryptsy scrypt.js

npm install remix-ide -g
remix-ide

然而,运行的时候,报错!!!
错误大概这样:

module.js:442
    throw err;
    ^
Error: Cannot find module './build/Release/scrypt'
    at Function.Module._resolveFilename (module.js:440:15)
    at Function.Module._load (module.js:388:25)
    at Module.require (module.js:468:17)

这就惆怅了。继续找了资料,类似的错误。先单独安装上scrypt

npm install -g scrypt

安装好了之后,到remix的安装模块路径:

/usr/local/lib/node_modules/remix-ide/node_modules/scrypt/build/Release

对比单独安装的scrypt,发现少了一个文件。从单独安装的目录中,把这个文件link过来:

link -s /usr/local/Cellar/node/12.7.0/lib/node_modules/scrypt/build/Release/scrypt.node scrypt.node

再次运行remix-ide,大功告成:

$ remix-ide
setup notifications for /Users/arthurlee/program/ethereum/mychain
Starting Remix IDE at http://localhost:8080 and sharing /Users/arthurlee/program/ethereum/mychain
Tue Nov 05 2019 11:35:45 GMT+0800 (CST) Remixd is listening on 127.0.0.1:65520

打开浏览器,输入地址:http://localhost:8080

编写和发布智能合约

gethremix-ide都安装好之后,启动,geth记得用方式二启动。打开浏览器进入合约开发界面。已经有一些例子。我们先搞一个更简单的:

pragma solidity ^0.4.18;
contract HelloWorld {
    string msg1;
    
    function HelloWorld(string _msg) public {
        msg1 = _msg;
    }

    function say() constant public returns (string) {
        return msg1;
    }
}

别的我还没细看。但就发现了一个很讨厌的事情pragma solidity ^0.4.18;这个,声明了这个合约用什么版的solidity来编写。简单了找了一下,居然没有完整的说明这个这个版本是如何定义的,可能是某种常态吧。但我是不相信这些程序能版本兼容的。至少我看到0.4和0.5的就很大不一样了。管他,按照这个例子来做。

左边工具栏第二个是浏览文件。点+符号。新建一个合约。起个文件名。把合约内容复制过去。

左边工具栏第三个是编译。在Compiler选择和合约对应的版本。进行编译。如果有错,在下面会显示错误信息。没错就啥都不显示了。

最先面的Details,可以看到这个合约被编译之后的内容。其中的WEB3DEPLOY部分应该就是可以复制出来部署的。这部分内容如下:

var _msg = /* var of type string here */ ;
var helloworldContract = web3.eth.contract([{"constant":true,"inputs":[],"name":"say","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_msg","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]);
var helloworld = helloworldContract.new(
   _msg,
   {
     from: web3.eth.accounts[0], 
     data: '0x6060604052341561000f57600080fd5b6040516102b83803806102b8833981016040528080518201919050508060009080519060200190610041929190610048565b50506100ed565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061008957805160ff19168380011785556100b7565b828001600101855582156100b7579182015b828111156100b657825182559160200191906001019061009b565b5b5090506100c491906100c8565b5090565b6100ea91905b808211156100e65760008160009055506001016100ce565b5090565b90565b6101bc806100fc6000396000f300606060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063954ab4b214610046575b600080fd5b341561005157600080fd5b6100596100d4565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561009957808201518184015260208101905061007e565b50505050905090810190601f1680156100c65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6100dc61017c565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156101725780601f1061014757610100808354040283529160200191610172565b820191906000526020600020905b81548152906001019060200180831161015557829003601f168201915b5050505050905090565b6020604051908101604052806000815250905600a165627a7a723058201893c1926120c368172f8f8211f6e1a723f12b417d25c83f4982b31ce3ca1d210029', 
     gas: '4700000'
   }, function (e, contract){
    console.log(e, contract);
    if (typeof contract.address !== 'undefined') {
         console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
    }
 })

其中,第一行的内容需要自己修改:

var _msg = /* var of type string here */ ;

后面注释部分改成需要的显示的内容,比如hello world
还可以改:

from: web3.eth.accounts[0], 

表示那个账户来执行这个合约。
按说可以把这段内容复制下来到控制终端直接黏贴过去发布合约的。黏贴的时候,一行就应该相当于一个命令,会返回好几次undefined。不用管。
最后如果显示:

Contract mined! address: 0x461b37e377da6ff6d73bef4c29142e160a1e4eeb transactionHash: 0x44b68decc1b692369b003cdd6c547b703546274a00653af81015a3ed843476dc

就算发布成功了。
对应账号的以太币会减少。但此时不一定能执行,需要等若干区块建立之后才能确认,做法就是执行转账了,执行十来次转账之后,然后执行:

helloworld.say()

应该能成功。

也可以直接用remix-ide来发布。

选择左边工具栏第四个,部署和运行。
先选择环境,选择Web3 Provider。会弹出一个窗口,让输入geth的地址和端口。我没有改,默认的。

http://localhost:8545

如果有问题连不上,会报错,但错误信息一闪而过。如果没问题,下面的Account会列出来当前节点可以控制的账号。选择一个相当于修改了

from: web3.eth.accounts[0], 

再下面,选择Gas啥的。在下面Deploy边上的输入框,随便输入点东西,相当于修改了

var _msg = /* var of type string here */ ;

但一定要记住,两边用双引号圈起来。否则部署的时候会报错:

Unexpected token h in JSON at position 1

点一下Deploy,开始部署。完成会显示类似信息:

[block:555 txIndex:0]from:0xcbb...b29dfto:HelloWorld.(constructor)value:0 weidata:0x606...00000logs:0hash:0x3ec...e23f9


就可以运行了。

哪个终端发布的合约,只能在自己终端来执行。换个终端无法执行。如果要在其他终端执行,需要拿出合约地址和abi。
在remix-ide部署的时候,从右下角的Debug边上的下拉箭头,点开,找到部署地址。然后在编译详情里面,复制出abi。
在这里插入图片描述
然后,去掉回车空格tab之类的,执行:

abi=[{"inputs": [{"name": "_msg","type": "uint256"}],"payable": false,"stateMutability": "nonpayable","type": "constructor"},{"constant": true,"inputs": [],"name": "say","outputs": [{"name": "","type": "uint256"}],"payable": false,"stateMutability": "view","type": "function"}]

=后面的内容就是复制出来的abi。
然后执行:

tt=eth.contract(abi).at("0x692a70D2e424a56D2C6C27aA97D1a86395877b3A")

长串的就是合约地址。之后就可以执行这个合约:

tt.say()

但我怎么看都有问题,如果合约返回的是uint256,一直返回0,其实我设置的参数是2.
如果是字符串,则直接报错:

Error: new BigNumber() not a base 16 Numver:

查了一下,应该是web3的bug。后学再看。

其他

给某个账号发布合约有可能说这个账户没有解锁。解锁的时候,会显示:

Error: account unlock with HTTP access is forbidden

如果这样,就在启动geth的时候增加如下参数:

--allow-insecure-unlock
发布了20 篇原创文章 · 获赞 7 · 访问量 2497

猜你喜欢

转载自blog.csdn.net/cfy_fantasyxx/article/details/102921366
今日推荐