星鉴网>IPFS热点>【Filecoin源码仓库全解析】第三章(下):存储提供方(矿工)的配置操作

【Filecoin源码仓库全解析】第三章(下):存储提供方(矿工)的配置操作

2019/2/27 15:00:11 2304人阅读

【导读】 本篇,我们将深度剖析存储矿工对象的源码结构,方便大家从根本上理解矿工的事务,并对存储矿工的生命周期做了一个总结。

不好意思,这篇开头就加了点八卦:

        

本来是不太想说这事的…


从18年看到现在,圈里的朋友和友商互相吐槽乃至攻击的事情愈演愈烈…最近还闹得比较大。


这里说两句:区块链存储在国内是一个刚诞生的新兴领域,探索阶段有错误真的很常见,至少大家都愿意花精力去努力盘活这个行业。


今天小编看到一句很深刻的话: 强者互持,弱者互撕,希望大家能意识到:因为同行者,你的存在和你所做的事情才有意义…



 好了,回归正题,欢迎大家来到第三章的下篇,经过上篇 《【Filecoin源码仓库全解析】第三章(上):存储提供方(矿工)的配置操作 》的内容阅读后,我们应该能会对Filecoin存储市场机制和市场中的各角色职能有了更深刻的认知,并且可以配置自身节点角色,成为存储提供方(矿工),参与挖矿了。


上一篇,我们讲解了如何在工程上申请存储矿工角色,本篇,我们将深度剖析存储矿工对象的源码结构,方便大家从根本上理解矿工的事务,并对存储矿工的生命周期做了一个总结。


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.2StorageMinerState


存储矿工会有自己的链上状态,仅在创建新区块时更新,并全网同步可追溯,可以理解为这是Filecoin网络为矿工们所维护的一组状态账本:


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:地址是创建矿工的地址,支付抵押品等。




小编认为需要这样区别和设计的原因归结为八个字:各司其职,安全第一。


 例如: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也非常重视矿工的利益。


参考文献:


https://github.com/filecoin-project/specs/blob/master/mining.md

https://github.com/filecoin-project/specs/blob/master/expected-consensus.md



本章是一个基础铺垫,深挖了底层的原理,这是为了让我们对Filecoin系统的理解,不光只停留在工程指令集的操作上面。


我们将在下一章《【Filecoin源码仓库全解析】第四章(下):存储需求方的配置操作》中重点介绍存储需求方(用户)的配置操作,并反过来验证第三章中存储矿工后续挖取新块的过程,帮助大家融会贯通,并在工程上验证整个挖矿行为的生命周期。



107

参与讨论

登录后参加评论......

全部评论 0

作者

返回顶部