fpost: better fault checks
This commit is contained in:
parent
03f07042ff
commit
4aaa758543
@ -108,6 +108,7 @@ type FullNode interface {
|
||||
StateMinerPeerID(ctx context.Context, m address.Address, ts *types.TipSet) (peer.ID, error)
|
||||
StateMinerElectionPeriodStart(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error)
|
||||
StateMinerSectorSize(context.Context, address.Address, *types.TipSet) (uint64, error)
|
||||
StateMinerFaults(context.Context, address.Address, *types.TipSet) ([]uint64, error)
|
||||
StatePledgeCollateral(context.Context, *types.TipSet) (types.BigInt, error)
|
||||
StateWaitMsg(context.Context, cid.Cid) (*MsgWait, error)
|
||||
StateListMiners(context.Context, *types.TipSet) ([]address.Address, error)
|
||||
|
@ -99,6 +99,7 @@ type FullNodeStruct struct {
|
||||
StateMinerPeerID func(ctx context.Context, m address.Address, ts *types.TipSet) (peer.ID, error) `perm:"read"`
|
||||
StateMinerElectionPeriodStart func(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) `perm:"read"`
|
||||
StateMinerSectorSize func(context.Context, address.Address, *types.TipSet) (uint64, error) `perm:"read"`
|
||||
StateMinerFaults func(context.Context, address.Address, *types.TipSet) ([]uint64, error) `perm:"read"`
|
||||
StateCall func(context.Context, *types.Message, *types.TipSet) (*api.MethodCall, error) `perm:"read"`
|
||||
StateReplay func(context.Context, *types.TipSet, cid.Cid) (*api.ReplayResults, error) `perm:"read"`
|
||||
StateGetActor func(context.Context, address.Address, *types.TipSet) (*types.Actor, error) `perm:"read"`
|
||||
@ -410,6 +411,10 @@ func (c *FullNodeStruct) StateMinerSectorSize(ctx context.Context, actor address
|
||||
return c.Internal.StateMinerSectorSize(ctx, actor, ts)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) StateMinerFaults(ctx context.Context, actor address.Address, ts *types.TipSet) ([]uint64, error) {
|
||||
return c.Internal.StateMinerFaults(ctx, actor, ts)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) StateCall(ctx context.Context, msg *types.Message, ts *types.TipSet) (*api.MethodCall, error) {
|
||||
return c.Internal.StateCall(ctx, msg, ts)
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package stmgr
|
||||
|
||||
import (
|
||||
"context"
|
||||
amt2 "github.com/filecoin-project/go-amt-ipld/v2"
|
||||
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
||||
|
||||
ffi "github.com/filecoin-project/filecoin-ffi"
|
||||
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
|
||||
@ -253,6 +255,21 @@ func GetMinerSlashed(ctx context.Context, sm *StateManager, ts *types.TipSet, ma
|
||||
return mas.SlashedAt, nil
|
||||
}
|
||||
|
||||
func GetMinerFaults(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]uint64, error) {
|
||||
var mas actors.StorageMinerActorState
|
||||
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("(get ssize) failed to load miner actor state: %w", err)
|
||||
}
|
||||
|
||||
ss, lerr := amt2.LoadAMT(amt.WrapBlockstore(sm.cs.Blockstore()), mas.Sectors)
|
||||
if lerr != nil {
|
||||
return nil, aerrors.HandleExternalError(lerr, "could not load proving set node")
|
||||
}
|
||||
|
||||
return mas.FaultSet.All(2 * ss.Count)
|
||||
}
|
||||
|
||||
func GetStorageDeal(ctx context.Context, sm *StateManager, dealId uint64, ts *types.TipSet) (*actors.OnChainDeal, error) {
|
||||
var state actors.StorageMarketState
|
||||
if _, err := sm.LoadActorState(ctx, actors.StorageMarketAddress, &state, ts); err != nil {
|
||||
|
@ -84,6 +84,10 @@ func (a *StateAPI) StateMinerSectorSize(ctx context.Context, actor address.Addre
|
||||
return stmgr.GetMinerSectorSize(ctx, a.StateManager, ts, actor)
|
||||
}
|
||||
|
||||
func (a *StateAPI) StateMinerFaults(ctx context.Context, addr address.Address, ts *types.TipSet) ([]uint64, error) {
|
||||
return stmgr.GetMinerFaults(ctx, a.StateManager, ts, addr)
|
||||
}
|
||||
|
||||
func (a *StateAPI) StatePledgeCollateral(ctx context.Context, ts *types.TipSet) (types.BigInt, error) {
|
||||
param, err := actors.SerializeParams(&actors.PledgeCollateralParams{Size: types.NewInt(0)})
|
||||
if err != nil {
|
||||
|
@ -50,52 +50,85 @@ func (s *fpostScheduler) doPost(ctx context.Context, eps uint64, ts *types.TipSe
|
||||
}()
|
||||
}
|
||||
|
||||
func (s *fpostScheduler) declareFaults(ctx context.Context, fc uint64, params *actors.DeclareFaultsParams) error {
|
||||
log.Warnf("DECLARING %d FAULTS", fc)
|
||||
|
||||
enc, aerr := actors.SerializeParams(params)
|
||||
if aerr != nil {
|
||||
return xerrors.Errorf("could not serialize declare faults parameters: %w", aerr)
|
||||
}
|
||||
|
||||
msg := &types.Message{
|
||||
To: s.actor,
|
||||
From: s.worker,
|
||||
Method: actors.MAMethods.DeclareFaults,
|
||||
Params: enc,
|
||||
Value: types.NewInt(0),
|
||||
GasLimit: types.NewInt(10000000), // i dont know help
|
||||
GasPrice: types.NewInt(1),
|
||||
}
|
||||
|
||||
sm, err := s.api.MpoolPushMessage(ctx, msg)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("pushing faults message to mpool: %w", err)
|
||||
}
|
||||
|
||||
rec, err := s.api.StateWaitMsg(ctx, sm.Cid())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("waiting for declare faults: %w", err)
|
||||
}
|
||||
|
||||
if rec.Receipt.ExitCode != 0 {
|
||||
return xerrors.Errorf("declare faults exit %d", rec.Receipt.ExitCode)
|
||||
}
|
||||
|
||||
log.Infof("Faults declared successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *fpostScheduler) checkFaults(ctx context.Context, ssi sectorbuilder.SortedPublicSectorInfo) ([]uint64, error) {
|
||||
faults := s.sb.Scrub(ssi)
|
||||
var faultIDs []uint64
|
||||
|
||||
declaredFaults := map[uint64]struct{}{}
|
||||
|
||||
{
|
||||
chainFaults, err := s.api.StateMinerFaults(ctx, s.actor, nil)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("checking on-chain faults: %w", err)
|
||||
}
|
||||
|
||||
for _, fault := range chainFaults {
|
||||
declaredFaults[fault] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
if len(faults) > 0 {
|
||||
params := &actors.DeclareFaultsParams{Faults: types.NewBitField()}
|
||||
|
||||
for _, fault := range faults {
|
||||
log.Warnf("fault detected: sector %d: %s", fault.SectorID, fault.Err)
|
||||
faultIDs = append(faultIDs, fault.SectorID)
|
||||
if _, ok := declaredFaults[fault.SectorID]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// TODO: omit already declared (with finality in mind though..)
|
||||
log.Warnf("new fault detected: sector %d: %s", fault.SectorID, fault.Err)
|
||||
declaredFaults[fault.SectorID] = struct{}{}
|
||||
params.Faults.Set(fault.SectorID)
|
||||
}
|
||||
|
||||
log.Warnf("DECLARING %d FAULTS", len(faults))
|
||||
|
||||
enc, aerr := actors.SerializeParams(params)
|
||||
if aerr != nil {
|
||||
return nil, xerrors.Errorf("could not serialize declare faults parameters: %w", aerr)
|
||||
}
|
||||
|
||||
msg := &types.Message{
|
||||
To: s.actor,
|
||||
From: s.worker,
|
||||
Method: actors.MAMethods.DeclareFaults,
|
||||
Params: enc,
|
||||
Value: types.NewInt(0),
|
||||
GasLimit: types.NewInt(10000000), // i dont know help
|
||||
GasPrice: types.NewInt(1),
|
||||
}
|
||||
|
||||
sm, err := s.api.MpoolPushMessage(ctx, msg)
|
||||
pc, err := params.Faults.Count()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("pushing faults message to mpool: %w", err)
|
||||
return nil, xerrors.Errorf("counting faults: %w", err)
|
||||
}
|
||||
if pc > 0 {
|
||||
if err := s.declareFaults(ctx, pc, params); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rec, err := s.api.StateWaitMsg(ctx, sm.Cid())
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("waiting for declare faults: %w", err)
|
||||
}
|
||||
|
||||
if rec.Receipt.ExitCode != 0 {
|
||||
return nil, xerrors.Errorf("declare faults exit %d", rec.Receipt.ExitCode)
|
||||
}
|
||||
log.Infof("Faults declared successfully")
|
||||
faultIDs := make([]uint64, 0, len(declaredFaults))
|
||||
for fault := range declaredFaults {
|
||||
faultIDs = append(faultIDs, fault)
|
||||
}
|
||||
|
||||
return faultIDs, nil
|
||||
|
@ -50,6 +50,7 @@ type storageMinerApi interface {
|
||||
StateGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error)
|
||||
StateGetReceipt(context.Context, cid.Cid, *types.TipSet) (*types.MessageReceipt, error)
|
||||
StateMarketStorageDeal(context.Context, uint64, *types.TipSet) (*actors.OnChainDeal, error)
|
||||
StateMinerFaults(context.Context, address.Address, *types.TipSet) ([]uint64, error)
|
||||
|
||||
MpoolPushMessage(context.Context, *types.Message) (*types.SignedMessage, error)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user