成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Derek解讀Bytom源碼-孤塊管理

Donne / 1343人閱讀

摘要:此時節(jié)點將放入到孤塊管理緩存池中,等待彼此的父塊。判斷當前塊是否存在于區(qū)塊鏈上或是否存在孤塊緩存池中,如果存在則返回。比如當前區(qū)塊高度為,則在孤塊緩存池中查詢是否有區(qū)塊高度為的區(qū)塊。

作者:Derek

簡介

Github地址:https://github.com/Bytom/bytom

Gitee地址:https://gitee.com/BytomBlockc...

本章介紹bytom代碼孤塊管理

作者使用MacOS操作系統(tǒng),其他平臺也大同小異

Golang Version: 1.8

孤塊介紹 什么是孤塊

當節(jié)點收到了一個有效的區(qū)塊,而在現有的主鏈中卻未找到它的父區(qū)塊,那么這個區(qū)塊被認為是“孤塊”。父區(qū)塊是指當前區(qū)塊的PreviousBlockHash字段指向上一區(qū)塊的hash值。

接收到的孤塊會被存儲在孤塊池中,直到它們的父區(qū)塊被節(jié)點收到。一旦收到了父區(qū)塊,節(jié)點就會將孤塊從孤塊池中取出,并且連接到它的父區(qū)塊,讓它作為區(qū)塊鏈的一部分。

孤塊出現的原因

當兩個或多個區(qū)塊在很短的時間間隔內被挖出來,節(jié)點有可能會以不同的順序接收到它們,這個時候孤塊現象就會出現。

我們假設有三個高度分別為100、101、102的塊,分別以102、101、100的顛倒順序被節(jié)點接收。此時節(jié)點將102、101放入到孤塊管理緩存池中,等待彼此的父塊。當高度為100的區(qū)塊被同步進來時,會被驗證區(qū)塊和交易,然后存儲到區(qū)塊鏈上。這時會對孤塊緩存池進行遞歸查詢,根據高度為100的區(qū)塊找到101的區(qū)塊并存儲到區(qū)塊鏈上,再根據高度為101的區(qū)塊找到102的區(qū)塊并存儲到區(qū)塊鏈上。

孤塊源碼分析 孤塊管理緩存池結構體

protocol/orphan_manage.go

type OrphanManage struct {
    orphan      map[bc.Hash]*types.Block
    prevOrphans map[bc.Hash][]*bc.Hash
    mtx         sync.RWMutex
}

func NewOrphanManage() *OrphanManage {
    return &OrphanManage{
        orphan:      make(map[bc.Hash]*types.Block),
        prevOrphans: make(map[bc.Hash][]*bc.Hash),
    }
}

orphan 存儲孤塊,key為block hash,value為block結構體

prevOrphans 存儲孤塊的父塊

mtx 互斥鎖,保護map結構在多并發(fā)讀寫狀態(tài)下保持數據一致

添加孤塊到緩存池
func (o *OrphanManage) Add(block *types.Block) {
    blockHash := block.Hash()
    o.mtx.Lock()
    defer o.mtx.Unlock()

    if _, ok := o.orphan[blockHash]; ok {
        return
    }

    o.orphan[blockHash] = block
    o.prevOrphans[block.PreviousBlockHash] = append(o.prevOrphans[block.PreviousBlockHash], &blockHash)

    log.WithFields(log.Fields{"hash": blockHash.String(), "height": block.Height}).Info("add block to orphan")
}

當一個孤塊被添加到緩存池中,還需要記錄該孤塊的父塊hash。用于父塊hash的查詢

查詢孤塊和父孤塊
func (o *OrphanManage) Get(hash *bc.Hash) (*types.Block, bool) {
    o.mtx.RLock()
    block, ok := o.orphan[*hash]
    o.mtx.RUnlock()
    return block, ok
}

func (o *OrphanManage) GetPrevOrphans(hash *bc.Hash) ([]*bc.Hash, bool) {
    o.mtx.RLock()
    prevOrphans, ok := o.prevOrphans[*hash]
    o.mtx.RUnlock()
    return prevOrphans, ok
}
刪除孤塊
func (o *OrphanManage) Delete(hash *bc.Hash) {
    o.mtx.Lock()
    defer o.mtx.Unlock()
    block, ok := o.orphan[*hash]
    if !ok {
        return
    }
    delete(o.orphan, *hash)

    prevOrphans, ok := o.prevOrphans[block.PreviousBlockHash]
    if !ok || len(prevOrphans) == 1 {
        delete(o.prevOrphans, block.PreviousBlockHash)
        return
    }

    for i, preOrphan := range prevOrphans {
        if preOrphan == hash {
            o.prevOrphans[block.PreviousBlockHash] = append(prevOrphans[:i], prevOrphans[i+1:]...)
            return
        }
    }
}

刪除孤塊的過程中,同時刪除父塊

孤塊處理邏輯

protocol/block.go

func (c *Chain) processBlock(block *types.Block) (bool, error) {
blockHash := block.Hash()
    if c.BlockExist(&blockHash) {
        log.WithFields(log.Fields{"hash": blockHash.String(), "height": block.Height}).Info("block has been processed")
        return c.orphanManage.BlockExist(&blockHash), nil
    }

    if parent := c.index.GetNode(&block.PreviousBlockHash); parent == nil {
        c.orphanManage.Add(block)
        return true, nil
    }

    if err := c.saveBlock(block); err != nil {
        return false, err
    }

    bestBlock := c.saveSubBlock(block)
    // ...
}    

