1. 程式人生 > >以太坊私有鏈搭建,建立節點叢集,部署智慧合約,攻擊智慧合約

以太坊私有鏈搭建,建立節點叢集,部署智慧合約,攻擊智慧合約

本文目的: 1.搭建Ethereum私有鏈和節點叢集; 2.熟悉以太坊智慧合約的部署和使用流程; 3.瞭解以太坊智慧合約的應用和常見安全性問題;

一、以太坊私有鏈搭建

參考:https://blog.csdn.net/sportshark/article/details/51855007 以太坊(英文Ethereum)是一個開源的有智慧合約功能的公共區塊鏈平臺,通過其專用加密貨幣以太幣(Ether)提供去中心化的虛擬機器(“以太虛擬機器” Ethereum Virtual Machine)來處理點對點合約。 區塊鏈1.0時代通常是指在2009年到2014年之間,以比特幣為代表的區塊鏈應用發展階段,它們主要致力於解決貨幣和支付手段的去中心化問題;2014年之後,開發者們越來越注重於解決比特幣在技術和擴充套件性方面的不足。2013年底,Vitalik Buterin(V神)釋出了以太坊白皮書《以太坊:下一代智慧合約和去中心化應用平臺》,將智慧合約引入區塊鏈,打開了區塊鏈在貨幣領域以外的應用,從而開啟了區塊鏈2.0時代。 截至2018年11月,以太坊是市值NO.2的加密貨幣,僅次於比特幣。

1.前言

我們先看看從比特幣到以太坊,智慧合約是如何演變的。注意下方智慧合約的位置,這個位置表明上方的應用(APP)必須通過智慧合約來實現對應區塊鏈網路的功能。 在這裡插入圖片描述 那麼,我們看一個簡單的例子,就是A轉賬給B,在比特幣和以太坊中大概都怎麼實現的: 在這裡插入圖片描述 在這裡插入圖片描述 以太坊智慧合約實現的方式貌似能看懂,比較易讀。 事實也是這樣的,智慧合約使得區塊鏈的擴充套件性更強,且實現上更簡潔,從而讓以太坊發展成為目前最大的一個區塊鏈開發平臺。

2.安裝geth

Go-ethereum客戶端通常被稱為Geth,它是個命令列介面,執行在Go上實現的完整以太坊節點。Geth得益於Go語言的多平臺特性,支援在多個平臺上使用(比如Windows、Linux、Mac)。Geth是以太坊協議的具體落地實現,通過Geth,你可以實現以太坊的各種功能,如賬戶的新建編輯刪除,開啟挖礦,ether幣的轉移,智慧合約的部署和執行等等。所以,我們選擇 geth工具來進行開發。 geth安裝方式(linux): 在這裡插入圖片描述

或者(windows): 在這裡插入圖片描述 或者(mac): 在這裡插入圖片描述 檢查是否安裝成功:$ geth --help 如果輸出一些幫助命令,則安裝成功。

3.初始化區塊鏈

定義創世區塊

以太坊支援自定義創世區塊,要執行私有鏈,我們就需要定義自己的創世區塊,創世區塊資訊寫在一個json格式的配置檔案中。檔案內容如下:

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

啟動Geth即可以啟動以太坊的區塊鏈,為了構建私有鏈 ,需要在Geth啟動時加入一些引數,Geth引數含義如下:

identity–區塊鏈的標示,隨便填寫,用於標示目前網路的名字

init–指定創世塊檔案的位置,並建立初始塊

datadir–設定當前區塊鏈網路資料存放的位置

port–網路監聽埠

rpc–啟動rpc通訊,可以進行智慧合約的部署和除錯

rpcapi–設定允許連線的rpc的客戶端,一般為db,eth,net,web3

networkid–設定當前區塊鏈的網路ID,用於區分不同的網路,是一個數字

console–啟動命令列模式,可以在Geth中執行命令

4.啟動私有鏈節點

