utxo
core目前的utxo架構(gòu)邏輯墨林,主要分為三個(gè)模塊:
- 第一類是硬盤上的腰涧,
- 第二類是對(duì)硬盤做的一個(gè)緩存韧掩,
- 第三類才是說mempool里面,交易進(jìn)來(lái)mempool之后窖铡,你后面的交易可以復(fù)用前面的mempool交易里面的utxo疗锐,事實(shí)上,這個(gè)交易是沒有成交的费彼,嚴(yán)格來(lái)講滑臊,稱不上一個(gè)utxo,但是它可以從它父鏈中的out推算出來(lái)箍铲。
當(dāng)一個(gè)交易進(jìn)來(lái)mempool之后雇卷,即使沒有打包,他也是可以產(chǎn)生可花費(fèi)的輸出的颠猴。這就對(duì)mempool有一個(gè)要求关划,當(dāng)我交易來(lái)的時(shí)候,如果我花費(fèi)的txin并不在標(biāo)準(zhǔn)的utxo里面的時(shí)候翘瓮,我需要去mempool里面去尋找贮折,他是不是花的還是沒有打包的交易,如果是资盅,我們需要在mempool中抽象出來(lái)一個(gè)東西调榄,內(nèi)存版的utxo踊赠,區(qū)別于utxo的cache,就是要把所有已經(jīng)進(jìn)入mempool中的out抽象為這個(gè)utxo存到集合中每庆。core將以上三個(gè)view使用繼承關(guān)系筐带,封裝出來(lái),實(shí)現(xiàn)有點(diǎn)復(fù)雜缤灵。
圖示如下:
jiangda:他們可以完全拆分開來(lái)伦籍,如果需要mempool的,我直接就去mempool中去尋找凤价。
根據(jù)上述分析鸽斟,我們可以將utxo模塊進(jìn)行拆分拔创,一部分是utxo集利诺,另一部分是mempool中的邏輯,我們將二者分開處理剩燥。
utxo cache是db utxo的一個(gè)子集慢逾,當(dāng)讀的時(shí)候,先去cache中尋找灭红,cache中沒有再去db中尋找侣滩,寫的時(shí)候,也是先往cache中寫变擒,然后君珠,再刷新到db中。當(dāng)重啟的時(shí)候娇斑,會(huì)把所需要的數(shù)據(jù)從db load進(jìn)cache中策添。
拆分后的邏輯,如下所示:
目前的思路是:coincache和db是一個(gè)邏輯毫缆,我先去coincache中尋找唯竹,找不到再去db中找,如果還是沒找到苦丁,再去coinpool中尋找浸颓,雖然先去查mempool更快,但是每一個(gè)節(jié)點(diǎn)的mempool都一樣旺拉,但是db是最準(zhǔn)的产上,所以只能是先去查cache再去mempool中找。
coinPool是對(duì)mempool的一個(gè)抽象蛾狗,coinCache是對(duì)utxoCache的一個(gè)抽象晋涣。
實(shí)現(xiàn)時(shí),可以封裝兩個(gè)函數(shù) getFromUTXO() 和 getFromMempool() 分別從utxo集和mempool中獲取數(shù)據(jù)淘太。
關(guān)于out設(shè)置為單個(gè)的coin還是數(shù)組的形式的爭(zhēng)論
設(shè)置為一個(gè)coin更符合utxo的設(shè)置邏輯
jiangda:關(guān)于之前數(shù)組的設(shè)計(jì)有一個(gè)重大的bug姻僧,會(huì)把所有內(nèi)存較小的節(jié)點(diǎn)搞掛掉规丽,所以最后都修改為單個(gè)coin的形式。
yujian:如果這個(gè)outpoint已經(jīng)花掉了撇贺,它在持久化的時(shí)候會(huì)獨(dú)立的存儲(chǔ)赌莺,單個(gè)的時(shí)候,只要這個(gè)key沒有松嘶,它是一定不能花的艘狭。
空間換時(shí)間:內(nèi)存和cpu需要舍棄一個(gè),數(shù)組的思路浪費(fèi)內(nèi)存翠订,內(nèi)存的使用效率沒有單個(gè)coin的好巢音,但是確實(shí)比單個(gè)coin的要快。
綜合考慮尽超,使用單個(gè)coin來(lái)實(shí)現(xiàn)官撼。
block
因?yàn)閷懙奖P上的現(xiàn)有數(shù)據(jù),你就必須承認(rèn)似谁,所以block的數(shù)據(jù)結(jié)構(gòu)沒有太大的變化傲绣。
圖示如下:
塊的數(shù)據(jù)同時(shí)會(huì)寫入db和undo文件中,undo文件是用來(lái)恢復(fù)塊的時(shí)候使用的巩踏,類似于mysql的undo log秃诵。
一個(gè)node節(jié)點(diǎn)中可以存儲(chǔ) blockheader 和block,block就是一個(gè)完整的塊塞琼,block header分為三類:
- active
- branch
- orphan
圖示如下:
當(dāng)我接收塊的時(shí)候菠净,我希望是按照上述正常的順序來(lái)接收,但事實(shí)上我是沒有辦法控制我接收的一個(gè)順序的彪杉,可能會(huì)造成下面的錯(cuò)誤的接收順序毅往,假設(shè)我先接收到block 3,那就是一個(gè)orphan在讶,也就是說煞抬,一個(gè)節(jié)點(diǎn)我只能根據(jù)pre hash找到我的父親,但是沒辦法去找到自己的孩子构哺,所以只有當(dāng)block 2進(jìn)來(lái)的時(shí)候革答,我block 3才是有價(jià)值的。
- orphan表示孤塊曙强,孤塊自己本身就是一條鏈残拐。
- branch記錄的是一段時(shí)間內(nèi),所有的塊數(shù)據(jù)碟嘴,它是按照工作量從小到大的順序排列溪食。
- active記錄的是當(dāng)前的激活鏈。
當(dāng)前塊的高度不是拿現(xiàn)在的塊的高度計(jì)算出來(lái)的娜扇,而是拿上一個(gè)塊的height+1計(jì)算出來(lái)的错沃,這樣能夠防止作弊栅组。