做者:微衆銀行html
做爲BSN首個引入的國產聯盟鏈底層框架,FISCO BCOS將在4月份完成BSN適配並開啓公測,屆時,開發者能夠免費部署一個具備三個記帳節點的應用。
java
目前,FISCO BCOS平臺支持Solidity和Precompiled兩種類型的智能合約,同時,提供交互式控制檯工具(Console),方便開發者與鏈進行交互,部署、調用智能合約。數據庫
爲了讓你們快速上手智能合約,FISCO BCOS推出了智能合約系列教程,本文爲系列教程精編,更多實操內容敬請關注FISCO BCOS開源社區公衆號。編程
1.智能合約簡介網絡
衆所周知,智能合約的出現,使區塊鏈不只能處理簡單的轉帳功能,還能實現複雜的業務邏輯,極大地推進了區塊鏈技術發展,加速應用落地。架構
目前,在衆多區塊鏈平臺中,大多數集成了以太坊虛擬機,並使用Solidity做爲智能合約開發語言。做爲一門面向合約的高級編程語言,Solidity借鑑了C++、Python和JavaScript等語言的設計,使用靜態類型,不只支持基礎/複雜數據類型操做、邏輯操做,同時提供高級語言的相關特性,好比繼承、重載、庫和用戶自定義類型等。併發
做爲最大最活躍的國產開源聯盟鏈社區,FISCO BOCS無縫支持Solidity合約,並提供從開發、編譯、部署到調用的全鏈路工具和完整解決方案,使智能合約和區塊鏈應用開發變得簡單。app
除此以外,基於大量探索和實踐,FISCO BCOS不只支持Solidity合約,還支持Precompiled合約,並在用戶層提供CRUD合約接口。面向庫表開發的CRUD合約不只更符合用戶開發習慣,進一步下降合約開發難度,提高性能,使區塊鏈應用知足高併發場景的訴求。框架
2.智能合約分類編程語言
FISCO BCOS平臺支持兩種類型的智能合約:Solidity合約和Precompiled合約。
2.1 Solidity合約
Solidity合約運行在EVM上,EVM爲以太坊虛擬機,採用哈佛架構,指令、數據和棧徹底分離。
在智能合約運行期間,首先建立一個沙盒環境(EVM實例),沙盒環境與外部環境徹底隔離,沒法訪問網絡、文件系統其它進程,智能合約在EVM內只容許進行有限的操做。交易執行時,EVM經過獲取合約的opcode,將opcode轉化爲對應的EVM指令,並按照指令進行執行。
從應用落地的數量來看,Solidity合約使用最爲普遍,幾乎全部區塊鏈平臺都支持,但Solidity也有不少缺點。以下:
●合約在EVM中串行執行,性能較差;
●跨合約調用會新建EVM,內存開銷較大;
●合約變量和數據存在MPT數中,不便於合約升級;
●邏輯和數據耦合,不便於存儲擴容。
2.2 Precompiled合約
Precompiled合約即預編譯合約。預編譯合約經過Precompiled引擎執行,採用C++編寫合約邏輯,合約編譯集成進FISCO BCOS底層節點。
調用合約不進EVM,可並行執行,突破EVM性能瓶頸;提供標準開發框架,只需繼承基類,實現call接口便可;適合於邏輯相對肯定、追求高併發的場景;數據存在表中,與合約分離,可升級合約邏輯。
固然,預編譯合約的使用有必定的門檻。以下:
●對於數據的存儲,須要建立FISCO BCOS特有的表結構;
●編寫合約時需繼承Precompiled類,而後實現Call接口函數;
●完成合約開發後,需在底層爲預編譯合約註冊地址;
●編寫完成合約後,須要從新編譯FISCO BCOS源碼。
爲了屏蔽預編譯合約在開發和使用中的門檻,FISCO BCOS基於預編譯合約和分佈式存儲設計了CRUD合約接口。用戶在編寫Solidity合約時,只須要引入抽象合約接口文件Table.sol,即可使用CRUD功能,用戶不須要關心底層的具體實現。
3.智能合約開發
本節將基於全球英文認證考試成績管理做爲場景,基於FISCO BCOS平臺對智能合約進行開發。全球認證考試包括GRE、TOEFL、IELTS等。爲了簡化合約邏輯,全部成績統一由考試管理中心發佈和管理,學生能夠根據本身的帳號(地址)查詢本身的考試成績。
3.1 Solidity合約開發
在 Solidity 中,合約相似於面向對象編程語言中的類。Solidity合約有自身的代碼結構,由幾個部分組成,以下所示。
●狀態變量:狀態變量是永久存儲在合約中的值
●構造函數:用於部署並初始化合約
●事件:事件是能方便地調用以太坊虛擬機日誌功能的接口
●修飾器:函數修飾器能夠用來改變函數的行爲,好比自動檢查,相似Spring的AOP
●函數:函數是合約中代碼的可執行單元
■建立合約
首先建立一個名爲StudentScoreBySol的合約,用於管理學生的成績。以下代碼所示,開頭須要引入合約版本。
■定義狀態變量
狀態變量用於存儲和管理學生的考試成績。
在當前場景中定義兩個變量,其中_owner爲合約的建立者,即考試管理中心;_scores用於存儲學生成績,爲一個嵌套mapping類型,第一個mapping的key(address)爲學生的帳戶(私鑰對應的地址),value也爲一個mapping類型,對應爲每一科的成績,在第二個mapping中key(bytes32)爲科目名稱,如GRE、TOEFL等,value(uint8)爲成績。以下所示。
■定義事件
定義一個事件setScoreEvent,用於跟蹤對學生成績的新增/修改操做,能夠在業務層面對事件進行監聽。事件的定義是可選的,若是沒有定義也不要緊,在業務層面能夠根據方法的返回值去判斷交易是否成功,但沒法作到更精細的問題定位。
■定義修飾器
智能合約中的修飾器(Modifier)相似面向對象編程中的AOP,知足條件纔會執行後續操做。以下所示,修飾器要求必須是合約的Owner才能進行後續操做,其中Owner爲考試管理中心。
■定義構造方法
構造方法用於實例化合約,在當前構造方法中,指定Owner爲合約的部署者。
■編寫函數
當前合約中,定義兩個函數,setScore函數用於新增/修改/刪除(score置爲0)學生成績,並使用了onlyOwner修飾器,只有Owner(考試管理中心)才能操做,並經過setScoreEvent事件跟蹤每次操做內容。getScore方法用於成績查詢,其中view修飾符表示不會修改狀態變量。
Solidity合約完整代碼以下所示。基於Solidity語言的合約開發,看似簡單,但須要對Solidity編程語言深刻學習,才能編寫出高可用的合約,具有必定學習成本。
經過FISCO BCOS開源社區推出的智能合約專題,開發者可瞭解更多運用Solidity編寫智能合約的方法與技巧,關注「FISCO BCOS開源社區」公衆號可獲取專題。
更多細節可參考Solidity官方文檔:
https://solidity-cn.readthedocs.io/zh/develop/
3.2 CRUD合約開發
CRUD合約是CRUD功能的核心,用戶能夠直接在合約中引用CRUD接口文件Table.sol,並在Solidity合約中調用CRUD接口。CRUD合約的開發徹底聽從數據庫的操做習慣,更容易理解和上手。
CRUD合約更多開發細節可參考:
https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/manual/smart_contract.html#crud■建立合約
CRUD建立的合約和Solidity建立的沒有太大區別,惟一區別在於須要引入CRUD接口文件Table.sol,以下所示。修飾器和構造方法的做用與Solidity合約相同。
■事件定義
在Solidity合約中能夠經過setScore完成成績的新增/修改/刪除,但在CRUD合約中,須要藉助CRUD接口文件的不一樣接口,經過不一樣函數實現,因此須要針對不一樣的函數定義不一樣時間,以下所示。
●createEvent:用於跟蹤建立表操做;
●insertEvent:用於跟蹤插入成績操做;
●updateEvent:用於跟蹤更新成績操做;
●removeEvent:用於跟蹤刪除成績操做。
■建立表函數
CRUD合約實現業務功能,首先須要像數據庫操做同樣,建立一張表,用於存放數據。
FISCO BCOS底層提供了TableFactory合約,該合約的地址固定爲0x1001,能夠經過TableFactory對象提供的方法對錶進行建立(createTable)和打開(openTable),以下所示。
createTable接口返回值爲0時,說明建立成功。須要注意的是,爲了讓建立的表可被多個合約共享訪問,表名必須是羣組內全局可見且惟一的,沒法在同一條鏈上的同一個羣組中,建立多個名稱相同的表。
■新增成績函數
對錶進行操做時,首先須要經過TableFactory打開對應的表,得到表對象,而後經過表對象的insert方法進行數據插入。在插入數據前,首先須要構建一個Entry對象實例,代碼以下所示。
須要注意的是,Table接口合約的insert、remove、update和select函數返回值相似數據庫,均爲受影響的記錄行數,且接口中key的類型爲string。
而在當前場景中,學生的studentId爲address類型,因此須要在函數內部將address類型轉化爲string類型,代碼以下。
■更新成績函數
更新成績操做步驟包括:經過TableFactory對象打開表,而後,像數據庫同樣構造篩選條件。
在CRUD合約接口中,提供了Condition對象,該對象提供了諸如大於、等於、小於等一系列條件方法。構造完成條件對象後,能夠調用table對象的udpdate接口,完成更新操做,代碼以下。
■刪除成績操做
刪除操做和更新操做相似,須要調用table.remove接口完成,再也不贅述,代碼以下。
■查詢成績操做
查詢成績操做很簡單,須要調用table.select接口完成,代碼以下。
至此基於CRUD的合約開發完成。
從當前場景的代碼行數來看,CRUD合約比較複雜,Solidity合約相對簡單。但這只是一個幻覺,實際狀況可能並不是如此。並且CRUD合約的開發更符合開發者習慣,沒有多餘的學習成本,更容易理解和上手。
4.合約部署及調用
開發完智能合約後,須要對合約進行編譯和部署,而後才能調用。FISCO BCOS平臺提供了交互式控制檯工具(Console),能夠很是方便地與鏈進行交互。下面將以上述智能合約爲例,採用控制檯工具進行部署和調用。
控制檯安裝及使用可參考:
https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/manual/console.html。
4.1準備工做
在對合約進行部署和調用前須要作三件事情。首先複製編寫好的合約到控制檯目錄console/contracts/solidity下。以下圖所示。
其次對合約進行編譯,能夠採用控制檯目錄下的sol2java.sh腳本對合約進行編譯,編譯結束後會在console/contracts/sdk目錄下生成以下文件夾,以下圖所示。
其中abi中存放合約的ABI,bin存放合約的二級制編碼文件(BINARY),JAVA文件夾中爲對應的JAVA合約,便於經過SDK和鏈進行交互。
須要注意的是對CRUD合約編譯時。須要將CRUD接口合約Table.sol一併放入console/contracts/solidity目錄下,否則會報錯。
最後,對合約進行部署時,依賴外部帳戶,因此首先須要生成帳戶。在控制檯中提供了帳戶生成工具get_account.sh,運行該腳本會在console/accounts目錄下生成帳戶。
咱們利用帳戶生成工具生成兩個帳戶。一個爲考試管理中心的帳戶,用於部署和新增/修改/刪除學生成績;一個爲學生帳戶,用於查看考試成績。以下所示。
4.2 Solidity合約部署和調用
首先採用考試管理中心帳戶啓動控制檯,以下圖所示,即表示控制檯啓動成功。
而後經過deploy命令對合約進行部署,合約部署成功以後會返回合約地址,以下圖所示。
合約部署完成以後,能夠經過控制檯的call命令調用合約函數。以下圖所示,新增學生的GRE成績爲70(修改和刪除都可經過調用setScore方法進行操做),函數返回值爲true,則表示交易成功。call命令的具體用法能夠經過call -h 查看。
採用學生帳戶啓動控制檯,經過getScore函數查當作績,以下圖所示,返回值爲70,說明沒有問題。也可使用學生帳戶調用setScore方法,會報錯,打印沒有權限,再也不贅述。
4.3 CRUD合約部署和調用
CRUD合約的部署和調用和Solidity合約沒有區別,這裏一樣採用控制檯進行。
首先採用考試管理中心帳戶啓動控制檯,並對StudentScoreByCRUD合約進行部署。以下圖所示。
合約部署完成以後,調用create函數建立stu_score表,以下所示,返回結果爲0,說明建立成功。
建立好表以後,就能夠調用相關接口對學生成績進行操做了,首先調用insert函數新增學生成績。以下所示,返回結果爲1,說明插入成績成功。
成績插入成功以後,關閉當前控制檯,用學生帳戶登陸控制檯,並調用select函數查詢成績,以下圖所示,返回70,說明查詢成功。剩餘函數測試可自行完成,再也不贅述。
5.結束語
本文重點介紹了FISCO BCOS平臺的智能合約開發。在FISCO BCOS平臺中,既能夠採用原生Solidity語言開發智能合約,也可使用預編譯合約模式開發合約。Solidity合約性能差、學習成本高;預編譯合約,採用預編譯引擎,支持並行計算,性能更高,同時支持存儲擴容等。
但因爲預編譯合約使用存在必定的門檻,基於此,FISCO BCOS平臺開發了CRUD合約接口,用戶不須要關心底層的實現邏輯,只須要引入Table.sol合約接口文件,經過調用相關接口便可完成合約的開發。
關注「FISCO BCOS開源社區」公衆號,獲取更多智能合約實操內容