接下來在windows啟動區塊鏈節點: 進入Windows下Geth的目錄 ,放置配置好的genesis.json檔案,執行如下命令: geth --datadir “%cd%\chain” init genesis.json 在這裡插入圖片描述 geth --identity “PICCetherum” -rpc --rpccorsdomain “*” --datadir “%cd%\chain” --port “30303” --rpcapi “db,eth,net,web3” --networkid 95518 console 在這裡插入圖片描述 如圖說明啟動成功。 這是一個互動式的Javascript執行環境,在這裡面可以執行Javascript程式碼,其中>是命令提示符。在這個環境裡也內建了一些用來操作以太坊的Javascript物件,可以直接使用這些物件。這些物件主要包括: eth:包含一些跟操作區塊鏈相關的方法 net:包含以下檢視p2p網路狀態的方法 admin:包含一些與管理節點相關的方法 miner:包含啟動&停止挖礦的一些方法 personal:主要包含一些管理賬戶的方法 txpool:包含一些檢視交易記憶體池的方法 web3:包含了以上物件,還包含一些單位換算的方法

初始化成功之後目錄如下: 在這裡插入圖片描述 其中geth/chaindata中存放的是區塊資料,keystore中存放的是賬戶資料。

5.以太坊Javascript Console

進入以太坊Javascript Console後,就可以使用裡面的內建物件做一些操作,這些內建物件提供的功能很豐富,比如檢視區塊和交易、建立賬戶、挖礦、傳送交易、部署智慧合約等。接下來介紹幾個常用功能,下面的操作中,前面帶>的表示在Javascript Console中執行的命令。

使用節點建立賬號

啟動節點成功後,會進入Geth的命令列模式,輸入如下命令 personal.newAccount() 系統會提示你輸入密碼,並確認,最後會顯示一個新生成的賬號。 Passphrase其實就是密碼的意思,輸入兩次密碼後,就建立了一個賬戶。 在這裡插入圖片描述 再次執行命令: 在這裡插入圖片描述 這時候用eth.accounts命令檢視,就會發現有兩個賬戶了: 在這裡插入圖片描述 賬戶預設會儲存在資料目錄的keystore資料夾中。檢視目錄結構,發現chain/keystore中多了兩個檔案,這兩個檔案就對應剛才建立的兩個賬戶,這是json格式的文字檔案,可以開啟檢視,裡面存的是私鑰經過密碼加密後的資訊: 在這裡插入圖片描述 每次記一長串的地址很麻煩,我們可以通過設定變數來表示賬戶: 在這裡插入圖片描述

檢視賬戶餘額

在這裡插入圖片描述

啟動、停止挖礦

在這裡插入圖片描述 其中start的引數表示挖礦使用的執行緒數。第一次啟動挖礦會先生成挖礦所需的DAG檔案,這個過程有點慢,等進度達到100%後,就會開始挖礦,此時螢幕會被挖礦資訊刷屏: 在這裡插入圖片描述

如果想停止挖礦,並且進度已經達到100%之後,可以在js console中輸入 在這裡插入圖片描述

在這裡插入圖片描述 挖到一個區塊會獎勵5個以太幣,挖礦所得的獎勵會進入礦工的賬戶,這個賬戶叫做coinbase,預設情況下coinbase是本地賬戶中的第一個賬戶: 在這裡插入圖片描述 和上文的第一個賬戶對比一下,是一致的。 getBalance()返回值的單位是wei,wei是以太幣的最小單位,1個以太幣=10的18次方個wei。要檢視有多少個以太幣,可以用web3.fromWei()將返回值換算成以太幣: 在這裡插入圖片描述

傳送一筆交易

eth.sendTransaction({from:acc0,to:acc1,value:20}) 在這裡插入圖片描述 這裡報錯了,原因是賬戶每隔一段時間就會被鎖住,要傳送交易,必須先解鎖賬戶,由於我們要從賬戶0傳送交易,所以要解鎖賬戶0: personal.unlockAccount(acc0) 輸入建立賬戶時設定的密碼,就可以成功解鎖賬戶。 在這裡插入圖片描述 解鎖後後再發送交易。 我們去檢視賬戶1中的餘額,發現還沒轉過去,此時交易已經提交到區塊鏈,但還未被處理,這可以通過檢視txpool來驗證: txpool.status 在這裡插入圖片描述 其中有一條pending的交易,pending表示已提交但還未被處理的交易。 要使交易被處理,必須要挖礦。這裡我們啟動挖礦,然後等待挖到一個區塊之後就停止挖礦: miner.start(1);admin.sleepBlocks(1);miner.stop(); 在這裡插入圖片描述 當miner.stop()返回true後,txpool中pending的交易數量應該為0了,說明交易已經被處理了,而賬戶1應該收到幣了: web3.fromWei(eth.getBalance(acc1),‘ether’) 在這裡插入圖片描述

