Filecoin的状态机角色

发布时间:2019年02月25日 价值:20000.00 / 共识:24

Filecoin的状态机角色

Filecoin actors的任何实现必须与go-filecoin actor实现完全字节兼容。下面的伪代码试图捕获大部分重要逻辑,但捕获所有细节需要完全嵌入来自go-filecoin的代码,所以目前,它只是信息丰富的伪代码。

该规范决定了在Filecoin状态机中运行的一组参与者。所有类型都在基本类型编码规范中定义。

Storage Market Actor 存储市场角色

  1. type StorageMarketActor struct {
  2. Miners AddressSet
  3. TotalStorage Integer
  4. }

CreateStorageMiner

参数:

  • pubkey PublicKey
  • pledge BytesAmount
  • pid PeerID

Return:Address

  1. func CreateStorageMiner(pubkey PublicKey, pledge BytesAmount, pid PeerID) Address {
  2. if pledge < MinimumPledge {
  3. Fatal("Pledge too low")
  4. }
  5. if msg.Value < MinimumCollateral(pledge) {
  6. Fatal("not enough funds to cover required collateral")
  7. }
  8. newminer := VM.CreateActor(MinerActor, msg.Value, pubkey, pledge, pid)
  9. self.Miners.Add(newminer)
  10. return newminer
  11. }

SlashConsensusFault

参数:

  • block1 BlockHeader
  • block2 BlockHeader

Return:None

  1. func SlashConsensusFault(block1, block2 BlockHeader) {
  2. if block1.Height != block2.Height {
  3. Fatal("cannot slash miner for blocks of differing heights")
  4. }
  5. if !ValidateSignature(block1.Signature) || !ValidateSignature(block2.Signature) {
  6. Fatal("Invalid blocks")
  7. }
  8. if AuthorOf(block1) != AuthorOf(block2) {
  9. Fatal("blocks must be from the same miner")
  10. }
  11. miner := AuthorOf(block1)
  12. // Burn all of the miners collateral
  13. miner.BurnCollateral()
  14. // TODO: Some of the slashed collateral should be paid to the slasher
  15. // Remove the miner from the list of network miners
  16. self.Miners.Remove(miner)
  17. self.UpdateStorage(-1 * miner.Power)
  18. // Now delete the miner (maybe this is a bit harsh, but i'm okay with it for now)
  19. miner.SelfDestruct()
  20. }

UpdateStorage

参数:

  • delta Integer

Return:None

  1. func UpdateStorage(delta Integer) {
  2. if !self.Miners.Has(msg.From) {
  3. Fatal("update storage must only be called by a miner actor")
  4. }
  5. self.TotalStorage += delta
  6. }

GetTotalStorage

参数:None
Return:Integer

  1. func GetTotalStorage() Integer {
  2. return self.TotalStorage
  3. }

存储矿工角色

  1. type StorageMiner struct {
  2. // Owner is the address of the account that owns this miner
  3. Owner Address
  4. // Worker is the address of the worker account for this miner
  5. Worker Address
  6. // PeerID is the libp2p peer identity that should be used to connect
  7. // to this miner
  8. PeerID peer.ID
  9. // PublicKey is the public portion of the key that the miner will use to sign blocks
  10. PublicKey PublicKey
  11. // PledgeBytes is the amount of space being offered by this miner to the network
  12. PledgeBytes BytesAmount
  13. // Collateral is locked up filecoin the miner has available to commit to storage.
  14. // When miners commit new sectors, tokens are moved from here to 'ActiveCollateral'
  15. // The sum of collateral here and in activecollateral should equal the required amount
  16. // for the size of the miners pledge.
  17. Collateral TokenAmount
  18. // ActiveCollateral is the amount of collateral currently committed to live storage
  19. ActiveCollateral TokenAmount
  20. // DePledgedCollateral is collateral that is waiting to be withdrawn
  21. DePledgedCollateral TokenAmount
  22. // DePledgeTime is the time at which the depledged collateral may be withdrawn
  23. DePledgeTime BlockHeight
  24. // Sectors is the set of all sectors this miner has committed
  25. Sectors SectorSet
  26. // ProvingSet is the set of sectors this miner is currently mining. It is only updated
  27. // when a PoSt is submitted (not as each new sector commitment is added)
  28. ProvingSet SectorSet
  29. // NextDoneSet is a set of sectors reported during the last PoSt submission as
  30. // being 'done'. The collateral for them is still being held until the next PoSt
  31. // submission in case early sector removal penalization is needed.
  32. NextDoneSet SectorSet
  33. // TODO: maybe this number is redundant with power
  34. LockedStorage BytesAmount
  35. // Power is the amount of power this miner has
  36. Power BytesAmount
  37. }

Constructor

随着调用,必须使用足够的filecoin以获得承诺所需的抵押品创建角色。

  1. func StorageMinerActor(pubkey PublicKey, pledge BytesAmount, pid PeerID) {
  2. if msg.Value < CollateralForPledgeSize(pledge) {
  3. Fatal("not enough collateral given")
  4. }
  5. self.Owner = message.From
  6. self.PublicKey = pubkey
  7. self.PeerID = pid
  8. self.PledgeBytes = pledge
  9. }

