摘要:區(qū)塊多線程簽名改動同步區(qū)塊時進行多線程簽名,過程中依然是單線程簽名。代碼解析塊簽名因為不適用多線程簽名,所以依舊沿用之前的簽名代碼,而同步則使用了新的部分。當(dāng)大家比較關(guān)注的使用并沒有得到改善,因為多線程簽名無法應(yīng)該在生產(chǎn)區(qū)塊上。
昨天早上,EOS 1.5.0 release 版本發(fā)布了。這次比較大改動點是在多線程簽名上面。它將同步區(qū)塊時的 block 簽名驗證和 trx 簽名驗證都使用多線程簽名驗證,來節(jié)省同步所需要的時間, 但是生產(chǎn)區(qū)塊所需要的成本是不變的,但為什么生產(chǎn)區(qū)塊成本不變呢。接下來介紹一下具體的改動。 區(qū)塊多線程簽名改動:同步區(qū)塊時進行多線程簽名, replay 過程中依然是單線程簽名。因為區(qū)塊同步時需要回滾 pending block 的 trx 操作, 這塊時間剛好可以用來并行處理簽名, 但 replay 的時候沒有這一步,即使用多線程簽名也無法節(jié)省時間,反而會讓主線程阻塞等待異步結(jié)果返回。 trx 多線程簽名改動:同步區(qū)塊以及 replay 過程都會進行多線程簽名, 因為有多個 trx 要執(zhí)行,所以執(zhí)行 trx 的時間可以供其他 trx 的簽名并行進行。 但生產(chǎn)區(qū)塊的時候無法使用,因為執(zhí)行 BP 接受到一個 廣播的 trx 就立馬去執(zhí)行了,執(zhí)行完之后才回去接受下一個廣播 trx, 所以無法使用多線程簽名。代碼解析: 塊簽名:
因為 replay 不適用多線程簽名, 所以 replay 依舊沿用之前的簽名代碼, 而同步則使用了新的部分。
// producer_plugin.cpp 接受到廣播塊 void on_incoming_block(const signed_block_ptr& block) { // ... // start processing of block // 調(diào)用一個線程去對塊進行簽名驗證 auto bsf = chain.create_block_state_future( block ); // abort the pending block // 回滾掉 pending block 的執(zhí)行 trx, 這段時間剛好可以用來并發(fā)執(zhí)行區(qū)塊簽名驗證 chain.abort_block(); // ... } // controller.cpp std::future交易簽名create_block_state_future( const signed_block_ptr& b ) { //驗證區(qū)塊是否存在。 EOS_ASSERT( b, block_validate_exception, "null block" ); auto id = b->id(); // no reason for a block_state if fork_db already knows about block auto existing = fork_db.get_block( id ); EOS_ASSERT( !existing, fork_database_exception, "we already know about this block: ${id}", ("id", id) ); auto prev = fork_db.get_block( b->previous ); EOS_ASSERT( prev, unlinkable_block_exception, "unlinkable block ${id}", ("id", id)("previous", b->previous) ); // 進行多線程簽名 return async_thread_pool( [b, prev]() { const bool skip_validate_signee = false; return std::make_shared ( *prev, move( b ), skip_validate_signee ); } ); } void push_block( std::future & block_state_future ) { controller::block_status s = controller::block_status::complete; EOS_ASSERT(!pending, block_validate_exception, "it is not valid to push a block when there is a pending block"); auto reset_prod_light_validation = fc::make_scoped_exit([old_value=trusted_producer_light_validation, this]() { trusted_producer_light_validation = old_value; }); try { // 獲取驗證結(jié)果, 當(dāng)區(qū)塊驗證失敗時會拋出異常,中止 push block block_state_ptr new_header_state = block_state_future.get(); auto& b = new_header_state->block; emit( self.pre_accepted_block, b ); fork_db.add( new_header_state, false ); if (conf.trusted_producers.count(b->producer)) { trusted_producer_light_validation = true; }; emit( self.accepted_block_header, new_header_state ); if ( read_mode != db_read_mode::IRREVERSIBLE ) { maybe_switch_forks( s ); } } FC_LOG_AND_RETHROW( ) }
從改動得知,apply_block 的時候才會啟動交易的多線程驗證簽名,而 bcast_transaction 則不會,因為并沒有多余的動作可以與驗證簽名并行。
void apply_block( const signed_block_ptr& b, controller::block_status s ) { try { try { EOS_ASSERT( b->block_extensions.size() == 0, block_validate_exception, "no supported extensions" ); auto producer_block_id = b->id(); start_block( b->timestamp, b->confirmed, s , producer_block_id); // 按順序啟動每個 trx 的多線程驗證簽名,生產(chǎn)對應(yīng)公鑰 std::vector總結(jié)packed_transactions; packed_transactions.reserve( b->transactions.size() ); for( const auto& receipt : b->transactions ) { if( receipt.trx.contains ()) { auto& pt = receipt.trx.get (); auto mtrx = std::make_shared ( pt ); if( !self.skip_auth_check() ) { std::weak_ptr mtrx_wp = mtrx; mtrx->signing_keys_future = async_thread_pool( [chain_id = this->chain_id, mtrx_wp]() { auto mtrx = mtrx_wp.lock(); return mtrx ? std::make_pair( chain_id, mtrx->trx.get_signature_keys( chain_id ) ) : std::make_pair( chain_id, decltype( mtrx->trx.get_signature_keys( chain_id ) ){} ); } ); } packed_transactions.emplace_back( std::move( mtrx ) ); } } // 執(zhí)行 trx // ... commit_block(false); return; } catch ( const fc::exception& e ) { edump((e.to_detail_string())); abort_block(); throw; } } FC_CAPTURE_AND_RETHROW() } /// apply_block // trx 執(zhí)行時獲取簽名返回的公鑰 const flat_set & recover_keys( const chain_id_type& chain_id ) { // Unlikely for more than one chain_id to be used in one nodeos instance if( !signing_keys || signing_keys->first != chain_id ) { if( signing_keys_future.valid() ) { // 獲取公鑰,如果未簽名完則阻塞等待簽名完畢 signing_keys = signing_keys_future.get(); if( signing_keys->first == chain_id ) { return signing_keys->second; } } // 當(dāng)沒開啟多線程簽名時, 直接驗證生成對應(yīng)公鑰 signing_keys = std::make_pair( chain_id, trx.get_signature_keys( chain_id )); } return signing_keys->second; }
從這次的改動可以看出主要優(yōu)化的地方是節(jié)點同步區(qū)塊的速度, 因為開啟了多線程簽名,所以在 block 驗證以及 apply_block 時節(jié)省了一定 CPU 時間, 可供其他地方使用。 例如 EOS 現(xiàn)在是當(dāng)線程的,所以當(dāng)你進行 RPC 訪問的時候,如果涉及到數(shù)據(jù)提取,主線程的同步時會暫停的,等待你的操作結(jié)束, 這樣就會影響節(jié)點的同步,所以 get_table_rows API 才會限制 10 ms。 現(xiàn)在同步所需時間減少,降低了節(jié)點既要同步數(shù)據(jù)也要提供 RPC API 的壓力。
當(dāng)大家比較關(guān)注的 CPU 使用并沒有得到改善, 因為多線程簽名無法應(yīng)該在生產(chǎn)區(qū)塊上。所以在生產(chǎn)區(qū)塊時, trx 執(zhí)行所需要的 CPU 時間并不會減少,也就是 CPU 資源的使用并沒有得到改善。
EOS 開發(fā)的小伙伴有技術(shù)問題可以進群討論喲
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/24469.html
摘要:最后一步付款和比特幣以及以太坊不一樣的是,在創(chuàng)建賬戶是有成本的,這也就是為什么我們需要一個賬戶才能創(chuàng)建賬戶的原因找個人來買單。 之前我們學(xué)習(xí)了如何編譯EOS程序,以及如何連接到EOS主網(wǎng),接下來我們要談一談大家最關(guān)心的,如何創(chuàng)建自己的EOS賬戶。 摘要 這篇我們會學(xué)習(xí)如何創(chuàng)建錢包、秘鑰對、主網(wǎng)賬戶,向大家介紹一些實用工具。最重要的是,我們會學(xué)習(xí)到在EOS里,公鑰和賬戶到底有什么區(qū)別。 ...
摘要:適用于最新的前言最近在研究的,但是由于官方文檔的不夠詳盡,新建賬號這一個操作就折騰了一個多星期?;侍觳回撚行娜?,終于調(diào)通了新建賬號,代幣轉(zhuǎn)賬也輕松解決。 適用于最新的 EOS Dawn 4.0/4.1 前言 最近在研究 EOS 的 RPC API,但是由于官方API文檔的不夠詳盡,新建賬號(new account)這一個操作就折騰了一個多星期?;侍觳回撚行娜?,終于調(diào)通了新建賬號,代幣轉(zhuǎn)...
摘要:在對一個交易進行簽名時,與之間會發(fā)生交互。錢包通過將鎖定的鍵值本地化存儲的方式,實現(xiàn)以安全的方式活動簽名。表示已解鎖,創(chuàng)建一個錢包默認是解鎖狀態(tài)錢包必須是狀態(tài)。自定義命名權(quán)限這些權(quán)限可用于進一步擴展帳戶管理。 account 介紹 帳戶是授權(quán)的集合,存儲在區(qū)塊鏈上,用于標(biāo)識發(fā)送方/接收方。它具有靈活的授權(quán)結(jié)構(gòu),允許根據(jù)權(quán)限的配置方式由個人或一組個人擁有。向區(qū)塊鏈發(fā)送或接收有效交易需要一...
摘要:的跟其他區(qū)塊鏈項目是類似的,都是一個基本功能本地儲存密鑰,僅此而已。公網(wǎng)上線后,一定要將存有密鑰的加密,并且將文件單獨備份好。字面意思是賬戶,但我覺得有個概念更適合法人。代幣就是由持有的。對于權(quán)限,則需要列表里至少兩個賬戶的授權(quán)才能行使。 如果你曾經(jīng)嘗試在本地運行 EOS 測試節(jié)點,會發(fā)現(xiàn)編譯、運行并不是特別復(fù)雜,但官方教程里兩個概念很容易把人搞暈: Account(賬戶) 和 Wal...
摘要:,調(diào)用函數(shù),重置標(biāo)志位為,計時器關(guān)閉,打印關(guān)閉提示日志。設(shè)定計時器的異步定時任務(wù),任務(wù)體直接調(diào)用函數(shù),對函數(shù)的返回值進行處理,如果有報錯信息一般是服務(wù)中止則調(diào)用函數(shù)關(guān)閉插件。 原文鏈接:醒者呆的博客園,https://www.cnblogs.com/Evswa... 本文內(nèi)容本屬于《【精解】EOS TPS 多維實測》的內(nèi)容,但由于在編寫時篇幅過長,所以我決定將這一部分單獨成文撰寫,以便...
閱讀 2659·2021-10-11 10:58
閱讀 1254·2021-09-29 09:34
閱讀 1660·2021-09-26 09:46
閱讀 3906·2021-09-22 15:31
閱讀 801·2019-08-30 15:54
閱讀 1532·2019-08-30 13:20
閱讀 1312·2019-08-30 13:13
閱讀 1556·2019-08-26 13:52