檢視交易

eth物件封裝了檢視交易和區塊資訊的方法。 檢視當前區塊總數: eth.blockNumber 在這裡插入圖片描述

5.圖形介面Ethereum Wallet連線私有鏈

Ethereum Wallet是以太坊提供的官方應用,具備建立賬戶,轉移以太幣,部署呼叫智慧合約等功能。這裡我們可以用它連線到我們自己的私有鏈上,作為輔助工具更方便地進行私鏈操作。

二、建立節點叢集

在私有網路中建立多個節點組成的叢集,並互相發現,產生交易。 如果是為了在本地網路執行多個以太坊節點的例項,必須確保以下幾點:

  1. 每個例項都有獨立的資料目錄(–datadir)
  2. 每個例項執行都有獨立的埠.(eth和rpc兩者都是)(–port 和 --rpcprot)
  3. 在叢集的情況下, 例項之間都必須要知道彼此.
  4. 唯一的ipc通訊端點,或者禁用ipc.

在這裡,我們選擇在不同的電腦上分別建立節點組成叢集,互相發現,產生交易。 在第一臺電腦上啟動節點: 在這裡插入圖片描述 在第二臺電腦上初始化(使用相同的json檔案)並啟動節點,注意網路ID要相同,確保節點都在一個私有網路中: 在這裡插入圖片描述 bootnodes後邊的引數是第一臺電腦上節點的enode url ,包括ip和埠號等資訊,都可以在第一臺電腦上通過如下命令來獲取: 在這裡插入圖片描述 至此兩個節點應該就連結成功了。 節點間傳送以太幣: 在這裡插入圖片描述 from中填當前節點的賬號地址,to中填要傳送給的節點的賬號地址。 執行以上命令傳送一個以太幣。注意傳送交易操作前要先解鎖賬號,然後執行挖礦才能讓交易生效。

三、在以太坊私有鏈上部署第一個智慧合約

智慧合約是一段程式碼和資料的集合,可以部署以太坊網路上執行。如果做比喻的話智慧合約更像是JAVA程式,JAVA程式通過JAVA虛擬機器(JVM)將程式碼解釋位元組進行執行,以太坊的智慧合約通過以太坊虛擬機器(EVM)解釋成位元組碼進行執行,如果你學過彙編,會發現編譯後的位元組碼和彙編很類似。同時智慧合約有自己的賬戶,在時間或事件的驅動下能自動執行一些功能,如可以在相互之間傳遞資訊,修改區塊鏈的狀態比如賬戶資訊等。以太坊的智慧合約最大的特點是圖靈完備,通俗來說可以完全模擬一臺計算機所能做的所有事情,大家熟知的比特幣其實也可以執行一些簡單指令碼,但是他就不是圖靈完備,比如迴圈指令比特幣就無法執行。 本文的智慧合約採用以太坊官方的示例合約,功能就是在區塊鏈上儲存一個數字,並能夠讀取出來。程式碼如下:

pragma solidity ^0.4.0;
contract SimpleStorage{
	uint storedData;

	function set(uint x){
	storedData=x;
	}

	function get() constant returns (uint retVal){
		return storedData;
	}

}

即使沒有學過Solidity語言也可以大致看出,該合約set函式儲存一個數字在X變數中,get函式從X變數中讀取這個數字出來,下面對這個合約進行部署。

獲得編譯後的程式碼

將原始碼複製到Remix,點選編譯。 在這裡插入圖片描述

