diff --git a/chain/actors/actor_miner.go b/chain/actors/actor_miner.go index 6a3dd3ec8..0691d559a 100644 --- a/chain/actors/actor_miner.go +++ b/chain/actors/actor_miner.go @@ -12,10 +12,13 @@ import ( "github.com/ipfs/go-cid" cbor "github.com/ipfs/go-ipld-cbor" "github.com/libp2p/go-libp2p-core/peer" + cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" ) var ProvingPeriodDuration = uint64(2 * 60) // an hour, for now +var PoSTChallangeTime = uint64(1 * 60) + const POST_SECTORS_COUNT = 8192 type StorageMinerActor struct{} @@ -118,9 +121,10 @@ type maMethods struct { IsLate uint64 PaymentVerifyInclusion uint64 PaymentVerifySector uint64 + AddFaults uint64 } -var MAMethods = maMethods{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18} +var MAMethods = maMethods{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19} func (sma StorageMinerActor) Exports() []interface{} { return []interface{}{ @@ -142,6 +146,7 @@ func (sma StorageMinerActor) Exports() []interface{} { //16: sma.IsLate, 17: sma.PaymentVerifyInclusion, 18: sma.PaymentVerifySector, + 19: nil, } } @@ -247,11 +252,6 @@ func (sma StorageMinerActor) CommitSector(act *types.Actor, vmctx types.VMContex return nil, aerrors.New(3, "not enough collateral") } - // ensure that the miner cannot commit more sectors than can be proved with a single PoSt - if self.SectorSetSize >= POST_SECTORS_COUNT { - return nil, aerrors.New(4, "too many sectors") - } - // Note: There must exist a unique index in the miner's sector set for each // sector ID. The `faults`, `recovered`, and `done` parameters of the // SubmitPoSt method express indices into this sector set. @@ -287,6 +287,8 @@ func (sma StorageMinerActor) CommitSector(act *types.Actor, vmctx types.VMContex } type SubmitPoStParams struct { + Proof []byte + DoneSet types.BitField // TODO: once the spec changes finish, we have more work to do here... } @@ -307,13 +309,99 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext, return nil, aerrors.New(1, "not authorized to submit post for miner") } - oldProvingSetSize := self.ProvingSetSize + feesRequired := types.NewInt(0) + nextProvingPeriodEnd := self.ProvingPeriodEnd + ProvingPeriodDuration + if vmctx.BlockHeight() > nextProvingPeriodEnd { + return nil, aerrors.New(1, "PoSt submited too late") + } - self.ProvingSet = self.Sectors - self.ProvingSetSize = self.SectorSetSize + var lateSubmission bool + if vmctx.BlockHeight() > self.ProvingPeriodEnd { + //TODO late fee calc + lateSubmission = true + feesRequired = types.BigAdd(feesRequired, types.NewInt(1000)) + } + + //TODO temporary sector failure fees + + msgVal := vmctx.Message().Value + if types.BigCmp(msgVal, feesRequired) < 0 { + return nil, aerrors.New(2, "not enough funds to pay post submission fees") + } + + if types.BigCmp(msgVal, feesRequired) > 0 { + _, err := vmctx.Send(vmctx.Message().From, 0, + types.BigSub(msgVal, feesRequired), nil) + if err != nil { + return nil, aerrors.Wrap(err, "could not refund excess fees") + } + } + + var seed [sectorbuilder.CommLen]byte + //TODO + if !lateSubmission { + //GetChainRandom(self.ProvingPeriodEnd-PoSTChallangeTime) + } else { + //GetChainRandom(nextProvingPeriodEnd-PoSTChallangeTime) + } + + pss, lerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingSet) + if lerr != nil { + return nil, aerrors.Escalate(lerr, "could not load sector set node") + } + + var sectorInfos []sectorbuilder.SectorInfo + if err := pss.ForEach(func(id uint64, v *cbg.Deferred) error { + var comms [][]byte + if err := cbor.DecodeInto(v.Raw, &comms); err != nil { + return xerrors.New("could not decode comms") + } + si := sectorbuilder.SectorInfo{ + SectorID: id, + } + commR := comms[0] + if len(commR) != len(si.CommR) { + return xerrors.Errorf("commR length is wrong: %d", len(commR)) + } + copy(si.CommR[:], commR) + + sectorInfos = append(sectorInfos, si) + + return nil + }); err != nil { + return nil, aerrors.Absorb(err, 3, "could not decode sectorset") + } + + faults := self.CurrentFaultSet.All() + + if ok, lerr := sectorbuilder.VerifyPost(mi.SectorSize.Uint64(), + sectorbuilder.NewSortedSectorInfo(sectorInfos), seed, params.Proof, + faults); !ok || lerr != nil { + if !ok { + return nil, aerrors.New(4, "PoST invalid") + } + if lerr != nil { + return nil, aerrors.Absorb(lerr, 4, "PoST error") + } + } + self.CurrentFaultSet = self.NextFaultSet + self.NextFaultSet = types.NewBitField() + + ss, lerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingSet) + if lerr != nil { + return nil, aerrors.Escalate(lerr, "could not load sector set node") + } + + _ = ss + //TODO: Remove done sectors from SectorSet + self.ProvingSet, lerr = ss.Flush() + if lerr != nil { + return nil, aerrors.Escalate(lerr, "could not flish AMT") + } oldPower := self.Power - self.Power = types.BigMul(types.NewInt(oldProvingSetSize), mi.SectorSize) + self.Power = types.BigMul(types.NewInt(self.ProvingSetSize-uint64(len(faults))), + mi.SectorSize) enc, err := SerializeParams(&UpdateStorageParams{Delta: types.BigSub(self.Power, oldPower)}) if err != nil { @@ -325,6 +413,10 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext, return nil, err } + self.ProvingSet = self.Sectors + self.ProvingSetSize = self.SectorSetSize + self.NextDoneSet = params.DoneSet + c, err := vmctx.Storage().Put(self) if err != nil { return nil, err diff --git a/chain/types/bitfield.go b/chain/types/bitfield.go index f708c2733..c59768ac1 100644 --- a/chain/types/bitfield.go +++ b/chain/types/bitfield.go @@ -13,6 +13,10 @@ type BitField struct { bits map[uint64]struct{} } +func NewBitField() BitField { + return BitField{bits: make(map[uint64]struct{})} +} + // Set ...s bit in the BitField func (bf BitField) Set(bit uint64) { bf.bits[bit] = struct{}{} @@ -29,6 +33,15 @@ func (bf BitField) Has(bit uint64) bool { return ok } +// All returns all set bits, in random order +func (bf BitField) All() []uint64 { + res := make([]uint64, 0, len(bf.bits)) + for i := range bf.bits { + res = append(res, i) + } + return res +} + func (bf BitField) MarshalCBOR(w io.Writer) error { ints := make([]uint64, 0, len(bf.bits)) for i := range bf.bits { diff --git a/go.mod b/go.mod index 99c2e7e12..e44aed8be 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( contrib.go.opencensus.io/exporter/jaeger v0.1.0 github.com/BurntSushi/toml v0.3.1 github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect - github.com/filecoin-project/go-amt-ipld v0.0.0-20190917010905-40ffeec492ae + github.com/filecoin-project/go-amt-ipld v0.0.0-20190917221444-2ed85149c65d github.com/filecoin-project/go-bls-sigs v0.0.0-20190718224239-4bc4b8a7bbf8 github.com/filecoin-project/go-leb128 v0.0.0-20190212224330-8d79a5489543 github.com/filecoin-project/go-sectorbuilder v0.0.0-00010101000000-000000000000 diff --git a/go.sum b/go.sum index 1059a4470..1a4a0d4be 100644 --- a/go.sum +++ b/go.sum @@ -68,8 +68,8 @@ github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5m github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/fatih/color v1.6.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/filecoin-project/go-amt-ipld v0.0.0-20190917010905-40ffeec492ae h1:rSg6wenxKdXby0piY57Vv5gOJR6Eibqq/4PxEk6KjvE= -github.com/filecoin-project/go-amt-ipld v0.0.0-20190917010905-40ffeec492ae/go.mod h1:lKjJYPg2kwbav5f78i5YA8kGccnZn18IySbpneXvaQs= +github.com/filecoin-project/go-amt-ipld v0.0.0-20190917221444-2ed85149c65d h1:fAJ40dcN0kpSFfdTssa1kLxlDImSEZy8e1d7a32tyBY= +github.com/filecoin-project/go-amt-ipld v0.0.0-20190917221444-2ed85149c65d/go.mod h1:lKjJYPg2kwbav5f78i5YA8kGccnZn18IySbpneXvaQs= github.com/filecoin-project/go-leb128 v0.0.0-20190212224330-8d79a5489543 h1:aMJGfgqe1QDhAVwxRg5fjCRF533xHidiKsugk7Vvzug= github.com/filecoin-project/go-leb128 v0.0.0-20190212224330-8d79a5489543/go.mod h1:mjrHv1cDGJWDlGmC0eDc1E5VJr8DmL9XMUcaFwiuKg8= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index ee7e4aecb..2d22dd884 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -107,7 +107,13 @@ func VerifyPieceInclusionProof(sectorSize uint64, pieceSize uint64, commP []byte return sectorbuilder.VerifyPieceInclusionProof(sectorSize, pieceSize, commPa, commDa, proof) } -func VerifyPost(sectorSize uint64, sortedCommRs [][CommLen]byte, challengeSeed [CommLen]byte, proofs [][]byte, faults []uint64) (bool, error) { - // sectorbuilder.VerifyPost() - panic("no") +type SortedSectorInfo = sectorbuilder.SortedSectorInfo +type SectorInfo = sectorbuilder.SectorInfo + +func NewSortedSectorInfo(sectors []SectorInfo) SortedSectorInfo { + return sectorbuilder.NewSortedSectorInfo(sectors...) +} + +func VerifyPost(sectorSize uint64, sectorInfo SortedSectorInfo, challengeSeed [CommLen]byte, proof []byte, faults []uint64) (bool, error) { + return sectorbuilder.VerifyPoSt(sectorSize, sectorInfo, challengeSeed, proof, faults) }