精通EOS:EOS 外掛系統
nodeos
從架構角度看,本質上是一個外掛系統,系統提供的主要功能都依賴它的外掛系統,通過不同的外掛組合來提供各種服務功能,如區塊鏈查詢,交易驗證執行,打包區塊,P2P網路通訊等服務。
外掛的繼承關係
系統的外掛系統位於eos/plugins
目錄下,外掛系統包含三個層次:
-
最頂層,這是一個位於
libraries/appbase/include/appbase/plugin.hpp
檔案中的抽象類abstract_plugin
。這個抽象類提供了外掛的基本介面,包括:- initialize初始化外掛。
- startup執行外掛。
- shutdown關閉外掛。
- set_program_options設定外掛可以接收的選項。
- get_state返回外掛的狀態。外掛當前有 4 種狀態,分別是:已註冊、已初始化、執行中、已停止。其中已登錄檔示外掛物件已經被例項化,但沒有做任何事情;已初始化表示外掛的引數已經被初始化,可以隨時執行;執行中外掛已經在執行狀態;已停止表示外掛已經停止執行。
-
name表示外掛的名稱,通過執行時類識別技術
RITT
,結合boost::core::demangle
來獲取,獲取到的名稱包括了名稱空間,比如:eosio::chain_api_plugin
。
-
中間層,這是一個位於
libraries/appbase/include/appbase/application.hpp
檔案中的模板類,它實現了抽象外掛中定義的方法,並且定義了一個虛擬函式來定義了外掛的依賴的。-
plugin建構函式。在方法中,通過 C++ 的
RTTI
執行時型別識別技術,獲得具體的例項化外掛的名稱,並儲存在_name
屬性中。這個名稱包含了名稱空間在內,比如:eosio::chain_api_plugin
。 -
get_state返回當前的狀態物件
_state
。 - name返回當前例項化類的名稱,見建構函式解釋。
-
register_dependencies通過
static_cast
方法,把當前外掛轉化為具體的例項化外掛,然後呼叫外掛的plugin_requires
模板方法,載入外掛依賴的其他外掛。 -
initialize如果當前外掛不是已註冊狀態,那麼不做任務處理。對於處在已註冊狀態的外掛,執行下面的處理:
- 首先,設定外掛狀態為已初始化;
-
其次,呼叫外掛的
plugin_requires
模板方法,載入外掛依賴的其他外掛,並且通過 Lambda 表示式執行其它外掛的initialize
方法; -
然後,呼叫外掛的
plugin_initialize
方法,進行初始化; -
最後,呼叫應用程式的
plugin_initialized
方法,把外掛加入已初始化集合initialized_plugins
。
-
startup如果當前外掛不是已初始化狀態,那麼不做任務處理。對於處在已初始化狀態的外掛,執行下面的處理:
- 首先,設定外掛狀態為已啟動;
-
其次,呼叫外掛的
plugin_requires
模板方法,載入外掛依賴的其他外掛,並且通過 Lambda 表示式執行其它外掛的startup
方法; -
然後,呼叫外掛的
plugin_startup
方法,進行啟動; -
最後,呼叫應用程式的
plugin_started
方法,把外掛加入已執行集合running_plugins
。
-
shutdown如果當前外掛不是已初始化狀態,那麼不做任務處理。對於處在已初始化狀態的外掛,執行下面的處理:
plugin_shutdown
main
函式中通過呼叫應用物件的application::iinitialize_impl
與application::startup
中被呼叫的 。 -
plugin建構函式。在方法中,通過 C++ 的
-
最下層的是承擔各種具體功能的外掛,這些外掛都位於
eos/plugins
,它們都定義了下面一些方法:
- plugin_requires模板方法,載入外掛的依賴,通過表示式依賴外掛的對應方法。
- set_program_options從抽象類類繼承的虛擬函式
- plugin_initialize例項化外掛
- plugin_startup啟動外掛
- plugin_shutdown關閉外掛
chain_plugin
、net_plugin
、http_plugin
、producer_plugin
這4個外掛不需要使用者手動註冊,節點會自動註冊。
系統提供的外掛及其功能如下所述:
-
chain_plugin這個外掛承載了
nodeos
節點程式與區塊鏈互動的基本功能,包括:- 讀取本地不可逆區塊鏈基本資訊;
- 設定本地鏈檢查點;
- 設定本地鏈引數;
- 設定可逆區塊資料庫引數;
- 設定賬戶黑/白名單;
- 設定智慧合約黑/白名單;
- 過載區塊鏈初始狀態檔案;
- 刪除、重寫、替換本地區塊鏈資料(包括開始、停止等動作);
-
net_plugin
這個外掛定義了 P2P 網路外掛,這個外掛承載了 EOS 系統的 P2P 網路中 TCP/IP 層相關功能,包括 4 個基本功能:
- 建立節點之間握手並互聯;
- 監聽/傳送/接收新交易請求;
- 監聽/傳送/接收新區塊請求;
- 驗證接收資料合法性;
-
http_plugin這個外掛定義了網路 http 外掛,這個外掛承載了 EOS 系統的 P2 P網路中 http 層相關功能,包括 3 個基本功能:
- 監聽/傳送/接收新交易請求;
- 監聽/傳送/接收新區塊請求;
- 驗證接收資料合法性;
-
producer_plugin定義了區塊生產節點的功能外掛,其中功能包括:
- 生產/打包新區塊資料;
- 對新區塊簽名;
- 對接收的區塊進行驗證,包括區塊頭合法性、簽名合法性和交易合法性;
-
wallet_plugin這個外掛定義了錢包外掛,這個外掛承載了
nodeos
節點程式與錢包互動的相關功能,包括3個基本功能:- 建立/讀取錢包檔案;
- 設定解鎖超時時間;
- 金鑰匯入錢包;
-
account_history_plugin這個外掛定義了歷史記錄查詢外掛,該外掛承載了節點程式對本地鏈發起查詢的相關功能,包括3個基本功能:
- 指定區塊查詢;
- 指定賬戶狀態查詢;
- 指定交易查詢;
-
bnet_plugin這個外掛定義了 EOS 的 P2P 網路中不同節點之間同步各自本地鏈資料的演算法,簡單來講,包括如下特徵:
- 查詢本地鏈上的最後一個區塊ID;
- 如果本地產生新區塊,則將該區塊傳送給其他節點;
- 如果本地不產生新區塊,則將接受到的未確認交易傳送給其他節點;
- faucet_testnet_plugin這個外掛定義了在測試網上快速建立測試帳號的外掛,該外掛為測試提供便利。
- history_plugin這個外掛定義了查詢指定賬戶中指定公鑰的所有歷史交易記錄。
- http_client_plugin這個外掛定義了eos網路http層響應請求,並做相應的安全驗證的客戶端外掛。
- mongo_db_plugin這個外掛定義了儲存並管理本地不可逆轉區塊鏈資料的MongoDB資料庫基本配置外掛。
- txn_test_gen_plugin這個外掛定定義了一個每秒自動產生指定數量的交易信息的外掛,該外掛主要用作對eos網路的吞吐量(TPS)測試。
-
chain_api_plugin這個外掛定義了一些使用者可以呼叫的、區塊鏈相關的 API。主要有:
- /v1/chain/abi_bin_to_json
- /v1/chain/abi_json_to_bin
- /v1/chain/get_abi
- /v1/chain/get_account
- /v1/chain/get_block
- /v1/chain/get_block_header_state
- /v1/chain/get_code
- /v1/chain/get_code_hash
- /v1/chain/get_currency_balance
- /v1/chain/get_currency_stats
- /v1/chain/get_info
- /v1/chain/get_producer_schedule
- /v1/chain/get_producers
- /v1/chain/get_raw_abi
- /v1/chain/get_raw_code_and_abi
- /v1/chain/get_required_keys
- /v1/chain/get_scheduled_transactions
- /v1/chain/get_table_by_scope
- /v1/chain/get_table_rows
- /v1/chain/get_transaction_id
- /v1/chain/push_block
- /v1/chain/push_transaction
- /v1/chain/push_transactions
-
db_size_api_plugin這個外掛定義了一些使用者可以呼叫的關於儲存相關的 API。主要有:
- /v1/db_size/get
-
history_api_plugin這個外掛定義了一些使用者可以呼叫的、歷史資料相關的 API。主要有:
- /v1/history/get_actions
- get_transaction
- get_key_accounts
- get_controlled_accounts
-
net_api_plugin這個外掛定義了一些使用者可以呼叫的、網路資料相關的 API。主要有:
- /v1/net/connect
- /v1/net/disconnect
- /v1/net/status
- /v1/net/connections
-
producer_api_plugin這個外掛定義了一些使用者可以呼叫的、生產區塊相關的 API。主要有:
- /v1/producer/pause
- /v1/producer/resume
- /v1/producer/paused
- /v1/producer/get_runtime_options
- /v1/producer/update_runtime_options
- /v1/producer/add_greylist_accounts
- /v1/producer/remove_greylist_accounts
- /v1/producer/get_greylist
- /v1/producer/get_whitelist_blacklist
- /v1/producer/set_whitelist_blacklist
- /v1/producer/get_integrity_hash
- /v1/producer/create_snapshot
-
wallet_api_plugin這個外掛定義了一些使用者可以呼叫的、錢包相關的 API。主要有:
- /v1/wallet/set_timeout
- /v1/wallet/sign_transaction
- /v1/wallet/sign_digest
- /v1/wallet/create
- /v1/wallet/open
- /v1/wallet/lock_all
- /v1/wallet/lock
- /v1/wallet/unlock
- /v1/wallet/import_key
- /v1/wallet/remove_key
- /v1/wallet/create_key
- /v1/wallet/list_wallets
- /v1/wallet/list_keys
- /v1/wallet/get_public_keys
外掛生命週期
EOS 的每個外掛,在生命期內都會經歷以下階段
- 外掛註冊
- 外掛初始化
- 外掛啟動
main
方法通過模板函式initialize
自動啟動的,還是使用者通過--plugin
引數或配置檔案指定的外掛都要經過上面說的 3 個生成生命週期。
1、外掛註冊
在 C++ 的main
函式執行前,系統會提前初始化靜態變數,這其中就包括了初始化外掛相關的變數,這些外掛都是通過呼叫app().register_plugin<xxx_plugin>()
方法時行註冊。我們簡單看下這個方法:
find_plugin plugins register_dependencies
系統中有如下一些外掛採用了靜態註冊:
- bnet_plugin
- chain_api_plugin
- db_size_api_plugin
- faucet_testnet_plugin
- history_api_plugin
- history_plugin
- http_plugin
- login_plugin
- mongo_db_plugin
- net_api_plugin
- net_plugin
- producer_api_plugin
- producer_plugin
- template_plugin
- test_control_api_plugin
- test_control_plugin
- txn_test_gen_plugin
- wallet_api_plugin
- wallet_plugin
系統通過這種靜態註冊方法和外掛間的依賴關係,間接地在系統啟動前把所有外掛都註冊到系統中。
如果我們新開發了一個外掛,因這個外掛沒有被任何現在的外掛依賴,所以一定要採用靜態註冊方法,在系統啟動之前就要進行註冊,然後才可以在配置檔案或引數中進行指定,這樣外掛才會進行初始化與啟動。
2、外掛初始化
無論是自動啟動的外掛,還是使用者通過--plugin
引數或配置檔案指定的外掛,所有的這此二外掛都是在main
函式中通過呼叫應用物件的application::iinitialize_impl
方法完成初始化的。
3、外掛啟動
在外掛初始化之後,已經完成初始化的外掛在main
函式中通過呼叫應用物件的application::startup
方法完成啟動的。
後記
由於本人水平所限,文中錯誤在所難免,歡迎您踴躍指出錯誤,在下感激不盡。我的微信聯絡方式:joepeak。
原創不易,尤其寒冬,歡迎贊助我一杯咖啡,本人比特幣地址如下:3C1gyc2tsVudvVNQCZfrwHviDQeUpPeT95
版權宣告:ofollow,noindex" target="_blank">自由轉載-非商用-非衍生-保持署名(創意共享4.0許可證)