摘要:在每個(gè)交易中,我們都會(huì)看到和這個(gè)參數(shù)有什么作用呢。先講下它的大致作用,再來(lái)對(duì)代碼進(jìn)行分析。這是白皮書(shū)對(duì)這個(gè)參數(shù)的作用描述他是用來(lái)防止有不包含區(qū)塊引用的交易被重放到某個(gè)分叉上,這樣能避免不是該分叉的區(qū)塊被添加到該分叉。
在每個(gè) trx 交易中,我們都會(huì)看到 ref_block_num 和 ref_block_prefix, 這2個(gè)參數(shù)有什么作用呢。
先講下它的大致作用,再來(lái)對(duì)代碼進(jìn)行分析。
這是白皮書(shū)對(duì)這2個(gè)參數(shù)的作用描述
Transaction as Proof of Stake (TaPoS) The EOS.IO software requires every transaction to include part of the hash of a recent block header. This hash serves two purposes: 1. prevents a replay of a transaction on forks that do not include the referenced block; and 2. signals the network that a particular user and their stake are on a specific fork. Over time all users end up directly confirming the blockchain which makes it difficult to forge counterfeit chains as the counterfeit would not be able to migrate transactions from the legitimate chain. 1. 他是用來(lái)防止有不包含區(qū)塊引用的交易被重放到某個(gè)分叉上, 這樣能避免不是該分叉的區(qū)塊被添加到該分叉。 2. 告訴用戶該塊是在哪個(gè)分支上面。
這樣做有什么作用呢?
假設(shè)現(xiàn)在有2個(gè)用戶 A 和 B, B 叫 A 說(shuō)你轉(zhuǎn) 2 個(gè) EOS 給我, 我就送你 100 個(gè) LIVE,A 說(shuō)好啊。 然后 A 就轉(zhuǎn) 2 個(gè) EOS 給 B 了, 這個(gè)時(shí)候 A 的區(qū)塊 a 還不是不可逆狀態(tài), 如果此時(shí) B 轉(zhuǎn)給 A 100 個(gè) LIVE, 要是 區(qū)塊 a 被回滾掉了怎么辦,那么 B 就白白給了 A 100 個(gè) LIVE 了。 這時(shí)候 ref-block 的作用就體現(xiàn)了,如果區(qū)塊 a 被回滾了,那么 B 轉(zhuǎn)給 A 100 個(gè) LIVE 的區(qū)塊 b 也會(huì)被丟棄掉。 所以 當(dāng)區(qū)塊 b ref-block 是 區(qū)塊 a 的時(shí)候,只有 區(qū)塊 a 被成功打包了, 區(qū)塊 b 才會(huì)被成功打包。
所以很顯然, 這兩個(gè)參數(shù)是為了讓鏈更穩(wěn)固,也讓用戶交易更安全。
先看下 transaction_header 對(duì)這兩個(gè)字段的描述。
struct transaction_header { // ... // 可以指定 head_block_num - 0xffff ~ head_block_num 之間的塊。 uint16_t ref_block_num = 0U; ///< specifies a block num in the last 2^16 blocks. // block_id 的按 32 bits分割的第二個(gè)部分,也就是 block_id._hash[1]; uint32_t ref_block_prefix = 0UL; ///< specifies the lower 32 bits of the blockid at // ... };
再來(lái)看下該參數(shù)如何被驗(yàn)證。
// 在 trx 初始化的時(shí)候便回去驗(yàn)證 void transaction_context::init_for_input_trx( uint64_t packed_trx_unprunable_size, uint64_t packed_trx_prunable_size, uint32_t num_signatures, bool skip_recording ) { //... if (!control.skip_trx_checks()) { control.validate_expiration(trx); control.validate_tapos(trx); control.validate_referenced_accounts(trx); } //... } void controller::validate_tapos( const transaction& trx )const { try { const auto& tapos_block_summary = db().get((uint16_t)trx.ref_block_num); //Verify TaPoS block summary has correct ID prefix, and that this block"s time is not past the expiration EOS_ASSERT(trx.verify_reference_block(tapos_block_summary.block_id), invalid_ref_block_exception, "Transaction"s reference block did not match. Is this transaction from a different fork?", ("tapos_summary", tapos_block_summary)); } FC_CAPTURE_AND_RETHROW() } bool transaction_header::verify_reference_block( const block_id_type& reference_block )const { return ref_block_num == (decltype(ref_block_num))fc::endian_reverse_u32(reference_block._hash[0]) && ref_block_prefix == (decltype(ref_block_prefix))reference_block._hash[1]; }
從 block_summary_object 獲取的 block 數(shù)據(jù)拿來(lái)跟 ref-block 的, 很奇怪為什么不直接用 get_block 那種方式取 block 的信息呢? 這樣不用維護(hù)多一個(gè)多索引容器,而且還能獲取全部的 block 。 來(lái)看看 block_summary_object 是如何創(chuàng)建和維護(hù)的。
// libraries/chain/include/eosio/chain/block_summary_object.hpp class block_summary_object : public chainbase::object{ OBJECT_CTOR(block_summary_object) id_type id; block_id_type block_id; }; struct by_block_id; using block_summary_multi_index = chainbase::shared_multi_index_container< block_summary_object, indexed_by< ordered_unique , BOOST_MULTI_INDEX_MEMBER(block_summary_object, block_summary_object::id_type, id)> // ordered_unique , BOOST_MULTI_INDEX_MEMBER(block_summary_object, block_id_type, block_id)> > >; // 創(chuàng)建了 id 從 0 ~ 65535 的數(shù)據(jù) void contoller_impl::initialize_database() { // Initialize block summary index for (int i = 0; i < 0x10000; i++) db.create ([&](block_summary_object&) {}); // ... } // 每次添加新的區(qū)塊的時(shí)候都回去更新 block_summary_object 的 索引表 void contoller_impl::finalize_block() { // ... auto p = pending->_pending_block_state; p->id = p->header.id(); create_block_summary(p->id); } FC_CAPTURE_AND_RETHROW() } void create_block_summary(const block_id_type& id) { auto block_num = block_header::num_from_id(id); // 從這里可以看出 block_summary_object 的 id 永遠(yuǎn)都是 0 ~ 65535。也就是說(shuō)它只維護(hù) head_block_num - 0xffff ~ head_block_num 的塊, 你 ref-block 只能是這個(gè)區(qū)間的塊, 如果 ref 更早的 block 就會(huì)驗(yàn)證出錯(cuò)。 auto sid = block_num & 0xffff; db.modify( db.get (sid), [&](block_summary_object& bso ) { bso.block_id = id; }); }
cleos 在 push transaction 的時(shí)候默認(rèn)的 ref-block 是取 last_irreversible_block ,當(dāng)head_block_num 跟 lib_num 相差超出 0xffff 個(gè)塊的時(shí)候就會(huì)出現(xiàn)該錯(cuò)誤:
Error 3040007: Invalid Reference Block
Ensure that the reference block exist in the blockchain!
Error Details:
Transaction"s reference block did not match. Is this transaction from a different fork?
如果你的私鏈出現(xiàn)問(wèn)題,檢查你鏈上有沒(méi) 2/3 個(gè) BP 在出塊,如果沒(méi)有則是因?yàn)闆](méi)確認(rèn)塊,導(dǎo)致 head_block 和 lib 之間超過(guò)了 0xffff 個(gè)塊而導(dǎo)致該錯(cuò)誤。
結(jié)論: ref-block 的主要作用從白皮書(shū)可以看出,它是為了建立一條難以造假的鏈, 因?yàn)槠渌溸`法從 合法鏈鏈直接遷移交易,只能添加交易。每個(gè) block 都會(huì) ref-block 前面的數(shù)據(jù), 你也無(wú)法直接 ref-block 的早期的塊,因?yàn)橹荒?ref-block 只能是從 head_block_num - 0xffff ~ head_block_num, 像比特幣,只要你算力足夠,你從第一個(gè)塊重新建造一條鏈都可以。 并且他告訴用戶當(dāng)前交易是在哪個(gè)分叉上, 這樣用戶可以根據(jù)交易需要在哪條分叉上成功來(lái)指定分叉, 也就是我們上面舉的例子。
原文: https://eos.live/detail/17094
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/24390.html
摘要:以太坊背后的主要人物是。以太坊通過(guò)在區(qū)塊鏈上引入智能合約,徹底改變了加密世界。以太坊使用名為以太坊虛擬機(jī)的虛擬機(jī)執(zhí)行其智能合約。以太坊最終將利用協(xié)議轉(zhuǎn)向權(quán)益證明。截至目前,以太坊在可擴(kuò)展性方面都失敗了。 不同的區(qū)塊鏈智能合約和區(qū)塊鏈技術(shù)現(xiàn)在風(fēng)靡一時(shí)。越來(lái)越多的人出于某種原因試圖進(jìn)入這個(gè)神奇的世界。如果你是這項(xiàng)技術(shù)的新手并正在尋找基于區(qū)塊鏈的開(kāi)發(fā)平臺(tái)的快速入門,那么本指南非常適合你。我們...
前言 未來(lái)的公司形態(tài)會(huì)不斷地演化,去中心化,分布式,強(qiáng)化合作,適應(yīng)變化,直到徹底地被網(wǎng)絡(luò)化。終極公司的形式將會(huì)變得與生物體相同,無(wú)縫地集成到生態(tài)圈中,成為其中的一個(gè)環(huán)節(jié)?!?凱文·凱利《失控》 小劇場(chǎng) 小二: 糖糖,我愛(ài)你哦~ 糖糖: 你騙人!男人的話能信母豬能上樹(shù)。 小二: 我可以向全世界證明,我說(shuō)的是真的~ 糖糖: 那你怎么證明啊~ 小二: 我可以用 區(qū)塊鏈 寫(xiě)下 糖糖我愛(ài)你哦~...
摘要:比特幣是第一個(gè)區(qū)塊鏈應(yīng)用,同時(shí)也是最著名的應(yīng)用之一,它所使用的共識(shí)機(jī)制就是。區(qū)塊鏈系統(tǒng)的參與者鎖定他們?cè)谠搮^(qū)塊鏈上持有的虛擬資產(chǎn)或,他們會(huì)簽署消息以達(dá)成一致意見(jiàn)。 一.POW(Proof Of Work) Proof Of Work,也就是工作量證明。工作量證明系統(tǒng)(或者說(shuō)協(xié)議、函數(shù)),是一種應(yīng)對(duì)拒絕服務(wù)攻擊和其他服務(wù)濫用的經(jīng)濟(jì)對(duì)策。它要求發(fā)起者進(jìn)行一定量的運(yùn)算,也就意味著需要消耗計(jì)算...
摘要:在以太坊出現(xiàn)后,進(jìn)入了第二階段。以太坊可以被視作區(qū)塊鏈?zhǔn)澜珙愃朴诤偷牡讓硬僮飨到y(tǒng)。通證經(jīng)濟(jì)的設(shè)計(jì)方向模式的組織,是天然的生態(tài)型組織。區(qū)塊鏈時(shí)代的生態(tài)組織,大致可以分成這幾種類型。 簡(jiǎn)介 ??區(qū)塊鏈最重要的應(yīng)用就是將實(shí)物價(jià)值或虛擬資產(chǎn)映射成鏈上Token,通過(guò)資產(chǎn)上鏈,實(shí)現(xiàn)跨地域、低成本的進(jìn)行資產(chǎn)交易與轉(zhuǎn)移,本質(zhì)上是權(quán)益再分配,核心是提高激勵(lì)性和效益。??很多人把Token譯為代幣,我更...
摘要:所以想要實(shí)現(xiàn)真正實(shí)用的智能合約平臺(tái),就要脫離比特幣系統(tǒng)的架構(gòu),尋找新的系統(tǒng)組織形式。比特幣和以太坊之所以設(shè)計(jì)了手續(xù)費(fèi)機(jī)制,就是防止大量垃圾交易使得系統(tǒng)擁堵。 區(qū)塊鏈系統(tǒng)中,去中心化程度與效率之間天然地存在矛盾關(guān)系。 如果區(qū)塊鏈智能合約系統(tǒng)想追求類似比特幣的去中心化程度,理論上效率就會(huì)大打折扣?,F(xiàn)實(shí)也是這樣的:比特幣每秒鐘只能處理7筆左右的交易,每一筆交易要用至少30分鐘才能確認(rèn),這種效...
閱讀 1986·2021-11-25 09:43
閱讀 3763·2021-11-24 10:32
閱讀 1266·2021-10-13 09:39
閱讀 2449·2021-09-10 11:24
閱讀 3424·2021-07-25 21:37
閱讀 3545·2019-08-30 15:56
閱讀 930·2019-08-30 15:44
閱讀 1517·2019-08-30 13:18