AddAsk

参数:

  • price TokenAmount
  • ttl Integer

Return: AskID

  1. func AddAsk(price TokenAmount, ttl Integer) AskID {
  2. if msg.From != self.Worker {
  3. Fatal("Asks may only be added via the worker address")
  4. }
  5. // Filter out expired asks
  6. self.Asks.FilterExpired()
  7. askid := self.NextAskID
  8. self.NextAskID++
  9. self.Asks.Append(Ask{
  10. Price: price,
  11. Expiry: CurrentBlockHeight + ttl,
  12. ID: askid,
  13. })
  14. return askid
  15. }

注意:这可能很快就会脱离区块链,不要担心测试过于繁重。

CommitSector

参数:

  • commD []byte
  • commR []byte
  • commRStar []byte
  • proof SealProof

Return:SectorID

  1. func CommitSector(commD, commR []byte, proof *SealProof) SectorID {
  2. if !miner.ValidatePoRep(commD, commR, miner.PublicKey, proof) {
  3. Fatal("bad proof!")
  4. }
  5. // make sure the miner isnt trying to submit a pre-existing sector
  6. if !miner.EnsureSectorIsUnique(commR) {
  7. Fatal("sector already committed!")
  8. }
  9. // make sure the miner has enough collateral to add more storage
  10. // currently, all sectors are the same size, and require the same collateral
  11. // in the future, we may have differently sized sectors and need special handling
  12. coll = CollateralForSector()
  13. if coll < miner.Collateral {
  14. Fatal("not enough collateral")
  15. }
  16. miner.Collateral -= coll
  17. miner.ActiveCollateral += coll
  18. sectorId = miner.Sectors.Add(commR)
  19. // TODO: sectors IDs might not be that useful. For now, this should just be the number of
  20. // the sector within the set of sectors, but that can change as the miner experiences
  21. // failures.
  22. // if miner is not mining, start their proving period now
  23. // Note: As written here, every miners first PoSt will only be over one sector.
  24. // We could set up a 'grace period' for starting mining that would allow miners
  25. // to submit several sectors for their first proving period. Alternatively, we
  26. // could simply make the 'CommitSector' call take multiple sectors at a time.
  27. if miner.ProvingSet.Size() == 0 {
  28. miner.ProvingSet = miner.Sectors
  29. miner.ProvingPeriodEnd = chain.Now() + ProvingPeriodDuration
  30. }
  31. return sectorId
  32. }

SubmitPoSt

参数:

  • proof PoStProof
  • fault []FailureSet
  • recovered SectorSet
  • done SectorSet

Return:None

  1. func SubmitPost(proof PoSt, faults []FaultSet, recovered BitField, done BitField) {
  2. if msg.From != miner.Worker {
  3. Fatal("not authorized to submit post for miner")
  4. }
  5. // ensure the fault sets properly stack, recovered is a subset of the combined
  6. // fault sets, and that done does not intersect with either, and that all sets
  7. // only reference sectors that currently exist
  8. if !miner.ValidateFaultSets(faults, recovered, done) {
  9. Fatal("fault sets invalid")
  10. }
  11. var feesRequired TokenAmount
  12. if chain.Now() > miner.ProvingPeriodEnd + GenerationAttackTime {
  13. // TODO: determine what exactly happens here. Is the miner permanently banned?
  14. Fatal("Post submission too late")
  15. } else if chain.Now() > miner.ProvingPeriodEnd {
  16. feesRequired += ComputeLateFee(chain.Now() - miner.ProvingPeriodEnd)
  17. }
  18. feesRequired += ComputeTemporarySectorFailureFee(recovered)
  19. if msg.Value < feesRequired {
  20. Fatal("not enough funds to pay post submission fees")
  21. }
  22. // we want to ensure that the miner can submit more fees than required, just in case
  23. if msg.Value > feesRequired {
  24. Refund(msg.Value - feesRequired)
  25. }
  26. if !CheckPostProof(proof, faults) {
  27. Fatal("proof invalid")
  28. }
  29. permLostSet = AggregateBitfields(faults).Subtract(recovered)
  30. // adjust collateral for 'done' sectors
  31. miner.ActiveCollateral -= CollateralForSectors(miner.NextDoneSet)
  32. miner.Collateral += CollateralForSectors(miner.NextDoneSet)
  33. // penalize collateral for lost sectors
  34. miner.Collateral -= CollateralForSectors(permLostSet)
  35. miner.ActiveCollateral -= CollateralForSectors(permLostSet)
  36. // burn funds for fees and collateral penalization
  37. BurnFunds(miner, CollateralForSectors(permLostSet) + feesRequired)
  38. // update sector sets and proving set
  39. miner.Sectors.Subtract(miner.NextDoneSet)
  40. miner.Sectors.Subtract(permLostSet)
  41. // update miner power to the amount of data actually proved during
  42. // the last proving period.
  43. miner.Power = SizeOf(Filter(miner.ProvingSet, faults))
  44. miner.ProvingSet = miner.Sectors
  45. // NEEDS REVIEW: early submission of PoSts may give the miner extra time for
  46. // their next PoSt, which could compound. Does the beacon reseeding for Posts
  47. // address this well enough?
  48. miner.ProvingPeriodEnd = miner.ProvingPeriodEnd + ProvingPeriodDuration
  49. // update next done set
  50. miner.NextDoneSet = done
  51. }

