天天看點

Substrate 代碼debug

前言

整理在開發pallet過程中使用到的代碼列印控制台。

主要有以下幾種:

  • Logging utilities
  • Printable trait
  • print
  • If std

建立項目

進入到/substrate-node-template中,接着進入到目錄pallets中,建立我們自己的lfhuang-debug-pallet。并且将這pallet加載到runtime中。

使用Logging utilities

通過使用 log crate 代碼包在代碼中使用log輸出日志,包括debug和info等,和Java類似用法。

需要引入的依賴:

[package]
name = "lfhuang-debug-pallet"
description = "FRAME pallet template for debug"
authors = ["lfhuang"]
...

[dependencies]
log = "0.4.17"
...
           

接着可以在lib.rs業務代碼使用log進行列印。

#[pallet::weight(0)]
pub fn do_something(origin: OriginFor<T>, something: u32) -> DispatchResult {
	let who = ensure_signed(origin)?;
	<Something<T>>::put(something);
    // Debug方式一 log
	log::info!(
		"   ######################## called by something:{:?} and signer:{:?}",
		something,
		who
	);
	Self::deposit_event(Event::SomethingStored(something, who));
	Ok(())
}
           

通過調用交易憑證能看到輸出日志資訊如下:

Substrate 代碼debug

使用Printable trait

通過使用Printable trait 代碼包實作它,下面通過Error類型實作列印輸出日志資訊。需要開啟debug環境變量模式啟動。

目前非test調試代碼,是以sp-runtime的相關依賴需要放到[dependencies]依賴下。

...

[dependencies]
sp-runtime = { version = "7.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.37" }
...
           
// 引入依賴
use sp_runtime::print;
use sp_runtime::traits::Printable;

...
    
#[pallet::error]
pub enum Error<T> {
	/// Value was None
	NoneValue,
	/// Value reached maximum and cannot be incremented further
	StorageOverflow,
}
impl<T: Config> Printable for Error<T> {
	fn print(&self) {
		match self {
			Error::NoneValue => "Invalid Value".print(),
			Error::StorageOverflow => "Value Exceeded and Overflowed".print(),
			_ => "Invalid Error Case".print(),
		}
	}
}

...

#[pallet::weight(0)]
pub fn cause_error(origin: OriginFor<T>) -> DispatchResult {
	// 檢查是否已簽名
	let _who = ensure_signed(origin)?;
	print("   ########### 錯誤原因... #############");
	match <Something<T>>::get() {
		None => {
			print(Error::<T>::NoneValue);	// Debug方式二,預設是debug級别,是以啟動時候把環境變量調整到debug啟動
			Err(Error::<T>::NoneValue)?
		},
		Some(old) => {
			let new = old.checked_add(1).ok_or({
				print(Error::<T>::StorageOverflow);
				Error::<T>::StorageOverflow
			})?;
			<Something<T>>::put(new);
			Ok(())
		},
	}
}
           

首次調用cause_error沒有值則會報Error::NoneValue錯誤,需要調用do_something方法設定一個值,接着再掉用cause_error方法則存儲值會加1,同時也會報Error::StorageOverflow錯誤。

Substrate 代碼debug

使用print

使用print函數進行調試記錄runtime執行狀态。需要導入use sp_runtime::print;和上面的Printable trait方式差不多,輸出列印日志都使用到了print();需要開啟debug環境變量模式啟動。

官網例子中的print!();編譯報錯。部分代碼例子如下:

#[pallet::weight(0)]
pub fn do_something(origin: OriginFor<T>, something: u32) -> DispatchResult {
	let who = ensure_signed(origin)?; // 檢查是否已簽名
	print("   開始設定值..."); // Debug方式三 print,預設是debug級别,是以啟動時候把環境變量調整到debug啟動
	<Something<T>>::put(something);
	print("   存儲值完成...");
	// Debug方式一 log
	log::info!(
		"   ######################## called by something:{:?} and signer:{:?}",
		something,
		who
	);
	Self::deposit_event(Event::SomethingStored(something, who));
	Ok(())
}
           

使用if_std

使用if_std宏的方式實作調試。

...

[dependencies]
sp-std = { version = "5.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.37" }
...
           
// 引入依賴
use sp_std::if_std;
           

println!語句應該在if_std宏的内部。

#[pallet::weight(0)]
pub fn do_something(origin: OriginFor<T>, something: u32) -> DispatchResult {
	let who = ensure_signed(origin)?; // 檢查是否已簽名
	print("   開始設定值..."); // Debug方式三 print,預設是debug級别,是以啟動時候把環境變量調整到debug啟動
	<Something<T>>::put(something);
	print("   存儲值完成...");
	// Debug方式一 log
	log::info!(
		"   ######################## called by something:{:?} and signer:{:?}",
		something,
		who
	);
	// Debug方式四 if_std!宏
	if_std! {
		println!("   ################## Hello native world! something value: {}",something);
		println!("   ################## 調用者的交易賬戶是: {:#?}", who);
	}
	Self::deposit_event(Event::SomethingStored(something, who));
	Ok(())
}
           
Substrate 代碼debug

檢查編譯代碼

cargo check -p node-template-runtime --release
           

編譯節點模闆

傳回到項目根目錄下/substrate-node-template

cargo build --package node-template --release
           

啟動節點

運作一個臨時節點,該節點将在流程結束時删除所有配置,指定開發鍊

./target/release/node-template --tmp --dev
           

使用RUST_LOG環境變量運作節點二進制檔案以列印值。

RUST_LOG=runtime=debug ./target/release/node-template --tmp --dev
           

連接配接節點

1、在浏覽器中輸入https://polkadot.js.org/apps/#/explorer
2、點選左上角會展開 
3、在展開的菜單中點選 DEVELOPMENT 
4、點選 Local Node 
5、點選 switch (轉換到本地網絡)           

繼續閱讀