Merge pull request #207 from filecoin-project/feat/post3
Rought PoST method
This commit is contained in:
commit
4b8461b393
@ -14,4 +14,7 @@ const DealVoucherSkewLimit = 10
|
||||
const ForkLengthThreshold = 20
|
||||
const RandomnessLookback = 20
|
||||
|
||||
const ProvingPeriodDuration = 2 * 60 // an hour, for now
|
||||
const PoSTChallangeTime = 1 * 60
|
||||
|
||||
// TODO: Move other important consts here
|
||||
|
@ -2,7 +2,9 @@ package actors
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/filecoin-project/go-lotus/build"
|
||||
"github.com/filecoin-project/go-lotus/chain/actors/aerrors"
|
||||
"github.com/filecoin-project/go-lotus/chain/address"
|
||||
"github.com/filecoin-project/go-lotus/chain/types"
|
||||
@ -12,10 +14,10 @@ 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
|
||||
const POST_SECTORS_COUNT = 8192
|
||||
|
||||
type StorageMinerActor struct{}
|
||||
@ -118,9 +120,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 +145,7 @@ func (sma StorageMinerActor) Exports() []interface{} {
|
||||
//16: sma.IsLate,
|
||||
17: sma.PaymentVerifyInclusion,
|
||||
18: sma.PaymentVerifySector,
|
||||
19: nil,
|
||||
}
|
||||
}
|
||||
|
||||
@ -247,11 +251,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.
|
||||
@ -272,7 +271,7 @@ func (sma StorageMinerActor) CommitSector(act *types.Actor, vmctx types.VMContex
|
||||
if self.ProvingSetSize == 0 {
|
||||
self.ProvingSet = self.Sectors
|
||||
self.ProvingSetSize = self.SectorSetSize
|
||||
self.ProvingPeriodEnd = vmctx.BlockHeight() + ProvingPeriodDuration
|
||||
self.ProvingPeriodEnd = vmctx.BlockHeight() + build.ProvingPeriodDuration
|
||||
}
|
||||
|
||||
nstate, err := vmctx.Storage().Put(self)
|
||||
@ -287,6 +286,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 +308,116 @@ 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 + build.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
|
||||
{
|
||||
var rand []byte
|
||||
var err ActorError
|
||||
if !lateSubmission {
|
||||
rand, err = vmctx.GetRandomness(self.ProvingPeriodEnd - build.PoSTChallangeTime)
|
||||
} else {
|
||||
rand, err = vmctx.GetRandomness(nextProvingPeriodEnd - build.PoSTChallangeTime)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, aerrors.Wrap(err, "could not get randomness for PoST")
|
||||
}
|
||||
if len(rand) < len(seed) {
|
||||
return nil, aerrors.Escalate(fmt.Errorf("randomness too small (%d < %d)",
|
||||
len(rand), len(seed)), "improper randomness")
|
||||
}
|
||||
copy(seed[:], rand)
|
||||
}
|
||||
|
||||
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 lerr != nil {
|
||||
// TODO: study PoST errors
|
||||
return nil, aerrors.Absorb(lerr, 4, "PoST error")
|
||||
}
|
||||
if !ok {
|
||||
return nil, aerrors.New(4, "PoST invalid")
|
||||
}
|
||||
}
|
||||
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")
|
||||
}
|
||||
|
||||
if err := ss.BatchDelete(params.DoneSet.All()); err != nil {
|
||||
// TODO: this could fail for system reasons (block not found) or for
|
||||
// bad user input reasons (e.g. bad doneset). The latter should be a
|
||||
// non-fatal error
|
||||
return nil, aerrors.Escalate(err, "failed to delete sectors in done set")
|
||||
}
|
||||
|
||||
self.ProvingSet, lerr = ss.Flush()
|
||||
if lerr != nil {
|
||||
return nil, aerrors.Escalate(lerr, "could not flush 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 +429,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
|
||||
|
@ -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 {
|
||||
|
@ -36,6 +36,7 @@ type VMContext interface {
|
||||
StateTree() (StateTree, aerrors.ActorError)
|
||||
VerifySignature(sig *Signature, from address.Address, data []byte) aerrors.ActorError
|
||||
ChargeGas(uint64) aerrors.ActorError
|
||||
GetRandomness(height uint64) ([]byte, aerrors.ActorError)
|
||||
}
|
||||
|
||||
type storageWrapper struct {
|
||||
|
@ -66,6 +66,15 @@ func (vmc *VMContext) Message() *types.Message {
|
||||
return vmc.msg
|
||||
}
|
||||
|
||||
func (vmc *VMContext) GetRandomness(height uint64) ([]byte, aerrors.ActorError) {
|
||||
relHeight := int(vmc.BlockHeight()) - int(height)
|
||||
res, err := vmc.vm.cs.GetRandomness(vmc.ctx, vmc.vm.cs.GetHeaviestTipSet(), nil, relHeight)
|
||||
if err != nil {
|
||||
return nil, aerrors.Escalate(err, "could not get randomness")
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Storage interface
|
||||
|
||||
func (vmc *VMContext) Put(i cbg.CBORMarshaler) (cid.Cid, aerrors.ActorError) {
|
||||
|
2
go.mod
2
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-20190919045431-3650716fff16
|
||||
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
|
||||
|
4
go.sum
4
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-20190919045431-3650716fff16 h1:NzojcJU1VbS6zdLG13JMYis/cQy/MrN3rxmZRq56jKA=
|
||||
github.com/filecoin-project/go-amt-ipld v0.0.0-20190919045431-3650716fff16/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=
|
||||
|
@ -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)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user