Merge pull request #207 from filecoin-project/feat/post3

Rought PoST method
This commit is contained in:
Jakub Sztandera 2019-09-19 16:31:52 +02:00 committed by GitHub
commit 4b8461b393
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 158 additions and 18 deletions

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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 {

View File

@ -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
View File

@ -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
View File

@ -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=

View File

@ -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)
}