This commit is contained in:
Raúl Kripalani 2020-07-20 14:45:17 +01:00
parent 4d2d8b2d11
commit 226786c1da
13 changed files with 210 additions and 42 deletions

View File

@ -375,7 +375,7 @@ type FileRef struct {
type MinerSectors struct { type MinerSectors struct {
Sectors uint64 Sectors uint64
Active uint64 Active uint64
} }
type SectorExpiration struct { type SectorExpiration struct {

View File

@ -127,7 +127,7 @@ type FullNodeStruct struct {
StateNetworkName func(context.Context) (dtypes.NetworkName, error) `perm:"read"` StateNetworkName func(context.Context) (dtypes.NetworkName, error) `perm:"read"`
StateMinerSectors func(context.Context, address.Address, *abi.BitField, bool, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"` StateMinerSectors func(context.Context, address.Address, *abi.BitField, bool, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"`
StateMinerActiveSectors func(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"` StateMinerActiveSectors func(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"`
StateMinerProvingDeadline func(context.Context, address.Address, types.TipSetKey) (*miner.DeadlineInfo, error) `perm:"read"` StateMinerProvingDeadline func(context.Context, address.Address, types.TipSetKey) (*miner.DeadlineInfo, error) `perm:"read"`
StateMinerPower func(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error) `perm:"read"` StateMinerPower func(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error) `perm:"read"`
StateMinerInfo func(context.Context, address.Address, types.TipSetKey) (api.MinerInfo, error) `perm:"read"` StateMinerInfo func(context.Context, address.Address, types.TipSetKey) (api.MinerInfo, error) `perm:"read"`

View File

@ -209,7 +209,7 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
// var newAddress address.Address // var newAddress address.Address
if (info.Type == genesis.TAccount) { if info.Type == genesis.TAccount {
var ainfo genesis.AccountMeta var ainfo genesis.AccountMeta
if err := json.Unmarshal(info.Meta, &ainfo); err != nil { if err := json.Unmarshal(info.Meta, &ainfo); err != nil {
return nil, xerrors.Errorf("unmarshaling account meta: %w", err) return nil, xerrors.Errorf("unmarshaling account meta: %w", err)
@ -226,7 +226,7 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
if err != nil { if err != nil {
return nil, xerrors.Errorf("setting account from actmap: %w", err) return nil, xerrors.Errorf("setting account from actmap: %w", err)
} }
} else if (info.Type == genesis.TMultisig) { } else if info.Type == genesis.TMultisig {
var ainfo genesis.MultisigMeta var ainfo genesis.MultisigMeta
if err := json.Unmarshal(info.Meta, &ainfo); err != nil { if err := json.Unmarshal(info.Meta, &ainfo); err != nil {
return nil, xerrors.Errorf("unmarshaling account meta: %w", err) return nil, xerrors.Errorf("unmarshaling account meta: %w", err)
@ -238,12 +238,12 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
} }
st, err := cst.Put(ctx, &multisig.State{ st, err := cst.Put(ctx, &multisig.State{
Signers: ainfo.Signers, Signers: ainfo.Signers,
NumApprovalsThreshold: uint64(ainfo.Threshold), NumApprovalsThreshold: uint64(ainfo.Threshold),
StartEpoch: abi.ChainEpoch(ainfo.VestingStart), StartEpoch: abi.ChainEpoch(ainfo.VestingStart),
UnlockDuration: abi.ChainEpoch(ainfo.VestingDuration), UnlockDuration: abi.ChainEpoch(ainfo.VestingDuration),
PendingTxns: pending, PendingTxns: pending,
InitialBalance: info.Balance, InitialBalance: info.Balance,
}) })
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -59,6 +59,15 @@ const (
evtTypeHeadChange = iota evtTypeHeadChange = iota
) )
type HeadChangeEvt struct {
From types.TipSetKey
FromHeight abi.ChainEpoch
To types.TipSetKey
ToHeight abi.ChainEpoch
RevertCount int
ApplyCount int
}
// ChainStore is the main point of access to chain data. // ChainStore is the main point of access to chain data.
// //
// Raw chain data is stored in the Blockstore, with relevant markers (genesis, // Raw chain data is stored in the Blockstore, with relevant markers (genesis,
@ -340,7 +349,7 @@ func (cs *ChainStore) reorgWorker(ctx context.Context, initialNotifees []ReorgNo
} }
journal.MaybeAddEntry(cs.journal, cs.evtTypes[evtTypeHeadChange], func() interface{} { journal.MaybeAddEntry(cs.journal, cs.evtTypes[evtTypeHeadChange], func() interface{} {
return journal.HeadChangeEvt{ return HeadChangeEvt{
From: r.old.Key(), From: r.old.Key(),
FromHeight: r.old.Height(), FromHeight: r.old.Height(),
To: r.new.Key(), To: r.new.Key(),

View File

@ -1,16 +0,0 @@
package journal
import (
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/lotus/chain/types"
)
type HeadChangeEvt struct {
From types.TipSetKey `json:"from"`
FromHeight abi.ChainEpoch `json:"from_height"`
To types.TipSetKey `json:"to"`
ToHeight abi.ChainEpoch `json:"to_height"`
RevertCount int `json:"rev_cnt"`
ApplyCount int `json:"apply_cnt"`
}

View File

@ -37,7 +37,7 @@ type fsJournal struct {
// OpenFSJournal constructs a rolling filesystem journal, with a default // OpenFSJournal constructs a rolling filesystem journal, with a default
// per-file size limit of 1GiB. // per-file size limit of 1GiB.
func OpenFSJournal(lr repo.LockedRepo, lc fx.Lifecycle, disabled []EventType) (Journal, error) { func OpenFSJournal(lr repo.LockedRepo, lc fx.Lifecycle, disabled DisabledEvents) (Journal, error) {
dir := filepath.Join(lr.Path(), "journal") dir := filepath.Join(lr.Path(), "journal")
if err := os.MkdirAll(dir, 0755); err != nil { if err := os.MkdirAll(dir, 0755); err != nil {
return nil, fmt.Errorf("failed to mk directory %s for file journal: %w", dir, err) return nil, fmt.Errorf("failed to mk directory %s for file journal: %w", dir, err)

View File

@ -50,7 +50,7 @@ func (o *observer) dispatch(entry *Entry) {
} }
} }
func NewMemoryJournal(lc fx.Lifecycle, disabled []EventType) *MemJournal { func NewMemoryJournal(lc fx.Lifecycle, disabled DisabledEvents) *MemJournal {
m := &MemJournal{ m := &MemJournal{
eventTypeFactory: newEventTypeFactory(disabled), eventTypeFactory: newEventTypeFactory(disabled),

View File

@ -5,6 +5,9 @@ import (
"time" "time"
) )
// DisabledEvents is the set of event types whose journaling is suppressed.
type DisabledEvents []EventType
// EventType represents the signature of an event. // EventType represents the signature of an event.
type EventType struct { type EventType struct {
System string System string
@ -70,7 +73,7 @@ type eventTypeFactory struct {
m map[string]EventType m map[string]EventType
} }
func newEventTypeFactory(disabled []EventType) *eventTypeFactory { func newEventTypeFactory(disabled DisabledEvents) *eventTypeFactory {
ret := &eventTypeFactory{ ret := &eventTypeFactory{
m: make(map[string]EventType, len(disabled)+32), // + extra capacity. m: make(map[string]EventType, len(disabled)+32), // + extra capacity.
} }

View File

@ -153,6 +153,7 @@ func defaults() []Option {
Override(new(dtypes.Bootstrapper), dtypes.Bootstrapper(false)), Override(new(dtypes.Bootstrapper), dtypes.Bootstrapper(false)),
Override(new(dtypes.ShutdownChan), make(chan struct{})), Override(new(dtypes.ShutdownChan), make(chan struct{})),
Override(new(journal.Journal), journal.OpenFSJournal), Override(new(journal.Journal), journal.OpenFSJournal),
Override(new(journal.DisabledEvents), journal.DisabledEvents{}),
Override(InitJournalKey, func(j *journal.Journal) { /* forces the creation of the journal at startup */ }), Override(InitJournalKey, func(j *journal.Journal) { /* forces the creation of the journal at startup */ }),
// Filecoin modules // Filecoin modules

View File

@ -42,6 +42,7 @@ import (
paramfetch "github.com/filecoin-project/go-paramfetch" paramfetch "github.com/filecoin-project/go-paramfetch"
"github.com/filecoin-project/go-statestore" "github.com/filecoin-project/go-statestore"
"github.com/filecoin-project/go-storedcounter" "github.com/filecoin-project/go-storedcounter"
"github.com/filecoin-project/lotus/journal"
"github.com/filecoin-project/lotus/node/config" "github.com/filecoin-project/lotus/node/config"
sectorstorage "github.com/filecoin-project/sector-storage" sectorstorage "github.com/filecoin-project/sector-storage"
"github.com/filecoin-project/sector-storage/ffiwrapper" "github.com/filecoin-project/sector-storage/ffiwrapper"
@ -137,7 +138,34 @@ func SectorIDCounter(ds dtypes.MetadataDS) sealing.SectorIDCounter {
return &sidsc{sc} return &sidsc{sc}
} }
func StorageMiner(mctx helpers.MetricsCtx, lc fx.Lifecycle, api lapi.FullNode, h host.Host, ds dtypes.MetadataDS, sealer sectorstorage.SectorManager, sc sealing.SectorIDCounter, verif ffiwrapper.Verifier, gsd dtypes.GetSealingDelayFunc) (*storage.Miner, error) { type StorageMinerParams struct {
fx.In
Lifecycle fx.Lifecycle
MetricsCtx helpers.MetricsCtx
API lapi.FullNode
Host host.Host
MetadataDS dtypes.MetadataDS
Sealer sectorstorage.SectorManager
SectorIDCounter sealing.SectorIDCounter
Verifier ffiwrapper.Verifier
GetSealingDelayFn dtypes.GetSealingDelayFunc
Journal journal.Journal
}
func StorageMiner(params StorageMinerParams) (*storage.Miner, error) {
var (
ds = params.MetadataDS
mctx = params.MetricsCtx
lc = params.Lifecycle
api = params.API
sealer = params.Sealer
h = params.Host
sc = params.SectorIDCounter
verif = params.Verifier
gsd = params.GetSealingDelayFn
jrnl = params.Journal
)
maddr, err := minerAddrFromDS(ds) maddr, err := minerAddrFromDS(ds)
if err != nil { if err != nil {
return nil, err return nil, err
@ -155,7 +183,7 @@ func StorageMiner(mctx helpers.MetricsCtx, lc fx.Lifecycle, api lapi.FullNode, h
return nil, err return nil, err
} }
fps, err := storage.NewWindowedPoStScheduler(api, sealer, sealer, maddr, worker) fps, err := storage.NewWindowedPoStScheduler(api, sealer, sealer, maddr, worker, jrnl)
if err != nil { if err != nil {
return nil, err return nil, err
} }

34
storage/journal_events.go Normal file
View File

@ -0,0 +1,34 @@
package storage
import (
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/ipfs/go-cid"
)
type WindowPoStEvt struct {
State string
Deadline *miner.DeadlineInfo
Height abi.ChainEpoch
TipSet []cid.Cid
Error error `json:",omitempty"`
Proofs *WindowPoStEvt_Proofs `json:",omitempty"`
Recoveries *WindowPoStEvt_Recoveries `json:",omitempty"`
Faults *WindowPoStEvt_Faults `json:",omitempty"`
}
type WindowPoStEvt_Proofs struct {
Partitions []miner.PoStPartition
MessageCID cid.Cid
}
type WindowPoStEvt_Recoveries struct {
Declarations []miner.RecoveryDeclaration
MessageCID cid.Cid
}
type WindowPoStEvt_Faults struct {
Declarations []miner.FaultDeclaration
MessageCID cid.Cid
}

View File

@ -14,17 +14,29 @@ import (
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/miner" "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/crypto" "github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/ipfs/go-cid"
"go.opencensus.io/trace" "go.opencensus.io/trace"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/journal"
) )
var errNoPartitions = errors.New("no partitions") var errNoPartitions = errors.New("no partitions")
func (s *WindowPoStScheduler) failPost(deadline *miner.DeadlineInfo) { func (s *WindowPoStScheduler) failPost(err error, deadline *miner.DeadlineInfo) {
journal.MaybeAddEntry(s.jrnl, s.evtTypes[evtTypeWindowPoSt], func() interface{} {
return WindowPoStEvt{
State: "failed",
Deadline: s.activeDeadline,
Height: s.cur.Height(),
TipSet: s.cur.Cids(),
Error: err,
}
})
log.Errorf("TODO") log.Errorf("TODO")
/*s.failLk.Lock() /*s.failLk.Lock()
if eps > s.failed { if eps > s.failed {
@ -39,6 +51,15 @@ func (s *WindowPoStScheduler) doPost(ctx context.Context, deadline *miner.Deadli
s.abort = abort s.abort = abort
s.activeDeadline = deadline s.activeDeadline = deadline
journal.MaybeAddEntry(s.jrnl, s.evtTypes[evtTypeWindowPoSt], func() interface{} {
return WindowPoStEvt{
State: "started",
Deadline: s.activeDeadline,
Height: s.cur.Height(),
TipSet: s.cur.Cids(),
}
})
go func() { go func() {
defer abort() defer abort()
@ -52,14 +73,23 @@ func (s *WindowPoStScheduler) doPost(ctx context.Context, deadline *miner.Deadli
case nil: case nil:
if err := s.submitPost(ctx, proof); err != nil { if err := s.submitPost(ctx, proof); err != nil {
log.Errorf("submitPost failed: %+v", err) log.Errorf("submitPost failed: %+v", err)
s.failPost(deadline) s.failPost(err, deadline)
return return
} }
default: default:
log.Errorf("runPost failed: %+v", err) log.Errorf("runPost failed: %+v", err)
s.failPost(deadline) s.failPost(err, deadline)
return return
} }
journal.MaybeAddEntry(s.jrnl, s.evtTypes[evtTypeWindowPoSt], func() interface{} {
return WindowPoStEvt{
State: "succeeded",
Deadline: s.activeDeadline,
Height: s.cur.Height(),
TipSet: s.cur.Cids(),
}
})
}() }()
} }
@ -112,11 +142,29 @@ func (s *WindowPoStScheduler) checkNextRecoveries(ctx context.Context, dlIdx uin
ctx, span := trace.StartSpan(ctx, "storage.checkNextRecoveries") ctx, span := trace.StartSpan(ctx, "storage.checkNextRecoveries")
defer span.End() defer span.End()
var sm *types.SignedMessage
faulty := uint64(0)
params := &miner.DeclareFaultsRecoveredParams{ params := &miner.DeclareFaultsRecoveredParams{
Recoveries: []miner.RecoveryDeclaration{}, Recoveries: []miner.RecoveryDeclaration{},
} }
faulty := uint64(0) defer journal.MaybeAddEntry(s.jrnl, s.evtTypes[evtTypeWindowPoSt], func() interface{} {
var mcid cid.Cid
if sm != nil {
mcid = sm.Cid()
}
return WindowPoStEvt{
State: "recoveries_processed",
Deadline: s.activeDeadline,
Height: s.cur.Height(),
TipSet: s.cur.Cids(),
Recoveries: &WindowPoStEvt_Recoveries{
Declarations: params.Recoveries,
MessageCID: mcid,
},
}
})
for partIdx, partition := range partitions { for partIdx, partition := range partitions {
unrecovered, err := bitfield.SubtractBitField(partition.Faults, partition.Recoveries) unrecovered, err := bitfield.SubtractBitField(partition.Faults, partition.Recoveries)
@ -180,7 +228,8 @@ func (s *WindowPoStScheduler) checkNextRecoveries(ctx context.Context, dlIdx uin
GasPrice: types.NewInt(2), GasPrice: types.NewInt(2),
} }
sm, err := s.api.MpoolPushMessage(ctx, msg) var err error
sm, err = s.api.MpoolPushMessage(ctx, msg)
if err != nil { if err != nil {
return xerrors.Errorf("pushing message to mpool: %w", err) return xerrors.Errorf("pushing message to mpool: %w", err)
} }
@ -203,11 +252,28 @@ func (s *WindowPoStScheduler) checkNextFaults(ctx context.Context, dlIdx uint64,
ctx, span := trace.StartSpan(ctx, "storage.checkNextFaults") ctx, span := trace.StartSpan(ctx, "storage.checkNextFaults")
defer span.End() defer span.End()
var sm *types.SignedMessage
bad := uint64(0)
params := &miner.DeclareFaultsParams{ params := &miner.DeclareFaultsParams{
Faults: []miner.FaultDeclaration{}, Faults: []miner.FaultDeclaration{},
} }
bad := uint64(0) defer journal.MaybeAddEntry(s.jrnl, s.evtTypes[evtTypeWindowPoSt], func() interface{} {
var mcid cid.Cid
if sm != nil {
mcid = sm.Cid()
}
return WindowPoStEvt{
State: "faults_processed",
Deadline: s.activeDeadline,
Height: s.cur.Height(),
TipSet: s.cur.Cids(),
Faults: &WindowPoStEvt_Faults{
Declarations: params.Faults,
MessageCID: mcid,
},
}
})
for partIdx, partition := range partitions { for partIdx, partition := range partitions {
toCheck, err := partition.ActiveSectors() toCheck, err := partition.ActiveSectors()
@ -264,7 +330,8 @@ func (s *WindowPoStScheduler) checkNextFaults(ctx context.Context, dlIdx uint64,
GasPrice: types.NewInt(2), GasPrice: types.NewInt(2),
} }
sm, err := s.api.MpoolPushMessage(ctx, msg) var err error
sm, err = s.api.MpoolPushMessage(ctx, msg)
if err != nil { if err != nil {
return xerrors.Errorf("pushing message to mpool: %w", err) return xerrors.Errorf("pushing message to mpool: %w", err)
} }
@ -450,6 +517,26 @@ func (s *WindowPoStScheduler) submitPost(ctx context.Context, proof *miner.Submi
ctx, span := trace.StartSpan(ctx, "storage.commitPost") ctx, span := trace.StartSpan(ctx, "storage.commitPost")
defer span.End() defer span.End()
var sm *types.SignedMessage
defer journal.MaybeAddEntry(s.jrnl, s.evtTypes[evtTypeWindowPoSt], func() interface{} {
var mcid cid.Cid
if sm != nil {
mcid = sm.Cid()
}
return WindowPoStEvt{
State: "proofs_processed",
Deadline: s.activeDeadline,
Height: s.cur.Height(),
TipSet: s.cur.Cids(),
Proofs: &WindowPoStEvt_Proofs{
Partitions: proof.Partitions,
MessageCID: mcid,
},
}
})
enc, aerr := actors.SerializeParams(proof) enc, aerr := actors.SerializeParams(proof)
if aerr != nil { if aerr != nil {
return xerrors.Errorf("could not serialize submit post parameters: %w", aerr) return xerrors.Errorf("could not serialize submit post parameters: %w", aerr)
@ -467,7 +554,8 @@ func (s *WindowPoStScheduler) submitPost(ctx context.Context, proof *miner.Submi
} }
// TODO: consider maybe caring about the output // TODO: consider maybe caring about the output
sm, err := s.api.MpoolPushMessage(ctx, msg) var err error
sm, err = s.api.MpoolPushMessage(ctx, msg)
if err != nil { if err != nil {
return xerrors.Errorf("pushing message to mpool: %w", err) return xerrors.Errorf("pushing message to mpool: %w", err)
} }

View File

@ -17,10 +17,16 @@ import (
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"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/journal"
) )
const StartConfidence = 4 // TODO: config const StartConfidence = 4 // TODO: config
// Journal event types.
const (
evtTypeWindowPoSt = iota
)
type WindowPoStScheduler struct { type WindowPoStScheduler struct {
api storageMinerApi api storageMinerApi
prover storage.Prover prover storage.Prover
@ -36,12 +42,14 @@ type WindowPoStScheduler struct {
// if a post is in progress, this indicates for which ElectionPeriodStart // if a post is in progress, this indicates for which ElectionPeriodStart
activeDeadline *miner.DeadlineInfo activeDeadline *miner.DeadlineInfo
abort context.CancelFunc abort context.CancelFunc
jrnl journal.Journal
evtTypes [1]journal.EventType
//failed abi.ChainEpoch // eps // failed abi.ChainEpoch // eps
//failLk sync.Mutex // failLk sync.Mutex
} }
func NewWindowedPoStScheduler(api storageMinerApi, sb storage.Prover, ft sectorstorage.FaultTracker, actor address.Address, worker address.Address) (*WindowPoStScheduler, error) { func NewWindowedPoStScheduler(api storageMinerApi, sb storage.Prover, ft sectorstorage.FaultTracker, actor address.Address, worker address.Address, jrnl journal.Journal) (*WindowPoStScheduler, error) {
mi, err := api.StateMinerInfo(context.TODO(), actor, types.EmptyTSK) mi, err := api.StateMinerInfo(context.TODO(), actor, types.EmptyTSK)
if err != nil { if err != nil {
return nil, xerrors.Errorf("getting sector size: %w", err) return nil, xerrors.Errorf("getting sector size: %w", err)
@ -61,6 +69,10 @@ func NewWindowedPoStScheduler(api storageMinerApi, sb storage.Prover, ft sectors
actor: actor, actor: actor,
worker: worker, worker: worker,
jrnl: jrnl,
evtTypes: [...]journal.EventType{
evtTypeWindowPoSt: jrnl.RegisterEventType("storage", "wdpost"),
},
}, nil }, nil
} }
@ -214,6 +226,15 @@ func (s *WindowPoStScheduler) abortActivePoSt() {
s.abort() s.abort()
} }
journal.MaybeAddEntry(s.jrnl, s.evtTypes[evtTypeWindowPoSt], func() interface{} {
return WindowPoStEvt{
State: "abort",
Deadline: s.activeDeadline,
Height: s.cur.Height(),
TipSet: s.cur.Cids(),
}
})
log.Warnf("Aborting Window PoSt (Deadline: %+v)", s.activeDeadline) log.Warnf("Aborting Window PoSt (Deadline: %+v)", s.activeDeadline)
s.activeDeadline = nil s.activeDeadline = nil