processBlock函數處理block塊加入區(qū)塊鏈上之前的過程。

c.BlockExist判斷當前block塊是否存在于區(qū)塊鏈上或是否存在孤塊緩存池中,如果存在則返回。

c.index.GetNode判斷block塊的父節(jié)點是否存在。如果在現有的主鏈中卻未找到它的父區(qū)塊則將block塊添加到孤塊緩存池。

c.saveBlock走到了這一步說明,block父節(jié)點是存在于區(qū)塊鏈,則將block塊存儲到區(qū)塊鏈。該函數會驗證區(qū)塊和交易有效性。

saveSubBlock 代碼如下:

func (c *Chain) saveSubBlock(block *types.Block) *types.Block {
    blockHash := block.Hash()
    prevOrphans, ok := c.orphanManage.GetPrevOrphans(&blockHash)
    if !ok {
        return block
    }

    bestBlock := block
    for _, prevOrphan := range prevOrphans {
        orphanBlock, ok := c.orphanManage.Get(prevOrphan)
        if !ok {
            log.WithFields(log.Fields{"hash": prevOrphan.String()}).Warning("saveSubBlock fail to get block from orphanManage")
            continue
        }
        if err := c.saveBlock(orphanBlock); err != nil {
            log.WithFields(log.Fields{"hash": prevOrphan.String(), "height": orphanBlock.Height}).Warning("saveSubBlock fail to save block")
            continue
        }

        if subBestBlock := c.saveSubBlock(orphanBlock); subBestBlock.Height > bestBlock.Height {
            bestBlock = subBestBlock
        }
    }
    return bestBlock
}

saveSubBlock 在孤塊緩存池中查詢是否存在當前區(qū)塊的下一個區(qū)塊。比如當前區(qū)塊高度為100,則在孤塊緩存池中查詢是否有區(qū)塊高度為101的區(qū)塊。如果存在則將101區(qū)塊存儲到區(qū)塊鏈并從孤塊緩存池中刪除該區(qū)塊。

saveSubBlock是一個遞歸函數的實現。目的是為了尋找最深葉子節(jié)點的遞歸方式。比如當前區(qū)塊高度為100的,遞歸查詢出高度為99、98、97等高度的區(qū)塊。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://systransis.cn/yun/24244.html

相關文章

  • Derek解讀Bytom源碼-Api Server接口服務

    摘要:首先讀取請求內容,解析請求,接著匹配相應的路由項,隨后調用路由項的回調函數來處理。每一個路由項由請求方法和回調函數組成將監(jiān)聽地址作為參數,最終執(zhí)行開始服務于外部請求創(chuàng)建對象首先,實例化對象。我們可以看到一條項由和對應的回調函數組成。 作者:Derek 簡介 Github地址:https://github.com/Bytom/bytom Gitee地址:https://gitee.com...

    GitCafe 評論0 收藏0
  • Derek解讀Bytom源碼-持久化存儲LevelDB

    摘要:函數總共操作有兩步從緩存中查詢值,如果查到則返回如果為從緩存中查詢到則回調回調函數?;卣{函數會將從磁盤上獲得到塊信息存儲到緩存中并返回該塊的信息?;卣{函數實際上調取的是下的,它會從磁盤中獲取信息并返回。 作者:Derek 簡介 Github地址:https://github.com/Bytom/bytom Gitee地址:https://gitee.com/BytomBlockc......

    Eminjannn 評論0 收藏0
  • Derek解讀Bytom源碼分析-持久化存儲LevelDB

    摘要:函數總共操作有兩步從緩存中查詢值,如果查到則返回如果為從緩存中查詢到則回調回調函數?;卣{函數會將從磁盤上獲得到塊信息存儲到緩存中并返回該塊的信息?;卣{函數實際上調取的是下的,它會從磁盤中獲取信息并返回。 簡介 Github地址:https://github.com/Bytom/bytom Gitee地址:https://gitee.com/BytomBlockc... 本章介紹Dere...

    GitChat 評論0 收藏0
  • Derek解讀Bytom源碼-啟動與停止

    摘要:只有當觸發(fā)了或才能終止進程退出。退出時執(zhí)行如下操作會將挖礦功能停止,網絡停止等操作。 作者:Derek 簡介 Github地址:https://github.com/Bytom/bytom Gitee地址:https://gitee.com/BytomBlockc... 本章介紹bytom代碼啟動、節(jié)點初始化、及停止的過程 作者使用MacOS操作系統(tǒng),其他平臺也大同小異Golang V...

    Godtoy 評論0 收藏0
  • Derek解讀Bytom源碼-P2P網絡 地址簿

    摘要:作者簡介地址地址本章介紹代碼網絡中地址簿作者使用操作系統(tǒng),其他平臺也大同小異介紹用于存儲網絡中保留最近的對端節(jié)點地址在下,默認的地址簿路徑存儲在地址簿格式地址類型在中存儲的地址有兩種標識新地址,不可靠地址未成功連接過。 作者:Derek 簡介 Github地址:https://github.com/Bytom/bytom Gitee地址:https://gitee.com/BytomB...

    Kahn 評論0 收藏0

發(fā)表評論

0條評論

Donne

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<