五一勞動節,講講NEO智慧合約的除錯

瘋光無線發表於2018-04-27

之前我們說過NEO智慧合約的除錯問題,過去了一段時間,有很多東西都發生了比較大的變化。讓我們重新再來探討一下這個話題。

先說日期,2018年4月27日,馬上迎來勞動節。

 

以後可能還會再次談論這個話題。

 

然後明確幾個問題,把一些經常糾結的地方先說清楚

  1. 如果你連neo同步區塊還沒搞明白,先不要湊智慧合約開發這個熱鬧。
  2. 我們只討論C#開發智慧合約的除錯問題,其它的暫無工具開發計劃。
  3. NEO官方沒有智慧合約除錯工具,所以我們的工具是有很多定製的成分。
    1. 為什麼要除錯

一次編碼,按下f5,一切正常,揮一揮衣袖就瀟灑的離開,那是傳說。

當程式碼執行不符合預期時,我們需要深入分析問題,需要更精細的觀測手段。

 

而NEO官方並沒有提供這樣的工具,於是我們開發了一攬子工具用於解決除錯問題

他們是:

  1. NeonDebug 替換的c#智慧合約編譯器
  2. NeoGUI-NEL 定製版NeoGUI 或者 NeoCli-NEl 定製版的NeoCli
  3. NeonDebugGUI,智慧合約執行情況觀測工具

 

為了3的正常執行,1 2 都是必須的,如果你想知道為什麼,原始碼可以告訴你答案

 

https://github.com/NewEconoLab/neondebug

https://github.com/NewEconoLab/neo-gui-nel

 

  1. 合約的編譯

你可曾聽過NeoVM,AVM檔案,就是智慧合約編譯生成的那東西,就是NeoVM的位元組碼,叫AVM是因為以前叫小蟻,ant的A,這個副檔名沒一起改。

 

為了方便不那麼瞭解虛擬機器的開發者理解,我和C#的類庫機制做一個對比。

 

這個AVM相當於是DLL,要除錯一個c# DLL,你需要DLL PDB cs原始碼三部分內容。DLL儲存位元組碼,PDB儲存位元組碼地址和原始碼位置的對映,這樣才能在斷點時根據位元組碼執行位置定位到原始碼位置,而cs原始碼,就是為了讓你除錯時對照到程式碼

 

那麼:

DLL-》AVM

PDB-》?

cs-》cs

 

標準的c#編譯器neon.exe(如果不知道neon.exe,再好好補一下C#智慧合約編譯的相關資料),只生成了一個AVM和一個ABI檔案,這個ABI是介面說明。

PDB對應的角色是空缺的

 

所以你需要 NEL 的 Neon.exe ,編譯neondebug倉庫的neondebug專案可以得到這個替換的neon.exe

 

設定環境變數,保證在任何路徑可以執行neon

注意紅框部分,有Debug字樣

 

這個替換的編譯器,就專門解決那個缺失的PDB問題,這個編譯器和官方編譯器程式碼隨時同步更新,你直接使用這個替換的編譯器就行,任何更新都會同步,不需要切換回官方編譯器。

 

重啟VS2017之後,來編譯一個智慧合約試試

注意紅框部分,已經使用了我們的替換版本編譯 有(debug)字樣

下一行告訴你,在c:\neo\smartcontracts輸出了些什麼,讓我們來看看。

首先原來的avm照樣輸出,這些是另外多輸出的

 

檔名全部替換為了合約hash,avm還是那個avm

Abi.json還是那個abi

Cs是把智慧合約原始碼copy 過來的,只支援一個智慧合約專案有一個程式碼檔案,所以不要分檔案。

Map就是替代PDB的那個了,他記錄位元組碼地址和原始碼地址的對映關係

 

生成在這個路徑也是有意義的,除錯檢視工具會直接來這個路徑找合約,以前需要用除錯檢視工具再開啟一次合約,現在不用了,直接用同一個路徑。

 

  1. 合約的呼叫

A,用neogui 測試執行合約

    用neogui-nel,測試執行一個合約,只有nel定製版支援。

    

