前 言
區塊鏈的發展伴隨着信息安全的話題。在Solidity不長的發展歷程中,發生過不止一次駭人聽聞、影響深遠的安全攻擊事件,給一些機構和組織造成不可挽回的損失。
『禍亂生於疏忽,測試先於交付』,如果這些缺陷和漏洞在測試環節被發現,就能有效避免損失。
測試是智能合約開發與交付過程中至關重要的一環。其能有效檢驗實際結果是否符合設計預期,有助識別錯誤、查缺補漏。同時,高質量、可複用的測試,還有助於提升整體開發效率。
前文介紹了Solidity的前世今生、語法特性、設計模式、編程攻略和底層原理。作爲系列終篇,本文將重點介紹和分享Solidity的測試場景、方法和實踐。
前置準備
進入測試前,需要完成以下步驟:鏈的搭建、控制檯安裝、智能合約開發、智能合約編譯與部署、利用Java等SDK開發一個應用。
詳細準備工作可參考《FISCO BCOS零基礎入門,五步輕鬆構建應用》和FISCO BCOS官方文檔,此處不再贅述。FISCO BCOS官方文檔地址:
https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/installation.html
測試環境
FISCO BCOS提供控制檯、WeBASE-Front和SDK代碼測試,這三種環境適用於不同測試場景:
- 控制檯:提供命令行交互界面,通過在控制檯創建合約和輸入調用、查詢指令,來進行簡單調試。適用於非常簡單的合約。
- WeBASE-Front:提供可視化交互界面以及簡易的IDE環境。適用於業務邏輯並不複雜的合約,更推薦開發人員進行一些調試。
- SDK:例如集成Java Web3sdk,創建一個Java項目,並編寫應用和測試代碼。適用於對智能合約質量要求較高、要求測試案例可複用、業務邏輯複雜或要求持續集成的場景。
控制檯測試
FISCO BCOS 2.0及以上版本提供了方便易用的命令行終端、『開箱即用』的區塊鏈利器,詳情可參考《FISCO BCOS 控制檯詳解,飛一般的區塊鏈體驗》。
接下來將通過一個合約示例來講解如何運用控制檯進行測試。
首先,我們寫一個HelloWorld合約:
pragma solidity ^0.4.25;
contract HelloWorld{
string public name;
constructor() public{
name = "Hello, World!";
}
function set(string n) public{
name = n;
}
}
然後,將這個合約命名爲HelloWorld.sol,並保存到控制檯所在的contracts/solidity/路徑下。隨後,執行./start.sh 啓動控制檯並部署合約:
=============================================================================================
Welcome to FISCO BCOS console(1.0.8)!
Type 'help' or 'h' for help. Type 'quit' or 'q' to quit console.
________ ______ ______ ______ ______ _______ ______ ______ ______
| | \/ \ / \ / \ | \ / \ / \ / \
| $$$$$$$$\$$$$$| $$$$$$| $$$$$$| $$$$$$\ | $$$$$$$| $$$$$$| $$$$$$| $$$$$$\
| $$__ | $$ | $$___\$| $$ \$| $$ | $$ | $$__/ $| $$ \$| $$ | $| $$___\$$
| $$ \ | $$ \$$ \| $$ | $$ | $$ | $$ $| $$ | $$ | $$\$$ \
| $$$$$ | $$ _\$$$$$$| $$ __| $$ | $$ | $$$$$$$| $$ __| $$ | $$_\$$$$$$\
| $$ _| $$_| \__| $| $$__/ | $$__/ $$ | $$__/ $| $$__/ | $$__/ $| \__| $$
| $$ | $$ \\$$ $$\$$ $$\$$ $$ | $$ $$\$$ $$\$$ $$\$$ $$
\$$ \$$$$$$ \$$$$$$ \$$$$$$ \$$$$$$ \$$$$$$$ \$$$$$$ \$$$$$$ \$$$$$$
=============================================================================================
[group:1]> deploy HelloWorld
contract address: 0x34e95689e05255d160fb96437a11ba97bb31809f
[group:1]>
合約被成功部署後就可以開始測試了。我們先打印這個合約中name的值,然後修改爲新的值,最後重新查詢name中的值。
[group:1]> call HelloWorld 0x34e95689e05255d160fb96437a11ba97bb31809f name
Hello, World!
[group:1]> call HelloWorld 0x34e95689e05255d160fb96437a11ba97bb31809f set "Hello, test!"
transaction hash: 0x72c8a95b651fb5d12c44b69624d5213d58af1509f00920757fce94d019b5eae8
[group:1]> call HelloWorld 0x34e95689e05255d160fb96437a11ba97bb31809f name
Hello, test!
[group:1]>
上述例子演示瞭如何使用控制檯部署與調試合約。控制檯設計簡潔優雅,使用體驗如絲般順滑。不過,在處理一些複雜場景,例如需要切換外部賬戶,或通過可視化界面進行操作時,WeBASE-Front當仁不讓地扛起大旗。
WeBASE-Front測試
WeBASE-Front爲開發者提供了運行核心信息的可視化操作、Solidity開發的IDE環境以及私鑰管理功能,讓大家更便捷地開啓區塊鏈之旅。
關於WeBASE-Front的介紹可參考《WeBASE節點前置組件功能解析》與《安裝部署說明》。《安裝部署說明》地址:
https://webasedoc.readthedocs.io/zh_CN/latest/docs/WeBASE-Install/developer.html#
接下來,我們演示一個需要切換外部賬戶的測試案例,以下是合約代碼:
pragma solidity ^0.4.25;
contract BasicAuth {
address public _owner;
constructor() public {
_owner = msg.sender;
}
function setOwner(address owner)
public
onlyOwner
{
_owner = owner;
}
modifier onlyOwner() {
require(msg.sender == _owner, "BasicAuth: only owner is authorized.");
_;
}
}
在這個示例中,合約owner被自動賦值爲合約部署者。修飾器onlyOwner決定了setOwner函數只能由_owner用戶來發起。
在合約管理-合約IDE中,創建test文件夾,並複製合約代碼:
然後,點擊私鑰管理-新增用戶,創建user1和user2兩個用戶。
這時,選擇部署合約,會彈出用戶地址窗口選項,選擇user1。
合約部署成功後,會展示合約地址、合約名、abi、合約binary等系列信息:
點擊合約調用,彈出調用窗口,『方法』下拉框裏包含了所有可調用的函數列表,選擇_owner函數,點擊確認,就可返回該合約的_owner變量值。
現在,我們來測試setOwner()函數。如上所述,本合約的_owner是user1,通過切換用戶user2來調用這個函數,預期結果是調用失敗。我們選擇setOwner方法,選擇私鑰地址爲user2:
正如預期,這個函數的調用失敗了:
以上執行結果打印出了整個交易的TransactionReceipt,點擊還原可轉換爲原始output值。『所見即所得』,WeBASE-Front讓區塊鏈變得更簡單易用。
使用WeBASE-Front測試最大短板在於測試案例無法複用。倘若合約非常複雜,那所有測試案例都得靠人工一遍遍輸入,操作原始低效。
SDK測試
在系統測試中,需要遵循經典的AIR實踐原則:
- Automatic:測試應該被全自動執行,這也是實現持續集成的前提。
- Independent:測試案例彼此保持獨立,不存在相互依賴和調用。
- Repeatable:測試案例必須可被複用。可以跨越軟硬件環境,被重複執行。
要滿足以上甚至更多測試實踐原則,使用控制檯或WeBASE-Front的方式就顯得有些力不從心,而集成SDK並編寫測試代碼的方式更值得推薦。
這種方式雖然前期花費時間較長、成本較高;但測試後期能大大降低重複的工作量,顯著提升整體測試效率。
這也符合IT公司現行的軟件測試實踐規範。一般這部分代碼由公司開發測試人員或質量保證(QA)工程師編寫。但在很多公司中,這部分代碼由開發人員編寫。良好的測試代碼,能提升代碼質量,降低代碼重構難度,提高開發效率。
FISCO BCOS提供了多語言SDK,如Java、Python、Node.js等,其中最爲成熟與常用的是Java版Web3SDK。《手把手教你在Eclipse中使用JavaSDK》詳細介紹了在Eclipse創建新工程以及將已經提供的示例項目導入Eclipse。
在Java開發實踐中,Springboot使用更爲深入人心,FISCO BCOS也提供了相應使用案例,相關配置文檔可以參考:《Spring Boot項目配置》,通過spring-boot-starter開發者可快速下載示例工程,並導入偏好的IDE中。
配置工程鏈基本環境後,下面將以上述spring-boot-starter工程爲例,介紹具體測試步驟和要點。
- 編寫合約:HelloWorld合約。
- 編譯智能合約,將其轉爲Java文件,從上述WeBASE-Front中,也能編譯並導出Java文件。
- 將編譯生成的Java文件導入工程中,如HelloWorld.java。
- 基於上述文件,調用合約功能和接口,編寫相關測試案例,例如:ContractTest。
- 基於Spring提供的gradle插件,我們可以通過"./gradlew test"命令來運行所有測試案例。
- 如果需要持續集成,可以在配置和初始化FISCO BCOS後,將步驟5命令加入自動化腳本中。
接下來,我們將具體分析核心測試代碼ContractTest:
@Test
public void deployAndCallHelloWorld() throws Exception {
// deploy contract
HelloWorld helloWorld = HelloWorld
.deploy(web3j, credentials, new StaticGasProvider(GasConstants.GAS_PRICE, GasConstants.GAS_LIMIT))
.send();
Assert.assertNotNull(helloWorld);
// call set function
helloWorld.set("Hello, World!").send();
// call get function
String result = helloWorld.get().send();
Assert.assertTrue("Hello, World!".equals(result));
}
- 第4行中,HelloWorld合約被部署。爲符合獨立性原則,建議在每個測試案例中部署獨立的合約,以避免測試案例執行順序對正常測試造成干擾。需要模擬合約依賴性的情況除外。
- 第9行和第11行,分別調用了set和get。爲符合可重複性原則,該測試案例必須設計成冪等,即在任意的軟硬件環境下,測試案例預期結果都是一致的。
- 第7行和第12行,使用了Junit框架提供的斷言方法,用來判斷智能合約執行結果是否符合預期。
值得一提的是,在Java SDK中,任意交易上鍊後,會獲得一個回執TransactionReceipt對象,該對象中包含了返回狀態和錯誤信息(如果交易成功,則message爲null),可通過這個狀態判斷交易是否正常,例如:
TransactionReceipt tr = helloWorld.set("Hello, World!").send();
Assert.assertEquals(tr.getMessage(), "0x0", tr.getStatus());
以上基於Springboot提供的測試特性,實現了合約測試,如果需要了解更多細節,請參考Spring的相關文檔。相關參考地址:
https://docs.spring.io/spring-boot/docs/2.2.6.RELEASE/reference/html/spring-boot-features.html#boot-features-testing
測試類型
如傳統軟件,智能合約的測試同樣可分爲功能測試、非功能測試、安全性測試和迴歸測試,下面將對這些測試作逐一介紹。
功能測試
功能測試包括但不限於單元測試、集成測試、冒煙測試、用戶驗收測試。除用戶驗收測試外,其他測試都可通過開發或測試人員編寫代碼實現。
智能合約測試重要目的之一是檢測合約代碼正確性,在預定輸入值前提下,檢查輸出值是否符合預期。
上文我們介紹了控制檯、WeBASE-Front和SDK三種測試環境。
在一些邏輯複雜的智能合約中,測試難點之一在於構造測試案例。在這種場景下,使用智能合約可以更好地模擬和構造測試數據,直接使用Solidity編寫智能合約更爲原生、友好。
最後,測試並不遊離於智能合約開發之外,而是其中重要的一環,測試也需遵循依賴關係原則,即開發者在進行開發時需要考慮智能合約的『可測試性』。
例如,假設測試代碼完全使用SDK編寫,那智能合約的修改就可能導致測試代碼需要做出對應變更,這會對測試效果造成影響,提升測試成本。基於軟件設計『不可依賴多變部分』的原則,可測試性同樣不能依賴於多變部分。
爲了解決上述問題,我們在智能合約層引入測試代碼。這些代碼僅被設計爲測試組件,不會發布到線上環境,以此將測試案例改動影響解耦並封裝到智能合約層。測試合約作爲獨立組件,支持開發和測試環節。
測試組件中首先可以抽象和定義一些測試的工具合約,例如:
pragma solidity 0.4.25;
library LibAssert {
event LogTest(bool indexed result, string message);
function equal(uint8 a, uint8 b, string message) internal returns (bool result) {
result = (a == b);
log(result, message);
}
function notEqual(uint8 a, uint8 b, string message) internal returns (bool result) {
result = (a != b);
log(result, message);
}
function log(bool result, string message) internal {
if(result)
emit LogTest(true, "");
else
emit LogTest(false, message);
}
}
這是一個最簡單的測試合約庫,提供了equal和notEqual的方法來判斷uint8變量,開發者可基於此工具擴展自己的測試工具合約。
其次,依託於工具合約,我們可以編寫獨立的測試合約案例。
下面將以上述Uint8MathTest爲例,演示如何使用此工具合約,首先,我們定義一個TestDemo合約:
pragma solidity ^0.4.25;
import "./Uint8MathTest.sol";
import "./LibAssert.sol";
contract TestDemo {
using LibAssert for uint8;
function testAdd() external returns (bool result) {
uint8 a = 1;
uint8 b = 1;
Uint8MathTest math = new Uint8MathTest();
uint8 c = math.add(a,b);
uint8 expectedValue = 2;
result = expectedValue.equal(c, "Not equal");
}
}
然後,在控制檯中運行這個測試案例:
[group:1]> deploy TestDemo
contract address: 0xd931b41c70d2ff7b54eb9b2453072f9b1a4dc05c
[group:1]> call TestDemo 0xd931b41c70d2ff7b54eb9b2453072f9b1a4dc05c testAdd
transaction hash: 0xe569e5d8eae1b949a0ffe27a60f0b4c8bd839f108648f9b18879833c11e94ee4
---------------------------------------------------------------------------------------------
Output
function: testAdd()
return type: (bool)
return value: (true)
---------------------------------------------------------------------------------------------
Event logs
---------------------------------------------------------------------------------------------
除了依賴自定義的智能合約測試代碼,也可以用智能合約本身來編寫測試案例。在SDK層,我們只需實現TestDemo中的測試函數代碼。即使未來測試邏輯改動,也無需改動SDK代碼,從而保證了測試代碼的健壯性。
合約測試代碼組件需貫徹智能合約在整體設計中所遵循的設計原則。
非功能測試
非功能測試主要包括性能測試、容量測試、可用性測試等。由於智能合約運行於FISCO BCOS的底層節點,容量測試和可用性測試更多與底層節點相關,因此,對用戶而言,非功能測試的重點就在性能測試上。
雖然,我們可以使用系列通用性能測試工具對智能合約進行測試,但是,實際壓測過程中會存在一些痛點,例如:
- 針對具體合約場景測試,存在大量且重複的測試代碼,費時費力;
- 性能指標缺乏統一度量,無法橫向對比;
- 展示結果不夠直觀。
爲了解決以上痛點,FISCO BCOS適配了區塊鏈測試專業工具Caliper,讓用戶可以優雅地進行性能測試。更多細節和內容請參考:《性能測試工具Caliper在FISCO BCOS平臺中的實踐》。
安全性測試
智能合約上線前需要進行嚴格的安全性測試。
安全性測試的方式包括:公開智能合約併發布懸賞、聘請專門的智能合約安全機構對合約進行檢測和評估、使用智能合約專用的工具進行審計等。
大家可以視自身合約的重要性及邏輯複雜程度選擇對應的安全性測試級別。對於個人開發者或非重大業務的智能合約,選擇免費的智能合約工具檢測即可。
下面以VS Code爲例,演示如何使用智能合約安全插件對合約進行安全性檢測。打開VS Code,在其插件庫中搜索Beosin-VaaS: ETH,選擇安裝。
隨後,打開智能合約文件,右鍵選擇Beosin-VaaS:ETH選項,在彈出的窗口中選擇當前合約代碼版本。安裝完成後,會自動彈出如下界面:
點擊start即可對所選合約進行安全檢測。以下是對HelloWorld合約的檢測結果:
start compile!
compile over!
start deploy!
deploy over!
start execute function name: set(string)
execute function name : set(string) end!
No problem was found in the contract
當我們對Uint8MathTest合約進行檢測時,會發現報錯:
####### Compile Problem #######
file: /Users/maojiayu/Downloads/Uint8MathTest.sol
title: Compile Problem
description: Function state mutability can be restricted to pure
code: function add(uint8 a, uint8 b) public returns (uint8 c) {
warningType: Info
line: 5
通過報錯信息,我們可以發現該函數既沒讀取也沒使用區塊鏈上的狀態,符合pure修飾符的使用條件,建議使用『pure』關鍵字來修飾。
安全性測試是合約測試過程中不可或缺的一環,需高度重視。在嚴格的工程實踐中,合約上生產前必須由相關的測試負責人出具安全性檢測報告。
此外,開發人員可以收集和總結Solidity安全編程規則和漏洞風險提示,並動態更新維護。在交付測試前,開發人員可組織代碼審查和走查,依據總結,集中、逐項進行風險排查。
安全性測試是檢測和評價智能合約是否安全的必備環節,但不能將合約安全性完全寄望於測試。更重要的是,在設計、開發和測試的各個階段,都需要用戶時刻保持安全意識,建立和培養安全編碼習慣。合約發佈上線後,也不能放鬆警惕,時刻關注業界最新的安全警告,並定期、動態對所有代碼進行檢測和掃描。
迴歸測試
迴歸測試通常包括執行持續集成的自動化測試案例以及合約上線前的人工測試。
上述SDK以及智能合約測試案例可有效覆蓋測試案例所執行的路徑和範圍。自動化的迴歸測試有助於快速檢測並發現問題,節省大量重複人力,保證合約經歷系列修改和測試後,不偏離主幹功能。同樣,開發者可使用Jenkins、Travis等工具進行構建和測試。
除了執行個別自動化測試無法執行的案例外,人工測試更多地是確認之前修改的代碼是否符合預期,智能合約的運行是否符合當初設計。此外,在合約最終發佈前,人工測試還起到審覈檢查作用,故而一定要認真對待。
測試要點
無論何種類型的系統測試,均需特別注意以下測試要點。
- 注意邊界值的測試,例如數字溢出、特殊取值、循環邊界值等。
- 注意檢查智能合約的實現是否符合預期,其運行邏輯和流程是否與設計一致。
- 除了正常流程外,還需要模擬和測試在各種異常環境,甚至是極端環境下,智能合約運作是否正常,能否達到預期的處理結果。
- 圍繞智能合約不變的業務邏輯,忽略變化值,進行對應測試。
邊界值
邊界值測試是一種常見的軟件測試方法。據統計,絕大多數的bug發生在輸入或輸出範圍的邊界上,而非其內部。
我們來演示一個典型的數值溢出測試案例。如下簡單的合約,實現了兩個uint8數值加法,並返回了結果:
pragma solidity 0.4.25;
contract Uint8MathTest {
function add(uint8 a, uint8 b) public returns (uint8 c) {
c = a + b;
}
}
這時,我們需要設計一個邊界值的測試案例。已知uint8的取值範圍在[0,28)即[0,256)之間,以此設計一個溢出的測試案例:(a=255, b=1),測試結果如下:
[group:1]> deploy Uint8MathTest
contract address: 0xd8a765995c58eb8da103bdcc2c033c0acb81e373
[group:1]> call Uint8MathTest 0xd8a765995c58eb8da103bdcc2c033c0acb81e373 add 255 1
transaction hash: 0x0583185839bc52870ac57cdfd00c0c18840c2674d718b4cc3cb7bc1ef4c173e0
---------------------------------------------------------------------------------------------
Output
function: add(uint8,uint8)
return type: (uint8)
return value: (0)
---------------------------------------------------------------------------------------------
可以看到最後結果變爲0,而不是預期的256,顯然,這是因爲結果發生了溢出。
當然,在使用邊界值測試方法取值時,並非只取有效邊界值,還應包含無效邊界值。邊界值測試可幫助查出更多錯誤和缺陷。
是否符合預期
在建築公司交付房屋後,開發商會依據設計標準檢驗房屋建造是否合格。同樣,除了檢查合約執行結果是否正確外,在測試中還需檢查合約交互、操作、數據流向、性能表現等各方面實現是否符合設計。
舉個例子,在金融業場景中,我們會使用Solidity開發具體鏈上業務邏輯。
其中,不可避免與金額打交道,就需要測試對應資產規模是否符合設計標準。在需求和設計階段,我們會預估運行在鏈上的資產規模並作設計要求,例如要求某個供應鏈金融區塊鏈業務系統能在千億資產規模下正常運行。
假設在智能合約中,定義金額的字段是uint32,可以計算其最大能表示的值爲232即不到43億。
雖然在智能合約發佈上線後大多數時間內,該問題不會造成任何影響;但是,一旦業務快速增長,當資產規模超過43億後,就會出現嚴重故障。
這類問題非常隱蔽,因此,需要更加全面、仔細的測試來提早發現和定位。
異常流程
在實際業務場景中,即便經過系列測試保證智能合約運行符合絕大多數場景需求,也可能因爲疏忽或遺漏,導致在特定異常流程下,出現問題,在智能合約發佈後造成了重大影響。
故而,開發者需要特別重視在測試範圍和內容中對異常流程的搜尋和覆蓋,儘可能測試覆蓋到所有的異常流程。
變與不變
使用Solidity測試與其他語言的顯著不同還在於合約中的很多交易和值無法復現。正如『人的一生無法兩次踏入同一條河流』,隨着私鑰、證書、環境等改變,其交易Hash值、區塊Hash、合約地址等也會隨之不同,這也給測試帶來一些客觀困難。
另一方面,Solidity對於一致性有着嚴苛要求,例如對EVM執行指令語義的一致性、對外部隨機變量的『排斥』等。掌握合約測試的關鍵在於抓住其中不變的方面。
測試技巧
作爲區塊鏈上專用編程語言,相比其他高級語言,Solidity有非常多限制。例如,缺乏成熟的測試工具支持,無法在運行時進行debug以及查看EVM虛擬機內的狀態與數據。
同時,Solidity缺乏獨立的數據抽象層,導致無法像傳統應用那樣直接通過連接數據庫來查看合約內詳細的變量狀態,只能通過在合約內增加查詢調用來『曲線救國』。
當然,我們也可以採取一些技巧,儘可能規避以上問題。
如何展示合約更多內部變量?
編寫Solidity代碼與其他高級語言最大差別是無法進行debug。這個問題解決辦法之一是打印和展示更多內部變量。
問題場景:
還是上述的HelloWorld合約,現在我們無法在set函數執行時獲取原有的name值,只能通過name()函數來查詢。有沒有辦法在set函數執行時,記錄和打印出name原來的值呢?
解決方案:
定義一個event,在set函數內部進行調用。例如:
pragma solidity ^0.4.25;
contract HelloWorld{
string public name;
event LogSet(string oldValue, string newValue, address sender);
constructor() public{
name = "Hello, World!";
}
function set(string n) public{
emit LogSet(n, name, msg.sender);
name = n;
}
}
然後,在控制檯中執行,可以看到剛纔定義的LogSet事件被打印出來了。我們在事件中還定義打印了msg.sender的地址,如下圖所示,對應地址也被打印出來。
Event相當於提供了log日誌的簡單機制,當出現無法解決且需要展示合約內部狀態的情況,Event提供了合適的方法和機制。
如何獲得鏈上全量數據模型?
問題場景:
都說Solidity是圖靈完備的語言,EVM是設計簡潔的狀態機,如果想要獲取狀態機內部每個狀態和交易的『世界狀態』蛛絲馬跡,有什麼好的解決方案?
解決方案:
Solidity缺乏獨立的可對外訪問的數據層,無法直接獲取每筆交易或每個狀態的詳情。不過,我們可以通過WeBASE數據導出組件來導出所有鏈上數據。
WeBASE-Collect-Bee可以導出區塊鏈上的基礎數據,如當前塊高、交易總量等。
如果正確配置了FISCO BCOS上運行的所有合約,WeBASE-Collect-Bee可以導出區塊鏈上合約的業務數據,包括event、構造函數、合約地址、執行函數的信息等。
數據導出組件WeBASE-Collect-Bee的目的在於降低獲取區塊鏈數據的開發門檻,提升研發效率。研發人員幾乎無需編寫任何代碼,只進行簡單配置,就可以把數據導出到Mysql數據庫。
還是以上面的HelloWorld爲例,參考安裝文檔:WeBASE-Collect-Bee快速部署。
安裝過程略過不表,導出以後會自動在數據庫中生成如下的表:
數據庫表的功能如下:
- account_info: 記錄了所有在鏈上部署的合約信息,包括了合約名、合約地址、塊高、上鍊時間等。
- blcok_detail_info: 記錄了每個區塊的信息,包括區塊hash、交易數量、塊高、上鍊時間等。
- block_task_pool:數據導出的任務表,記錄了任務詳情和狀態信息。
- block_tx_detail_info:記錄了每筆交易的信息,包括了交易的合約名稱、函數名稱、交易發送者地址、交易接收者地址、交易hash等。
- hello_world_log_set_event:數據導出會自動生成每個event的數據庫表,命名規則爲合約名+事件名。上面例子中定義的event所自動生成的表,包括了event中定義的所有變量和交易信息等。
- hello_world_set_method:數據導出會自動生成不同transaction的數據庫表,命名規則爲合約名+函數名。上面例子中定義的set函數表,包含了函數的入參、返回碼和交易hash等。
hello_world_log_set_event顯示了所有HelloWorld合約中,LogSetEvent事件記錄的信息。
hello_world_set_method顯示了歷史調用的所有函數信息。
有了上述的數據庫導出狀態與信息,使用區塊鏈瞬間變得容易,測試也更加得心應手、如虎添翼。數據庫會如實地導出和記錄區塊鏈上所有操作,讓一切鏈上數據都盡在掌握中!
總 結
優質的測試環節能夠提升智能合約編寫的質量,杜絕因爲合約編寫漏洞而造成的重大損失,還能使合約開發曲線趨緩,有助於提升智能合約開發效率。
『翻過高山,正遇江海。行過雪原,恰逢花期。』只有經歷了艱苦、嚴謹、細心、反覆的測試周期,才能迎接智能合約發佈的曙光。
至此,智能合約系列也行至尾聲。本教程從智能合約的概念引入,介紹了Solidity的基本語言特性、設計模式、編程攻略,再到深入到EVM核心、Solidity測試。
短短几篇小文難以窮盡Solidity編程所有細節,期待社區的開發者,一起參與和分享更多知識和經驗,共同建設更好的FISCO BCOS社區。
參考資料
Spring Boot項目配置參考
https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/sdk/java_sdk.html#spring-boot
spring-boot-starter
https://github.com/FISCO-BCOS/spring-boot-starter
HelloWorld合約
https://github.com/FISCO-BCOS/spring-boot-starter/blob/master/src/test/resources/contract/HelloWorld.sol
轉爲Java文件
https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/manual/console.html#id12
HelloWorld.java
https://github.com/FISCO-BCOS/spring-boot-starter/blob/master/src/test/java/org/fisco/bcos/solidity/HelloWorld.java
ContractTest
https://github.com/FISCO-BCOS/spring-boot-starter/blob/master/src/test/java/org/fisco/bcos/ContractTest.java
WeBASE-Collect-Bee快速部署
https://webasedoc.readthedocs.io/zh_CN/latest/docs/WeBASE-Codegen-Monkey/install.html#
我們鼓勵機構成員、開發者等社區夥伴參與開源共建事業,有你在一起,會更了不起。多樣參與方式:
1、進入微信社羣,隨時隨地與圈內最活躍、最頂尖的團隊暢聊技術話題(進羣請添加小助手微信,
微信ID:FISCOBCOS010);
2、訂閱我們的公衆號:“FISCO BCOS開源社區”,我們爲你準備了開發資料庫、最新FISCO BCOS動態、活動、大賽等信息;
3、來Meetup與開發團隊面對面交流,FISCO BCOS正在全國舉辦巡迴Meetup,深圳、北京、上海、成都……歡迎您公衆號在菜單欄【找活動】中找到附近的Meetup,前往結識技術大咖,暢聊硬核技術;
4、參與代碼貢獻,您可以在Github提交Issue進行問題交流,歡迎向FISCO BCOS提交Pull Request,包括但不限於文檔修改、修復發現的bug、提交新的功能特性。
代碼貢獻指引:
https://github.com/FISCO-BCOS/FISCO-BCOS/blob/master/docs/CONTRIBUTING_CN.md