IncreasePledge

参数:

  • addspace BytesAmount

Return:None

  1. func IncreasePledge(addspace BytesAmount) {
  2. // Note: msg.Value is implicitly transferred to the miner actor
  3. if miner.Collateral + msg.Value < CollateralForPledge(addspace + miner.PledgeBytes) {
  4. Fatal("not enough total collateral for the requested pledge")
  5. }
  6. miner.Collateral += msg.Value
  7. miner.PledgeBytes += addspace
  8. }

SlashStorageFault

参数:

  • miner Address

Return:None

  1. func SlashStorageFault(miner Address) {
  2. if self.SlashedAt > 0 {
  3. Fatal("miner already slashed")
  4. }
  5. if chain.Now() <= miner.ProvingPeriodEnd + GenerationAttackTime {
  6. Fatal("miner is not yet tardy")
  7. }
  8. if miner.ProvingSet.Size() == 0 {
  9. Fatal("miner is inactive")
  10. }
  11. // Strip miner of their power
  12. StorageMarketActor.UpdateStorage(-1 * self.Power)
  13. self.Power = 0
  14. // TODO: make this less hand wavey
  15. BurnCollateral(self.ConsensusCollateral)
  16. self.SlashedAt = CurrentBlockHeight
  17. }

GetCurrentProvingSet

参数:None

Return: [][]byte

  1. func GetCurrentProvingSet() [][]byte {
  2. return self.ProvingSet
  3. }

注意:这永远不可能被称为on-chain,而且将是一个非常大的数据量。我们应该重新考虑列出所有扇区承诺的必要性(可能是用累加器修正?)

ArbitrateDeal

参数:

  • deal Deal

Return:None

  1. func AbitrateDeal(d Deal) {
  2. if !ValidateSignature(d, self.Worker) {
  3. Fatal("invalid signature on deal")
  4. }
  5. if CurrentBlockHeight < d.StartTime {
  6. Fatal("Deal not yet started")
  7. }
  8. if d.Expiry < CurrentBlockHeight {
  9. Fatal("Deal is expired")
  10. }
  11. if !self.NextDoneSet.Has(d.PieceCommitment.Sector) {
  12. Fatal("Deal agreement not broken, or arbitration too late")
  13. }
  14. coll := CollateralForDeal(d)
  15. self.BurnFunds(coll)
  16. self.NextDoneSet.Remove(d.PieceCommitment.Sector)
  17. }

TODO(scaling):按照当前的设计,每个扇区必须调用此方法一次。如果一个矿工同意为一个特定的客户端存储1TB(1000个扇区),并且丢失了所有这些数据,那么客户端必须调用这个方法1000次,这将非常昂贵。

DelPledge

参数:

  • amt TokenAmount

Return:None

  1. func DePledge(amt TokenAmount) {
  2. // TODO: Do both the worker and the owner have the right to call this?
  3. if msg.From != miner.Worker && msg.From != miner.Owner {
  4. Fatal("Not authorized to call DePledge")
  5. }
  6. if miner.DePledgeTime > 0 {
  7. if miner.DePledgeTime > CurrentBlockHeight {
  8. Fatal("too early to withdraw collateral")
  9. }
  10. TransferFunds(miner.Owner, miner.DePledgedCollateral)
  11. miner.DePledgeTime = 0
  12. miner.DePledgedCollateral = 0
  13. return
  14. }
  15. if amt > miner.Collateral {
  16. Fatal("Not enough free collateral to withdraw that much")
  17. }
  18. miner.Collateral -= amt
  19. miner.DePledgedCollateral = amt
  20. miner.DePledgeTime = CurrentBlockHeight + DePledgeCooldown
  21. }

GetOwner

参数:None

Return:Address

  1. func GetOwner() Address {
  2. return self.Owner
  3. }

GetWorkerAddr

参数:None
Return:Address

  1. func GetWorkerAddr() Address {
  2. return self.Worker
  3. }

GetPower

参数:None
Return:Integer

  1. func GetPower() Integer {
  2. return self.Power
  3. }

GetKey

参数:None
Return:PublicKey

  1. func GetKey() PublicKey {
  2. return self.PublicKey
  3. }

GetPeerID

参数:None
Return:PeerID

  1. func GetPeerID() PeerID {
  2. return self.PeerID
  3. }

UpdatePeerID

参数:

  • pid PeerID

return:None

  1. func UpdatePeerID(pid PeerID) {
  2. if msg.From != self.Worker {
  3. Fatal("only the mine worker may update the peer ID")
  4. }
  5. self.PeerID = pid
  6. }

Payment Channel Broker Actor 支付通道代理角色

TODO

  • 分享 收藏
0 条评论
  • 这篇文章暂无评论,赶紧评论一下吧~