Parity的Substrate區塊鏈框架在最近幾個月裏的開發進展很迅速,基於Substrate的Polkadot區塊鏈的開發也是如火如荼。這個教程的目的是介紹如何構建一個能夠支持本身的運行時模塊的Substrate鏈。php
本教程的主要內容包括:java
Substrate和運行時模塊都是使用Rust開發的。node
Rust是一種底層靜態類型語言,它的特色在於速度保障與可靠性,可是學習難度比較高。在區塊鏈開發中一個很是重要但卻常常被忽略的話題是:如何掌握Rust。在這個教程中咱們不會分析Rust代碼,可是對於但願使用Susbtrate進行區塊鏈開發的工程師來講,掌握Rust是一個前提條件。python
做爲一種程序開發語言,Rust的學習曲線是比較陡峭的。部分緣由在於Rust所採用語法規範,極其依賴於像泛型、特性萃取、生命週期和宏這樣的特性,以及其餘一些考慮例如做用於和不變性。react
其餘的Substrate學習資源,例如Substrate Kitties collectibles workshop 生成Rust很是容易掌握,但這不是真實的狀況,除非你已經有比較多的底層語言的開發經歷,例如C++,並且接觸過比較多的涉及系統級管理的API。git
實際上,若是你是剛接觸Rust,那麼須要一點耐心,須要花時間來了解這門開發語言的核心概念和特性。在掌握Rust以後,Substrate的開發將變得使人享受。這本Rust書寫的很好,很適合新手學習,也適合有經驗的用戶溫習Rust。github
安裝Substrate只須要調用Parity網站上的一個bash腳本。Substrate提供了兩種安裝方式:json
若是但願快速掌握區塊鏈應用的開發,推薦匯智網的區塊鏈應用開發系列教程, 內容涵蓋比特幣、以太坊、eos、超級帳本fabric和tendermint等多種區塊鏈, 以及 java、go、nodejs、python、php、dart等多種開發語言瀏覽器
快速安裝將安裝預構建的Substrate開發鏈、Substrate腳本、Substrate鏈命令行配置工具和運行時模塊。bash
使用--fast
標誌來運行Substrate安裝腳本會跳過安裝那些對運行Sbustrate來講並不是必要的工具:
~$ curl https://getsubstrate.io -sSf | bash -s -- --fast
上面的命令將拉取Susbtrate的依賴項,包括Rust、OpenSSL、LLVM等等,而後進行安裝。
完整安裝除了包含上面的內容,還將安裝如下兩個工具:
運行下面的命令進行完整安裝:
// full Substrate installation ~$ curl https://getsubstrate.io -sSf | bash
一旦安裝腳本執行完畢,更新你的cargo環境以便調用新安裝的程序:
~$ source ~/.cargo/env
如今使用substrate命令就能夠訪問預編譯好的Substrate節點了。要驗證Substrate node和SubKey是否正確安裝,能夠檢查這兩個程序的版本:
~$ substrate --version ~$ subkey --version
注意:Polkadot JS 應用已經在其帳戶管理界面中實現了subkey的功能 —— 能夠在瀏覽器中管理帳戶而無需subkey,這也是subkey是可選安裝的緣由。
默認狀況下,Substrate和工具程序安裝在 ~/.cargo/bin目錄中。你能夠看一下具體的 安裝內容:
~$ cd ~/.cargo/bin ~/.cargo/bin$ ls
你會注意到除了substrate和subkey,還有substrate-node-new和substrate-module-new這兩個程序,接下來咱們將使用這些程序來建立新的定製節點和運行時模塊。
更新Substrate腳本須要克隆最新版本,而後使用下面的命令替換cargo的二進制程序:
~$ f=`mktemp -d` ~$ git clone https://github.com/paritytech/substrate-up $f ~$ cp -a $f/substrate-* ~/.cargo/bin ~$ cp -a $f/polkadot-* ~/.cargo/bin
如今咱們已經安裝好了Substrate工具,能夠運行Substrate開發節點了。這個節點會開始出塊,可是對於開發而言沒什麼用。
在任何狀況下,咱們可使用下面的命令啓動Substrate開發鏈:
~$ substrate --dev
節點如今就起來了,你能夠看到開始出塊。要查看區塊鏈的更多信息,例如每一個支持模塊的狀態,咱們將使用Polkadot JS應用。
要查看substrate的命令行選項,能夠查看--help
的輸出:
~$ substrate --help
熟悉一下help命令的輸出,是瞭解命令行程序的功能的獲得驗證的方法。目前的版本包含了一些對測試有用的標誌,例如預配置的帳戶--alice
、 --bob
等等。--light
標誌能夠按輕量模式運行節點,在框架中內置了對輕量客戶端的支持。
在咱們開始定製構建以前,然咱們回顧一下如何查看Substrate鏈。基本的方法是使用Polkadot JS應用,該應用使用Typescript和react開發。
Polkadot JS應用提供了基本的區塊鏈瀏覽器功能,同時也提供了管理Substrate模塊的API和接口。正如其名稱所示,這個應用也支持Polkadot區塊鏈。咱們有兩種途徑來使用Polkadot JS:
讓咱們克隆項目在本地運行,一旦安裝完成,咱們能夠指向咱們的Susbtrate鏈的節點,在咱們機器上的另外一個運行進程。
首先克隆並運行Polkadot JS應用:
~$ git clone https://github.com/polkadot-js/apps.git ~$ mv apps polkadot.js ~$ cd polkadot.js && yarn start
而後在另外一個終端啓動substrate開發鏈:
substrate --dev
在瀏覽器中訪問localhost:3000
。爲了讓JS App鏈接到咱們本地的開發鏈,在側欄菜單中選擇Settings,而後切換到Local Node endpoint,相似下圖:
點擊Save & Reload,你將注意到側欄菜單中的許多連接激活了,具體哪些連接會激活取決於你的鏈的支持。
讓咱們看一下幾乎全部鏈都會支持的特性 - 帳戶。進入到應用的Accounts部分 - 在My Account選項頁你將看到一組帳戶,這些都是預配置的含餘額的帳戶,咱們也能夠在這些帳戶之間轉帳、刪除帳戶以及備份帳戶密鑰。這代表了Plokadot JS App的定位 —— 在UI層與你的Substrate鏈交互。
在繼續以前,咱們要提一下Polkadot UI能夠完成的任務:
你能夠會困惑,哪些預配置的帳戶是哪裏來的。事實上,這些帳戶,包括運行時邏輯自身的編譯代碼,都是保存在一個Chain Specification文件中,也被稱爲chain spec。
鏈配置是一個大型JSON對象,使用substrate的build-spec命令生成。該命令將提取節點引入的運行時模塊的配置項,有些是空值,有些則提供了默認值。
基本上,運行時模塊能夠依賴於創世配置,也就是在區塊鏈初始化時咱們提供的配置。區塊鏈狀態是由創世區塊 —— 鏈的第一個區塊 —— 來初始化的。chain specJSON文件的工做,就是定義這個初始狀態。
一旦生成配置文件,咱們就能夠打開該文件,根據咱們的須要進行修改。
節點提供了purge-chain
命令來複位區塊鏈,這一般用於開發中:
~$ substrate purge-chain --dev
框架提供了三個默認的鏈規格,也就是配置:dev、local和staging。
咱們如今要作的,就是使用build-spec命令建立一個新的chainspec,將輸出結果存入單獨的文件。例如,將規格寫入當前用戶主目錄的my-chainspec.json文件:
~$ substrate build-spec --chain=dev > ~/my-chainspec.json
在文件編輯器裏打開這個文件,查看可用的配置選項。
一旦修改完chainspec文件,咱們能夠用--raw
標誌將其轉化爲原始編碼狀態:
~$ substrate build-spec --chain ~/chainspec.json --raw > ~/mychain.json
最終,咱們使用這個鏈規格文件來啓動咱們的substrate鏈。如下假設你運行了一個自定義編譯的substrate節點,使用節點的路徑替換下面的<node_path>
:
<node_path> --chain ~/mychain.json --validator
接下來讓咱們看看如何初始化並編譯自定義的Substrate節點。
到目前位置,咱們已經使用了預編譯的Substrate節點。對於測試一下開發鏈很好,可是這限制了咱們使用本身的運行時模塊以及自定義配置。爲解決此問題,咱們須要下載Substrate源代碼。
有兩種方法來着手咱們的自定義Substrate鏈:
基本上全部的Substrate項目都會基於官方的節點模板展開,除非一些特殊狀況。
用下面的命令生成一個新的節點模板:
~$ substrate-node-new my-node "Ross Bulat"
命令執行須要花點時間 —— 要拉取最新的Substrate源碼而且進行編譯。
一旦完成,能夠修改runtime/src目錄下的lib.rs文件。同時也包含了運行時模塊的模板template.rs。 接下來咱們看一下運行時模塊。
在節點目錄中,在使用cargo編譯出二進制程序以前,使用build.sh腳本將節點編譯爲wasm:
# build wasm ./scripts/build.sh # build binary cargo build --release
節點程序如今位於./target/release/ 目錄。
以前咱們已經使用substrate調用了一些命令,如今可使用咱們新編譯出來的程序。要復位區塊鏈並從新運行,執行以下命令:
# clear chain state ./target/release/<node_name> purge-chain --dev # run in dev mode ./target/release/<node_name> --dev
咱們要介紹的最後一部份內容,是運行時模塊。讓咱們看看什麼是運行時模塊以及如何在substrate節點中引入運行時模塊。
Substrate的通用和模塊化結構使其實用性大大加強,開發人員能夠將功能以插件形式加載到節點運行時,從而能夠輕鬆地建立知足個性化需求的區塊鏈。
這些插件化的功能包被稱爲模塊,或者更確切地說,運行時模塊。Substrate預置的運行時模塊集合被稱爲Substrate運行時模塊庫 —— SRML。
這些模塊很是有用,它們實現了其餘區塊鏈框架中的不少功能,能夠在github瀏覽這些模塊的代碼。有了這些模塊,開發人員不須要從新發明輪子,能夠節省大量時間。當實現新特性時,也是以運行時模塊的形式開發的。
SRML模塊由Substrate統一維護,所以可靠性獲得保障。下面是如今可用的一些模塊:
你會注意到這些模塊都是Rust crate格式,該格式被設計用於Substrate運行時環境。
每一個SRML模塊都打包爲crates,並在模塊名前加以srml_前綴,在Parity的crate庫的左側菜單中,能夠找到這些模塊。
每一個模塊都是定義在它本身的src/lib.rs文件中,遵循約定的結果。咱們能夠看一下一個substrate模塊的頂層特徵:
最後一點指的是什麼?一個模塊爲你的區塊鏈增長功能,功能能夠多種形式的組件提供:
事件:一個模塊能夠聲明自定義事件,當特定條件知足時觸發,例如,當你鑄造非同質化通證時,多是一個TokenCreated事件。事件被封裝在 decl_event! 宏裏:
decl_event!( pub enum Event<T> where <T as system::Trait>::AccountId, <T as system::Trait>::Hash { TokenCreated(AccountId, Hash), } );
存儲:一個模塊能夠定義鏈上的持久化數據結構,例如映射表、列表等等。存儲條目定義 在decl_storage!宏裏:
decl_storage! { trait Store for Module<T: Trait> as NFTStorage { TokenToOwner get(token): map T::Hash => Token<T::Hash, T::Hash>; TokenIndex get(get_token_by_index): map u64 => T::Hash; TotalTokens get(total_tokens): u64; ... } }
可分發函數:JSON RPC能夠調用的函數。
公開/私有函數:模塊能夠提供在運行時環境中可調用的公開函數,以及只能夠在模塊中調用的私有函數。
結構:模塊能夠定義結構,例如,在一個跟蹤全球運輸的區塊鏈實現中,可能會定義一個ShipmenItem結構。
#[derive(Encode, Decode, Default, Clone, PartialEq)] pub struct ShipmentItem<Hash, Balance> { id: Hash, container_id: Hash, price: Balance, weight: u64 }
相似於substrate-node-new工具,咱們也下載了substrate-module-new工具。在節點運行時目錄,使用下面的命令準備一個新的模塊:
substrate-module-new <module_name>
讓咱們將其命名爲my-module:
cd runtime/src substrate-module-new my-module > SRML module created as ./my-module.rs and added to git. > Ensure that you include in your ./lib.rs the line: > mod my_module;
結果文件my-module,將和最初目錄中包含的template.rs文件一致。可是使用substrate-module-new是初始化一個新的運行時模塊的官方推薦的方式。
如今咱們能夠開發這個模塊,打包稱create,甚至分發到github以便你們均可以維護。