智慧合約初體驗

aiee發表於2018-08-16

什麼是智慧合約

    智慧合約是程式碼和資料的集合,寄存與Blockchain的具體的地址。智慧合約更想是在Blockchain中的一個自動化的代理(或者說是機器人or NPC),智慧合約有自己的賬戶,在時間或事件的驅動下能自動執行一些功能,如可以在相互之間傳遞資訊,修改區塊鏈的狀態(賬戶資訊等),以及圖靈完備計算(可以用圖靈機做到的所有事情,通俗來說就是一般程式語言可以做的所有事情)。以太坊的智慧合約是以太坊特定的位元組碼,被叫做EVM位元組碼。

智慧合約高階語言

    使用者不可能直接編寫EVM位元組碼,所以以太坊提供了幾種編寫智慧合約的高階語言。

    Solidity:類JavaScript,這是以太坊推薦的旗艦語言,也是最流行的智慧合約語言。具體用法參加Solidity文件

    Serpent:類Python

    LLL:類Lisp

    可以根據不同的習慣選擇不同的高階語言。這裡選用最流行的Solidity

相關概念

    以下的概念是智慧合約可能用到的,這裡不做詳細介紹,想了解的可以參考 智慧合約菜鳥教程

    公鑰加密系統:

    點對點網路:

    區塊鏈:區塊鏈可以看做是智慧合約的基礎設施

    以太坊虛擬機器:解釋執行智慧合約位元組碼的東西,功能類似於Java虛擬機器

    節點:

    礦工:區塊鏈中參與處理區塊的節點叫做礦工。當前以太坊活躍的礦工:https://ethstats.net/

    工作量證明:礦工們總是在競爭解決一些數學問題。第一個解出答案的(算出下一個區塊)將獲得以太幣作為獎勵。然後所有節點都更新自己的區塊鏈。所有想要算出下一個區塊的礦工都有與其他節點保持同步,並且維護同一個區塊鏈的動力,因此整個網路總是能達成共識。

    以太幣:ETH,以太坊中的虛擬貨幣,可以購買和使用,也可以與真實貨幣交易。以太幣的走勢圖

    Gas:相當於手續費。在以太坊執行程式以儲存資料都要消耗一定量的以太幣。這個機制可以控制區塊鏈中計算的數量,保證效率。

智慧合約與DApp

    以太坊社群把基於智慧合約的應用稱為去中心化的應用程式(Decentralized App)。DApp的目標是(或者應該是)讓你的智慧合約有一個友好的介面,外加一些額外的東西,例如IPFS(可以儲存和讀取資料的去中心化網路,不是出自以太坊團隊但有類似的精神)。DApp可以跑在一臺能與以太坊節點互動的中心化伺服器上,也可以跑在任意一個以太坊平等節點上。(花一分鐘思考一下:與一般的網站不同,DApp不能跑在普通的伺服器上。他們需要提交交易到區塊鏈並且從區塊鏈而不是中心化資料庫讀取重要資料。相對於典型的使用者登入系統,使用者有可能被表示成一個錢包地址而其它使用者資料儲存在本地。許多事情都會與目前的web應用有不同架構。)

    DApp流程:

  1. 用Solidity(或其他語言)編寫智慧合約(字尾為.sol)
  2. 用solc編譯器將.sol合約編譯成EVM位元組碼
  3. 編譯好的位元組碼回送給dapp前端
  4. 前端將編譯好的智慧合約部署到區塊鏈中
  5. 區塊鏈返回智慧合約地址+ABI(合約介面的二進位制表示。合約介面用JSON表示,包括變數,事件和可以呼叫的方法)
  6. 前端通過Address+ABI+nonce,呼叫智慧合約。智慧合約開始處理。

 

智慧合約編譯器

    Solidity智慧合約可以通過多種方式進行編譯

    在這裡選擇solc和web3.eth.compile.solidity方式

geth安裝

    參考:go Ethereum client。安裝不比較簡單,這裡詳細說了

solc安裝

