天天看點

Mac安裝以太坊、remix-ide和智能合約初步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 [email protected] -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

Mac安裝以太坊、remix-ide和智能合約初步Mac安裝以太坊、remix-ide和智能合約初步

編寫和釋出智能合約

geth

remix-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的就很大不一樣了。管他,按照這個例子來做。

Mac安裝以太坊、remix-ide和智能合約初步Mac安裝以太坊、remix-ide和智能合約初步

左邊工具欄第二個是浏覽檔案。點

+

符号。建立一個合約。起個檔案名。把合約内容複制過去。

Mac安裝以太坊、remix-ide和智能合約初步Mac安裝以太坊、remix-ide和智能合約初步

左邊工具欄第三個是編譯。在

Compiler

選擇和合約對應的版本。進行編譯。如果有錯,在下面會顯示錯誤資訊。沒錯就啥都不顯示了。

Mac安裝以太坊、remix-ide和智能合約初步Mac安裝以太坊、remix-ide和智能合約初步

最先面的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來釋出。

Mac安裝以太坊、remix-ide和智能合約初步Mac安裝以太坊、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
           
Mac安裝以太坊、remix-ide和智能合約初步Mac安裝以太坊、remix-ide和智能合約初步

就可以運作了。

哪個終端釋出的合約,隻能在自己終端來執行。換個終端無法執行。如果要在其他終端執行,需要拿出合約位址和abi。

在remix-ide部署的時候,從右下角的

Debug

邊上的下拉箭頭,點開,找到部署位址。然後在編譯詳情裡面,複制出abi。

Mac安裝以太坊、remix-ide和智能合約初步Mac安裝以太坊、remix-ide和智能合約初步

然後,去掉回車空格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
           

繼續閱讀