Use state store for sectors
This commit is contained in:
parent
080a84970c
commit
82344649d3
@ -49,4 +49,4 @@ type Version struct {
|
|||||||
func (v Version) String() string {
|
func (v Version) String() string {
|
||||||
vM, vm, vp := build.VersionInts(v.APIVersion)
|
vM, vm, vp := build.VersionInts(v.APIVersion)
|
||||||
return fmt.Sprintf("%s+api%d.%d.%d", v.Version, vM, vm, vp)
|
return fmt.Sprintf("%s+api%d.%d.%d", v.Version, vM, vm, vp)
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,17 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/address"
|
"github.com/filecoin-project/lotus/chain/address"
|
||||||
"github.com/filecoin-project/lotus/lib/sectorbuilder"
|
"github.com/filecoin-project/lotus/lib/sectorbuilder"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SectorState int
|
// alias because cbor-gen doesn't like non-alias types
|
||||||
|
type SectorState = uint64
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Undefined SectorState = iota
|
UndefinedSectorState SectorState = iota
|
||||||
|
|
||||||
Empty // TODO: Is this useful
|
Empty // TODO: Is this useful
|
||||||
Packing // sector not in sealStore, and not on chain
|
Packing // sector not in sealStore, and not on chain
|
||||||
@ -19,8 +21,33 @@ const (
|
|||||||
PreCommitting // on chain pre-commit
|
PreCommitting // on chain pre-commit
|
||||||
PreCommitted // waiting for seed
|
PreCommitted // waiting for seed
|
||||||
Committing
|
Committing
|
||||||
|
Proving
|
||||||
|
|
||||||
|
SectorNoUpdate = UndefinedSectorState
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func SectorStateStr(s SectorState) string {
|
||||||
|
switch s {
|
||||||
|
case UndefinedSectorState:
|
||||||
|
return "UndefinedSectorState"
|
||||||
|
case Empty:
|
||||||
|
return "Empty"
|
||||||
|
case Packing:
|
||||||
|
return "Packing"
|
||||||
|
case Unsealed:
|
||||||
|
return "Unsealed"
|
||||||
|
case PreCommitting:
|
||||||
|
return "PreCommitting"
|
||||||
|
case PreCommitted:
|
||||||
|
return "PreCommitted"
|
||||||
|
case Committing:
|
||||||
|
return "Committing"
|
||||||
|
case Proving:
|
||||||
|
return "Proving"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("<Unknown %d>", s)
|
||||||
|
}
|
||||||
|
|
||||||
// StorageMiner is a low-level interface to the Filecoin network storage miner node
|
// StorageMiner is a low-level interface to the Filecoin network storage miner node
|
||||||
type StorageMiner interface {
|
type StorageMiner interface {
|
||||||
Common
|
Common
|
||||||
|
@ -1470,3 +1470,118 @@ func (t *StorageAsk) UnmarshalCBOR(r io.Reader) error {
|
|||||||
t.SeqNo = extra
|
t.SeqNo = extra
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *ExpTipSet) MarshalCBOR(w io.Writer) error {
|
||||||
|
if t == nil {
|
||||||
|
_, err := w.Write(cbg.CborNull)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := w.Write([]byte{131}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.Cids ([]cid.Cid)
|
||||||
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Cids)))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, v := range t.Cids {
|
||||||
|
if err := cbg.WriteCid(w, v); err != nil {
|
||||||
|
return xerrors.Errorf("failed writing cid field t.Cids: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.Blocks ([]*types.BlockHeader)
|
||||||
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Blocks)))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, v := range t.Blocks {
|
||||||
|
if err := v.MarshalCBOR(w); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.Height (uint64)
|
||||||
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, t.Height)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *ExpTipSet) UnmarshalCBOR(r io.Reader) error {
|
||||||
|
br := cbg.GetPeeker(r)
|
||||||
|
|
||||||
|
maj, extra, err := cbg.CborReadHeader(br)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if maj != cbg.MajArray {
|
||||||
|
return fmt.Errorf("cbor input should be of type array")
|
||||||
|
}
|
||||||
|
|
||||||
|
if extra != 3 {
|
||||||
|
return fmt.Errorf("cbor input had wrong number of fields")
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.Cids ([]cid.Cid)
|
||||||
|
|
||||||
|
maj, extra, err = cbg.CborReadHeader(br)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if extra > 8192 {
|
||||||
|
return fmt.Errorf("t.Cids: array too large (%d)", extra)
|
||||||
|
}
|
||||||
|
|
||||||
|
if maj != cbg.MajArray {
|
||||||
|
return fmt.Errorf("expected cbor array")
|
||||||
|
}
|
||||||
|
if extra > 0 {
|
||||||
|
t.Cids = make([]cid.Cid, extra)
|
||||||
|
}
|
||||||
|
for i := 0; i < int(extra); i++ {
|
||||||
|
|
||||||
|
c, err := cbg.ReadCid(br)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("reading cid field t.Cids failed: %w", err)
|
||||||
|
}
|
||||||
|
t.Cids[i] = c
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.Blocks ([]*types.BlockHeader)
|
||||||
|
|
||||||
|
maj, extra, err = cbg.CborReadHeader(br)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if extra > 8192 {
|
||||||
|
return fmt.Errorf("t.Blocks: array too large (%d)", extra)
|
||||||
|
}
|
||||||
|
|
||||||
|
if maj != cbg.MajArray {
|
||||||
|
return fmt.Errorf("expected cbor array")
|
||||||
|
}
|
||||||
|
if extra > 0 {
|
||||||
|
t.Blocks = make([]*BlockHeader, extra)
|
||||||
|
}
|
||||||
|
for i := 0; i < int(extra); i++ {
|
||||||
|
|
||||||
|
var v BlockHeader
|
||||||
|
if err := v.UnmarshalCBOR(br); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Blocks[i] = &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.Height (uint64)
|
||||||
|
|
||||||
|
maj, extra, err = cbg.CborReadHeader(br)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if maj != cbg.MajUnsignedInt {
|
||||||
|
return fmt.Errorf("wrong type for uint64 field")
|
||||||
|
}
|
||||||
|
t.Height = extra
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
@ -20,14 +21,14 @@ type TipSet struct {
|
|||||||
|
|
||||||
// why didnt i just export the fields? Because the struct has methods with the
|
// why didnt i just export the fields? Because the struct has methods with the
|
||||||
// same names already
|
// same names already
|
||||||
type expTipSet struct {
|
type ExpTipSet struct {
|
||||||
Cids []cid.Cid
|
Cids []cid.Cid
|
||||||
Blocks []*BlockHeader
|
Blocks []*BlockHeader
|
||||||
Height uint64
|
Height uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ts *TipSet) MarshalJSON() ([]byte, error) {
|
func (ts *TipSet) MarshalJSON() ([]byte, error) {
|
||||||
return json.Marshal(expTipSet{
|
return json.Marshal(ExpTipSet{
|
||||||
Cids: ts.cids,
|
Cids: ts.cids,
|
||||||
Blocks: ts.blks,
|
Blocks: ts.blks,
|
||||||
Height: ts.height,
|
Height: ts.height,
|
||||||
@ -35,7 +36,7 @@ func (ts *TipSet) MarshalJSON() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ts *TipSet) UnmarshalJSON(b []byte) error {
|
func (ts *TipSet) UnmarshalJSON(b []byte) error {
|
||||||
var ets expTipSet
|
var ets ExpTipSet
|
||||||
if err := json.Unmarshal(b, &ets); err != nil {
|
if err := json.Unmarshal(b, &ets); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -50,6 +51,30 @@ func (ts *TipSet) UnmarshalJSON(b []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ts *TipSet) MarshalCBOR(w io.Writer) error {
|
||||||
|
return (&ExpTipSet{
|
||||||
|
Cids: ts.cids,
|
||||||
|
Blocks: ts.blks,
|
||||||
|
Height: ts.height,
|
||||||
|
}).MarshalCBOR(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ts *TipSet) UnmarshalCBOR(r io.Reader) error {
|
||||||
|
var ets ExpTipSet
|
||||||
|
if err := ets.UnmarshalCBOR(r); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ots, err := NewTipSet(ets.Blocks)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*ts = *ots
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func tipsetSortFunc(blks []*BlockHeader) func(i, j int) bool {
|
func tipsetSortFunc(blks []*BlockHeader) func(i, j int) bool {
|
||||||
return func(i, j int) bool {
|
return func(i, j int) bool {
|
||||||
ti := blks[i].LastTicket()
|
ti := blks[i].LastTicket()
|
||||||
|
11
gen/main.go
11
gen/main.go
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/chain/actors"
|
"github.com/filecoin-project/lotus/chain/actors"
|
||||||
"github.com/filecoin-project/lotus/chain/deals"
|
"github.com/filecoin-project/lotus/chain/deals"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
"github.com/filecoin-project/lotus/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -26,6 +27,7 @@ func main() {
|
|||||||
types.BlockMsg{},
|
types.BlockMsg{},
|
||||||
types.SignedStorageAsk{},
|
types.SignedStorageAsk{},
|
||||||
types.StorageAsk{},
|
types.StorageAsk{},
|
||||||
|
types.ExpTipSet{},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
@ -109,4 +111,13 @@ func main() {
|
|||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = gen.WriteTupleEncodersToFile("./storage/cbor_gen.go", "storage",
|
||||||
|
storage.SealTicket{},
|
||||||
|
storage.SectorInfo{},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,13 @@ package statestore
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/filecoin-project/lotus/lib/cborrpc"
|
"reflect"
|
||||||
|
|
||||||
"github.com/ipfs/go-datastore"
|
"github.com/ipfs/go-datastore"
|
||||||
"github.com/ipfs/go-datastore/query"
|
"github.com/ipfs/go-datastore/query"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
"reflect"
|
|
||||||
|
"github.com/filecoin-project/lotus/lib/cborrpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StateStore struct {
|
type StateStore struct {
|
||||||
@ -81,7 +83,7 @@ func cborMutator(mutator interface{}) func([]byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// mutator func(*T) error
|
// mutator func(*T) error
|
||||||
func (st *StateStore) Mutate(i fmt.Stringer, mutator interface{}) error {
|
func (st *StateStore) Mutate(i interface{}, mutator interface{}) error {
|
||||||
return st.mutate(i, cborMutator(mutator))
|
return st.mutate(i, cborMutator(mutator))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ func (sm *StorageMinerAPI) StoreGarbageData(ctx context.Context) error {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := sm.Miner.SealSector(ctx, sectorId); err != nil {
|
if err := sm.Miner.SealSector(context.TODO(), sectorId); err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -90,6 +90,7 @@ func StorageMiner(mctx helpers.MetricsCtx, lc fx.Lifecycle, api api.FullNode, h
|
|||||||
OnStart: func(context.Context) error {
|
OnStart: func(context.Context) error {
|
||||||
return sm.Run(ctx)
|
return sm.Run(ctx)
|
||||||
},
|
},
|
||||||
|
OnStop: sm.Stop,
|
||||||
})
|
})
|
||||||
|
|
||||||
return sm, nil
|
return sm, nil
|
||||||
|
319
storage/cbor_gen.go
Normal file
319
storage/cbor_gen.go
Normal file
@ -0,0 +1,319 @@
|
|||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
cbg "github.com/whyrusleeping/cbor-gen"
|
||||||
|
xerrors "golang.org/x/xerrors"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
/* This file was generated by github.com/whyrusleeping/cbor-gen */
|
||||||
|
|
||||||
|
var _ = xerrors.Errorf
|
||||||
|
|
||||||
|
func (t *SealTicket) MarshalCBOR(w io.Writer) error {
|
||||||
|
if t == nil {
|
||||||
|
_, err := w.Write(cbg.CborNull)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := w.Write([]byte{130}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.BlockHeight (uint64)
|
||||||
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, t.BlockHeight)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.TicketBytes ([]uint8)
|
||||||
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.TicketBytes)))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := w.Write(t.TicketBytes); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SealTicket) UnmarshalCBOR(r io.Reader) error {
|
||||||
|
br := cbg.GetPeeker(r)
|
||||||
|
|
||||||
|
maj, extra, err := cbg.CborReadHeader(br)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if maj != cbg.MajArray {
|
||||||
|
return fmt.Errorf("cbor input should be of type array")
|
||||||
|
}
|
||||||
|
|
||||||
|
if extra != 2 {
|
||||||
|
return fmt.Errorf("cbor input had wrong number of fields")
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.BlockHeight (uint64)
|
||||||
|
|
||||||
|
maj, extra, err = cbg.CborReadHeader(br)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if maj != cbg.MajUnsignedInt {
|
||||||
|
return fmt.Errorf("wrong type for uint64 field")
|
||||||
|
}
|
||||||
|
t.BlockHeight = extra
|
||||||
|
// t.t.TicketBytes ([]uint8)
|
||||||
|
|
||||||
|
maj, extra, err = cbg.CborReadHeader(br)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if extra > 8192 {
|
||||||
|
return fmt.Errorf("t.TicketBytes: array too large (%d)", extra)
|
||||||
|
}
|
||||||
|
|
||||||
|
if maj != cbg.MajByteString {
|
||||||
|
return fmt.Errorf("expected byte array")
|
||||||
|
}
|
||||||
|
t.TicketBytes = make([]byte, extra)
|
||||||
|
if _, err := io.ReadFull(br, t.TicketBytes); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SectorInfo) MarshalCBOR(w io.Writer) error {
|
||||||
|
if t == nil {
|
||||||
|
_, err := w.Write(cbg.CborNull)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := w.Write([]byte{137}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.State (api.SectorState)
|
||||||
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, t.State)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.SectorID (uint64)
|
||||||
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, t.SectorID)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.CommD ([]uint8)
|
||||||
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.CommD)))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := w.Write(t.CommD); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.CommR ([]uint8)
|
||||||
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.CommR)))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := w.Write(t.CommR); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.Ticket (storage.SealTicket)
|
||||||
|
if err := t.Ticket.MarshalCBOR(w); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.PreCommitMessage (cid.Cid)
|
||||||
|
|
||||||
|
if t.PreCommitMessage == nil {
|
||||||
|
if _, err := w.Write(cbg.CborNull); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := cbg.WriteCid(w, *t.PreCommitMessage); err != nil {
|
||||||
|
return xerrors.Errorf("failed to write cid field t.PreCommitMessage: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.RandHeight (uint64)
|
||||||
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, t.RandHeight)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.RandTs (types.TipSet)
|
||||||
|
if err := t.RandTs.MarshalCBOR(w); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.CommitMessage (cid.Cid)
|
||||||
|
|
||||||
|
if t.CommitMessage == nil {
|
||||||
|
if _, err := w.Write(cbg.CborNull); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := cbg.WriteCid(w, *t.CommitMessage); err != nil {
|
||||||
|
return xerrors.Errorf("failed to write cid field t.CommitMessage: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SectorInfo) UnmarshalCBOR(r io.Reader) error {
|
||||||
|
br := cbg.GetPeeker(r)
|
||||||
|
|
||||||
|
maj, extra, err := cbg.CborReadHeader(br)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if maj != cbg.MajArray {
|
||||||
|
return fmt.Errorf("cbor input should be of type array")
|
||||||
|
}
|
||||||
|
|
||||||
|
if extra != 9 {
|
||||||
|
return fmt.Errorf("cbor input had wrong number of fields")
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.State (api.SectorState)
|
||||||
|
|
||||||
|
maj, extra, err = cbg.CborReadHeader(br)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if maj != cbg.MajUnsignedInt {
|
||||||
|
return fmt.Errorf("wrong type for uint64 field")
|
||||||
|
}
|
||||||
|
t.State = extra
|
||||||
|
// t.t.SectorID (uint64)
|
||||||
|
|
||||||
|
maj, extra, err = cbg.CborReadHeader(br)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if maj != cbg.MajUnsignedInt {
|
||||||
|
return fmt.Errorf("wrong type for uint64 field")
|
||||||
|
}
|
||||||
|
t.SectorID = extra
|
||||||
|
// t.t.CommD ([]uint8)
|
||||||
|
|
||||||
|
maj, extra, err = cbg.CborReadHeader(br)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if extra > 8192 {
|
||||||
|
return fmt.Errorf("t.CommD: array too large (%d)", extra)
|
||||||
|
}
|
||||||
|
|
||||||
|
if maj != cbg.MajByteString {
|
||||||
|
return fmt.Errorf("expected byte array")
|
||||||
|
}
|
||||||
|
t.CommD = make([]byte, extra)
|
||||||
|
if _, err := io.ReadFull(br, t.CommD); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// t.t.CommR ([]uint8)
|
||||||
|
|
||||||
|
maj, extra, err = cbg.CborReadHeader(br)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if extra > 8192 {
|
||||||
|
return fmt.Errorf("t.CommR: array too large (%d)", extra)
|
||||||
|
}
|
||||||
|
|
||||||
|
if maj != cbg.MajByteString {
|
||||||
|
return fmt.Errorf("expected byte array")
|
||||||
|
}
|
||||||
|
t.CommR = make([]byte, extra)
|
||||||
|
if _, err := io.ReadFull(br, t.CommR); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// t.t.Ticket (storage.SealTicket)
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
if err := t.Ticket.UnmarshalCBOR(br); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// t.t.PreCommitMessage (cid.Cid)
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
pb, err := br.PeekByte()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if pb == cbg.CborNull[0] {
|
||||||
|
var nbuf [1]byte
|
||||||
|
if _, err := br.Read(nbuf[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
c, err := cbg.ReadCid(br)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("failed to read cid field t.PreCommitMessage: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.PreCommitMessage = &c
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// t.t.RandHeight (uint64)
|
||||||
|
|
||||||
|
maj, extra, err = cbg.CborReadHeader(br)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if maj != cbg.MajUnsignedInt {
|
||||||
|
return fmt.Errorf("wrong type for uint64 field")
|
||||||
|
}
|
||||||
|
t.RandHeight = extra
|
||||||
|
// t.t.RandTs (types.TipSet)
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
pb, err := br.PeekByte()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if pb == cbg.CborNull[0] {
|
||||||
|
var nbuf [1]byte
|
||||||
|
if _, err := br.Read(nbuf[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t.RandTs = new(types.TipSet)
|
||||||
|
if err := t.RandTs.UnmarshalCBOR(br); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// t.t.CommitMessage (cid.Cid)
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
pb, err := br.PeekByte()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if pb == cbg.CborNull[0] {
|
||||||
|
var nbuf [1]byte
|
||||||
|
if _, err := br.Read(nbuf[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
c, err := cbg.ReadCid(br)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("failed to read cid field t.CommitMessage: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.CommitMessage = &c
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -2,6 +2,8 @@ package storage
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/filecoin-project/lotus/lib/statestore"
|
||||||
|
"github.com/ipfs/go-datastore/namespace"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
@ -15,7 +17,6 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/chain/events"
|
"github.com/filecoin-project/lotus/chain/events"
|
||||||
"github.com/filecoin-project/lotus/chain/store"
|
"github.com/filecoin-project/lotus/chain/store"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/lib/sectorbuilder"
|
|
||||||
"github.com/filecoin-project/lotus/storage/sector"
|
"github.com/filecoin-project/lotus/storage/sector"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -26,19 +27,23 @@ const PoStConfidence = 3
|
|||||||
type Miner struct {
|
type Miner struct {
|
||||||
api storageMinerApi
|
api storageMinerApi
|
||||||
events *events.Events
|
events *events.Events
|
||||||
|
h host.Host
|
||||||
|
secst *sector.Store
|
||||||
|
|
||||||
secst *sector.Store
|
maddr address.Address
|
||||||
|
|
||||||
maddr address.Address
|
|
||||||
|
|
||||||
worker address.Address
|
worker address.Address
|
||||||
|
|
||||||
h host.Host
|
// PoSt
|
||||||
|
postLk sync.Mutex
|
||||||
ds datastore.Batching
|
|
||||||
|
|
||||||
schedLk sync.Mutex
|
|
||||||
schedPost uint64
|
schedPost uint64
|
||||||
|
|
||||||
|
// Sealing
|
||||||
|
sectors *statestore.StateStore
|
||||||
|
|
||||||
|
sectorIncoming chan *SectorInfo
|
||||||
|
sectorUpdated chan sectorUpdate
|
||||||
|
stop chan struct{}
|
||||||
|
stopped chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
type storageMinerApi interface {
|
type storageMinerApi interface {
|
||||||
@ -72,8 +77,9 @@ func NewMiner(api storageMinerApi, addr address.Address, h host.Host, ds datasto
|
|||||||
|
|
||||||
maddr: addr,
|
maddr: addr,
|
||||||
h: h,
|
h: h,
|
||||||
ds: ds,
|
|
||||||
secst: secst,
|
secst: secst,
|
||||||
|
|
||||||
|
sectors: statestore.New(namespace.Wrap(ds, datastore.NewKey("/sectors"))),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,11 +91,18 @@ func (m *Miner) Run(ctx context.Context) error {
|
|||||||
m.events = events.NewEvents(ctx, m.api)
|
m.events = events.NewEvents(ctx, m.api)
|
||||||
|
|
||||||
go m.beginPosting(ctx)
|
go m.beginPosting(ctx)
|
||||||
|
go m.sectorStateLoop(ctx)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Miner) commitSector(ctx context.Context, sinfo sectorbuilder.SectorSealingStatus) error {
|
func (m *Miner) Stop(ctx context.Context) error {
|
||||||
return m.SealSector(ctx, sinfo.SectorID)
|
close(m.stop)
|
||||||
|
select {
|
||||||
|
case <-m.stopped:
|
||||||
|
return nil
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Miner) runPreflightChecks(ctx context.Context) error {
|
func (m *Miner) runPreflightChecks(ctx context.Context) error {
|
||||||
|
@ -30,10 +30,10 @@ func (m *Miner) beginPosting(ctx context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
m.schedLk.Lock()
|
m.postLk.Lock()
|
||||||
if m.schedPost > 0 {
|
if m.schedPost > 0 {
|
||||||
log.Warnf("PoSts already running %d", m.schedPost)
|
log.Warnf("PoSts already running %d", m.schedPost)
|
||||||
m.schedLk.Unlock()
|
m.postLk.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ func (m *Miner) beginPosting(ctx context.Context) {
|
|||||||
ppe, _ = actors.ProvingPeriodEnd(ppe, ts.Height()+1)
|
ppe, _ = actors.ProvingPeriodEnd(ppe, ts.Height()+1)
|
||||||
m.schedPost = ppe
|
m.schedPost = ppe
|
||||||
|
|
||||||
m.schedLk.Unlock()
|
m.postLk.Unlock()
|
||||||
|
|
||||||
log.Infof("Scheduling post at height %d", ppe-build.PoStChallangeTime)
|
log.Infof("Scheduling post at height %d", ppe-build.PoStChallangeTime)
|
||||||
err = m.events.ChainAt(m.computePost(m.schedPost), func(ts *types.TipSet) error { // Revert
|
err = m.events.ChainAt(m.computePost(m.schedPost), func(ts *types.TipSet) error { // Revert
|
||||||
@ -71,16 +71,16 @@ func (m *Miner) scheduleNextPost(ppe uint64) {
|
|||||||
ppe = headPPE
|
ppe = headPPE
|
||||||
}
|
}
|
||||||
|
|
||||||
m.schedLk.Lock()
|
m.postLk.Lock()
|
||||||
if m.schedPost >= ppe {
|
if m.schedPost >= ppe {
|
||||||
// this probably can't happen
|
// this probably can't happen
|
||||||
log.Errorw("PoSt already scheduled", "schedPost", m.schedPost, "ppe", ppe)
|
log.Errorw("PoSt already scheduled", "schedPost", m.schedPost, "ppe", ppe)
|
||||||
m.schedLk.Unlock()
|
m.postLk.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
m.schedPost = ppe
|
m.schedPost = ppe
|
||||||
m.schedLk.Unlock()
|
m.postLk.Unlock()
|
||||||
|
|
||||||
log.Infow("scheduling PoSt", "post-height", ppe-build.PoStChallangeTime,
|
log.Infow("scheduling PoSt", "post-height", ppe-build.PoStChallangeTime,
|
||||||
"height", ts.Height(), "ppe", ppe, "proving-period", provingPeriod)
|
"height", ts.Height(), "ppe", ppe, "proving-period", provingPeriod)
|
||||||
|
@ -2,154 +2,120 @@ package storage
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"github.com/filecoin-project/lotus/api"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/build"
|
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
cid "github.com/ipfs/go-cid"
|
cid "github.com/ipfs/go-cid"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (m *Miner) SealSector(ctx context.Context, sid uint64) error {
|
type SealTicket struct {
|
||||||
log.Info("committing sector: ", sid)
|
BlockHeight uint64
|
||||||
|
TicketBytes []byte
|
||||||
ssize, err := m.SectorSize(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("failed to check out own sector size: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = ssize
|
|
||||||
|
|
||||||
log.Info("performing sector replication...")
|
|
||||||
if err := m.secst.SealPreCommit(ctx, sid); err != nil {
|
|
||||||
return xerrors.Errorf("seal pre commit failed: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
sinfo, err := m.secst.SectorStatus(sid)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("failed to check status for sector %d: %w", sid, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
params := &actors.SectorPreCommitInfo{
|
|
||||||
CommD: sinfo.CommD[:],
|
|
||||||
CommR: sinfo.CommR[:],
|
|
||||||
Epoch: sinfo.Ticket.BlockHeight,
|
|
||||||
|
|
||||||
//DealIDs: deals,
|
|
||||||
SectorNumber: sinfo.SectorID,
|
|
||||||
}
|
|
||||||
enc, aerr := actors.SerializeParams(params)
|
|
||||||
if aerr != nil {
|
|
||||||
return errors.Wrap(aerr, "could not serialize commit sector parameters")
|
|
||||||
}
|
|
||||||
|
|
||||||
msg := &types.Message{
|
|
||||||
To: m.maddr,
|
|
||||||
From: m.worker,
|
|
||||||
Method: actors.MAMethods.PreCommitSector,
|
|
||||||
Params: enc,
|
|
||||||
Value: types.NewInt(0), // TODO: need to ensure sufficient collateral
|
|
||||||
GasLimit: types.NewInt(1000000 /* i dont know help */),
|
|
||||||
GasPrice: types.NewInt(1),
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Info("submitting precommit for sector: ", sid)
|
|
||||||
smsg, err := m.api.MpoolPushMessage(ctx, msg)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "pushing message to mpool")
|
|
||||||
}
|
|
||||||
|
|
||||||
go m.waitForPreCommitMessage(context.TODO(), sinfo.SectorID, smsg.Cid())
|
|
||||||
|
|
||||||
// TODO: maybe return a wait channel?
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Miner) waitForPreCommitMessage(ctx context.Context, sid uint64, mcid cid.Cid) {
|
type SectorInfo struct {
|
||||||
// would be ideal to just use the events.Called handler, but it wouldnt be able to handle individual message timeouts
|
State api.SectorState
|
||||||
mw, err := m.api.StateWaitMsg(ctx, mcid)
|
SectorID uint64
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if mw.Receipt.ExitCode != 0 {
|
// PreCommit
|
||||||
log.Error("sector precommit failed: ", mw.Receipt.ExitCode)
|
CommD []byte
|
||||||
return
|
CommR []byte
|
||||||
}
|
Ticket SealTicket
|
||||||
|
|
||||||
randHeight := mw.TipSet.Height() + build.InteractivePoRepDelay
|
PreCommitMessage *cid.Cid
|
||||||
log.Infof("precommit for sector %d made it on chain, will start post computation at height %d", sid, randHeight)
|
|
||||||
|
|
||||||
err = m.events.ChainAt(func(ts *types.TipSet, curH uint64) error {
|
// PreCommitted
|
||||||
return m.scheduleComputeProof(ctx, sid, ts, randHeight)
|
RandHeight uint64
|
||||||
}, func(ts *types.TipSet) error {
|
RandTs *types.TipSet
|
||||||
log.Warn("revert in interactive commit sector step")
|
|
||||||
return nil
|
// Committing
|
||||||
}, 3, mw.TipSet.Height()+build.InteractivePoRepDelay)
|
CommitMessage *cid.Cid
|
||||||
if err != nil {
|
|
||||||
log.Warn("waitForPreCommitMessage ChainAt errored: ", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Miner) scheduleComputeProof(ctx context.Context, sid uint64, ts *types.TipSet, rheight uint64) error {
|
type sectorUpdate struct {
|
||||||
log.Info("scheduling post computation...")
|
newState api.SectorState
|
||||||
|
id uint64
|
||||||
|
err error
|
||||||
|
mut func(*SectorInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Miner) sectorStateLoop(ctx context.Context) {
|
||||||
|
// TODO: restore state
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
rand, err := m.api.ChainGetRandomness(ctx, ts, nil, int(ts.Height()-rheight))
|
defer log.Warn("quitting deal provider loop")
|
||||||
if err != nil {
|
defer close(m.stopped)
|
||||||
log.Error(fmt.Errorf("failed to get randomness for computing seal proof: %w", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
proof, err := m.secst.SealComputeProof(ctx, sid, rheight, rand)
|
for {
|
||||||
if err != nil {
|
select {
|
||||||
log.Error(fmt.Errorf("computing seal proof failed: %w", err))
|
case sector := <-m.sectorIncoming:
|
||||||
return
|
m.onSectorIncoming(sector)
|
||||||
|
case update := <-m.sectorUpdated:
|
||||||
|
m.onSectorUpdated(ctx, update)
|
||||||
|
case <-m.stop:
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
params := &actors.SectorProveCommitInfo{
|
|
||||||
Proof: proof,
|
|
||||||
SectorID: sid,
|
|
||||||
//DealIDs: deals,
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = params
|
|
||||||
enc, aerr := actors.SerializeParams(nil)
|
|
||||||
if aerr != nil {
|
|
||||||
log.Error(errors.Wrap(aerr, "could not serialize commit sector parameters"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
msg := &types.Message{
|
|
||||||
To: m.maddr,
|
|
||||||
From: m.worker,
|
|
||||||
Method: actors.MAMethods.ProveCommitSector,
|
|
||||||
Params: enc,
|
|
||||||
Value: types.NewInt(0), // TODO: need to ensure sufficient collateral
|
|
||||||
GasLimit: types.NewInt(1000000 /* i dont know help */),
|
|
||||||
GasPrice: types.NewInt(1),
|
|
||||||
}
|
|
||||||
|
|
||||||
smsg, err := m.api.MpoolPushMessage(ctx, msg)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(errors.Wrap(err, "pushing message to mpool"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: now wait for this to get included and handle errors?
|
|
||||||
mw, err := m.api.StateWaitMsg(ctx, smsg.Cid())
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed to wait for porep inclusion: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if mw.Receipt.ExitCode != 0 {
|
|
||||||
log.Error("UNHANDLED: submitting sector proof failed")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
m.beginPosting(ctx)
|
|
||||||
}()
|
}()
|
||||||
|
}
|
||||||
return nil
|
|
||||||
|
func (m *Miner) onSectorIncoming(sector *SectorInfo) {
|
||||||
|
if err := m.sectors.Begin(sector.SectorID, sector); err != nil {
|
||||||
|
// We may have re-sent the proposal
|
||||||
|
log.Errorf("deal tracking failed: %s", err)
|
||||||
|
m.failSector(sector.SectorID, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
m.sectorUpdated <- sectorUpdate{
|
||||||
|
newState: api.Unsealed,
|
||||||
|
id: sector.SectorID,
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Miner) onSectorUpdated(ctx context.Context, update sectorUpdate) {
|
||||||
|
log.Infof("Sector %s updated state to %s", update.id, api.SectorStateStr(update.newState))
|
||||||
|
var sector SectorInfo
|
||||||
|
err := m.sectors.Mutate(update.id, func(s *SectorInfo) error {
|
||||||
|
s.State = update.newState
|
||||||
|
sector = *s
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if update.err != nil {
|
||||||
|
log.Errorf("deal %s failed: %s", update.id, update.err)
|
||||||
|
m.failSector(update.id, update.err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
m.failSector(update.id, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch update.newState {
|
||||||
|
case api.Unsealed:
|
||||||
|
m.handle(ctx, sector, m.sealPreCommit, api.PreCommitting)
|
||||||
|
case api.PreCommitting:
|
||||||
|
m.handle(ctx, sector, m.preCommit, api.PreCommitted)
|
||||||
|
case api.PreCommitted:
|
||||||
|
m.handle(ctx, sector, m.preCommitted, api.SectorNoUpdate)
|
||||||
|
case api.Committing:
|
||||||
|
m.handle(ctx, sector, m.committing, api.Proving)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Miner) failSector(id uint64, err error) {
|
||||||
|
panic(err) // todo: better error handling strategy
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Miner) SealSector(ctx context.Context, sid uint64) error {
|
||||||
|
select {
|
||||||
|
case m.sectorIncoming <- &SectorInfo{
|
||||||
|
State: api.UndefinedSectorState,
|
||||||
|
SectorID: sid,
|
||||||
|
}:
|
||||||
|
return nil
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,19 +131,13 @@ func (s *Store) DealsForCommit(sectorID uint64) ([]uint64, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) SealPreCommit(ctx context.Context, sectorID uint64) error {
|
func (s *Store) SealPreCommit(ctx context.Context, sectorID uint64) (sectorbuilder.SealPreCommitOutput, error) {
|
||||||
tkt, err := s.tktFn(ctx)
|
tkt, err := s.tktFn(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return sectorbuilder.SealPreCommitOutput{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: That's not async, is it?
|
return s.sb.SealPreCommit(sectorID, *tkt)
|
||||||
// - If not then we probably can drop this wait-for-seal hack below
|
|
||||||
_, err = s.sb.SealPreCommit(sectorID, *tkt)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) SealComputeProof(ctx context.Context, sectorID uint64, height uint64, rand []byte) ([]byte, error) {
|
func (s *Store) SealComputeProof(ctx context.Context, sectorID uint64, height uint64, rand []byte) ([]byte, error) {
|
||||||
@ -160,7 +154,7 @@ func (s *Store) SealComputeProof(ctx context.Context, sectorID uint64, height ui
|
|||||||
return sco.Proof, nil
|
return sco.Proof, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) Commited() ([]sectorbuilder.SectorSealingStatus, error) {
|
func (s *Store) Committed() ([]sectorbuilder.SectorSealingStatus, error) {
|
||||||
l, err := s.sb.GetAllStagedSectors()
|
l, err := s.sb.GetAllStagedSectors()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
183
storage/sector_states.go
Normal file
183
storage/sector_states.go
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/filecoin-project/lotus/build"
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors"
|
||||||
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
type providerHandlerFunc func(ctx context.Context, deal SectorInfo) (func(*SectorInfo), error)
|
||||||
|
|
||||||
|
func (m *Miner) handle(ctx context.Context, sector SectorInfo, cb providerHandlerFunc, next api.SectorState) {
|
||||||
|
go func() {
|
||||||
|
mut, err := cb(ctx, sector)
|
||||||
|
|
||||||
|
if err == nil && next == api.SectorNoUpdate {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case m.sectorUpdated <- sectorUpdate{
|
||||||
|
newState: next,
|
||||||
|
id: sector.SectorID,
|
||||||
|
err: err,
|
||||||
|
mut: mut,
|
||||||
|
}:
|
||||||
|
case <-m.stop:
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Miner) sealPreCommit(ctx context.Context, sector SectorInfo) (func(*SectorInfo), error) {
|
||||||
|
log.Infow("performing sector replication...", "sector", sector.SectorID)
|
||||||
|
sinfo, err := m.secst.SealPreCommit(ctx, sector.SectorID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("seal pre commit failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return func(info *SectorInfo) {
|
||||||
|
info.CommD = sinfo.CommD[:]
|
||||||
|
info.CommR = sinfo.CommR[:]
|
||||||
|
info.Ticket = SealTicket{
|
||||||
|
BlockHeight: sinfo.Ticket.BlockHeight,
|
||||||
|
TicketBytes: sinfo.Ticket.TicketBytes[:],
|
||||||
|
}
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Miner) preCommit(ctx context.Context, sector SectorInfo) (func(*SectorInfo), error) {
|
||||||
|
params := &actors.SectorPreCommitInfo{
|
||||||
|
CommD: sector.CommD,
|
||||||
|
CommR: sector.CommR,
|
||||||
|
Epoch: sector.Ticket.BlockHeight,
|
||||||
|
|
||||||
|
SectorNumber: sector.SectorID,
|
||||||
|
}
|
||||||
|
enc, aerr := actors.SerializeParams(params)
|
||||||
|
if aerr != nil {
|
||||||
|
return nil, xerrors.Errorf("could not serialize commit sector parameters: %w", aerr)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := &types.Message{
|
||||||
|
To: m.maddr,
|
||||||
|
From: m.worker,
|
||||||
|
Method: actors.MAMethods.PreCommitSector,
|
||||||
|
Params: enc,
|
||||||
|
Value: types.NewInt(0), // TODO: need to ensure sufficient collateral
|
||||||
|
GasLimit: types.NewInt(1000000 /* i dont know help */),
|
||||||
|
GasPrice: types.NewInt(1),
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("submitting precommit for sector: ", sector.SectorID)
|
||||||
|
smsg, err := m.api.MpoolPushMessage(ctx, msg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("pushing message to mpool: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return func(info *SectorInfo) {
|
||||||
|
mcid := smsg.Cid()
|
||||||
|
info.PreCommitMessage = &mcid
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Miner) preCommitted(ctx context.Context, sector SectorInfo) (func(*SectorInfo), error) {
|
||||||
|
// would be ideal to just use the events.Called handler, but it wouldnt be able to handle individual message timeouts
|
||||||
|
mw, err := m.api.StateWaitMsg(ctx, *sector.PreCommitMessage)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if mw.Receipt.ExitCode != 0 {
|
||||||
|
log.Error("sector precommit failed: ", mw.Receipt.ExitCode)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
randHeight := mw.TipSet.Height() + build.InteractivePoRepDelay
|
||||||
|
log.Infof("precommit for sector %d made it on chain, will start post computation at height %d", sector.SectorID, randHeight)
|
||||||
|
|
||||||
|
err = m.events.ChainAt(func(ts *types.TipSet, curH uint64) error {
|
||||||
|
m.sectorUpdated <- sectorUpdate{
|
||||||
|
newState: api.Committing,
|
||||||
|
id: sector.SectorID,
|
||||||
|
mut: func(info *SectorInfo) {
|
||||||
|
info.RandHeight = randHeight
|
||||||
|
info.RandTs = ts
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}, func(ts *types.TipSet) error {
|
||||||
|
log.Warn("revert in interactive commit sector step")
|
||||||
|
return nil
|
||||||
|
}, 3, mw.TipSet.Height()+build.InteractivePoRepDelay)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("waitForPreCommitMessage ChainAt errored: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Miner) committing(ctx context.Context, sector SectorInfo) (func(*SectorInfo), error) {
|
||||||
|
log.Info("scheduling seal proof computation...")
|
||||||
|
|
||||||
|
rand, err := m.api.ChainGetRandomness(ctx, sector.RandTs, nil, int(sector.RandTs.Height()-sector.RandHeight))
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("failed to get randomness for computing seal proof: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
proof, err := m.secst.SealComputeProof(ctx, sector.SectorID, sector.RandHeight, rand)
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("computing seal proof failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
params := &actors.SectorProveCommitInfo{
|
||||||
|
Proof: proof,
|
||||||
|
SectorID: sector.SectorID,
|
||||||
|
//DealIDs: deals,
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = params
|
||||||
|
enc, aerr := actors.SerializeParams(nil)
|
||||||
|
if aerr != nil {
|
||||||
|
return nil, xerrors.Errorf("could not serialize commit sector parameters: %w", aerr)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := &types.Message{
|
||||||
|
To: m.maddr,
|
||||||
|
From: m.worker,
|
||||||
|
Method: actors.MAMethods.ProveCommitSector,
|
||||||
|
Params: enc,
|
||||||
|
Value: types.NewInt(0), // TODO: need to ensure sufficient collateral
|
||||||
|
GasLimit: types.NewInt(1000000 /* i dont know help */),
|
||||||
|
GasPrice: types.NewInt(1),
|
||||||
|
}
|
||||||
|
|
||||||
|
smsg, err := m.api.MpoolPushMessage(ctx, msg)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(errors.Wrap(err, "pushing message to mpool"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Separate state before this wait, so we persist message cid?
|
||||||
|
|
||||||
|
mw, err := m.api.StateWaitMsg(ctx, smsg.Cid())
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("failed to wait for porep inclusion: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if mw.Receipt.ExitCode != 0 {
|
||||||
|
log.Error("UNHANDLED: submitting sector proof failed")
|
||||||
|
return nil, xerrors.New("UNHANDLED: submitting sector proof failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
m.beginPosting(ctx)
|
||||||
|
|
||||||
|
return func(info *SectorInfo) {
|
||||||
|
mcid := smsg.Cid()
|
||||||
|
info.CommitMessage = &mcid
|
||||||
|
}, nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user