摘要:區(qū)塊多線程簽名改動(dòng)同步區(qū)塊時(shí)進(jìn)行多線程簽名,過(guò)程中依然是單線程簽名。代碼解析塊簽名因?yàn)椴贿m用多線程簽名,所以依舊沿用之前的簽名代碼,而同步則使用了新的部分。當(dāng)大家比較關(guān)注的使用并沒有得到改善,因?yàn)槎嗑€程簽名無(wú)法應(yīng)該在生產(chǎn)區(qū)塊上。
昨天早上,EOS 1.5.0 release 版本發(fā)布了。這次比較大改動(dòng)點(diǎn)是在多線程簽名上面。它將同步區(qū)塊時(shí)的 block 簽名驗(yàn)證和 trx 簽名驗(yàn)證都使用多線程簽名驗(yàn)證,來(lái)節(jié)省同步所需要的時(shí)間, 但是生產(chǎn)區(qū)塊所需要的成本是不變的,但為什么生產(chǎn)區(qū)塊成本不變呢。接下來(lái)介紹一下具體的改動(dòng)。 區(qū)塊多線程簽名改動(dòng):同步區(qū)塊時(shí)進(jìn)行多線程簽名, replay 過(guò)程中依然是單線程簽名。因?yàn)閰^(qū)塊同步時(shí)需要回滾 pending block 的 trx 操作, 這塊時(shí)間剛好可以用來(lái)并行處理簽名, 但 replay 的時(shí)候沒有這一步,即使用多線程簽名也無(wú)法節(jié)省時(shí)間,反而會(huì)讓主線程阻塞等待異步結(jié)果返回。 trx 多線程簽名改動(dòng):同步區(qū)塊以及 replay 過(guò)程都會(huì)進(jìn)行多線程簽名, 因?yàn)橛卸鄠€(gè) trx 要執(zhí)行,所以執(zhí)行 trx 的時(shí)間可以供其他 trx 的簽名并行進(jìn)行。 但生產(chǎn)區(qū)塊的時(shí)候無(wú)法使用,因?yàn)閳?zhí)行 BP 接受到一個(gè) 廣播的 trx 就立馬去執(zhí)行了,執(zhí)行完之后才回去接受下一個(gè)廣播 trx, 所以無(wú)法使用多線程簽名。代碼解析: 塊簽名:
因?yàn)?replay 不適用多線程簽名, 所以 replay 依舊沿用之前的簽名代碼, 而同步則使用了新的部分。
// producer_plugin.cpp 接受到廣播塊 void on_incoming_block(const signed_block_ptr& block) { // ... // start processing of block // 調(diào)用一個(gè)線程去對(duì)塊進(jìn)行簽名驗(yàn)證 auto bsf = chain.create_block_state_future( block ); // abort the pending block // 回滾掉 pending block 的執(zhí)行 trx, 這段時(shí)間剛好可以用來(lái)并發(fā)執(zhí)行區(qū)塊簽名驗(yàn)證 chain.abort_block(); // ... } // controller.cpp std::future交易簽名create_block_state_future( const signed_block_ptr& b ) { //驗(yàn)證區(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) ); // 進(jìn)行多線程簽名 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 { // 獲取驗(yàn)證結(jié)果, 當(dāng)區(qū)塊驗(yàn)證失敗時(shí)會(huì)拋出異常,中止 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( ) }
從改動(dòng)得知,apply_block 的時(shí)候才會(huì)啟動(dòng)交易的多線程驗(yàn)證簽名,而 bcast_transaction 則不會(huì),因?yàn)椴]有多余的動(dòng)作可以與驗(yàn)證簽名并行。
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); // 按順序啟動(dòng)每個(gè) trx 的多線程驗(yàn)證簽名,生產(chǎn)對(duì)應(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í)行時(shí)獲取簽名返回的公鑰 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)沒開啟多線程簽名時(shí), 直接驗(yàn)證生成對(duì)應(yīng)公鑰 signing_keys = std::make_pair( chain_id, trx.get_signature_keys( chain_id )); } return signing_keys->second; }
從這次的改動(dòng)可以看出主要優(yōu)化的地方是節(jié)點(diǎn)同步區(qū)塊的速度, 因?yàn)殚_啟了多線程簽名,所以在 block 驗(yàn)證以及 apply_block 時(shí)節(jié)省了一定 CPU 時(shí)間, 可供其他地方使用。 例如 EOS 現(xiàn)在是當(dāng)線程的,所以當(dāng)你進(jìn)行 RPC 訪問的時(shí)候,如果涉及到數(shù)據(jù)提取,主線程的同步時(shí)會(huì)暫停的,等待你的操作結(jié)束, 這樣就會(huì)影響節(jié)點(diǎn)的同步,所以 get_table_rows API 才會(huì)限制 10 ms。 現(xiàn)在同步所需時(shí)間減少,降低了節(jié)點(diǎn)既要同步數(shù)據(jù)也要提供 RPC API 的壓力。
當(dāng)大家比較關(guān)注的 CPU 使用并沒有得到改善, 因?yàn)槎嗑€程簽名無(wú)法應(yīng)該在生產(chǎn)區(qū)塊上。所以在生產(chǎn)區(qū)塊時(shí), trx 執(zhí)行所需要的 CPU 時(shí)間并不會(huì)減少,也就是 CPU 資源的使用并沒有得到改善。
EOS 開發(fā)的小伙伴有技術(shù)問題可以進(jìn)群討論喲
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/24469.html
摘要:最后一步付款和比特幣以及以太坊不一樣的是,在創(chuàng)建賬戶是有成本的,這也就是為什么我們需要一個(gè)賬戶才能創(chuàng)建賬戶的原因找個(gè)人來(lái)買單。 之前我們學(xué)習(xí)了如何編譯EOS程序,以及如何連接到EOS主網(wǎng),接下來(lái)我們要談一談大家最關(guān)心的,如何創(chuàng)建自己的EOS賬戶。 摘要 這篇我們會(huì)學(xué)習(xí)如何創(chuàng)建錢包、秘鑰對(duì)、主網(wǎng)賬戶,向大家介紹一些實(shí)用工具。最重要的是,我們會(huì)學(xué)習(xí)到在EOS里,公鑰和賬戶到底有什么區(qū)別。 ...
摘要:適用于最新的前言最近在研究的,但是由于官方文檔的不夠詳盡,新建賬號(hào)這一個(gè)操作就折騰了一個(gè)多星期?;侍觳回?fù)有心人,終于調(diào)通了新建賬號(hào),代幣轉(zhuǎn)賬也輕松解決。 適用于最新的 EOS Dawn 4.0/4.1 前言 最近在研究 EOS 的 RPC API,但是由于官方API文檔的不夠詳盡,新建賬號(hào)(new account)這一個(gè)操作就折騰了一個(gè)多星期?;侍觳回?fù)有心人,終于調(diào)通了新建賬號(hào),代幣轉(zhuǎn)...
摘要:在對(duì)一個(gè)交易進(jìn)行簽名時(shí),與之間會(huì)發(fā)生交互。錢包通過(guò)將鎖定的鍵值本地化存儲(chǔ)的方式,實(shí)現(xiàn)以安全的方式活動(dòng)簽名。表示已解鎖,創(chuàng)建一個(gè)錢包默認(rèn)是解鎖狀態(tài)錢包必須是狀態(tài)。自定義命名權(quán)限這些權(quán)限可用于進(jìn)一步擴(kuò)展帳戶管理。 account 介紹 帳戶是授權(quán)的集合,存儲(chǔ)在區(qū)塊鏈上,用于標(biāo)識(shí)發(fā)送方/接收方。它具有靈活的授權(quán)結(jié)構(gòu),允許根據(jù)權(quán)限的配置方式由個(gè)人或一組個(gè)人擁有。向區(qū)塊鏈發(fā)送或接收有效交易需要一...
摘要:的跟其他區(qū)塊鏈項(xiàng)目是類似的,都是一個(gè)基本功能本地儲(chǔ)存密鑰,僅此而已。公網(wǎng)上線后,一定要將存有密鑰的加密,并且將文件單獨(dú)備份好。字面意思是賬戶,但我覺得有個(gè)概念更適合法人。代幣就是由持有的。對(duì)于權(quán)限,則需要列表里至少兩個(gè)賬戶的授權(quán)才能行使。 如果你曾經(jīng)嘗試在本地運(yùn)行 EOS 測(cè)試節(jié)點(diǎn),會(huì)發(fā)現(xiàn)編譯、運(yùn)行并不是特別復(fù)雜,但官方教程里兩個(gè)概念很容易把人搞暈: Account(賬戶) 和 Wal...
摘要:,調(diào)用函數(shù),重置標(biāo)志位為,計(jì)時(shí)器關(guān)閉,打印關(guān)閉提示日志。設(shè)定計(jì)時(shí)器的異步定時(shí)任務(wù),任務(wù)體直接調(diào)用函數(shù),對(duì)函數(shù)的返回值進(jìn)行處理,如果有報(bào)錯(cuò)信息一般是服務(wù)中止則調(diào)用函數(shù)關(guān)閉插件。 原文鏈接:醒者呆的博客園,https://www.cnblogs.com/Evswa... 本文內(nèi)容本屬于《【精解】EOS TPS 多維實(shí)測(cè)》的內(nèi)容,但由于在編寫時(shí)篇幅過(guò)長(zhǎng),所以我決定將這一部分單獨(dú)成文撰寫,以便...
閱讀 2586·2021-10-11 10:58
閱讀 1169·2021-09-29 09:34
閱讀 1530·2021-09-26 09:46
閱讀 3851·2021-09-22 15:31
閱讀 748·2019-08-30 15:54
閱讀 1472·2019-08-30 13:20
閱讀 1266·2019-08-30 13:13
閱讀 1499·2019-08-26 13:52