1. 作為cpp-ethereum的一部分安裝  

    如果通過編譯的方式安裝了cpp-ethereum(參考:http://www.cnblogs.com/fengzhiwu/p/5547911.html),那麼solc編譯器就會作為cpp-ethereum的一個子專案也被編譯安裝,在webthree-umbrella/build/solidity/solc目錄下找到solc編譯器的可執行檔案。

image

    然後,在/bin或/usr/bin目錄下建立軟連結就行了

ln -s /home/vagrant/Code/workspace/webthree-umbrella/build/solidity/solc/solc /bin/solc

2. 單獨安裝solc

參考:http://solidity.readthedocs.io/en/latest/installing-solidity.html

  • 通過npm安裝:這種比較簡單,執行npm install solc就行了,不過我沒有在console中找到solc
  • 通過apt-get安裝:

sudo add-apt-repository ppa:ethereum/ethereum

sudo apt-get update

sudo apt-get install solc

which solc

    把solc新增入geth中直接使用(在geth中輸入)

admin.setSolc("path/to/solc")
  • 從原始碼編譯安裝

    這種方法和安裝cpp-etheruemle類似,不過最後的編譯步驟改為:

cd webthree-umbrella
./webthree-helpers/scripts/ethupdate.sh --no-push --simple-pull --project solidity # update Solidity repo
./webthree-helpers/scripts/ethbuild.sh --no-git --project solidity --cores 4 -DEVMJIT=0 -DETHASHCL=0 # build Solidity only

測試

    開啟一個geth console,輸入:web3.eth.getCompilers(),就會列印

image

 

智慧合約體驗

編譯一個簡單的合約

    直接在console中編譯一個簡單的合約程式碼

> source = "contract test { function multiply(uint a) returns(uint d) { return a * 7; } }"
> clientContract = eth.compile.solidity(source).test

編譯返回的結果的JSON格式如下



 
    其中,
    code:編譯後的EVM位元組碼
    info:編譯器返回的metadata
        abiDefination:Application Binary Interface定義。具體介面規則參見這裡
    compilerVersion:編譯此程式碼的solidity編譯器版本
    developerDoc:針對開發者的Natural Specification Format,類似於Doxygen。具體規則參見這裡
    language:合約語言
    languageVersion:合約語言版本
    source:原始碼
    userDoc:針對使用者的Ethereum的Natural Specification Format,類似於Doxygen。

 
    編譯器返回的JSON結構反映了合約部署的兩種不同的路徑。info資訊真實的存在於區中心化的雲中,作為metadata資訊來公開驗證Blockchain中合約程式碼的實現。而code資訊通過建立交易的方式部署到區塊鏈中。

 

建立和部署合約

    在進行此步驟前,確保你有一個解鎖的賬戶並且賬戶中有餘額。(可以建立自己獨立的測試網路,即自己的區塊鏈,初始化的時候就可以初始化一些有餘額的賬戶)。參考:Test Networks

 
    現在就可以在區塊鏈中建立一個合約了。建立合約的方式是傳送一個交易,交易的目的地址是空地址,資料是前面JSON結構中的code欄位。
    建立合約的流程如下
var primaryAddress = eth.accounts[0]
var abi = [{ constant: false, inputs: [{ name: 'a', type: 'uint256' } ]}]
var MyContract = eth.contract(abi)
var contract = MyContract.new(arg1, arg2, ..., {from: primaryAddress, data: evmByteCodeFromPreviousSection}) //arg1,arg2,...是構造引數,這裡沒有,需要去掉。紅色部分用前面生成的code代替
    i. 獲得賬戶
    ii. 定義一個abi (abi是個js的陣列,否則不成功)
    iii. 建立智慧合約
    iv. 傳送交易部署合約

 
    如果交易被pending,如圖說明你的miner沒有在挖礦,

 
    啟動一個礦工
miner.setEtherbase(eth.primaryAddress)    //設定開採賬戶
miner.start(8)
eth.getBlock("pending", true).transactions
    這時候發現交易已經在區塊中
    不過會發現,交易還是pending,這是因為該交易區塊沒有人協助進行運算驗證,這時候只需要再啟動一個礦工就行了
miner.start(8)
參考:Private Testnet
發現區塊1部署了交易

 

與合約進行互動

    可以通過eth.contract()定義一個合約物件,這個物件包含變數合約介面的abi
Multiply7 = eth.contract(clientContract.info.abiDefinition);
var myMultiply7 = Multiply7.at(contract.address);
    到這兒,就可以呼叫智慧合約的函式了。
myMultiply7.multiply.call(3)
myMultiply7.multiply.sendTransaction(3, {from: contract.address})

 

結束

    到此,對智慧合約的初次體驗就結束了。另外智慧合約以及DApp還可以幹很多NB的事情。以後會進一步討論。