【Filecoin源碼倉庫全解析】第三章(下):存儲提供方(礦工)的配置操做

很差意思,這篇加了點八卦:html

原本是不太想說這事的,從18年看到如今,很多見圈裏的朋友和友商互相吐槽乃至攻擊...最近還鬧得比較大。這裏說兩句:區塊鏈存儲在中國是一個剛誕生的新興領域,探索階段有錯誤是常態,至少你們都願意把臉放下地在盤活這個行業git

今天小編看到一句很深入的話:強者互持,弱者互撕,但願你們能意識到:由於同行者,你的存在和你所作的事情纔有意義...github

歡迎你們來到第三章的下篇,通過前章 【Filecoin源碼倉庫全解析】第三章(上):存儲提供方(礦工)的配置操做的內容閱讀後,咱們應該能會對Filecoin存儲市場機制和市場中的各角色職能有了更深入的認知,而且能夠配置自身節點角色,成爲存儲提供方(礦工),參與挖礦了。json

上一篇,咱們講解了如何在工程上申請存儲礦工角色,本篇,咱們將深度剖析存儲礦工對象的源碼結構,方便你們從根本上理解礦工的事務,並對一次挖礦的生命週期作一個總結。安全

3.6 存儲礦工對象剖析

首先,咱們來深度剖析一個存儲礦工對象的源碼結構,這樣便於你們從根本上理解礦工的事務。微信

3.6.1 StorageMinerActor

咱們在鏈上成功註冊一個新的礦工身份後,Filecoin存儲市場Actor(上帝)將調用CreateMiner()方法爲咱們生成一個新的存儲礦工實例對象(StorageMinerActor),並返回其地址,這個新的實例對象結構以下:網絡