試執行固定產生一個0x00 的log檔案,看這個log就可以除錯了,這個下一節再說,我們這裡之說產生log檔案的辦法。

 

產生這個log是除錯的唯一辦法。

 

B 、用NEOCLI 測試執行合約

呼叫NEOCLI -NEL的 rpc invokescript 介面,會在返回值多返回一個fulllog欄位,將其儲存為檔案,就是這個llvmhex檔案,可以用來除錯。

只有nel定製版支援

C、用NEOGUI發交易

用NEL定製版NEOGUI發起交易,只有nel定製版支援

 

 

發起交易,

會得到交易id同名的llvm檔案

Id[0]

Id[1]

這種為鑑權合約的log

只有通過neogui nel定製版發起交易 或者 neocli nel定製版的 rpc介面 sendraw發起交易

才會產生鑑權合約的log,才可以除錯鑑權合約,其他只除錯應用合約

D、通過NEOCLI的sendraw RPC 發起交易

只有nel定製版支援

會得到交易id同名的llvm檔案

Id[0]

Id[1]

這種為鑑權合約的log

E、通過其他方式產生的交易

由於交易會同步給每一個節點,定製的neo-gui-nel,和neo-gui-cli

可以得到所有的交易,無論是誰產生的。

但是做智慧合約的除錯的LOG是很耗時的,所以他並不總是開啟的,有一個開關去控制他

這個開關在config.json裡面

NEOGUI-nel的設定為true,表示只生成這個GUI自己發起的交易的LOG

開啟這個同步就會變得非常慢,除錯的時候再用。

 

NEOGUI-nel不修改這個config 也可以開啟生成任何人發起的交易的開關

這裡按一下讓他顯示為=false,然後之後同步的每一筆交易都會生成除錯LOG了

這個只在記憶體修改,每次開啟neo-gui都要看一眼。

 

  1. 合約的除錯

編譯,啟動NeonDebugGUI

略,他也在NeonDebug倉庫中

 

使用Load 開啟對應的llvmhex.txt檔案即可除錯

這兩個load,一個是開啟一個對話方塊,一個是輸入txid自己去找,結果都一樣。

 

功能介紹

開啟除錯LOG以後

圖中紅黃藍部分先注意一下

紅色部分最重要,首先觀察合約執行狀態 halt break 為vm正常停機,程式正常走到結束。

Fault break為vm異常停機,你可以直接反著從最下邊看看到底怎麼了。

 

紅色部分為整個VM內Dump下來的執行流程,也就是整個智慧合約的過程到底幹了什麼,從紅色部分選擇最上面一項,然後用鍵盤的方向鍵下,往下挪,先完整的看幾個合約,可以建立一些基本的感覺。

 

黃色部分為智慧合約原始碼,當紅色部分選中條目變化時,如果能找到對應的原始碼,黃色部分就會跳轉高亮。

 

通常最主要的除錯觀測方法就是選紅色、看黃色。

 

然後藍色部分收集了所有syscall,因為neoVM的虛擬機器自身是純計算,所有對鏈產生影響或者和鏈互訪的功能都是通過syscall進行的,看一個合約有哪些syscall就能快速瞭解這個合約的行為,當然這需要建立在熟悉的基礎上,只要多看,就能熟悉。

除錯小提示

  1. 紅色部分最重要
  2. 選中條目時,執行棧顯示的這條指令執行之後的狀態。

比如

Equal指令是==表示式,他顯示的false只能告訴你是不想等,要看是誰和誰比較,往前倒退一條指令

倒退後觀測計算棧,valuetool 會幫助你顯示這個資料可能是什麼

  1. 是多條虛擬機器指令對應一條cs原始碼,並且有些是對應不到的。

記住這一點,而不能只盯著原始碼,左邊最重要,左邊要選到關鍵的程式碼。

你要搞清楚那些最關鍵的指令,比如syscall appcall equal

這並不會有多複雜,知道找關鍵指令就會快很多。

  1. 一定要熟悉syscall

最重要的storage.put 就是一個syscall

相關文章