要訪問已編譯的程式碼,直接點選選單右邊的details按鈕。 在彈出視窗中,向下滾動並複製WEB3DEPLOY文字框中的所有程式碼: 在這裡插入圖片描述 可以將結果直接貼上到geth視窗中,然後執行挖礦: miner.start(1);admin.sleepBlocks(1);miner.stop(); 等待一會終端中會看到這樣的訊息: 在這裡插入圖片描述 可能必須先使用你在開始時選擇的密碼來“解鎖”傳送交易的帳戶,因為你需要支付部署合同的GAS費用。 可以使用以下命令來驗證已部署的程式碼(將被編譯): eth.getCode(simplestorage.address) 在這裡插入圖片描述 如果它返回“0x”以外的任何內容,那麼恭喜,程式碼已經被部署了。 如果再次建立合同(通過執行另一個eth.sendTransaction),它將釋出到新地址。

執行合約

只需在終端上輸入以下命令: simplestorage.get() 在這裡插入圖片描述 如果出現以下問題:在這裡插入圖片描述 請輸入: 在這裡插入圖片描述 出現賬戶鎖定問題時解鎖賬戶即可。

讓其他節點與合約程式碼互動

為了讓其他人來執行你的合同,他們需要兩個東西: 1.合同所在地址 2. ABI(應用程式二進位制介面),這是一種使用者手冊,描述合同功能的名稱以及如何將它們呼叫到您的JavaScript控制檯 想要獲取地址,請執行以下命令: simplestorage.address 在這裡插入圖片描述 為了得到ABI,你需要直接從Remix複製ABI,類似於複製WEB3DEPLOY編譯程式碼的方式。 在右側窗格中,單擊詳細資訊按鈕並向下滾動到ABI文字框。 點選複製按鈕複製整個ABI,然後將其貼上到臨時文字中。 在這裡插入圖片描述 然後,你可以例項化一個可用於在連線到網路的任何計算機上呼叫合同的JavaScript物件。 在以下行中,替換ABI(一個數組)和Address(一個字串)以在JavaScript中建立合同物件: var simplestorage = eth.contract(ABI).at(Address) 如下: 在這裡插入圖片描述 這樣別的節點就也可以通過 在這裡插入圖片描述 來呼叫你的智慧合約了。 當某個節點改變了合約中儲存的值,任一節點啟動挖礦確認交易之後,每個節點都可以再次通過呼叫函式看到改變後的新值。

四、攻擊一份智慧合約

據相關統計,以太坊、EOS等平臺上每日智慧合約建立數量呈現上升趨勢,其管理的數字資產數量提升,面臨的威脅也隨之增長。然而由於一般開發人員的安全意識不夠,可能在開發智慧合約時無意留下了安全隱患,從而造成損失。並且智慧合約難以通過傳統的升級、打補丁等方式填補漏洞,每一個暴露在開放網路上的智慧合約都有可能成為專業黑客團隊的攻擊目標。 用例選自Ethernaut levels/04: https://ethernaut.zeppelin.solutions/level/0x6b7b4a5260b67c1ee9196a42dd1ed8633231ba0a 以下是一個非常簡單的智慧合約,可能已經被其他任何人部署,我們需要做的是改變這個合約的owner,使之成為自己的地址。 在這裡插入圖片描述 可以看到合約本身提供了changeOwner的方法,但是直接呼叫是行不通的,需要滿足if語句中的條件,相關參考: https://bitshuo.com/topic/59afc169fbcd445a40a3e2e6 理解了原理,我們就可以寫一份攻擊合約: 在這裡插入圖片描述 先看看此時合約的擁有者: 在這裡插入圖片描述 部署併成功呼叫攻擊合約: 在這裡插入圖片描述 之後,可以發現owner成功改變為自身地址: 在這裡插入圖片描述 更多關卡請檢視: https://ethernaut.zeppelin.solutions/

實際上,在現有各大區塊鏈平臺上,利用各種漏洞部署惡意合約程式碼進行攻擊的手段屢見不鮮。區塊鏈具有的開放共識、去中心、去信任、匿名性、安全不可篡改、可追溯性等特點能夠為如何有效地保障資料安全提供一條解決問題的思路,但也帶來了很多新的安全問題,區塊鏈技術的成熟和完善正經歷著考驗。