diff --git a/chain/blocksync/blocksync.go b/chain/blocksync/blocksync.go index 81bd1920d..873426d0b 100644 --- a/chain/blocksync/blocksync.go +++ b/chain/blocksync/blocksync.go @@ -128,7 +128,7 @@ func (bss *BlockSyncService) processRequest(ctx context.Context, req *BlockSyncR if err != nil { log.Warn("encountered error while responding to block sync request: ", err) return &BlockSyncResponse{ - Status: 203, + Status: 203, Message: err.Error(), }, nil } diff --git a/chain/messagepool.go b/chain/messagepool.go index 7fa476b8c..428b81241 100644 --- a/chain/messagepool.go +++ b/chain/messagepool.go @@ -1,7 +1,6 @@ package chain import ( - "fmt" "sync" lru "github.com/hashicorp/golang-lru" @@ -16,15 +15,15 @@ import ( ) var ( - ErrMessageTooBig = fmt.Errorf("message too big") + ErrMessageTooBig = errors.New("message too big") - ErrMessageValueTooHigh = fmt.Errorf("cannot send more filecoin than will ever exist") + ErrMessageValueTooHigh = errors.New("cannot send more filecoin than will ever exist") - ErrNonceTooLow = fmt.Errorf("message nonce too low") + ErrNonceTooLow = errors.New("message nonce too low") - ErrNotEnoughFunds = fmt.Errorf("not enough funds to execute transaction") + ErrNotEnoughFunds = errors.New("not enough funds to execute transaction") - ErrInvalidToAddr = fmt.Errorf("message had invalid to address") + ErrInvalidToAddr = errors.New("message had invalid to address") ) type MessagePool struct { @@ -81,7 +80,13 @@ func NewMessagePool(sm *stmgr.StateManager, ps *pubsub.PubSub) *MessagePool { maxTxPoolSize: 100000, blsSigCache: cache, } - sm.ChainStore().SubscribeHeadChanges(mp.HeadChange) + sm.ChainStore().SubscribeHeadChanges(func(rev, app []*types.TipSet) error { + err := mp.HeadChange(rev, app) + if err != nil { + log.Errorf("mpool head notif handler error: %+v", err) + } + return err + }) return mp } @@ -102,7 +107,7 @@ func (mp *MessagePool) Push(m *types.SignedMessage) error { func (mp *MessagePool) Add(m *types.SignedMessage) error { // big messages are bad, anti DOS if m.Size() > 32*1024 { - return ErrMessageTooBig + return xerrors.Errorf("mpool message too large (%dB): %w", m.Size(), ErrMessageTooBig) } if m.Message.To == address.Undef { @@ -124,7 +129,7 @@ func (mp *MessagePool) Add(m *types.SignedMessage) error { } if snonce > m.Message.Nonce { - return ErrNonceTooLow + return xerrors.Errorf("minimum expected nonce is %d: %w", snonce, ErrNonceTooLow) } balance, err := mp.getStateBalance(m.Message.From) @@ -133,7 +138,7 @@ func (mp *MessagePool) Add(m *types.SignedMessage) error { } if balance.LessThan(m.Message.RequiredFunds()) { - return ErrNotEnoughFunds + return xerrors.Errorf("not enough funds (required: %s, balance: %s): %w", types.FIL(m.Message.RequiredFunds()), types.FIL(balance), ErrNotEnoughFunds) } mp.lk.Lock() diff --git a/chain/sub/incoming.go b/chain/sub/incoming.go index 5e6c31de1..cb90750e3 100644 --- a/chain/sub/incoming.go +++ b/chain/sub/incoming.go @@ -73,7 +73,7 @@ func HandleIncomingMessages(ctx context.Context, mpool *chain.MessagePool, msub } if err := mpool.Add(m); err != nil { - log.Errorf("failed to add message from network to message pool: %s", err) + log.Errorf("failed to add message from network to message pool (From: %s, To: %s, Nonce: %d, Value: %s): %+v", m.Message.From, m.Message.To, m.Message.Nonce, types.FIL(m.Message.Value), err) continue } } diff --git a/chain/types/bigint.go b/chain/types/bigint.go index b3927155f..b958ecf26 100644 --- a/chain/types/bigint.go +++ b/chain/types/bigint.go @@ -67,6 +67,10 @@ func BigDiv(a, b BigInt) BigInt { return BigInt{big.NewInt(0).Div(a.Int, b.Int)} } +func BigMod(a, b BigInt) BigInt { + return BigInt{big.NewInt(0).Mod(a.Int, b.Int)} +} + func BigAdd(a, b BigInt) BigInt { return BigInt{big.NewInt(0).Add(a.Int, b.Int)} } diff --git a/chain/validation/applier.go b/chain/validation/applier.go index 0e7185caa..c97b60a3a 100644 --- a/chain/validation/applier.go +++ b/chain/validation/applier.go @@ -49,7 +49,7 @@ func (a *Applier) ApplyMessage(eCtx *vchain.ExecutionContext, state vstate.Wrapp mr := vchain.MessageReceipt{ ExitCode: ret.ExitCode, ReturnValue: ret.Return, - GasUsed: vstate.GasUnit(ret.GasUsed.Uint64()), + GasUsed: vstate.GasUnit(ret.GasUsed.Uint64()), } return mr, nil diff --git a/chain/validation/message.go b/chain/validation/message.go index 0bd80b261..99ffb9b64 100644 --- a/chain/validation/message.go +++ b/chain/validation/message.go @@ -60,7 +60,7 @@ func (mf *MessageFactory) MakeMessage(from, to state.Address, method chain.Metho return msg, nil } -func (mf *MessageFactory) FromSingletonAddress(addr state.SingletonActorID) (state.Address) { +func (mf *MessageFactory) FromSingletonAddress(addr state.SingletonActorID) state.Address { return fromSingletonAddress(addr) } @@ -70,15 +70,15 @@ var methods = []uint64{ chain.NoMethod: 0, chain.InitExec: actors.IAMethods.Exec, - chain.StoragePowerConstructor: actors.SPAMethods.Constructor, + chain.StoragePowerConstructor: actors.SPAMethods.Constructor, chain.StoragePowerCreateStorageMiner: actors.SPAMethods.CreateStorageMiner, - chain.StoragePowerUpdatePower: actors.SPAMethods.UpdateStorage, + chain.StoragePowerUpdatePower: actors.SPAMethods.UpdateStorage, - chain.StorageMinerUpdatePeerID: actors.MAMethods.UpdatePeerID, - chain.StorageMinerGetOwner: actors.MAMethods.GetOwner, - chain.StorageMinerGetPower: actors.MAMethods.GetPower, + chain.StorageMinerUpdatePeerID: actors.MAMethods.UpdatePeerID, + chain.StorageMinerGetOwner: actors.MAMethods.GetOwner, + chain.StorageMinerGetPower: actors.MAMethods.GetPower, chain.StorageMinerGetWorkerAddr: actors.MAMethods.GetWorkerAddr, - chain.StorageMinerGetPeerID: actors.MAMethods.GetPeerID, + chain.StorageMinerGetPeerID: actors.MAMethods.GetPeerID, chain.StorageMinerGetSectorSize: actors.MAMethods.GetSectorSize, // More to follow... } diff --git a/chain/validation/message_test.go b/chain/validation/message_test.go index cc294f8c3..4a3a452ad 100644 --- a/chain/validation/message_test.go +++ b/chain/validation/message_test.go @@ -28,7 +28,7 @@ func TestMessageFactory(t *testing.T) { require.NoError(t, err) bfAddr := factory.FromSingletonAddress(state.BurntFundsAddress) - m, err := p.Transfer(state.Address(sender.Bytes()), bfAddr,0, 1) + m, err := p.Transfer(state.Address(sender.Bytes()), bfAddr, 0, 1) require.NoError(t, err) messages := p.Messages() diff --git a/chain/validation/state.go b/chain/validation/state.go index 15fd5da5b..9886c43f7 100644 --- a/chain/validation/state.go +++ b/chain/validation/state.go @@ -114,7 +114,7 @@ func (s *StateWrapper) SetActor(addr vstate.Address, code vstate.ActorCodeID, ba return actr, s.storage, s.flush(tree) } -func (s *StateWrapper) SetSingletonActor(addr vstate.SingletonActorID, balance vstate.AttoFIL) (vstate.Actor, vstate.Storage, error){ +func (s *StateWrapper) SetSingletonActor(addr vstate.SingletonActorID, balance vstate.AttoFIL) (vstate.Actor, vstate.Storage, error) { vaddr := fromSingletonAddress(addr) tree, err := state.LoadStateTree(s.cst, s.stateRoot) if err != nil { diff --git a/cmd/lotus-storage-miner/info.go b/cmd/lotus-storage-miner/info.go index dc449c66e..b1df59cb3 100644 --- a/cmd/lotus-storage-miner/info.go +++ b/cmd/lotus-storage-miner/info.go @@ -43,7 +43,7 @@ var infoCmd = &cli.Command{ return err } - fmt.Printf("Sector Size: %s\n", sizeStr(sizeByte)) + fmt.Printf("Sector Size: %s\n", sizeStr(types.NewInt(sizeByte))) pow, err := api.StateMinerPower(ctx, maddr, nil) if err != nil { @@ -51,7 +51,7 @@ var infoCmd = &cli.Command{ } percI := types.BigDiv(types.BigMul(pow.MinerPower, types.NewInt(1000)), pow.TotalPower) - fmt.Printf("Power: %s / %s (%0.2f%%)\n", pow.MinerPower, pow.TotalPower, float64(percI.Int64())/1000*100) + fmt.Printf("Power: %s / %s (%0.4f%%)\n", sizeStr(pow.MinerPower), sizeStr(pow.TotalPower), float64(percI.Int64())/100000*10000) // TODO: indicate whether the post worker is in use wstat, err := nodeApi.WorkerStats(ctx) @@ -90,16 +90,16 @@ var infoCmd = &cli.Command{ }, } -var Units = []string{"B", "KiB", "MiB", "GiB", "TiB"} +var Units = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB"} -func sizeStr(size uint64) string { +func sizeStr(size types.BigInt) string { + size = types.BigMul(size, types.NewInt(100)) i := 0 - unitSize := float64(size) - for unitSize >= 1024 && i < len(Units)-1 { - unitSize = unitSize / 1024 + for types.BigCmp(size, types.NewInt(102400)) >= 0 && i < len(Units)-1 { + size = types.BigDiv(size, types.NewInt(1024)) i++ } - return fmt.Sprintf("%g %s", unitSize, Units[i]) + return fmt.Sprintf("%s.%s %s", types.BigDiv(size, types.NewInt(100)), types.BigMod(size, types.NewInt(100)), Units[i]) } func sectorsInfo(ctx context.Context, napi api.StorageMiner) (map[string]int, error) { diff --git a/cmd/lotus-storage-miner/sectors.go b/cmd/lotus-storage-miner/sectors.go index 627e11c14..b1794f393 100644 --- a/cmd/lotus-storage-miner/sectors.go +++ b/cmd/lotus-storage-miner/sectors.go @@ -30,7 +30,7 @@ var sectorsCmd = &cli.Command{ Usage: "interact with sector store", Subcommands: []*cli.Command{ sectorsStatusCmd, - sectorsStagedListCmd, + sectorsListCmd, sectorsRefsCmd, }, } @@ -74,24 +74,71 @@ var sectorsStatusCmd = &cli.Command{ }, } -var sectorsStagedListCmd = &cli.Command{ - Name: "list-staged", // TODO: nest this under a 'staged' subcommand? idk - Usage: "List staged sectors", +var sectorsListCmd = &cli.Command{ + Name: "list", + Usage: "List sectors", Action: func(cctx *cli.Context) error { nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx) if err != nil { return err } defer closer() + + fullApi, closer2, err := lcli.GetFullNodeAPI(cctx) // TODO: consider storing full node address in config + if err != nil { + return err + } + defer closer2() + ctx := lcli.ReqContext(cctx) - staged, err := nodeApi.SectorsList(ctx) + list, err := nodeApi.SectorsList(ctx) if err != nil { return err } - for _, s := range staged { - fmt.Println(s) + maddr, err := nodeApi.ActorAddress(ctx) + if err != nil { + return err + } + + pset, err := fullApi.StateMinerProvingSet(ctx, maddr, nil) + if err != nil { + return err + } + provingIDs := make(map[uint64]struct{}, len(pset)) + for _, info := range pset { + provingIDs[info.SectorID] = struct{}{} + } + + sset, err := fullApi.StateMinerSectors(ctx, maddr, nil) + if err != nil { + return err + } + commitedIDs := make(map[uint64]struct{}, len(pset)) + for _, info := range sset { + commitedIDs[info.SectorID] = struct{}{} + } + + for _, s := range list { + st, err := nodeApi.SectorsStatus(ctx, s) + if err != nil { + fmt.Printf("%d:\tError: %s\n", s, err) + continue + } + + _, inSSet := commitedIDs[s] + _, inPSet := provingIDs[s] + + fmt.Printf("%d: %s\tsSet: %s\tpSet: %s\ttktH: %d\tseedH: %d\tdeals: %v\n", + s, + api.SectorStateStr(st.State), + yesno(inSSet), + yesno(inPSet), + st.Ticket.BlockHeight, + st.Seed.BlockHeight, + st.Deals, + ) } return nil }, @@ -122,3 +169,10 @@ var sectorsRefsCmd = &cli.Command{ return nil }, } + +func yesno(b bool) string { + if b { + return "YES" + } + return "NO" +} diff --git a/storage/sealing.go b/storage/sealing.go index 77ce1312c..abb831676 100644 --- a/storage/sealing.go +++ b/storage/sealing.go @@ -205,6 +205,9 @@ func (m *Miner) onSectorUpdated(ctx context.Context, update sectorUpdate) { m.handle(ctx, sector, m.preCommitted, api.SectorNoUpdate) case api.Committing: m.handle(ctx, sector, m.committing, api.Proving) + case api.Proving: + // TODO: track sector health / expiration + log.Infof("Proving sector %d", update.id) case api.SectorNoUpdate: // noop default: log.Errorf("unexpected sector update state: %d", update.newState)