type StorageMinerActor interface {
    //礦工向存儲市場發送訂單的方法。
    AddAsk(price TokenAmount, expiry uint64) AskID
    //提交扇區的方法。
    CommitSector(commD, commR, commRStar []byte, proof SealProof) SectorID
    //用於向鏈上提交時空證實的方法,證實礦工已實際存儲了其聲稱的文件。
    SubmitPoSt(p PoSt, faults []FailureSet, recovered SectorSet, doneSet SectorSet)
    // 容許礦工爲網絡提供更多存儲空間的方法
    IncreasePledge(addspace Integer)
    // 若缺少複製證實證據,將用此方法懲罰礦工
    SlashStorageFault()

3.6.2 StorageMinerState

存儲礦工會有本身的鏈上狀態,僅在建立新區塊時更新,並全網同步可追溯,能夠理解爲這是Filecoin網絡爲礦工們所維護的一組狀態帳本:app

type StorageMinerState struct {
    //Owner 是擁有此礦工節點的帳戶地址
    Owner Address
    
    //Worker 是此礦工節點的工做帳號地址
    Worker Address
    
    //PeerID 是應該用於鏈接這個礦工節點的libp2p對等身份
    PeerID peer.ID
    
    //PublicKey是礦工用於對區塊進行簽名的密鑰的公共部分
    PublicKey PublicKey
    
    //PledgeBytes是此礦工提供給網絡的空間量
    PledgeBytes BytesAmount
    
    //被鎖定的抵押金額
    Collateral TokenAmount
    
    //當前抵押金額
    ActiveCollateral TokenAmount
    
    //未提取的抵押金額
    DePledgedCollateral TokenAmount
    
    //提取抵押幣的時間
    DePledgeTime BlockHeight
    
    //Sectors 扇區集合
    Sectors SectorSet
    
    //提交PoSt證實的扇區
    ProvingSet SectorSet
    
    //在上一次PoSt提交期間狀態變動爲「完成」的一組扇區。
    NextDoneSet SectorSet
    
    //礦工所擁有的算力算量
    Power BytesAmount
}

3.6.3 Owner與Worker

存儲礦工角色有兩個不一樣的地址:函數

  • 一個是Worker:負責完成全部事務活動,參與Ask訂單、提交證實,提交新扇區等。
  • 另外一個是Owner:地址是建立礦工的地址,支付抵押品,並得到出塊獎勵。

小編認爲須要這樣區別和設計的緣由歸結爲八個字:各司其職,安全第一post

例如:Owner適合冷存密鑰,安全級別更高,Worker常遷移和變動,安全級別更低。

以下圖所示,咱們能夠在~./filecoin/config.json下分別獲取到worker和Owner的地址數據:

  • Worker => minerAddress
  • Owner => defaultAddress

注意:查詢Ask訂單,選擇交易時必定注意用worker地址來檢索

3.7 存儲礦工的生命週期

畫了一個腦海中的草圖,方便你們理解和記憶:

如圖所示,存儲礦工的生命線主要有四條:

  • 存儲交易
  • 建立區塊
  • 中止挖礦
  • 失責懲罰(WIP)

下面依次來介紹其生命週期中的這幾個過程:

3.7.1 存儲交易

Step1:操做節點參與鏈上身份註冊,提交抵押與存儲容量,成爲一個存儲礦工

Step2:建立Ask訂單,與用戶節點交易。

Step3:密封數據並提交複製證實(PoRep)於鏈上,更新訂單狀態,完成交易,並開啓PoSt證實週期(證實期是礦工必須向網絡提交空間時間證實的固定時間。)

備註:這塊內容能夠繼續深挖,後面有時間考慮單開一章節:與FilecoinProof相關

Step4:存儲礦工收集證實集合,建立PoSt,計算ProveStorage和StoragePower(算力)。

備註:在證實期內,證實集會始終保持一致。在此期間系統增長的任何扇區都將順延至下一個證實期內。

Step5:當礦工完成他們的PoSt時,調用SubmitPoSt將其提交給網絡,並伴隨區塊更新同步狀態。

3.7.2 建立區塊

當經歷完存儲交易的過程後,存儲礦工已經具有了參與建立區塊節點的競選了,選票的生成邏輯以下所示:

//這塊函數體內部邏輯官方提示將改動,就不一一解析了

func IsTicketAWinner(t Ticket, minersPower, totalPower Integer) bool {
    return ToFloat(sha256.Sum(ticket)) * totalPower < minersPower
}

pTipSet := getHeaviestTipSet()

smallestTicket := selectSmallestTicket(pTipSet)

var tickets []Signature
baseTicket := smallestTicket
for {
   
    challenge := sha256.Sum(baseTicket.Bytes())

    postCount := estimator.GetPostCount(chain, pTipSet)

    proof := post.Prove(storage, challenge, postCount)

    ticket := minerPrivKey.Sign(sha256.Sum(proof.Bytes()))
    tickets = append(tickets, ticket)

    totalPower := getTotalPower(pTipSet)
    ourPower := getMinerPower(pTipSet, minerID)

    if IsTicketAWinner(ticket, ourPower, totalPower) {

        return tickets
    } else {

        baseTicket = ticket
    }
}

同時,爲了防止女巫攻擊,選票須要被其餘節點驗證,同時,自身也將驗證其餘節點的選票:

//這塊函數體內部邏輯官方提示將改動,就不一一解析了
func VerifyTicket(b Block) error {

    curTicket := selectSmallestTicket(b.Parents)

    for _, ticket := range b.Tickets {
        challenge := sha256.Sum(curTicket)
        if !VerifyProof(b.Proof, b.Miner, challenge) {
            return "Proof failed to validate"
        }
        pubk := getPublicKeyForMiner(b.Miner)
        if !pubk.VerifySignature(ticket, sha256.Sum(b.Proof.Bytes())) {
            return "Ticket was not a valid signature over the proof"
        }
        curTicket = ticket

    }
    state := getStateTree(b.Parents)
    minersPower := state.getPowerForMiner(b.Miner)
    totalPower := state.getTotalPower()
    if !IsTicketAWinner(curTicket, minersPower, totalPower) {
       return "Ticket was not a winning ticket"
    }
    return nil
}

建立區塊以前,首先要贏得選票,令全部對等節點之間達成一致。這裏涉及到預期(Expected Consensus)共識,簡而言之:

是Filecoin基於拜占庭容錯基礎上的改進版,策略是每一輪裏選舉出來一名或者多名存儲礦工來建立新的區塊,贏選票的可能性和礦工已分配的存儲(即與上文中ProveStorage、StoragePower強相關) 成比例。

備註:這塊內容也能夠繼續深挖,後面有時間考慮單開一章節:與Expected Consensus相關

當你僥倖得到一張優勝選票時,將建立新塊,結構體以下所示:

//這塊函數體內部邏輯官方提示TODO,應該後期改動會比較大

type Block struct {

    Parents []*cid.Cid

    Tickets []Signature

    Proof post.Proof

    Ticket Signature

    MsgRoot *cid.Cid

    ReceiptsRoot *cid.Cid

    StateRoot *cid.Cid

    BlockSig Signature
}

當完成區塊建立以後,隨之而來的是豐厚的上帝獎勵(FIL分發),具體的分發策略也處於WIP狀態,目前測試網階段是1000FIL/Block。

3.7.3 中止挖礦

若是須要中止採礦,礦工必須履行完全部存儲訂單(即:名下全部Ask訂單狀態爲Poster),並在PoSt提交期間將其從證實集中刪除。

以後,可經過客戶端指令調用DePledge()來取回他們的抵押品,並中止挖礦進程。

備註:此過程也會參與鏈上操做。

3.7.4 失責懲罰(WIP)

若是礦工因未能按時提交PoSt而被slashed,他們將失去全部抵押品。

備註:官方仍在Work in Process之中,須要更多社區的建議和討論,目前設置了多種保險和從新驗證機制,可見Filecoin也很是重視礦工的利益。

參考文獻:


本章是一個基礎鋪墊,深挖了底層的原理,這是爲了讓咱們對Filecoin系統的理解,不光只停留在工程指令集的操做上面。

咱們將在下一章《【Filecoin源碼倉庫全解析】第四章(下):存儲需求方的配置操做》中重點介紹存儲需求方(用戶)的配置操做,並反過來驗證第三章中存儲礦工後續挖取新塊的過程,幫助你們融會貫通,並在工程上驗證整個挖礦行爲的生命週期。

本章贊助品牌:

搜搜IPFS:是專一於IPFS生態的垂直媒體。內容涵蓋IPFS的行業資訊、新聞動態、項目評測、人物專訪等。咱們努力爲IPFS用戶們創造更豐富,更有趣,更靠譜的媒體服務,致力於成爲IPFS愛好者服務的媒體。目前已成爲華中區最大、最具影響力的IPFS垂直媒體。

感謝 搜IPFS嘉樂SOHO的原創內容提供支持。

聯繫做者:

本人從業經驗有限,難免有不足之處,歡迎指正和更多討論,可私信微信公衆號:jialesoho,或者加我微信:daijiale6239,若是以爲對您有幫助,能夠幫點擊好看推廣打賞支持噢,感激涕零!

(識別圖中二維碼,關注嘉樂SOHO微信公衆號)

相關文章
相關標籤/搜索