arity Substrate是一個(gè)區(qū)塊鏈開發(fā)框架,具有許多很酷的功能,如可升級(jí)的區(qū)塊鏈,模塊化架構(gòu),可定制的塊執(zhí)行邏輯和熱插拔共識(shí)。
Substrate安裝
開始使用Substrate的第一步是設(shè)置開發(fā)環(huán)境。Substrate團(tuán)隊(duì)創(chuàng)建了一個(gè)bash腳本,它安裝所有依賴項(xiàng)并編譯相關(guān)的包作為安裝Substrate框架的一部分。
在終端中運(yùn)行以下命令,將配置Substrate。
curl https://getsubstrate.io -sSf | bash
該命令需要幾分鐘才能完成(取決于您的硬件),因?yàn)樗€編譯了Substrate框架所需的所有Rust包。
還有一個(gè)更快的選項(xiàng),只安裝依賴項(xiàng),不編譯Substrate包。要使用此選項(xiàng),請(qǐng)運(yùn)行以下命令。
curl https://getsubstrate.io -sSf | bash -s -- --fast
注意:在該的選項(xiàng)中,不會(huì)在全局系統(tǒng)中安裝Substrate CLI。
Substrate節(jié)點(diǎn)模板
一旦安裝腳本完成執(zhí)行,以及依賴項(xiàng),您還將在計(jì)算機(jī)上運(yùn)行以下幾個(gè)命令。
其中一個(gè)命令是substrate -bode-new命令可幫助您設(shè)置模板節(jié)點(diǎn)。 將此視為項(xiàng)目框架模板。該命令下載Rust代碼庫(kù)并進(jìn)行編譯。此代碼庫(kù)將設(shè)置Substrate運(yùn)行時(shí)所需的所有引導(dǎo)代碼打包在一起。
創(chuàng)建節(jié)點(diǎn)模板的實(shí)例,請(qǐng)?jiān)诮K端中運(yùn)行以下命令。
substrate-node-new 《project name》 《author name》
第一個(gè)參數(shù)是區(qū)塊鏈項(xiàng)目的名稱,第二個(gè)(可選)參數(shù)是該鏈作者的名稱。
例如:
substrate-node-new substrate-demo demoauthor
一旦該命令完成,它將在substrate demo(或您使用的項(xiàng)目名稱)目錄中創(chuàng)建以下目錄結(jié)構(gòu)。它還將初始化此目錄中的Git存儲(chǔ)庫(kù)。
Runtime子目錄包含區(qū)塊鏈運(yùn)行時(shí)相關(guān)邏輯。運(yùn)行時(shí)可以稱為區(qū)塊鏈的業(yè)務(wù)邏輯。它進(jìn)一步分為運(yùn)行時(shí)模塊和每個(gè)模塊包,它們各自的狀態(tài)(存儲(chǔ))和行為(邏輯)。運(yùn)行時(shí)目錄包含運(yùn)行時(shí)模塊的文件。
src目錄包含低級(jí)代碼,它將Substrate框架的所有組件集合在一起以執(zhí)行運(yùn)行時(shí)。
scripts目錄包含一個(gè)build.sh腳本,該腳本允許我們?yōu)閃asm(Web Assembly)環(huán)境構(gòu)建Substrate運(yùn)行時(shí)。
運(yùn)行Substrate節(jié)點(diǎn)
baseline-node-new命令完成執(zhí)行,它還將編譯節(jié)點(diǎn)模板的源代碼(花費(fèi)幾分鐘)。此時(shí),您已經(jīng)可以啟動(dòng)節(jié)點(diǎn),它將開始生成區(qū)塊。
要啟動(dòng)Substrate節(jié)點(diǎn),請(qǐng)?jiān)趎ode-template目錄的上下文中運(yùn)行以下命令。以下命令將使用dev配置基于node-template啟動(dòng)Substrate節(jié)點(diǎn)。實(shí)質(zhì)上,它運(yùn)行由節(jié)點(diǎn)模板代碼庫(kù)編譯生成的可執(zhí)行文件。
cd substrate-demo // in case you haven‘t done this already
。/target/release/substrate-demo --dev
該命令將生成類似于以下內(nèi)容的輸出。
2019-07-25 17:28:31 Substrate Node
2019-07-25 17:28:31 version 1.0.0-x86_64-linux-gnu
2019-07-25 17:28:31 by demoauthor, 2017, 2018
2019-07-25 17:28:31 Chain specification: Development
2019-07-25 17:28:31 Node name: adorable-wind-3578
2019-07-25 17:28:31 Roles: AUTHORITY
2019-07-25 17:28:31 Initializing Genesis block/state (state: 0x4397…ab51, header-hash: 0x0353…30ef)
2019-07-25 17:28:31 Loaded block-time = 10 seconds from genesis on first-launch
2019-07-25 17:28:31 Best block: #0
2019-07-25 17:28:31 Local node address is: /ip4/0.0.0.0/tcp/30333/p2p/QmYsPTbsxQiKV8Dk3rWL19xFXxfpt2NrzFRd2P63AjRM3o
2019-07-25 17:28:31 Listening for new connections on 127.0.0.1:9944.
2019-07-25 17:28:31 Using authority key 5FA9nQDVg267DEd8m1ZypXLBnvN7SFxYwV7ndqSYGiN9TmTd
2019-07-25 17:28:40 Starting consensus session on top of parent 0x03534673f220e0514d5324acd179438094e05f4c2419f33226c42e33f5cf30ef
2019-07-25 17:28:40 Prepared block for proposing at 1 [hash: 0xdc6de1c9b04607fe51bf4abed8cfdbd6313a74e9eeda78e3db4f6d2b60e69903; parent_hash: 0x0353…30ef; extrinsics: [0x0421…0149]]
2019-07-25 17:28:40 Pre-sealed block for proposal at 1. Hash now 0x1e5375649660d9e8b8e41fde74c861185a1e55153285e4332111dd0aa240684a, previously 0xdc6de1c9b04607fe51bf4abed8cfdbd6313a74e9eeda78e3db4f6d2b60e69903.
2019-07-25 17:28:40 Imported #1 (0x1e53…684a)
如您所見,節(jié)點(diǎn)已經(jīng)開始生成區(qū)塊。
構(gòu)建Substrate runtime模塊
既然我們都已經(jīng)使用Substrate設(shè)置并且我們的模板節(jié)點(diǎn)正在按預(yù)期工作,那么讓我們?yōu)閰^(qū)塊鏈構(gòu)建一些自定義邏輯。
區(qū)塊鏈的業(yè)務(wù)邏輯駐留在runtime模塊中。
假設(shè)我們想為令牌傳輸功能構(gòu)建一個(gè)簡(jiǎn)單的區(qū)塊鏈運(yùn)行。為實(shí)現(xiàn)這一點(diǎn),我們需要以下內(nèi)容:
狀態(tài):
· 令牌的總供應(yīng)量
· 帳戶和余額映射
行為:
· 令牌初始化(分配給所有者帳戶的總供應(yīng)量)
· 在帳戶之間轉(zhuǎn)移令牌
如前所述,Substrate運(yùn)行時(shí)模塊將自己的狀態(tài)和行為打包在一起。我們將使用存儲(chǔ)項(xiàng)和函數(shù)創(chuàng)建自定義運(yùn)行時(shí)模塊。
在node-template目錄中,在runtime / src目錄中,您將找到兩個(gè)文件- lib.rs和temaplate.rs。
lib.rs是Runtime的Rust crate root。它導(dǎo)入所有必需的依賴項(xiàng)和類型。它還使用Substrate框架的一些Rust宏部分初始化runtime模塊。
template.rs是Substrate runtiem的模板,它包含在節(jié)點(diǎn)模板中。它包含一些虛擬狀態(tài)和行為(在代碼注釋中有描述),并且本身就是rumtiem模塊的功能。
要實(shí)現(xiàn)上述令牌功能,我們對(duì)template.rs文件進(jìn)行一些更改。
存儲(chǔ)聲明
首先,讓我們聲明令牌功能所需的存儲(chǔ)項(xiàng)。在decl_storage! 宏調(diào)用,讓我們?yōu)榱钆频目偣?yīng)和余額映射添加以下兩項(xiàng)。
TotalSupply get(total_supply): u64 = 21000000;
BalanceOf get(balance_of): map T::AccountId =》 u64;
在第一行中,我們添加了一個(gè)存儲(chǔ)項(xiàng)TotalSupply來保存令牌的總數(shù)。我們還為此存儲(chǔ)項(xiàng)目(21000000)設(shè)置了一個(gè)值。
在第二行中,我們將另一個(gè)存儲(chǔ)項(xiàng)創(chuàng)建為StorageMap,并在AccountId和與之關(guān)聯(lián)的令牌余額之間建立映射。我們稱這個(gè)存儲(chǔ)項(xiàng)目為BalanceOf。
此模塊的完整存儲(chǔ)聲明代碼如下所示。(注意:我們刪除了模板模塊附帶的虛擬存儲(chǔ)項(xiàng)。)
// storage for this runtime module
decl_storage! {
trait Store for Module《T: Trait》 as Template {
TotalSupply get(total_supply): u64 = 21000000;
BalanceOf get(balance_of): map T::AccountId =》 u64;
}
}
實(shí)現(xiàn)runtime邏輯
現(xiàn)在我們已經(jīng)為Substrate模塊定義了存儲(chǔ),讓我們編寫一些代碼來操作這些存儲(chǔ)項(xiàng)。
在Substrate模塊中,使用decl_module!宏 ,定義公共可調(diào)度函數(shù) 我們有兩個(gè)函數(shù)可以在我們的模塊中實(shí)現(xiàn)簡(jiǎn)單的令牌傳輸功能。這些是令牌和傳遞函數(shù)的初始化。
在下面的代碼片段中,這兩個(gè)可調(diào)度函數(shù) - init和transfer在decl_module! 宏中定義。
decl_module! {
pub struct Module《T: Trait》 for enum Call where origin: T::Origin {
// initialize the token
// transfers the total_supply amout to the caller
fn init(origin) -》 Result {
let sender = ensure_signed(origin)?;
《BalanceOf《T》》::insert(sender, Self::total_supply());
Ok(())
}
// transfer tokens from one account to another
fn transfer(_origin, to: T::AccountId, value: u64) -》 Result {
let sender = ensure_signed(_origin)?;
let sender_balance = Self::balance_of(sender.clone());
ensure!(sender_balance 》= value, “Not enough balance.”);
let updated_from_balance =
sender_balance.checked_sub(value)
.ok_or(“overflow in calculating balance”)?;
let receiver_balance = Self::balance_of(to.clone());
let updated_to_balance = receiver_balance.checked_add(value)
.ok_or(“overflow in calculating balance”)?;
// reduce sender’s balance
《BalanceOf《T》》::insert(sender, updated_from_balance);
// increase receiver‘s balance
《BalanceOf《T》》::insert(to.clone(), updated_to_balance);
Ok(())
}
}
}
請(qǐng)注意,我們?nèi)绾问褂胹elf::total_supply()和《balanceof《t》》訪問模塊的存儲(chǔ),以獲取和設(shè)置這些存儲(chǔ)項(xiàng)的值。
注意:從安全性的角度來看,這些函數(shù)在檢查和驗(yàn)證方面需要更多。但為了簡(jiǎn)單起見,我們暫時(shí)跳過它們。
就是這樣;我們現(xiàn)在已經(jīng)定義了我們的小型區(qū)塊鏈運(yùn)行時(shí)的狀態(tài)和行為。
構(gòu)建和運(yùn)行substrate節(jié)點(diǎn)
現(xiàn)在讓我們通過template.rs文件中的令牌傳遞函數(shù)運(yùn)行我們剛創(chuàng)建的Substrate運(yùn)行時(shí)。
編譯
首先,要編譯Wasm環(huán)境的運(yùn)行時(shí),請(qǐng)?jiān)趓epository目錄的華寧中運(yùn)行以下命令。
。/scripts/build.sh
完成上述命令后,運(yùn)行以下命令為本機(jī)環(huán)境構(gòu)建Substrate節(jié)點(diǎn)。
cargo build --release
運(yùn)行節(jié)點(diǎn)
在創(chuàng)建節(jié)點(diǎn)模板之后,運(yùn)行該節(jié)點(diǎn)與我們之前所做的相同。
。/target/release/substrate-demo --dev
此命令應(yīng)該再次具有類似的輸出,并且該節(jié)點(diǎn)應(yīng)該啟動(dòng)并運(yùn)行和生成區(qū)塊。
Substrate節(jié)點(diǎn)與用戶界面連接
現(xiàn)在我們已經(jīng)使用令牌傳輸運(yùn)行了Substrate節(jié)點(diǎn),讓我們將它與UI連接以查看它是否正常工作。
最簡(jiǎn)單的方法是使用Polkadot Apps Portal。它是一個(gè)托管的Web應(yīng)用程序,主要用于連接到Polkadot網(wǎng)絡(luò)節(jié)點(diǎn),但它也可以連接到本地Substrate節(jié)點(diǎn)。
要使用Polkadot Apps UI進(jìn)行嘗試,請(qǐng)按照以下步驟操作:
· 本地節(jié)點(diǎn)運(yùn)行后,在瀏覽器中打開以下內(nèi)容,https://polkadot.js.org/apps/
轉(zhuǎn)到設(shè)置頁面,然后選擇遠(yuǎn)程節(jié)點(diǎn)/端點(diǎn)中的本地節(jié)點(diǎn)以連接到輸入。單擊“保存并重新加載”。
應(yīng)用程序門戶將連接到您的本地Substrate節(jié)點(diǎn),如果您轉(zhuǎn)到Explorer頁面,它應(yīng)該顯示生成的塊。以下屏幕截圖顯示了連接了本地節(jié)點(diǎn)的Polkadot Apps門戶的資源管理器視圖。
從UI調(diào)用Dispatchable函數(shù)
要初始化令牌,請(qǐng)調(diào)用Apps門戶的Extrinsics頁面中模板部分下的init()函數(shù)。 請(qǐng)參閱以下屏幕截圖以供參考。
如您所見,有一個(gè)預(yù)先選擇的帳戶Alice,當(dāng)單擊Submit Transaction按鈕時(shí),它將用于簽署函數(shù)調(diào)用。
當(dāng)此事務(wù)在區(qū)塊中完成時(shí),帳戶Alice將根據(jù)模塊中init()函數(shù)中的邏輯具有所有21000000個(gè)令牌。
從UI查詢存儲(chǔ)值
從UI調(diào)用init()函數(shù)后,帳戶Alice應(yīng)該具有更新的令牌余額21000000.讓我們通過檢查UI中的存儲(chǔ)值來驗(yàn)證。
回想一下上一節(jié),我們使用名為BalanceOf的存儲(chǔ)項(xiàng)來存儲(chǔ)針對(duì)AccountIds的令牌余額。我們來看看Alice的AccountId存儲(chǔ)的余額是多少。
您可以使用門戶的Chainstate頁面來查詢存儲(chǔ)項(xiàng)目。導(dǎo)航到此頁面,從第一個(gè)下拉菜單(模塊列表)中選擇模板,然后從下一個(gè)菜單中選擇balanceOf(AccountId):u64。從AccountId菜單中,選擇Alice。現(xiàn)在點(diǎn)擊+按鈕。它將顯示Alice的令牌余額的更新值(如以下屏幕截圖所示)。
就這樣。我們構(gòu)建了一個(gè)簡(jiǎn)單的區(qū)塊鏈運(yùn)行時(shí),并在不到20分鐘內(nèi)將其連接到一個(gè)UI。
評(píng)論