From 159ce13f5e20beb238ac8bf8ac99f53ec4d89a70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sun, 6 Sep 2020 18:47:16 +0200 Subject: [PATCH 001/313] Async worker API --- api/api_storage.go | 1 + api/api_worker.go | 17 +- api/apistruct/struct.go | 130 +++++++--- build/version.go | 2 +- extern/sector-storage/localworker.go | 265 ++++++++++++++------- extern/sector-storage/manager.go | 8 +- extern/sector-storage/storiface/storage.go | 1 + extern/sector-storage/storiface/worker.go | 45 +++- 8 files changed, 321 insertions(+), 148 deletions(-) create mode 100644 extern/sector-storage/storiface/storage.go diff --git a/api/api_storage.go b/api/api_storage.go index 48f6e9e45..77c052595 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -64,6 +64,7 @@ type StorageMiner interface { WorkerConnect(context.Context, string) error WorkerStats(context.Context) (map[uint64]storiface.WorkerStats, error) WorkerJobs(context.Context) (map[uint64][]storiface.WorkerJob, error) + storiface.WorkerReturn // SealingSchedDiag dumps internal sealing scheduler state SealingSchedDiag(context.Context) (interface{}, error) diff --git a/api/api_worker.go b/api/api_worker.go index 00c4df8bc..b64c7ec24 100644 --- a/api/api_worker.go +++ b/api/api_worker.go @@ -2,15 +2,12 @@ package api import ( "context" - "io" - "github.com/ipfs/go-cid" + "github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/lotus/extern/sector-storage/sealtasks" "github.com/filecoin-project/lotus/extern/sector-storage/stores" "github.com/filecoin-project/lotus/extern/sector-storage/storiface" - "github.com/filecoin-project/specs-actors/actors/abi" - "github.com/filecoin-project/specs-storage/storage" "github.com/filecoin-project/lotus/build" ) @@ -23,18 +20,12 @@ type WorkerAPI interface { Paths(context.Context) ([]stores.StoragePath, error) Info(context.Context) (storiface.WorkerInfo, error) - AddPiece(ctx context.Context, sector abi.SectorID, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage.Data) (abi.PieceInfo, error) + storiface.WorkerCalls - storage.Sealer - - MoveStorage(ctx context.Context, sector abi.SectorID, types stores.SectorFileType) error - - UnsealPiece(context.Context, abi.SectorID, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize, abi.SealRandomness, cid.Cid) error - ReadPiece(context.Context, io.Writer, abi.SectorID, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize) (bool, error) + // Storage / Other + Remove(ctx context.Context, sector abi.SectorID) error StorageAddLocal(ctx context.Context, path string) error - Fetch(context.Context, abi.SectorID, stores.SectorFileType, stores.PathType, stores.AcquireMode) error - Closing(context.Context) (<-chan struct{}, error) } diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index e2444f16b..5fb80433d 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -270,6 +270,18 @@ type StorageMinerStruct struct { WorkerStats func(context.Context) (map[uint64]storiface.WorkerStats, error) `perm:"admin"` WorkerJobs func(context.Context) (map[uint64][]storiface.WorkerJob, error) `perm:"admin"` + ReturnAddPiece func(ctx context.Context, callID storiface.CallID, pi abi.PieceInfo, err string) error `perm:"admin"` + ReturnSealPreCommit1 func(ctx context.Context, callID storiface.CallID, p1o storage.PreCommit1Out, err string) error `perm:"admin"` + ReturnSealPreCommit2 func(ctx context.Context, callID storiface.CallID, sealed storage.SectorCids, err string) error `perm:"admin"` + ReturnSealCommit1 func(ctx context.Context, callID storiface.CallID, out storage.Commit1Out, err string) error `perm:"admin"` + ReturnSealCommit2 func(ctx context.Context, callID storiface.CallID, proof storage.Proof, err string) error `perm:"admin"` + ReturnFinalizeSector func(ctx context.Context, callID storiface.CallID, err string) error `perm:"admin"` + ReturnReleaseUnsealed func(ctx context.Context, callID storiface.CallID, err string) error `perm:"admin"` + ReturnMoveStorage func(ctx context.Context, callID storiface.CallID, err string) error `perm:"admin"` + ReturnUnsealPiece func(ctx context.Context, callID storiface.CallID, err string) error `perm:"admin"` + ReturnReadPiece func(ctx context.Context, callID storiface.CallID, ok bool, err string) error `perm:"admin"` + ReturnFetch func(ctx context.Context, callID storiface.CallID, err string) error `perm:"admin"` + SealingSchedDiag func(context.Context) (interface{}, error) `perm:"admin"` StorageList func(context.Context) (map[stores.ID][]stores.Decl, error) `perm:"admin"` @@ -317,21 +329,21 @@ type WorkerStruct struct { Paths func(context.Context) ([]stores.StoragePath, error) `perm:"admin"` Info func(context.Context) (storiface.WorkerInfo, error) `perm:"admin"` - AddPiece func(ctx context.Context, sector abi.SectorID, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage.Data) (abi.PieceInfo, error) `perm:"admin"` - SealPreCommit1 func(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storage.PreCommit1Out, error) `perm:"admin"` - SealPreCommit2 func(context.Context, abi.SectorID, storage.PreCommit1Out) (cids storage.SectorCids, err error) `perm:"admin"` - SealCommit1 func(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storage.Commit1Out, error) `perm:"admin"` - SealCommit2 func(context.Context, abi.SectorID, storage.Commit1Out) (storage.Proof, error) `perm:"admin"` - FinalizeSector func(context.Context, abi.SectorID, []storage.Range) error `perm:"admin"` - ReleaseUnsealed func(ctx context.Context, sector abi.SectorID, safeToFree []storage.Range) error `perm:"admin"` - Remove func(ctx context.Context, sector abi.SectorID) error `perm:"admin"` - MoveStorage func(ctx context.Context, sector abi.SectorID, types stores.SectorFileType) error `perm:"admin"` - StorageAddLocal func(ctx context.Context, path string) error `perm:"admin"` + AddPiece func(ctx context.Context, sector abi.SectorID, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage.Data) (storiface.CallID, error) `perm:"admin"` + SealPreCommit1 func(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storiface.CallID, error) `perm:"admin"` + SealPreCommit2 func(ctx context.Context, sector abi.SectorID, pc1o storage.PreCommit1Out) (storiface.CallID, error) `perm:"admin"` + SealCommit1 func(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storiface.CallID, error) `perm:"admin"` + SealCommit2 func(ctx context.Context, sector abi.SectorID, c1o storage.Commit1Out) (storiface.CallID, error) `perm:"admin"` + FinalizeSector func(ctx context.Context, sector abi.SectorID, keepUnsealed []storage.Range) (storiface.CallID, error) `perm:"admin"` + ReleaseUnsealed func(ctx context.Context, sector abi.SectorID, safeToFree []storage.Range) (storiface.CallID, error) `perm:"admin"` + MoveStorage func(ctx context.Context, sector abi.SectorID, types stores.SectorFileType) (storiface.CallID, error) `perm:"admin"` + UnsealPiece func(context.Context, abi.SectorID, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize, abi.SealRandomness, cid.Cid) (storiface.CallID, error) `perm:"admin"` + ReadPiece func(context.Context, io.Writer, abi.SectorID, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize) (storiface.CallID, error) `perm:"admin"` + Fetch func(context.Context, abi.SectorID, stores.SectorFileType, stores.PathType, stores.AcquireMode) (storiface.CallID, error) `perm:"admin"` - UnsealPiece func(context.Context, abi.SectorID, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize, abi.SealRandomness, cid.Cid) error `perm:"admin"` - ReadPiece func(context.Context, io.Writer, abi.SectorID, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize) (bool, error) `perm:"admin"` + Remove func(ctx context.Context, sector abi.SectorID) error `perm:"admin"` + StorageAddLocal func(ctx context.Context, path string) error `perm:"admin"` - Fetch func(context.Context, abi.SectorID, stores.SectorFileType, stores.PathType, stores.AcquireMode) error `perm:"admin"` Closing func(context.Context) (<-chan struct{}, error) `perm:"admin"` } @@ -1038,6 +1050,50 @@ func (c *StorageMinerStruct) WorkerJobs(ctx context.Context) (map[uint64][]stori return c.Internal.WorkerJobs(ctx) } +func (c *StorageMinerStruct) ReturnAddPiece(ctx context.Context, callID storiface.CallID, pi abi.PieceInfo, err string) error { + return c.Internal.ReturnAddPiece(ctx, callID, pi, err) +} + +func (c *StorageMinerStruct) ReturnSealPreCommit1(ctx context.Context, callID storiface.CallID, p1o storage.PreCommit1Out, err string) error { + return c.Internal.ReturnSealPreCommit1(ctx, callID, p1o, err) +} + +func (c *StorageMinerStruct) ReturnSealPreCommit2(ctx context.Context, callID storiface.CallID, sealed storage.SectorCids, err string) error { + return c.Internal.ReturnSealPreCommit2(ctx, callID, sealed, err) +} + +func (c *StorageMinerStruct) ReturnSealCommit1(ctx context.Context, callID storiface.CallID, out storage.Commit1Out, err string) error { + return c.Internal.ReturnSealCommit1(ctx, callID, out, err) +} + +func (c *StorageMinerStruct) ReturnSealCommit2(ctx context.Context, callID storiface.CallID, proof storage.Proof, err string) error { + return c.Internal.ReturnSealCommit2(ctx, callID, proof, err) +} + +func (c *StorageMinerStruct) ReturnFinalizeSector(ctx context.Context, callID storiface.CallID, err string) error { + return c.Internal.ReturnFinalizeSector(ctx, callID, err) +} + +func (c *StorageMinerStruct) ReturnReleaseUnsealed(ctx context.Context, callID storiface.CallID, err string) error { + return c.Internal.ReturnReleaseUnsealed(ctx, callID, err) +} + +func (c *StorageMinerStruct) ReturnMoveStorage(ctx context.Context, callID storiface.CallID, err string) error { + return c.Internal.ReturnMoveStorage(ctx, callID, err) +} + +func (c *StorageMinerStruct) ReturnUnsealPiece(ctx context.Context, callID storiface.CallID, err string) error { + return c.Internal.ReturnUnsealPiece(ctx, callID, err) +} + +func (c *StorageMinerStruct) ReturnReadPiece(ctx context.Context, callID storiface.CallID, ok bool, err string) error { + return c.Internal.ReturnReadPiece(ctx, callID, ok, err) +} + +func (c *StorageMinerStruct) ReturnFetch(ctx context.Context, callID storiface.CallID, err string) error { + return c.Internal.ReturnFetch(ctx, callID, err) +} + func (c *StorageMinerStruct) SealingSchedDiag(ctx context.Context) (interface{}, error) { return c.Internal.SealingSchedDiag(ctx) } @@ -1220,58 +1276,58 @@ func (w *WorkerStruct) Info(ctx context.Context) (storiface.WorkerInfo, error) { return w.Internal.Info(ctx) } -func (w *WorkerStruct) AddPiece(ctx context.Context, sector abi.SectorID, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage.Data) (abi.PieceInfo, error) { +func (w *WorkerStruct) AddPiece(ctx context.Context, sector abi.SectorID, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage.Data) (storiface.CallID, error) { return w.Internal.AddPiece(ctx, sector, pieceSizes, newPieceSize, pieceData) } -func (w *WorkerStruct) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storage.PreCommit1Out, error) { +func (w *WorkerStruct) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storiface.CallID, error) { return w.Internal.SealPreCommit1(ctx, sector, ticket, pieces) } -func (w *WorkerStruct) SealPreCommit2(ctx context.Context, sector abi.SectorID, p1o storage.PreCommit1Out) (storage.SectorCids, error) { - return w.Internal.SealPreCommit2(ctx, sector, p1o) +func (w *WorkerStruct) SealPreCommit2(ctx context.Context, sector abi.SectorID, pc1o storage.PreCommit1Out) (storiface.CallID, error) { + return w.Internal.SealPreCommit2(ctx, sector, pc1o) } -func (w *WorkerStruct) SealCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storage.Commit1Out, error) { +func (w *WorkerStruct) SealCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storiface.CallID, error) { return w.Internal.SealCommit1(ctx, sector, ticket, seed, pieces, cids) } -func (w *WorkerStruct) SealCommit2(ctx context.Context, sector abi.SectorID, c1o storage.Commit1Out) (storage.Proof, error) { +func (w *WorkerStruct) SealCommit2(ctx context.Context, sector abi.SectorID, c1o storage.Commit1Out) (storiface.CallID, error) { return w.Internal.SealCommit2(ctx, sector, c1o) } -func (w *WorkerStruct) FinalizeSector(ctx context.Context, sector abi.SectorID, keepUnsealed []storage.Range) error { +func (w *WorkerStruct) FinalizeSector(ctx context.Context, sector abi.SectorID, keepUnsealed []storage.Range) (storiface.CallID, error) { return w.Internal.FinalizeSector(ctx, sector, keepUnsealed) } -func (w *WorkerStruct) ReleaseUnsealed(ctx context.Context, sector abi.SectorID, safeToFree []storage.Range) error { +func (w *WorkerStruct) ReleaseUnsealed(ctx context.Context, sector abi.SectorID, safeToFree []storage.Range) (storiface.CallID, error) { return w.Internal.ReleaseUnsealed(ctx, sector, safeToFree) } +func (w *WorkerStruct) MoveStorage(ctx context.Context, sector abi.SectorID, types stores.SectorFileType) (storiface.CallID, error) { + return w.Internal.MoveStorage(ctx, sector, types) +} + +func (w *WorkerStruct) UnsealPiece(ctx context.Context, sector abi.SectorID, offset storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, ticket abi.SealRandomness, c cid.Cid) (storiface.CallID, error) { + return w.Internal.UnsealPiece(ctx, sector, offset, size, ticket, c) +} + +func (w *WorkerStruct) ReadPiece(ctx context.Context, sink io.Writer, sector abi.SectorID, offset storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize) (storiface.CallID, error) { + return w.Internal.ReadPiece(ctx, sink, sector, offset, size) +} + +func (w *WorkerStruct) Fetch(ctx context.Context, id abi.SectorID, fileType stores.SectorFileType, ptype stores.PathType, am stores.AcquireMode) (storiface.CallID, error) { + return w.Internal.Fetch(ctx, id, fileType, ptype, am) +} + func (w *WorkerStruct) Remove(ctx context.Context, sector abi.SectorID) error { return w.Internal.Remove(ctx, sector) } -func (w *WorkerStruct) MoveStorage(ctx context.Context, sector abi.SectorID, types stores.SectorFileType) error { - return w.Internal.MoveStorage(ctx, sector, types) -} - func (w *WorkerStruct) StorageAddLocal(ctx context.Context, path string) error { return w.Internal.StorageAddLocal(ctx, path) } -func (w *WorkerStruct) UnsealPiece(ctx context.Context, id abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, randomness abi.SealRandomness, c cid.Cid) error { - return w.Internal.UnsealPiece(ctx, id, index, size, randomness, c) -} - -func (w *WorkerStruct) ReadPiece(ctx context.Context, writer io.Writer, id abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize) (bool, error) { - return w.Internal.ReadPiece(ctx, writer, id, index, size) -} - -func (w *WorkerStruct) Fetch(ctx context.Context, id abi.SectorID, fileType stores.SectorFileType, ptype stores.PathType, am stores.AcquireMode) error { - return w.Internal.Fetch(ctx, id, fileType, ptype, am) -} - func (w *WorkerStruct) Closing(ctx context.Context) (<-chan struct{}, error) { return w.Internal.Closing(ctx) } diff --git a/build/version.go b/build/version.go index a3c5d1552..b57a72b49 100644 --- a/build/version.go +++ b/build/version.go @@ -53,7 +53,7 @@ func (ve Version) EqMajorMinor(v2 Version) bool { } // APIVersion is a semver version of the rpc api exposed -var APIVersion Version = newVer(0, 14, 0) +var APIVersion Version = newVer(0, 15, 0) //nolint:varcheck,deadcode const ( diff --git a/extern/sector-storage/localworker.go b/extern/sector-storage/localworker.go index 773ef2d3b..9d451309d 100644 --- a/extern/sector-storage/localworker.go +++ b/extern/sector-storage/localworker.go @@ -7,6 +7,7 @@ import ( "runtime" "github.com/elastic/go-sysinfo" + "github.com/google/uuid" "github.com/hashicorp/go-multierror" "github.com/ipfs/go-cid" "golang.org/x/xerrors" @@ -33,6 +34,7 @@ type LocalWorker struct { storage stores.Store localStore *stores.Local sindex stores.SectorIndex + ret storiface.WorkerReturn acceptTasks map[sealtasks.TaskType]struct{} } @@ -95,6 +97,25 @@ func (l *LocalWorker) sb() (ffiwrapper.Storage, error) { return ffiwrapper.New(&localWorkerPathProvider{w: l}, l.scfg) } +func (l *LocalWorker) asyncCall(sector abi.SectorID, work func(ci storiface.CallID)) (storiface.CallID, error) { + ci := storiface.CallID{ + Sector: sector, + ID: uuid.New(), + } + + go work(ci) + + return ci, nil +} + +func errstr(err error) string { + if err != nil { + return err.Error() + } + + return "" +} + func (l *LocalWorker) NewSector(ctx context.Context, sector abi.SectorID) error { sb, err := l.sb() if err != nil { @@ -104,92 +125,140 @@ func (l *LocalWorker) NewSector(ctx context.Context, sector abi.SectorID) error return sb.NewSector(ctx, sector) } -func (l *LocalWorker) AddPiece(ctx context.Context, sector abi.SectorID, epcs []abi.UnpaddedPieceSize, sz abi.UnpaddedPieceSize, r io.Reader) (abi.PieceInfo, error) { +func (l *LocalWorker) AddPiece(ctx context.Context, sector abi.SectorID, epcs []abi.UnpaddedPieceSize, sz abi.UnpaddedPieceSize, r io.Reader) (storiface.CallID, error) { sb, err := l.sb() if err != nil { - return abi.PieceInfo{}, err + return storiface.UndefCall, err } - return sb.AddPiece(ctx, sector, epcs, sz, r) + return l.asyncCall(sector, func(ci storiface.CallID) { + pi, err := sb.AddPiece(ctx, sector, epcs, sz, r) + + if err := l.ret.ReturnAddPiece(ctx, ci, pi, errstr(err)); err != nil { + log.Errorf("ReturnAddPiece: %+v", err) + } + }) } -func (l *LocalWorker) Fetch(ctx context.Context, sector abi.SectorID, fileType stores.SectorFileType, ptype stores.PathType, am stores.AcquireMode) error { - _, done, err := (&localWorkerPathProvider{w: l, op: am}).AcquireSector(ctx, sector, fileType, stores.FTNone, ptype) - if err != nil { - return err - } - done() - return nil -} - -func (l *LocalWorker) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (out storage2.PreCommit1Out, err error) { - { - // cleanup previous failed attempts if they exist - if err := l.storage.Remove(ctx, sector, stores.FTSealed, true); err != nil { - return nil, xerrors.Errorf("cleaning up sealed data: %w", err) +func (l *LocalWorker) Fetch(ctx context.Context, sector abi.SectorID, fileType stores.SectorFileType, ptype stores.PathType, am stores.AcquireMode) (storiface.CallID, error) { + return l.asyncCall(sector, func(ci storiface.CallID) { + _, done, err := (&localWorkerPathProvider{w: l, op: am}).AcquireSector(ctx, sector, fileType, stores.FTNone, ptype) + if err == nil { + done() } - if err := l.storage.Remove(ctx, sector, stores.FTCache, true); err != nil { - return nil, xerrors.Errorf("cleaning up cache data: %w", err) + if err := l.ret.ReturnFetch(ctx, ci, errstr(err)); err != nil { + log.Errorf("ReturnFetch: %+v", err) } - } - - sb, err := l.sb() - if err != nil { - return nil, err - } - - return sb.SealPreCommit1(ctx, sector, ticket, pieces) + }) } -func (l *LocalWorker) SealPreCommit2(ctx context.Context, sector abi.SectorID, phase1Out storage2.PreCommit1Out) (cids storage2.SectorCids, err error) { - sb, err := l.sb() - if err != nil { - return storage2.SectorCids{}, err - } +func (l *LocalWorker) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storiface.CallID, error) { + return l.asyncCall(sector, func(ci storiface.CallID) { + var err error + var p1o storage2.PreCommit1Out + defer func() { + if err := l.ret.ReturnSealPreCommit1(ctx, ci, p1o, errstr(err)); err != nil { + log.Errorf("ReturnSealPreCommit1: %+v", err) + } + }() - return sb.SealPreCommit2(ctx, sector, phase1Out) -} + { + // cleanup previous failed attempts if they exist + if err = l.storage.Remove(ctx, sector, stores.FTSealed, true); err != nil { + err = xerrors.Errorf("cleaning up sealed data: %w", err) + return + } -func (l *LocalWorker) SealCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage2.SectorCids) (output storage2.Commit1Out, err error) { - sb, err := l.sb() - if err != nil { - return nil, err - } - - return sb.SealCommit1(ctx, sector, ticket, seed, pieces, cids) -} - -func (l *LocalWorker) SealCommit2(ctx context.Context, sector abi.SectorID, phase1Out storage2.Commit1Out) (proof storage2.Proof, err error) { - sb, err := l.sb() - if err != nil { - return nil, err - } - - return sb.SealCommit2(ctx, sector, phase1Out) -} - -func (l *LocalWorker) FinalizeSector(ctx context.Context, sector abi.SectorID, keepUnsealed []storage2.Range) error { - sb, err := l.sb() - if err != nil { - return err - } - - if err := sb.FinalizeSector(ctx, sector, keepUnsealed); err != nil { - return xerrors.Errorf("finalizing sector: %w", err) - } - - if len(keepUnsealed) == 0 { - if err := l.storage.Remove(ctx, sector, stores.FTUnsealed, true); err != nil { - return xerrors.Errorf("removing unsealed data: %w", err) + if err = l.storage.Remove(ctx, sector, stores.FTCache, true); err != nil { + err = xerrors.Errorf("cleaning up cache data: %w", err) + return + } } - } - return nil + var sb ffiwrapper.Storage + sb, err = l.sb() + if err != nil { + return + } + + p1o, err = sb.SealPreCommit1(ctx, sector, ticket, pieces) + }) } -func (l *LocalWorker) ReleaseUnsealed(ctx context.Context, sector abi.SectorID, safeToFree []storage2.Range) error { - return xerrors.Errorf("implement me") +func (l *LocalWorker) SealPreCommit2(ctx context.Context, sector abi.SectorID, phase1Out storage2.PreCommit1Out) (storiface.CallID, error) { + sb, err := l.sb() + if err != nil { + return storiface.UndefCall, err + } + + return l.asyncCall(sector, func(ci storiface.CallID) { + cs, err := sb.SealPreCommit2(ctx, sector, phase1Out) + + if err := l.ret.ReturnSealPreCommit2(ctx, ci, cs, errstr(err)); err != nil { + log.Errorf("ReturnSealPreCommit2: %+v", err) + } + }) +} + +func (l *LocalWorker) SealCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage2.SectorCids) (storiface.CallID, error) { + sb, err := l.sb() + if err != nil { + return storiface.UndefCall, err + } + + return l.asyncCall(sector, func(ci storiface.CallID) { + c1o, err := sb.SealCommit1(ctx, sector, ticket, seed, pieces, cids) + + if err := l.ret.ReturnSealCommit1(ctx, ci, c1o, errstr(err)); err != nil { + log.Errorf("ReturnSealCommit1: %+v", err) + } + }) +} + +func (l *LocalWorker) SealCommit2(ctx context.Context, sector abi.SectorID, phase1Out storage2.Commit1Out) (storiface.CallID, error) { + sb, err := l.sb() + if err != nil { + return storiface.UndefCall, err + } + + return l.asyncCall(sector, func(ci storiface.CallID) { + proof, err := sb.SealCommit2(ctx, sector, phase1Out) + + if err := l.ret.ReturnSealCommit2(ctx, ci, proof, errstr(err)); err != nil { + log.Errorf("ReturnSealCommit2: %+v", err) + } + }) +} + +func (l *LocalWorker) FinalizeSector(ctx context.Context, sector abi.SectorID, keepUnsealed []storage2.Range) (storiface.CallID, error) { + sb, err := l.sb() + if err != nil { + return storiface.UndefCall, err + } + + return l.asyncCall(sector, func(ci storiface.CallID) { + if err := sb.FinalizeSector(ctx, sector, keepUnsealed); err != nil { + if err := l.ret.ReturnFinalizeSector(ctx, ci, errstr(xerrors.Errorf("finalizing sector: %w", err))); err != nil { + log.Errorf("ReturnFinalizeSector: %+v", err) + } + } + + if len(keepUnsealed) == 0 { + err = xerrors.Errorf("removing unsealed data: %w", err) + if err := l.ret.ReturnFinalizeSector(ctx, ci, errstr(err)); err != nil { + log.Errorf("ReturnFinalizeSector: %+v", err) + } + } + + if err := l.ret.ReturnFinalizeSector(ctx, ci, errstr(err)); err != nil { + log.Errorf("ReturnFinalizeSector: %+v", err) + } + }) +} + +func (l *LocalWorker) ReleaseUnsealed(ctx context.Context, sector abi.SectorID, safeToFree []storage2.Range) (storiface.CallID, error) { + return storiface.UndefCall, xerrors.Errorf("implement me") } func (l *LocalWorker) Remove(ctx context.Context, sector abi.SectorID) error { @@ -208,42 +277,60 @@ func (l *LocalWorker) Remove(ctx context.Context, sector abi.SectorID) error { return err } -func (l *LocalWorker) MoveStorage(ctx context.Context, sector abi.SectorID, types stores.SectorFileType) error { - if err := l.storage.MoveStorage(ctx, sector, l.scfg.SealProofType, types); err != nil { - return xerrors.Errorf("moving sealed data to storage: %w", err) - } +func (l *LocalWorker) MoveStorage(ctx context.Context, sector abi.SectorID, types stores.SectorFileType) (storiface.CallID, error) { + return l.asyncCall(sector, func(ci storiface.CallID) { + err := l.storage.MoveStorage(ctx, sector, l.scfg.SealProofType, types) - return nil + if err := l.ret.ReturnMoveStorage(ctx, ci, errstr(err)); err != nil { + log.Errorf("ReturnMoveStorage: %+v", err) + } + }) } -func (l *LocalWorker) UnsealPiece(ctx context.Context, sector abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, randomness abi.SealRandomness, cid cid.Cid) error { +func (l *LocalWorker) UnsealPiece(ctx context.Context, sector abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, randomness abi.SealRandomness, cid cid.Cid) (storiface.CallID, error) { sb, err := l.sb() if err != nil { - return err + return storiface.UndefCall, err } - if err := sb.UnsealPiece(ctx, sector, index, size, randomness, cid); err != nil { - return xerrors.Errorf("unsealing sector: %w", err) - } + return l.asyncCall(sector, func(ci storiface.CallID) { + var err error + defer func() { + if err := l.ret.ReturnUnsealPiece(ctx, ci, errstr(err)); err != nil { + log.Errorf("ReturnUnsealPiece: %+v", err) + } + }() - if err := l.storage.RemoveCopies(ctx, sector, stores.FTSealed); err != nil { - return xerrors.Errorf("removing source data: %w", err) - } + if err = sb.UnsealPiece(ctx, sector, index, size, randomness, cid); err != nil { + err = xerrors.Errorf("unsealing sector: %w", err) + return + } - if err := l.storage.RemoveCopies(ctx, sector, stores.FTCache); err != nil { - return xerrors.Errorf("removing source data: %w", err) - } + if err = l.storage.RemoveCopies(ctx, sector, stores.FTSealed); err != nil { + err = xerrors.Errorf("removing source data: %w", err) + return + } - return nil + if err = l.storage.RemoveCopies(ctx, sector, stores.FTCache); err != nil { + err = xerrors.Errorf("removing source data: %w", err) + return + } + }) } -func (l *LocalWorker) ReadPiece(ctx context.Context, writer io.Writer, sector abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize) (bool, error) { +func (l *LocalWorker) ReadPiece(ctx context.Context, writer io.Writer, sector abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize) (storiface.CallID, error) { sb, err := l.sb() if err != nil { - return false, err + return storiface.UndefCall, err } - return sb.ReadPiece(ctx, writer, sector, index, size) + return l.asyncCall(sector, func(ci storiface.CallID) { + ok, err := sb.ReadPiece(ctx, writer, sector, index, size) + + if err := l.ret.ReturnReadPiece(ctx, ci, ok, errstr(err)); err != nil { + log.Errorf("ReturnReadPiece: %+v", err) + } + }) } func (l *LocalWorker) TaskTypes(context.Context) (map[sealtasks.TaskType]struct{}, error) { diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index 300958e39..683f34505 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -29,13 +29,7 @@ var ErrNoWorkers = errors.New("no suitable workers found") type URLs []string type Worker interface { - ffiwrapper.StorageSealer - - MoveStorage(ctx context.Context, sector abi.SectorID, types stores.SectorFileType) error - - Fetch(ctx context.Context, s abi.SectorID, ft stores.SectorFileType, ptype stores.PathType, am stores.AcquireMode) error - UnsealPiece(context.Context, abi.SectorID, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize, abi.SealRandomness, cid.Cid) error - ReadPiece(context.Context, io.Writer, abi.SectorID, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize) (bool, error) + storiface.WorkerCalls TaskTypes(context.Context) (map[sealtasks.TaskType]struct{}, error) diff --git a/extern/sector-storage/storiface/storage.go b/extern/sector-storage/storiface/storage.go new file mode 100644 index 000000000..f1de3656e --- /dev/null +++ b/extern/sector-storage/storiface/storage.go @@ -0,0 +1 @@ +package storiface diff --git a/extern/sector-storage/storiface/worker.go b/extern/sector-storage/storiface/worker.go index 37e4aad1d..9f79e37be 100644 --- a/extern/sector-storage/storiface/worker.go +++ b/extern/sector-storage/storiface/worker.go @@ -1,10 +1,18 @@ package storiface import ( + "context" + "io" "time" - "github.com/filecoin-project/lotus/extern/sector-storage/sealtasks" + "github.com/google/uuid" + "github.com/ipfs/go-cid" + "github.com/filecoin-project/specs-actors/actors/abi" + "github.com/filecoin-project/specs-storage/storage" + + "github.com/filecoin-project/lotus/extern/sector-storage/sealtasks" + "github.com/filecoin-project/lotus/extern/sector-storage/stores" ) type WorkerInfo struct { @@ -40,3 +48,38 @@ type WorkerJob struct { RunWait int // 0 - running, 1+ - assigned Start time.Time } + +type CallID struct { + Sector abi.SectorID + ID uuid.UUID +} + +var UndefCall CallID + +type WorkerCalls interface { + AddPiece(ctx context.Context, sector abi.SectorID, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage.Data) (CallID, error) + SealPreCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (CallID, error) + SealPreCommit2(ctx context.Context, sector abi.SectorID, pc1o storage.PreCommit1Out) (CallID, error) + SealCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (CallID, error) + SealCommit2(ctx context.Context, sector abi.SectorID, c1o storage.Commit1Out) (CallID, error) + FinalizeSector(ctx context.Context, sector abi.SectorID, keepUnsealed []storage.Range) (CallID, error) + ReleaseUnsealed(ctx context.Context, sector abi.SectorID, safeToFree []storage.Range) (CallID, error) + MoveStorage(ctx context.Context, sector abi.SectorID, types stores.SectorFileType) (CallID, error) + UnsealPiece(context.Context, abi.SectorID, UnpaddedByteIndex, abi.UnpaddedPieceSize, abi.SealRandomness, cid.Cid) (CallID, error) + ReadPiece(context.Context, io.Writer, abi.SectorID, UnpaddedByteIndex, abi.UnpaddedPieceSize) (CallID, error) + Fetch(context.Context, abi.SectorID, stores.SectorFileType, stores.PathType, stores.AcquireMode) (CallID, error) +} + +type WorkerReturn interface { + ReturnAddPiece(ctx context.Context, callID CallID, pi abi.PieceInfo, err string) error + ReturnSealPreCommit1(ctx context.Context, callID CallID, p1o storage.PreCommit1Out, err string) error + ReturnSealPreCommit2(ctx context.Context, callID CallID, sealed storage.SectorCids, err string) error + ReturnSealCommit1(ctx context.Context, callID CallID, out storage.Commit1Out, err string) error + ReturnSealCommit2(ctx context.Context, callID CallID, proof storage.Proof, err string) error + ReturnFinalizeSector(ctx context.Context, callID CallID, err string) error + ReturnReleaseUnsealed(ctx context.Context, callID CallID, err string) error + ReturnMoveStorage(ctx context.Context, callID CallID, err string) error + ReturnUnsealPiece(ctx context.Context, callID CallID, err string) error + ReturnReadPiece(ctx context.Context, callID CallID, ok bool, err string) error + ReturnFetch(ctx context.Context, callID CallID, err string) error +} From 5d7394392965fe7b4bb339606c434530461a7e9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sun, 6 Sep 2020 18:54:00 +0200 Subject: [PATCH 002/313] storage: Fix import cycle --- api/apistruct/struct.go | 63 ++++++++------- cmd/lotus-bench/main.go | 4 +- cmd/lotus-seed/seed/seed.go | 5 +- cmd/lotus-storage-miner/storage.go | 7 +- extern/sector-storage/faults.go | 6 +- .../sector-storage/ffiwrapper/basicfs/fs.go | 29 ++++--- .../sector-storage/ffiwrapper/sealer_cgo.go | 25 +++--- .../sector-storage/ffiwrapper/sealer_test.go | 4 +- extern/sector-storage/ffiwrapper/types.go | 7 +- .../sector-storage/ffiwrapper/verifier_cgo.go | 5 +- extern/sector-storage/localworker.go | 36 ++++----- extern/sector-storage/manager.go | 74 ++++++++--------- extern/sector-storage/roprov.go | 15 ++-- extern/sector-storage/sched_test.go | 6 +- extern/sector-storage/selector_alloc.go | 7 +- extern/sector-storage/selector_existing.go | 5 +- extern/sector-storage/stores/http_handler.go | 23 +++--- extern/sector-storage/stores/index.go | 43 +++++----- extern/sector-storage/stores/index_locks.go | 25 +++--- .../sector-storage/stores/index_locks_test.go | 65 +++++++-------- extern/sector-storage/stores/interface.go | 24 ++---- extern/sector-storage/stores/local.go | 79 +++++++++---------- extern/sector-storage/stores/remote.go | 54 ++++++------- .../{stores => storiface}/filetype.go | 4 +- extern/sector-storage/storiface/storage.go | 14 ++++ extern/sector-storage/storiface/worker.go | 5 +- extern/sector-storage/testworker_test.go | 4 +- extern/sector-storage/work_tracker.go | 3 +- 28 files changed, 323 insertions(+), 318 deletions(-) rename extern/sector-storage/{stores => storiface}/filetype.go (96%) diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 5fb80433d..bc51f9b86 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -284,18 +284,18 @@ type StorageMinerStruct struct { SealingSchedDiag func(context.Context) (interface{}, error) `perm:"admin"` - StorageList func(context.Context) (map[stores.ID][]stores.Decl, error) `perm:"admin"` - StorageLocal func(context.Context) (map[stores.ID]string, error) `perm:"admin"` - StorageStat func(context.Context, stores.ID) (fsutil.FsStat, error) `perm:"admin"` - StorageAttach func(context.Context, stores.StorageInfo, fsutil.FsStat) error `perm:"admin"` - StorageDeclareSector func(context.Context, stores.ID, abi.SectorID, stores.SectorFileType, bool) error `perm:"admin"` - StorageDropSector func(context.Context, stores.ID, abi.SectorID, stores.SectorFileType) error `perm:"admin"` - StorageFindSector func(context.Context, abi.SectorID, stores.SectorFileType, abi.RegisteredSealProof, bool) ([]stores.SectorStorageInfo, error) `perm:"admin"` - StorageInfo func(context.Context, stores.ID) (stores.StorageInfo, error) `perm:"admin"` - StorageBestAlloc func(ctx context.Context, allocate stores.SectorFileType, spt abi.RegisteredSealProof, sealing stores.PathType) ([]stores.StorageInfo, error) `perm:"admin"` - StorageReportHealth func(ctx context.Context, id stores.ID, report stores.HealthReport) error `perm:"admin"` - StorageLock func(ctx context.Context, sector abi.SectorID, read stores.SectorFileType, write stores.SectorFileType) error `perm:"admin"` - StorageTryLock func(ctx context.Context, sector abi.SectorID, read stores.SectorFileType, write stores.SectorFileType) (bool, error) `perm:"admin"` + StorageList func(context.Context) (map[stores.ID][]stores.Decl, error) `perm:"admin"` + StorageLocal func(context.Context) (map[stores.ID]string, error) `perm:"admin"` + StorageStat func(context.Context, stores.ID) (fsutil.FsStat, error) `perm:"admin"` + StorageAttach func(context.Context, stores.StorageInfo, fsutil.FsStat) error `perm:"admin"` + StorageDeclareSector func(context.Context, stores.ID, abi.SectorID, storiface.SectorFileType, bool) error `perm:"admin"` + StorageDropSector func(context.Context, stores.ID, abi.SectorID, storiface.SectorFileType) error `perm:"admin"` + StorageFindSector func(context.Context, abi.SectorID, storiface.SectorFileType, abi.RegisteredSealProof, bool) ([]stores.SectorStorageInfo, error) `perm:"admin"` + StorageInfo func(context.Context, stores.ID) (stores.StorageInfo, error) `perm:"admin"` + StorageBestAlloc func(ctx context.Context, allocate storiface.SectorFileType, spt abi.RegisteredSealProof, sealing storiface.PathType) ([]stores.StorageInfo, error) `perm:"admin"` + StorageReportHealth func(ctx context.Context, id stores.ID, report stores.HealthReport) error `perm:"admin"` + StorageLock func(ctx context.Context, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) error `perm:"admin"` + StorageTryLock func(ctx context.Context, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) (bool, error) `perm:"admin"` DealsImportData func(ctx context.Context, dealPropCid cid.Cid, file string) error `perm:"write"` DealsList func(ctx context.Context) ([]storagemarket.StorageDeal, error) `perm:"read"` @@ -329,22 +329,21 @@ type WorkerStruct struct { Paths func(context.Context) ([]stores.StoragePath, error) `perm:"admin"` Info func(context.Context) (storiface.WorkerInfo, error) `perm:"admin"` - AddPiece func(ctx context.Context, sector abi.SectorID, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage.Data) (storiface.CallID, error) `perm:"admin"` - SealPreCommit1 func(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storiface.CallID, error) `perm:"admin"` - SealPreCommit2 func(ctx context.Context, sector abi.SectorID, pc1o storage.PreCommit1Out) (storiface.CallID, error) `perm:"admin"` - SealCommit1 func(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storiface.CallID, error) `perm:"admin"` - SealCommit2 func(ctx context.Context, sector abi.SectorID, c1o storage.Commit1Out) (storiface.CallID, error) `perm:"admin"` - FinalizeSector func(ctx context.Context, sector abi.SectorID, keepUnsealed []storage.Range) (storiface.CallID, error) `perm:"admin"` - ReleaseUnsealed func(ctx context.Context, sector abi.SectorID, safeToFree []storage.Range) (storiface.CallID, error) `perm:"admin"` - MoveStorage func(ctx context.Context, sector abi.SectorID, types stores.SectorFileType) (storiface.CallID, error) `perm:"admin"` - UnsealPiece func(context.Context, abi.SectorID, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize, abi.SealRandomness, cid.Cid) (storiface.CallID, error) `perm:"admin"` - ReadPiece func(context.Context, io.Writer, abi.SectorID, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize) (storiface.CallID, error) `perm:"admin"` - Fetch func(context.Context, abi.SectorID, stores.SectorFileType, stores.PathType, stores.AcquireMode) (storiface.CallID, error) `perm:"admin"` + AddPiece func(ctx context.Context, sector abi.SectorID, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage.Data) (storiface.CallID, error) `perm:"admin"` + SealPreCommit1 func(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storiface.CallID, error) `perm:"admin"` + SealPreCommit2 func(ctx context.Context, sector abi.SectorID, pc1o storage.PreCommit1Out) (storiface.CallID, error) `perm:"admin"` + SealCommit1 func(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storiface.CallID, error) `perm:"admin"` + SealCommit2 func(ctx context.Context, sector abi.SectorID, c1o storage.Commit1Out) (storiface.CallID, error) `perm:"admin"` + FinalizeSector func(ctx context.Context, sector abi.SectorID, keepUnsealed []storage.Range) (storiface.CallID, error) `perm:"admin"` + ReleaseUnsealed func(ctx context.Context, sector abi.SectorID, safeToFree []storage.Range) (storiface.CallID, error) `perm:"admin"` + MoveStorage func(ctx context.Context, sector abi.SectorID, types storiface.SectorFileType) (storiface.CallID, error) `perm:"admin"` + UnsealPiece func(context.Context, abi.SectorID, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize, abi.SealRandomness, cid.Cid) (storiface.CallID, error) `perm:"admin"` + ReadPiece func(context.Context, io.Writer, abi.SectorID, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize) (storiface.CallID, error) `perm:"admin"` + Fetch func(context.Context, abi.SectorID, storiface.SectorFileType, storiface.PathType, storiface.AcquireMode) (storiface.CallID, error) `perm:"admin"` Remove func(ctx context.Context, sector abi.SectorID) error `perm:"admin"` StorageAddLocal func(ctx context.Context, path string) error `perm:"admin"` - Closing func(context.Context) (<-chan struct{}, error) `perm:"admin"` } } @@ -1102,15 +1101,15 @@ func (c *StorageMinerStruct) StorageAttach(ctx context.Context, si stores.Storag return c.Internal.StorageAttach(ctx, si, st) } -func (c *StorageMinerStruct) StorageDeclareSector(ctx context.Context, storageId stores.ID, s abi.SectorID, ft stores.SectorFileType, primary bool) error { +func (c *StorageMinerStruct) StorageDeclareSector(ctx context.Context, storageId stores.ID, s abi.SectorID, ft storiface.SectorFileType, primary bool) error { return c.Internal.StorageDeclareSector(ctx, storageId, s, ft, primary) } -func (c *StorageMinerStruct) StorageDropSector(ctx context.Context, storageId stores.ID, s abi.SectorID, ft stores.SectorFileType) error { +func (c *StorageMinerStruct) StorageDropSector(ctx context.Context, storageId stores.ID, s abi.SectorID, ft storiface.SectorFileType) error { return c.Internal.StorageDropSector(ctx, storageId, s, ft) } -func (c *StorageMinerStruct) StorageFindSector(ctx context.Context, si abi.SectorID, types stores.SectorFileType, spt abi.RegisteredSealProof, allowFetch bool) ([]stores.SectorStorageInfo, error) { +func (c *StorageMinerStruct) StorageFindSector(ctx context.Context, si abi.SectorID, types storiface.SectorFileType, spt abi.RegisteredSealProof, allowFetch bool) ([]stores.SectorStorageInfo, error) { return c.Internal.StorageFindSector(ctx, si, types, spt, allowFetch) } @@ -1130,7 +1129,7 @@ func (c *StorageMinerStruct) StorageInfo(ctx context.Context, id stores.ID) (sto return c.Internal.StorageInfo(ctx, id) } -func (c *StorageMinerStruct) StorageBestAlloc(ctx context.Context, allocate stores.SectorFileType, spt abi.RegisteredSealProof, pt stores.PathType) ([]stores.StorageInfo, error) { +func (c *StorageMinerStruct) StorageBestAlloc(ctx context.Context, allocate storiface.SectorFileType, spt abi.RegisteredSealProof, pt storiface.PathType) ([]stores.StorageInfo, error) { return c.Internal.StorageBestAlloc(ctx, allocate, spt, pt) } @@ -1138,11 +1137,11 @@ func (c *StorageMinerStruct) StorageReportHealth(ctx context.Context, id stores. return c.Internal.StorageReportHealth(ctx, id, report) } -func (c *StorageMinerStruct) StorageLock(ctx context.Context, sector abi.SectorID, read stores.SectorFileType, write stores.SectorFileType) error { +func (c *StorageMinerStruct) StorageLock(ctx context.Context, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) error { return c.Internal.StorageLock(ctx, sector, read, write) } -func (c *StorageMinerStruct) StorageTryLock(ctx context.Context, sector abi.SectorID, read stores.SectorFileType, write stores.SectorFileType) (bool, error) { +func (c *StorageMinerStruct) StorageTryLock(ctx context.Context, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) (bool, error) { return c.Internal.StorageTryLock(ctx, sector, read, write) } @@ -1304,7 +1303,7 @@ func (w *WorkerStruct) ReleaseUnsealed(ctx context.Context, sector abi.SectorID, return w.Internal.ReleaseUnsealed(ctx, sector, safeToFree) } -func (w *WorkerStruct) MoveStorage(ctx context.Context, sector abi.SectorID, types stores.SectorFileType) (storiface.CallID, error) { +func (w *WorkerStruct) MoveStorage(ctx context.Context, sector abi.SectorID, types storiface.SectorFileType) (storiface.CallID, error) { return w.Internal.MoveStorage(ctx, sector, types) } @@ -1316,7 +1315,7 @@ func (w *WorkerStruct) ReadPiece(ctx context.Context, sink io.Writer, sector abi return w.Internal.ReadPiece(ctx, sink, sector, offset, size) } -func (w *WorkerStruct) Fetch(ctx context.Context, id abi.SectorID, fileType stores.SectorFileType, ptype stores.PathType, am stores.AcquireMode) (storiface.CallID, error) { +func (w *WorkerStruct) Fetch(ctx context.Context, id abi.SectorID, fileType storiface.SectorFileType, ptype storiface.PathType, am storiface.AcquireMode) (storiface.CallID, error) { return w.Internal.Fetch(ctx, id, fileType, ptype, am) } diff --git a/cmd/lotus-bench/main.go b/cmd/lotus-bench/main.go index 694987f27..c63d9673a 100644 --- a/cmd/lotus-bench/main.go +++ b/cmd/lotus-bench/main.go @@ -23,7 +23,7 @@ import ( lcli "github.com/filecoin-project/lotus/cli" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper/basicfs" - "github.com/filecoin-project/lotus/extern/sector-storage/stores" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/builtin/miner" "github.com/filecoin-project/specs-storage/storage" @@ -612,7 +612,7 @@ func runSeals(sb *ffiwrapper.Sealer, sbfs *basicfs.Provider, numSectors int, par if !skipunseal { log.Infof("[%d] Unsealing sector", i) { - p, done, err := sbfs.AcquireSector(context.TODO(), abi.SectorID{Miner: mid, Number: 1}, stores.FTUnsealed, stores.FTNone, stores.PathSealing) + p, done, err := sbfs.AcquireSector(context.TODO(), abi.SectorID{Miner: mid, Number: 1}, storiface.FTUnsealed, storiface.FTNone, storiface.PathSealing) if err != nil { return xerrors.Errorf("acquire unsealed sector for removing: %w", err) } diff --git a/cmd/lotus-seed/seed/seed.go b/cmd/lotus-seed/seed/seed.go index f892709f6..0ae61e6b8 100644 --- a/cmd/lotus-seed/seed/seed.go +++ b/cmd/lotus-seed/seed/seed.go @@ -6,6 +6,7 @@ import ( "encoding/hex" "encoding/json" "fmt" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "io/ioutil" "os" "path/filepath" @@ -187,7 +188,7 @@ func presealSector(sb *ffiwrapper.Sealer, sbfs *basicfs.Provider, sid abi.Sector } func presealSectorFake(sbfs *basicfs.Provider, sid abi.SectorID, spt abi.RegisteredSealProof, ssize abi.SectorSize) (*genesis.PreSeal, error) { - paths, done, err := sbfs.AcquireSector(context.TODO(), sid, 0, stores.FTSealed|stores.FTCache, stores.PathSealing) + paths, done, err := sbfs.AcquireSector(context.TODO(), sid, 0, storiface.FTSealed|storiface.FTCache, storiface.PathSealing) if err != nil { return nil, xerrors.Errorf("acquire unsealed sector: %w", err) } @@ -211,7 +212,7 @@ func presealSectorFake(sbfs *basicfs.Provider, sid abi.SectorID, spt abi.Registe } func cleanupUnsealed(sbfs *basicfs.Provider, sid abi.SectorID) error { - paths, done, err := sbfs.AcquireSector(context.TODO(), sid, stores.FTUnsealed, stores.FTNone, stores.PathSealing) + paths, done, err := sbfs.AcquireSector(context.TODO(), sid, storiface.FTUnsealed, storiface.FTNone, storiface.PathSealing) if err != nil { return err } diff --git a/cmd/lotus-storage-miner/storage.go b/cmd/lotus-storage-miner/storage.go index 7fadcf83f..5f3d2ac25 100644 --- a/cmd/lotus-storage-miner/storage.go +++ b/cmd/lotus-storage-miner/storage.go @@ -3,6 +3,7 @@ package main import ( "encoding/json" "fmt" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "io/ioutil" "os" "path/filepath" @@ -294,17 +295,17 @@ var storageFindCmd = &cli.Command{ Number: abi.SectorNumber(snum), } - u, err := nodeApi.StorageFindSector(ctx, sid, stores.FTUnsealed, 0, false) + u, err := nodeApi.StorageFindSector(ctx, sid, storiface.FTUnsealed, 0, false) if err != nil { return xerrors.Errorf("finding unsealed: %w", err) } - s, err := nodeApi.StorageFindSector(ctx, sid, stores.FTSealed, 0, false) + s, err := nodeApi.StorageFindSector(ctx, sid, storiface.FTSealed, 0, false) if err != nil { return xerrors.Errorf("finding sealed: %w", err) } - c, err := nodeApi.StorageFindSector(ctx, sid, stores.FTCache, 0, false) + c, err := nodeApi.StorageFindSector(ctx, sid, storiface.FTCache, 0, false) if err != nil { return xerrors.Errorf("finding cache: %w", err) } diff --git a/extern/sector-storage/faults.go b/extern/sector-storage/faults.go index 06c823bb8..9c5948ab1 100644 --- a/extern/sector-storage/faults.go +++ b/extern/sector-storage/faults.go @@ -3,12 +3,12 @@ package sectorstorage import ( "context" "fmt" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "os" "path/filepath" "golang.org/x/xerrors" - "github.com/filecoin-project/lotus/extern/sector-storage/stores" "github.com/filecoin-project/specs-actors/actors/abi" ) @@ -32,7 +32,7 @@ func (m *Manager) CheckProvable(ctx context.Context, spt abi.RegisteredSealProof ctx, cancel := context.WithCancel(ctx) defer cancel() - locked, err := m.index.StorageTryLock(ctx, sector, stores.FTSealed|stores.FTCache, stores.FTNone) + locked, err := m.index.StorageTryLock(ctx, sector, storiface.FTSealed|storiface.FTCache, storiface.FTNone) if err != nil { return xerrors.Errorf("acquiring sector lock: %w", err) } @@ -43,7 +43,7 @@ func (m *Manager) CheckProvable(ctx context.Context, spt abi.RegisteredSealProof return nil } - lp, _, err := m.localStore.AcquireSector(ctx, sector, spt, stores.FTSealed|stores.FTCache, stores.FTNone, stores.PathStorage, stores.AcquireMove) + lp, _, err := m.localStore.AcquireSector(ctx, sector, spt, storiface.FTSealed|storiface.FTCache, storiface.FTNone, storiface.PathStorage, storiface.AcquireMove) if err != nil { log.Warnw("CheckProvable Sector FAULT: acquire sector in checkProvable", "sector", sector, "error", err) bad = append(bad, sector) diff --git a/extern/sector-storage/ffiwrapper/basicfs/fs.go b/extern/sector-storage/ffiwrapper/basicfs/fs.go index ae17273e9..491aeabc1 100644 --- a/extern/sector-storage/ffiwrapper/basicfs/fs.go +++ b/extern/sector-storage/ffiwrapper/basicfs/fs.go @@ -8,13 +8,12 @@ import ( "github.com/filecoin-project/specs-actors/actors/abi" - "github.com/filecoin-project/lotus/extern/sector-storage/stores" "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) type sectorFile struct { abi.SectorID - stores.SectorFileType + storiface.SectorFileType } type Provider struct { @@ -24,24 +23,24 @@ type Provider struct { waitSector map[sectorFile]chan struct{} } -func (b *Provider) AcquireSector(ctx context.Context, id abi.SectorID, existing stores.SectorFileType, allocate stores.SectorFileType, ptype stores.PathType) (stores.SectorPaths, func(), error) { - if err := os.Mkdir(filepath.Join(b.Root, stores.FTUnsealed.String()), 0755); err != nil && !os.IsExist(err) { // nolint - return stores.SectorPaths{}, nil, err +func (b *Provider) AcquireSector(ctx context.Context, id abi.SectorID, existing storiface.SectorFileType, allocate storiface.SectorFileType, ptype storiface.PathType) (storiface.SectorPaths, func(), error) { + if err := os.Mkdir(filepath.Join(b.Root, storiface.FTUnsealed.String()), 0755); err != nil && !os.IsExist(err) { // nolint + return storiface.SectorPaths{}, nil, err } - if err := os.Mkdir(filepath.Join(b.Root, stores.FTSealed.String()), 0755); err != nil && !os.IsExist(err) { // nolint - return stores.SectorPaths{}, nil, err + if err := os.Mkdir(filepath.Join(b.Root, storiface.FTSealed.String()), 0755); err != nil && !os.IsExist(err) { // nolint + return storiface.SectorPaths{}, nil, err } - if err := os.Mkdir(filepath.Join(b.Root, stores.FTCache.String()), 0755); err != nil && !os.IsExist(err) { // nolint - return stores.SectorPaths{}, nil, err + if err := os.Mkdir(filepath.Join(b.Root, storiface.FTCache.String()), 0755); err != nil && !os.IsExist(err) { // nolint + return storiface.SectorPaths{}, nil, err } done := func() {} - out := stores.SectorPaths{ + out := storiface.SectorPaths{ ID: id, } - for _, fileType := range stores.PathTypes { + for _, fileType := range storiface.PathTypes { if !existing.Has(fileType) && !allocate.Has(fileType) { continue } @@ -61,10 +60,10 @@ func (b *Provider) AcquireSector(ctx context.Context, id abi.SectorID, existing case ch <- struct{}{}: case <-ctx.Done(): done() - return stores.SectorPaths{}, nil, ctx.Err() + return storiface.SectorPaths{}, nil, ctx.Err() } - path := filepath.Join(b.Root, fileType.String(), stores.SectorName(id)) + path := filepath.Join(b.Root, fileType.String(), storiface.SectorName(id)) prevDone := done done = func() { @@ -75,11 +74,11 @@ func (b *Provider) AcquireSector(ctx context.Context, id abi.SectorID, existing if !allocate.Has(fileType) { if _, err := os.Stat(path); os.IsNotExist(err) { done() - return stores.SectorPaths{}, nil, storiface.ErrSectorNotFound + return storiface.SectorPaths{}, nil, storiface.ErrSectorNotFound } } - stores.SetPathByType(&out, fileType, path) + storiface.SetPathByType(&out, fileType, path) } return out, done, nil diff --git a/extern/sector-storage/ffiwrapper/sealer_cgo.go b/extern/sector-storage/ffiwrapper/sealer_cgo.go index d4f796dcb..b3032a243 100644 --- a/extern/sector-storage/ffiwrapper/sealer_cgo.go +++ b/extern/sector-storage/ffiwrapper/sealer_cgo.go @@ -21,7 +21,6 @@ import ( "github.com/filecoin-project/specs-storage/storage" "github.com/filecoin-project/lotus/extern/sector-storage/fr32" - "github.com/filecoin-project/lotus/extern/sector-storage/stores" "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "github.com/filecoin-project/lotus/extern/sector-storage/zerocomm" ) @@ -80,9 +79,9 @@ func (sb *Sealer) AddPiece(ctx context.Context, sector abi.SectorID, existingPie } }() - var stagedPath stores.SectorPaths + var stagedPath storiface.SectorPaths if len(existingPieceSizes) == 0 { - stagedPath, done, err = sb.sectors.AcquireSector(ctx, sector, 0, stores.FTUnsealed, stores.PathSealing) + stagedPath, done, err = sb.sectors.AcquireSector(ctx, sector, 0, storiface.FTUnsealed, storiface.PathSealing) if err != nil { return abi.PieceInfo{}, xerrors.Errorf("acquire unsealed sector: %w", err) } @@ -92,7 +91,7 @@ func (sb *Sealer) AddPiece(ctx context.Context, sector abi.SectorID, existingPie return abi.PieceInfo{}, xerrors.Errorf("creating unsealed sector file: %w", err) } } else { - stagedPath, done, err = sb.sectors.AcquireSector(ctx, sector, stores.FTUnsealed, 0, stores.PathSealing) + stagedPath, done, err = sb.sectors.AcquireSector(ctx, sector, storiface.FTUnsealed, 0, storiface.PathSealing) if err != nil { return abi.PieceInfo{}, xerrors.Errorf("acquire unsealed sector: %w", err) } @@ -199,12 +198,12 @@ func (sb *Sealer) UnsealPiece(ctx context.Context, sector abi.SectorID, offset s maxPieceSize := abi.PaddedPieceSize(sb.ssize) // try finding existing - unsealedPath, done, err := sb.sectors.AcquireSector(ctx, sector, stores.FTUnsealed, stores.FTNone, stores.PathStorage) + unsealedPath, done, err := sb.sectors.AcquireSector(ctx, sector, storiface.FTUnsealed, storiface.FTNone, storiface.PathStorage) var pf *partialFile switch { case xerrors.Is(err, storiface.ErrSectorNotFound): - unsealedPath, done, err = sb.sectors.AcquireSector(ctx, sector, stores.FTNone, stores.FTUnsealed, stores.PathStorage) + unsealedPath, done, err = sb.sectors.AcquireSector(ctx, sector, storiface.FTNone, storiface.FTUnsealed, storiface.PathStorage) if err != nil { return xerrors.Errorf("acquire unsealed sector path (allocate): %w", err) } @@ -241,7 +240,7 @@ func (sb *Sealer) UnsealPiece(ctx context.Context, sector abi.SectorID, offset s return nil } - srcPaths, srcDone, err := sb.sectors.AcquireSector(ctx, sector, stores.FTCache|stores.FTSealed, stores.FTNone, stores.PathStorage) + srcPaths, srcDone, err := sb.sectors.AcquireSector(ctx, sector, storiface.FTCache|storiface.FTSealed, storiface.FTNone, storiface.PathStorage) if err != nil { return xerrors.Errorf("acquire sealed sector paths: %w", err) } @@ -362,7 +361,7 @@ func (sb *Sealer) UnsealPiece(ctx context.Context, sector abi.SectorID, offset s } func (sb *Sealer) ReadPiece(ctx context.Context, writer io.Writer, sector abi.SectorID, offset storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize) (bool, error) { - path, done, err := sb.sectors.AcquireSector(ctx, sector, stores.FTUnsealed, stores.FTNone, stores.PathStorage) + path, done, err := sb.sectors.AcquireSector(ctx, sector, storiface.FTUnsealed, storiface.FTNone, storiface.PathStorage) if err != nil { return false, xerrors.Errorf("acquire unsealed sector path: %w", err) } @@ -414,7 +413,7 @@ func (sb *Sealer) ReadPiece(ctx context.Context, writer io.Writer, sector abi.Se } func (sb *Sealer) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (out storage.PreCommit1Out, err error) { - paths, done, err := sb.sectors.AcquireSector(ctx, sector, stores.FTUnsealed, stores.FTSealed|stores.FTCache, stores.PathSealing) + paths, done, err := sb.sectors.AcquireSector(ctx, sector, storiface.FTUnsealed, storiface.FTSealed|storiface.FTCache, storiface.PathSealing) if err != nil { return nil, xerrors.Errorf("acquiring sector paths: %w", err) } @@ -471,7 +470,7 @@ func (sb *Sealer) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticke } func (sb *Sealer) SealPreCommit2(ctx context.Context, sector abi.SectorID, phase1Out storage.PreCommit1Out) (storage.SectorCids, error) { - paths, done, err := sb.sectors.AcquireSector(ctx, sector, stores.FTSealed|stores.FTCache, 0, stores.PathSealing) + paths, done, err := sb.sectors.AcquireSector(ctx, sector, storiface.FTSealed|storiface.FTCache, 0, storiface.PathSealing) if err != nil { return storage.SectorCids{}, xerrors.Errorf("acquiring sector paths: %w", err) } @@ -489,7 +488,7 @@ func (sb *Sealer) SealPreCommit2(ctx context.Context, sector abi.SectorID, phase } func (sb *Sealer) SealCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storage.Commit1Out, error) { - paths, done, err := sb.sectors.AcquireSector(ctx, sector, stores.FTSealed|stores.FTCache, 0, stores.PathSealing) + paths, done, err := sb.sectors.AcquireSector(ctx, sector, storiface.FTSealed|storiface.FTCache, 0, storiface.PathSealing) if err != nil { return nil, xerrors.Errorf("acquire sector paths: %w", err) } @@ -539,7 +538,7 @@ func (sb *Sealer) FinalizeSector(ctx context.Context, sector abi.SectorID, keepU } } - paths, done, err := sb.sectors.AcquireSector(ctx, sector, stores.FTUnsealed, 0, stores.PathStorage) + paths, done, err := sb.sectors.AcquireSector(ctx, sector, storiface.FTUnsealed, 0, storiface.PathStorage) if err != nil { return xerrors.Errorf("acquiring sector cache path: %w", err) } @@ -576,7 +575,7 @@ func (sb *Sealer) FinalizeSector(ctx context.Context, sector abi.SectorID, keepU } } - paths, done, err := sb.sectors.AcquireSector(ctx, sector, stores.FTCache, 0, stores.PathStorage) + paths, done, err := sb.sectors.AcquireSector(ctx, sector, storiface.FTCache, 0, storiface.PathStorage) if err != nil { return xerrors.Errorf("acquiring sector cache path: %w", err) } diff --git a/extern/sector-storage/ffiwrapper/sealer_test.go b/extern/sector-storage/ffiwrapper/sealer_test.go index b484b391f..372af05be 100644 --- a/extern/sector-storage/ffiwrapper/sealer_test.go +++ b/extern/sector-storage/ffiwrapper/sealer_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "fmt" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "io" "io/ioutil" "math/rand" @@ -28,7 +29,6 @@ import ( ffi "github.com/filecoin-project/filecoin-ffi" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper/basicfs" - "github.com/filecoin-project/lotus/extern/sector-storage/stores" ) func init() { @@ -123,7 +123,7 @@ func (s *seal) unseal(t *testing.T, sb *Sealer, sp *basicfs.Provider, si abi.Sec t.Fatal("read wrong bytes") } - p, sd, err := sp.AcquireSector(context.TODO(), si, stores.FTUnsealed, stores.FTNone, stores.PathStorage) + p, sd, err := sp.AcquireSector(context.TODO(), si, storiface.FTUnsealed, storiface.FTNone, storiface.PathStorage) if err != nil { t.Fatal(err) } diff --git a/extern/sector-storage/ffiwrapper/types.go b/extern/sector-storage/ffiwrapper/types.go index a634134ee..71fe3cf39 100644 --- a/extern/sector-storage/ffiwrapper/types.go +++ b/extern/sector-storage/ffiwrapper/types.go @@ -10,13 +10,12 @@ import ( "github.com/filecoin-project/specs-storage/storage" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper/basicfs" - "github.com/filecoin-project/lotus/extern/sector-storage/stores" "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) type Validator interface { - CanCommit(sector stores.SectorPaths) (bool, error) - CanProve(sector stores.SectorPaths) (bool, error) + CanCommit(sector storiface.SectorPaths) (bool, error) + CanProve(sector storiface.SectorPaths) (bool, error) } type StorageSealer interface { @@ -43,7 +42,7 @@ type Verifier interface { type SectorProvider interface { // * returns storiface.ErrSectorNotFound if a requested existing sector doesn't exist // * returns an error when allocate is set, and existing isn't, and the sector exists - AcquireSector(ctx context.Context, id abi.SectorID, existing stores.SectorFileType, allocate stores.SectorFileType, ptype stores.PathType) (stores.SectorPaths, func(), error) + AcquireSector(ctx context.Context, id abi.SectorID, existing storiface.SectorFileType, allocate storiface.SectorFileType, ptype storiface.PathType) (storiface.SectorPaths, func(), error) } var _ SectorProvider = &basicfs.Provider{} diff --git a/extern/sector-storage/ffiwrapper/verifier_cgo.go b/extern/sector-storage/ffiwrapper/verifier_cgo.go index de6fc0849..c72070ef7 100644 --- a/extern/sector-storage/ffiwrapper/verifier_cgo.go +++ b/extern/sector-storage/ffiwrapper/verifier_cgo.go @@ -4,6 +4,7 @@ package ffiwrapper import ( "context" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "golang.org/x/xerrors" @@ -11,8 +12,6 @@ import ( ffi "github.com/filecoin-project/filecoin-ffi" - "github.com/filecoin-project/lotus/extern/sector-storage/stores" - "go.opencensus.io/trace" ) @@ -64,7 +63,7 @@ func (sb *Sealer) pubSectorToPriv(ctx context.Context, mid abi.ActorID, sectorIn sid := abi.SectorID{Miner: mid, Number: s.SectorNumber} - paths, d, err := sb.sectors.AcquireSector(ctx, sid, stores.FTCache|stores.FTSealed, 0, stores.PathStorage) + paths, d, err := sb.sectors.AcquireSector(ctx, sid, storiface.FTCache|storiface.FTSealed, 0, storiface.PathStorage) if err != nil { log.Warnw("failed to acquire sector, skipping", "sector", sid, "error", err) skipped = append(skipped, sid) diff --git a/extern/sector-storage/localworker.go b/extern/sector-storage/localworker.go index 9d451309d..1a2232dd1 100644 --- a/extern/sector-storage/localworker.go +++ b/extern/sector-storage/localworker.go @@ -22,7 +22,7 @@ import ( "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) -var pathTypes = []stores.SectorFileType{stores.FTUnsealed, stores.FTSealed, stores.FTCache} +var pathTypes = []storiface.SectorFileType{storiface.FTUnsealed, storiface.FTSealed, storiface.FTCache} type WorkerConfig struct { SealProof abi.RegisteredSealProof @@ -59,19 +59,19 @@ func NewLocalWorker(wcfg WorkerConfig, store stores.Store, local *stores.Local, type localWorkerPathProvider struct { w *LocalWorker - op stores.AcquireMode + op storiface.AcquireMode } -func (l *localWorkerPathProvider) AcquireSector(ctx context.Context, sector abi.SectorID, existing stores.SectorFileType, allocate stores.SectorFileType, sealing stores.PathType) (stores.SectorPaths, func(), error) { +func (l *localWorkerPathProvider) AcquireSector(ctx context.Context, sector abi.SectorID, existing storiface.SectorFileType, allocate storiface.SectorFileType, sealing storiface.PathType) (storiface.SectorPaths, func(), error) { paths, storageIDs, err := l.w.storage.AcquireSector(ctx, sector, l.w.scfg.SealProofType, existing, allocate, sealing, l.op) if err != nil { - return stores.SectorPaths{}, nil, err + return storiface.SectorPaths{}, nil, err } - releaseStorage, err := l.w.localStore.Reserve(ctx, sector, l.w.scfg.SealProofType, allocate, storageIDs, stores.FSOverheadSeal) + releaseStorage, err := l.w.localStore.Reserve(ctx, sector, l.w.scfg.SealProofType, allocate, storageIDs, storiface.FSOverheadSeal) if err != nil { - return stores.SectorPaths{}, nil, xerrors.Errorf("reserving storage space: %w", err) + return storiface.SectorPaths{}, nil, xerrors.Errorf("reserving storage space: %w", err) } log.Debugf("acquired sector %d (e:%d; a:%d): %v", sector, existing, allocate, paths) @@ -84,9 +84,9 @@ func (l *localWorkerPathProvider) AcquireSector(ctx context.Context, sector abi. continue } - sid := stores.PathByType(storageIDs, fileType) + sid := storiface.PathByType(storageIDs, fileType) - if err := l.w.sindex.StorageDeclareSector(ctx, stores.ID(sid), sector, fileType, l.op == stores.AcquireMove); err != nil { + if err := l.w.sindex.StorageDeclareSector(ctx, stores.ID(sid), sector, fileType, l.op == storiface.AcquireMove); err != nil { log.Errorf("declare sector error: %+v", err) } } @@ -140,9 +140,9 @@ func (l *LocalWorker) AddPiece(ctx context.Context, sector abi.SectorID, epcs [] }) } -func (l *LocalWorker) Fetch(ctx context.Context, sector abi.SectorID, fileType stores.SectorFileType, ptype stores.PathType, am stores.AcquireMode) (storiface.CallID, error) { +func (l *LocalWorker) Fetch(ctx context.Context, sector abi.SectorID, fileType storiface.SectorFileType, ptype storiface.PathType, am storiface.AcquireMode) (storiface.CallID, error) { return l.asyncCall(sector, func(ci storiface.CallID) { - _, done, err := (&localWorkerPathProvider{w: l, op: am}).AcquireSector(ctx, sector, fileType, stores.FTNone, ptype) + _, done, err := (&localWorkerPathProvider{w: l, op: am}).AcquireSector(ctx, sector, fileType, storiface.FTNone, ptype) if err == nil { done() } @@ -165,12 +165,12 @@ func (l *LocalWorker) SealPreCommit1(ctx context.Context, sector abi.SectorID, t { // cleanup previous failed attempts if they exist - if err = l.storage.Remove(ctx, sector, stores.FTSealed, true); err != nil { + if err = l.storage.Remove(ctx, sector, storiface.FTSealed, true); err != nil { err = xerrors.Errorf("cleaning up sealed data: %w", err) return } - if err = l.storage.Remove(ctx, sector, stores.FTCache, true); err != nil { + if err = l.storage.Remove(ctx, sector, storiface.FTCache, true); err != nil { err = xerrors.Errorf("cleaning up cache data: %w", err) return } @@ -264,20 +264,20 @@ func (l *LocalWorker) ReleaseUnsealed(ctx context.Context, sector abi.SectorID, func (l *LocalWorker) Remove(ctx context.Context, sector abi.SectorID) error { var err error - if rerr := l.storage.Remove(ctx, sector, stores.FTSealed, true); rerr != nil { + if rerr := l.storage.Remove(ctx, sector, storiface.FTSealed, true); rerr != nil { err = multierror.Append(err, xerrors.Errorf("removing sector (sealed): %w", rerr)) } - if rerr := l.storage.Remove(ctx, sector, stores.FTCache, true); rerr != nil { + if rerr := l.storage.Remove(ctx, sector, storiface.FTCache, true); rerr != nil { err = multierror.Append(err, xerrors.Errorf("removing sector (cache): %w", rerr)) } - if rerr := l.storage.Remove(ctx, sector, stores.FTUnsealed, true); rerr != nil { + if rerr := l.storage.Remove(ctx, sector, storiface.FTUnsealed, true); rerr != nil { err = multierror.Append(err, xerrors.Errorf("removing sector (unsealed): %w", rerr)) } return err } -func (l *LocalWorker) MoveStorage(ctx context.Context, sector abi.SectorID, types stores.SectorFileType) (storiface.CallID, error) { +func (l *LocalWorker) MoveStorage(ctx context.Context, sector abi.SectorID, types storiface.SectorFileType) (storiface.CallID, error) { return l.asyncCall(sector, func(ci storiface.CallID) { err := l.storage.MoveStorage(ctx, sector, l.scfg.SealProofType, types) @@ -306,12 +306,12 @@ func (l *LocalWorker) UnsealPiece(ctx context.Context, sector abi.SectorID, inde return } - if err = l.storage.RemoveCopies(ctx, sector, stores.FTSealed); err != nil { + if err = l.storage.RemoveCopies(ctx, sector, storiface.FTSealed); err != nil { err = xerrors.Errorf("removing source data: %w", err) return } - if err = l.storage.RemoveCopies(ctx, sector, stores.FTCache); err != nil { + if err = l.storage.RemoveCopies(ctx, sector, storiface.FTCache); err != nil { err = xerrors.Errorf("removing source data: %w", err) return } diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index 683f34505..dacd3439f 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -191,7 +191,7 @@ func schedNop(context.Context, Worker) error { return nil } -func schedFetch(sector abi.SectorID, ft stores.SectorFileType, ptype stores.PathType, am stores.AcquireMode) func(context.Context, Worker) error { +func schedFetch(sector abi.SectorID, ft storiface.SectorFileType, ptype storiface.PathType, am storiface.AcquireMode) func(context.Context, Worker) error { return func(ctx context.Context, worker Worker) error { return worker.Fetch(ctx, sector, ft, ptype, am) } @@ -201,21 +201,21 @@ func (m *Manager) ReadPiece(ctx context.Context, sink io.Writer, sector abi.Sect ctx, cancel := context.WithCancel(ctx) defer cancel() - if err := m.index.StorageLock(ctx, sector, stores.FTSealed|stores.FTCache, stores.FTUnsealed); err != nil { + if err := m.index.StorageLock(ctx, sector, storiface.FTSealed|storiface.FTCache, storiface.FTUnsealed); err != nil { return xerrors.Errorf("acquiring sector lock: %w", err) } // passing 0 spt because we only need it when allowFetch is true - best, err := m.index.StorageFindSector(ctx, sector, stores.FTUnsealed, 0, false) + best, err := m.index.StorageFindSector(ctx, sector, storiface.FTUnsealed, 0, false) if err != nil { return xerrors.Errorf("read piece: checking for already existing unsealed sector: %w", err) } var selector WorkerSelector if len(best) == 0 { // new - selector = newAllocSelector(m.index, stores.FTUnsealed, stores.PathSealing) + selector = newAllocSelector(m.index, storiface.FTUnsealed, storiface.PathSealing) } else { // append to existing - selector = newExistingSelector(m.index, sector, stores.FTUnsealed, false) + selector = newExistingSelector(m.index, sector, storiface.FTUnsealed, false) } var readOk bool @@ -223,9 +223,9 @@ func (m *Manager) ReadPiece(ctx context.Context, sink io.Writer, sector abi.Sect if len(best) > 0 { // There is unsealed sector, see if we can read from it - selector = newExistingSelector(m.index, sector, stores.FTUnsealed, false) + selector = newExistingSelector(m.index, sector, storiface.FTUnsealed, false) - err = m.sched.Schedule(ctx, sector, sealtasks.TTReadUnsealed, selector, schedFetch(sector, stores.FTUnsealed, stores.PathSealing, stores.AcquireMove), func(ctx context.Context, w Worker) error { + err = m.sched.Schedule(ctx, sector, sealtasks.TTReadUnsealed, selector, schedFetch(sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { readOk, err = w.ReadPiece(ctx, sink, sector, offset, size) return err }) @@ -239,12 +239,12 @@ func (m *Manager) ReadPiece(ctx context.Context, sink io.Writer, sector abi.Sect } unsealFetch := func(ctx context.Context, worker Worker) error { - if err := worker.Fetch(ctx, sector, stores.FTSealed|stores.FTCache, stores.PathSealing, stores.AcquireCopy); err != nil { + if err := worker.Fetch(ctx, sector, storiface.FTSealed|storiface.FTCache, storiface.PathSealing, storiface.AcquireCopy); err != nil { return xerrors.Errorf("copy sealed/cache sector data: %w", err) } if len(best) > 0 { - if err := worker.Fetch(ctx, sector, stores.FTUnsealed, stores.PathSealing, stores.AcquireMove); err != nil { + if err := worker.Fetch(ctx, sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove); err != nil { return xerrors.Errorf("copy unsealed sector data: %w", err) } } @@ -258,9 +258,9 @@ func (m *Manager) ReadPiece(ctx context.Context, sink io.Writer, sector abi.Sect return err } - selector = newExistingSelector(m.index, sector, stores.FTUnsealed, false) + selector = newExistingSelector(m.index, sector, storiface.FTUnsealed, false) - err = m.sched.Schedule(ctx, sector, sealtasks.TTReadUnsealed, selector, schedFetch(sector, stores.FTUnsealed, stores.PathSealing, stores.AcquireMove), func(ctx context.Context, w Worker) error { + err = m.sched.Schedule(ctx, sector, sealtasks.TTReadUnsealed, selector, schedFetch(sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { readOk, err = w.ReadPiece(ctx, sink, sector, offset, size) return err }) @@ -284,16 +284,16 @@ func (m *Manager) AddPiece(ctx context.Context, sector abi.SectorID, existingPie ctx, cancel := context.WithCancel(ctx) defer cancel() - if err := m.index.StorageLock(ctx, sector, stores.FTNone, stores.FTUnsealed); err != nil { + if err := m.index.StorageLock(ctx, sector, storiface.FTNone, storiface.FTUnsealed); err != nil { return abi.PieceInfo{}, xerrors.Errorf("acquiring sector lock: %w", err) } var selector WorkerSelector var err error if len(existingPieces) == 0 { // new - selector = newAllocSelector(m.index, stores.FTUnsealed, stores.PathSealing) + selector = newAllocSelector(m.index, storiface.FTUnsealed, storiface.PathSealing) } else { // use existing - selector = newExistingSelector(m.index, sector, stores.FTUnsealed, false) + selector = newExistingSelector(m.index, sector, storiface.FTUnsealed, false) } var out abi.PieceInfo @@ -313,15 +313,15 @@ func (m *Manager) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticke ctx, cancel := context.WithCancel(ctx) defer cancel() - if err := m.index.StorageLock(ctx, sector, stores.FTUnsealed, stores.FTSealed|stores.FTCache); err != nil { + if err := m.index.StorageLock(ctx, sector, storiface.FTUnsealed, storiface.FTSealed|storiface.FTCache); err != nil { return nil, xerrors.Errorf("acquiring sector lock: %w", err) } // TODO: also consider where the unsealed data sits - selector := newAllocSelector(m.index, stores.FTCache|stores.FTSealed, stores.PathSealing) + selector := newAllocSelector(m.index, storiface.FTCache|storiface.FTSealed, storiface.PathSealing) - err = m.sched.Schedule(ctx, sector, sealtasks.TTPreCommit1, selector, schedFetch(sector, stores.FTUnsealed, stores.PathSealing, stores.AcquireMove), func(ctx context.Context, w Worker) error { + err = m.sched.Schedule(ctx, sector, sealtasks.TTPreCommit1, selector, schedFetch(sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { p, err := w.SealPreCommit1(ctx, sector, ticket, pieces) if err != nil { return err @@ -337,13 +337,13 @@ func (m *Manager) SealPreCommit2(ctx context.Context, sector abi.SectorID, phase ctx, cancel := context.WithCancel(ctx) defer cancel() - if err := m.index.StorageLock(ctx, sector, stores.FTSealed, stores.FTCache); err != nil { + if err := m.index.StorageLock(ctx, sector, storiface.FTSealed, storiface.FTCache); err != nil { return storage.SectorCids{}, xerrors.Errorf("acquiring sector lock: %w", err) } - selector := newExistingSelector(m.index, sector, stores.FTCache|stores.FTSealed, true) + selector := newExistingSelector(m.index, sector, storiface.FTCache|storiface.FTSealed, true) - err = m.sched.Schedule(ctx, sector, sealtasks.TTPreCommit2, selector, schedFetch(sector, stores.FTCache|stores.FTSealed, stores.PathSealing, stores.AcquireMove), func(ctx context.Context, w Worker) error { + err = m.sched.Schedule(ctx, sector, sealtasks.TTPreCommit2, selector, schedFetch(sector, storiface.FTCache|storiface.FTSealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { p, err := w.SealPreCommit2(ctx, sector, phase1Out) if err != nil { return err @@ -358,16 +358,16 @@ func (m *Manager) SealCommit1(ctx context.Context, sector abi.SectorID, ticket a ctx, cancel := context.WithCancel(ctx) defer cancel() - if err := m.index.StorageLock(ctx, sector, stores.FTSealed, stores.FTCache); err != nil { + if err := m.index.StorageLock(ctx, sector, storiface.FTSealed, storiface.FTCache); err != nil { return storage.Commit1Out{}, xerrors.Errorf("acquiring sector lock: %w", err) } // NOTE: We set allowFetch to false in so that we always execute on a worker // with direct access to the data. We want to do that because this step is // generally very cheap / fast, and transferring data is not worth the effort - selector := newExistingSelector(m.index, sector, stores.FTCache|stores.FTSealed, false) + selector := newExistingSelector(m.index, sector, storiface.FTCache|storiface.FTSealed, false) - err = m.sched.Schedule(ctx, sector, sealtasks.TTCommit1, selector, schedFetch(sector, stores.FTCache|stores.FTSealed, stores.PathSealing, stores.AcquireMove), func(ctx context.Context, w Worker) error { + err = m.sched.Schedule(ctx, sector, sealtasks.TTCommit1, selector, schedFetch(sector, storiface.FTCache|storiface.FTSealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { p, err := w.SealCommit1(ctx, sector, ticket, seed, pieces, cids) if err != nil { return err @@ -397,26 +397,26 @@ func (m *Manager) FinalizeSector(ctx context.Context, sector abi.SectorID, keepU ctx, cancel := context.WithCancel(ctx) defer cancel() - if err := m.index.StorageLock(ctx, sector, stores.FTNone, stores.FTSealed|stores.FTUnsealed|stores.FTCache); err != nil { + if err := m.index.StorageLock(ctx, sector, storiface.FTNone, storiface.FTSealed|storiface.FTUnsealed|storiface.FTCache); err != nil { return xerrors.Errorf("acquiring sector lock: %w", err) } - unsealed := stores.FTUnsealed + unsealed := storiface.FTUnsealed { - unsealedStores, err := m.index.StorageFindSector(ctx, sector, stores.FTUnsealed, 0, false) + unsealedStores, err := m.index.StorageFindSector(ctx, sector, storiface.FTUnsealed, 0, false) if err != nil { return xerrors.Errorf("finding unsealed sector: %w", err) } if len(unsealedStores) == 0 { // Is some edge-cases unsealed sector may not exist already, that's fine - unsealed = stores.FTNone + unsealed = storiface.FTNone } } - selector := newExistingSelector(m.index, sector, stores.FTCache|stores.FTSealed, false) + selector := newExistingSelector(m.index, sector, storiface.FTCache|storiface.FTSealed, false) err := m.sched.Schedule(ctx, sector, sealtasks.TTFinalize, selector, - schedFetch(sector, stores.FTCache|stores.FTSealed|unsealed, stores.PathSealing, stores.AcquireMove), + schedFetch(sector, storiface.FTCache|storiface.FTSealed|unsealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { return w.FinalizeSector(ctx, sector, keepUnsealed) }) @@ -424,18 +424,18 @@ func (m *Manager) FinalizeSector(ctx context.Context, sector abi.SectorID, keepU return err } - fetchSel := newAllocSelector(m.index, stores.FTCache|stores.FTSealed, stores.PathStorage) + fetchSel := newAllocSelector(m.index, storiface.FTCache|storiface.FTSealed, storiface.PathStorage) moveUnsealed := unsealed { if len(keepUnsealed) == 0 { - moveUnsealed = stores.FTNone + moveUnsealed = storiface.FTNone } } err = m.sched.Schedule(ctx, sector, sealtasks.TTFetch, fetchSel, - schedFetch(sector, stores.FTCache|stores.FTSealed|moveUnsealed, stores.PathStorage, stores.AcquireMove), + schedFetch(sector, storiface.FTCache|storiface.FTSealed|moveUnsealed, storiface.PathStorage, storiface.AcquireMove), func(ctx context.Context, w Worker) error { - return w.MoveStorage(ctx, sector, stores.FTCache|stores.FTSealed|moveUnsealed) + return w.MoveStorage(ctx, sector, storiface.FTCache|storiface.FTSealed|moveUnsealed) }) if err != nil { return xerrors.Errorf("moving sector to storage: %w", err) @@ -453,19 +453,19 @@ func (m *Manager) Remove(ctx context.Context, sector abi.SectorID) error { ctx, cancel := context.WithCancel(ctx) defer cancel() - if err := m.index.StorageLock(ctx, sector, stores.FTNone, stores.FTSealed|stores.FTUnsealed|stores.FTCache); err != nil { + if err := m.index.StorageLock(ctx, sector, storiface.FTNone, storiface.FTSealed|storiface.FTUnsealed|storiface.FTCache); err != nil { return xerrors.Errorf("acquiring sector lock: %w", err) } var err error - if rerr := m.storage.Remove(ctx, sector, stores.FTSealed, true); rerr != nil { + if rerr := m.storage.Remove(ctx, sector, storiface.FTSealed, true); rerr != nil { err = multierror.Append(err, xerrors.Errorf("removing sector (sealed): %w", rerr)) } - if rerr := m.storage.Remove(ctx, sector, stores.FTCache, true); rerr != nil { + if rerr := m.storage.Remove(ctx, sector, storiface.FTCache, true); rerr != nil { err = multierror.Append(err, xerrors.Errorf("removing sector (cache): %w", rerr)) } - if rerr := m.storage.Remove(ctx, sector, stores.FTUnsealed, true); rerr != nil { + if rerr := m.storage.Remove(ctx, sector, storiface.FTUnsealed, true); rerr != nil { err = multierror.Append(err, xerrors.Errorf("removing sector (unsealed): %w", rerr)) } diff --git a/extern/sector-storage/roprov.go b/extern/sector-storage/roprov.go index fe58a8445..60dcea740 100644 --- a/extern/sector-storage/roprov.go +++ b/extern/sector-storage/roprov.go @@ -2,6 +2,7 @@ package sectorstorage import ( "context" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "golang.org/x/xerrors" @@ -16,25 +17,25 @@ type readonlyProvider struct { spt abi.RegisteredSealProof } -func (l *readonlyProvider) AcquireSector(ctx context.Context, id abi.SectorID, existing stores.SectorFileType, allocate stores.SectorFileType, sealing stores.PathType) (stores.SectorPaths, func(), error) { - if allocate != stores.FTNone { - return stores.SectorPaths{}, nil, xerrors.New("read-only storage") +func (l *readonlyProvider) AcquireSector(ctx context.Context, id abi.SectorID, existing storiface.SectorFileType, allocate storiface.SectorFileType, sealing storiface.PathType) (storiface.SectorPaths, func(), error) { + if allocate != storiface.FTNone { + return storiface.SectorPaths{}, nil, xerrors.New("read-only storage") } ctx, cancel := context.WithCancel(ctx) // use TryLock to avoid blocking - locked, err := l.index.StorageTryLock(ctx, id, existing, stores.FTNone) + locked, err := l.index.StorageTryLock(ctx, id, existing, storiface.FTNone) if err != nil { cancel() - return stores.SectorPaths{}, nil, xerrors.Errorf("acquiring sector lock: %w", err) + return storiface.SectorPaths{}, nil, xerrors.Errorf("acquiring sector lock: %w", err) } if !locked { cancel() - return stores.SectorPaths{}, nil, xerrors.Errorf("failed to acquire sector lock") + return storiface.SectorPaths{}, nil, xerrors.Errorf("failed to acquire sector lock") } - p, _, err := l.stor.AcquireSector(ctx, id, l.spt, existing, allocate, sealing, stores.AcquireMove) + p, _, err := l.stor.AcquireSector(ctx, id, l.spt, existing, allocate, sealing, storiface.AcquireMove) return p, cancel, err } diff --git a/extern/sector-storage/sched_test.go b/extern/sector-storage/sched_test.go index 4c39370a0..834a9f6dd 100644 --- a/extern/sector-storage/sched_test.go +++ b/extern/sector-storage/sched_test.go @@ -82,11 +82,11 @@ func (s *schedTestWorker) AddPiece(ctx context.Context, sector abi.SectorID, pie panic("implement me") } -func (s *schedTestWorker) MoveStorage(ctx context.Context, sector abi.SectorID, types stores.SectorFileType) error { +func (s *schedTestWorker) MoveStorage(ctx context.Context, sector abi.SectorID, types storiface.SectorFileType) error { panic("implement me") } -func (s *schedTestWorker) Fetch(ctx context.Context, id abi.SectorID, ft stores.SectorFileType, ptype stores.PathType, am stores.AcquireMode) error { +func (s *schedTestWorker) Fetch(ctx context.Context, id abi.SectorID, ft storiface.SectorFileType, ptype storiface.PathType, am storiface.AcquireMode) error { panic("implement me") } @@ -215,7 +215,7 @@ func TestSched(t *testing.T) { done := make(chan struct{}) rm.done[taskName] = done - sel := newAllocSelector(index, stores.FTCache, stores.PathSealing) + sel := newAllocSelector(index, storiface.FTCache, storiface.PathSealing) rm.wg.Add(1) go func() { diff --git a/extern/sector-storage/selector_alloc.go b/extern/sector-storage/selector_alloc.go index ca4b99bfc..dfe6e5d41 100644 --- a/extern/sector-storage/selector_alloc.go +++ b/extern/sector-storage/selector_alloc.go @@ -2,6 +2,7 @@ package sectorstorage import ( "context" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "golang.org/x/xerrors" @@ -13,11 +14,11 @@ import ( type allocSelector struct { index stores.SectorIndex - alloc stores.SectorFileType - ptype stores.PathType + alloc storiface.SectorFileType + ptype storiface.PathType } -func newAllocSelector(index stores.SectorIndex, alloc stores.SectorFileType, ptype stores.PathType) *allocSelector { +func newAllocSelector(index stores.SectorIndex, alloc storiface.SectorFileType, ptype storiface.PathType) *allocSelector { return &allocSelector{ index: index, alloc: alloc, diff --git a/extern/sector-storage/selector_existing.go b/extern/sector-storage/selector_existing.go index 1e97db539..124ccb5c1 100644 --- a/extern/sector-storage/selector_existing.go +++ b/extern/sector-storage/selector_existing.go @@ -2,6 +2,7 @@ package sectorstorage import ( "context" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "golang.org/x/xerrors" @@ -14,11 +15,11 @@ import ( type existingSelector struct { index stores.SectorIndex sector abi.SectorID - alloc stores.SectorFileType + alloc storiface.SectorFileType allowFetch bool } -func newExistingSelector(index stores.SectorIndex, sector abi.SectorID, alloc stores.SectorFileType, allowFetch bool) *existingSelector { +func newExistingSelector(index stores.SectorIndex, sector abi.SectorID, alloc storiface.SectorFileType, allowFetch bool) *existingSelector { return &existingSelector{ index: index, sector: sector, diff --git a/extern/sector-storage/stores/http_handler.go b/extern/sector-storage/stores/http_handler.go index 97af6e769..a5a2cd913 100644 --- a/extern/sector-storage/stores/http_handler.go +++ b/extern/sector-storage/stores/http_handler.go @@ -2,6 +2,7 @@ package stores import ( "encoding/json" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "io" "net/http" "os" @@ -55,7 +56,7 @@ func (handler *FetchHandler) remoteGetSector(w http.ResponseWriter, r *http.Requ log.Infof("SERVE GET %s", r.URL) vars := mux.Vars(r) - id, err := ParseSectorID(vars["id"]) + id, err := storiface.ParseSectorID(vars["id"]) if err != nil { log.Error("%+v", err) w.WriteHeader(500) @@ -72,7 +73,7 @@ func (handler *FetchHandler) remoteGetSector(w http.ResponseWriter, r *http.Requ // The caller has a lock on this sector already, no need to get one here // passing 0 spt because we don't allocate anything - paths, _, err := handler.Local.AcquireSector(r.Context(), id, 0, ft, FTNone, PathStorage, AcquireMove) + paths, _, err := handler.Local.AcquireSector(r.Context(), id, 0, ft, storiface.FTNone, storiface.PathStorage, storiface.AcquireMove) if err != nil { log.Error("%+v", err) w.WriteHeader(500) @@ -81,7 +82,7 @@ func (handler *FetchHandler) remoteGetSector(w http.ResponseWriter, r *http.Requ // TODO: reserve local storage here - path := PathByType(paths, ft) + path := storiface.PathByType(paths, ft) if path == "" { log.Error("acquired path was empty") w.WriteHeader(500) @@ -120,7 +121,7 @@ func (handler *FetchHandler) remoteDeleteSector(w http.ResponseWriter, r *http.R log.Infof("SERVE DELETE %s", r.URL) vars := mux.Vars(r) - id, err := ParseSectorID(vars["id"]) + id, err := storiface.ParseSectorID(vars["id"]) if err != nil { log.Error("%+v", err) w.WriteHeader(500) @@ -141,14 +142,14 @@ func (handler *FetchHandler) remoteDeleteSector(w http.ResponseWriter, r *http.R } } -func ftFromString(t string) (SectorFileType, error) { +func ftFromString(t string) (storiface.SectorFileType, error) { switch t { - case FTUnsealed.String(): - return FTUnsealed, nil - case FTSealed.String(): - return FTSealed, nil - case FTCache.String(): - return FTCache, nil + case storiface.FTUnsealed.String(): + return storiface.FTUnsealed, nil + case storiface.FTSealed.String(): + return storiface.FTSealed, nil + case storiface.FTCache.String(): + return storiface.FTCache, nil default: return 0, xerrors.Errorf("unknown sector file type: '%s'", t) } diff --git a/extern/sector-storage/stores/index.go b/extern/sector-storage/stores/index.go index 256dc9651..a2c329de8 100644 --- a/extern/sector-storage/stores/index.go +++ b/extern/sector-storage/stores/index.go @@ -2,6 +2,7 @@ package stores import ( "context" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "net/url" gopath "path" "sort" @@ -53,20 +54,20 @@ type SectorIndex interface { // part of storage-miner api StorageInfo(context.Context, ID) (StorageInfo, error) StorageReportHealth(context.Context, ID, HealthReport) error - StorageDeclareSector(ctx context.Context, storageID ID, s abi.SectorID, ft SectorFileType, primary bool) error - StorageDropSector(ctx context.Context, storageID ID, s abi.SectorID, ft SectorFileType) error - StorageFindSector(ctx context.Context, sector abi.SectorID, ft SectorFileType, spt abi.RegisteredSealProof, allowFetch bool) ([]SectorStorageInfo, error) + StorageDeclareSector(ctx context.Context, storageID ID, s abi.SectorID, ft storiface.SectorFileType, primary bool) error + StorageDropSector(ctx context.Context, storageID ID, s abi.SectorID, ft storiface.SectorFileType) error + StorageFindSector(ctx context.Context, sector abi.SectorID, ft storiface.SectorFileType, spt abi.RegisteredSealProof, allowFetch bool) ([]SectorStorageInfo, error) - StorageBestAlloc(ctx context.Context, allocate SectorFileType, spt abi.RegisteredSealProof, pathType PathType) ([]StorageInfo, error) + StorageBestAlloc(ctx context.Context, allocate storiface.SectorFileType, spt abi.RegisteredSealProof, pathType storiface.PathType) ([]StorageInfo, error) // atomically acquire locks on all sector file types. close ctx to unlock - StorageLock(ctx context.Context, sector abi.SectorID, read SectorFileType, write SectorFileType) error - StorageTryLock(ctx context.Context, sector abi.SectorID, read SectorFileType, write SectorFileType) (bool, error) + StorageLock(ctx context.Context, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) error + StorageTryLock(ctx context.Context, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) (bool, error) } type Decl struct { abi.SectorID - SectorFileType + storiface.SectorFileType } type declMeta struct { @@ -104,10 +105,10 @@ func (i *Index) StorageList(ctx context.Context) (map[ID][]Decl, error) { i.lk.RLock() defer i.lk.RUnlock() - byID := map[ID]map[abi.SectorID]SectorFileType{} + byID := map[ID]map[abi.SectorID]storiface.SectorFileType{} for id := range i.stores { - byID[id] = map[abi.SectorID]SectorFileType{} + byID[id] = map[abi.SectorID]storiface.SectorFileType{} } for decl, ids := range i.sectors { for _, id := range ids { @@ -180,12 +181,12 @@ func (i *Index) StorageReportHealth(ctx context.Context, id ID, report HealthRep return nil } -func (i *Index) StorageDeclareSector(ctx context.Context, storageID ID, s abi.SectorID, ft SectorFileType, primary bool) error { +func (i *Index) StorageDeclareSector(ctx context.Context, storageID ID, s abi.SectorID, ft storiface.SectorFileType, primary bool) error { i.lk.Lock() defer i.lk.Unlock() loop: - for _, fileType := range PathTypes { + for _, fileType := range storiface.PathTypes { if fileType&ft == 0 { continue } @@ -212,11 +213,11 @@ loop: return nil } -func (i *Index) StorageDropSector(ctx context.Context, storageID ID, s abi.SectorID, ft SectorFileType) error { +func (i *Index) StorageDropSector(ctx context.Context, storageID ID, s abi.SectorID, ft storiface.SectorFileType) error { i.lk.Lock() defer i.lk.Unlock() - for _, fileType := range PathTypes { + for _, fileType := range storiface.PathTypes { if fileType&ft == 0 { continue } @@ -246,14 +247,14 @@ func (i *Index) StorageDropSector(ctx context.Context, storageID ID, s abi.Secto return nil } -func (i *Index) StorageFindSector(ctx context.Context, s abi.SectorID, ft SectorFileType, spt abi.RegisteredSealProof, allowFetch bool) ([]SectorStorageInfo, error) { +func (i *Index) StorageFindSector(ctx context.Context, s abi.SectorID, ft storiface.SectorFileType, spt abi.RegisteredSealProof, allowFetch bool) ([]SectorStorageInfo, error) { i.lk.RLock() defer i.lk.RUnlock() storageIDs := map[ID]uint64{} isprimary := map[ID]bool{} - for _, pathType := range PathTypes { + for _, pathType := range storiface.PathTypes { if ft&pathType == 0 { continue } @@ -280,7 +281,7 @@ func (i *Index) StorageFindSector(ctx context.Context, s abi.SectorID, ft Sector return nil, xerrors.Errorf("failed to parse url: %w", err) } - rl.Path = gopath.Join(rl.Path, ft.String(), SectorName(s)) + rl.Path = gopath.Join(rl.Path, ft.String(), storiface.SectorName(s)) urls[k] = rl.String() } @@ -333,7 +334,7 @@ func (i *Index) StorageFindSector(ctx context.Context, s abi.SectorID, ft Sector return nil, xerrors.Errorf("failed to parse url: %w", err) } - rl.Path = gopath.Join(rl.Path, ft.String(), SectorName(s)) + rl.Path = gopath.Join(rl.Path, ft.String(), storiface.SectorName(s)) urls[k] = rl.String() } @@ -365,7 +366,7 @@ func (i *Index) StorageInfo(ctx context.Context, id ID) (StorageInfo, error) { return *si.info, nil } -func (i *Index) StorageBestAlloc(ctx context.Context, allocate SectorFileType, spt abi.RegisteredSealProof, pathType PathType) ([]StorageInfo, error) { +func (i *Index) StorageBestAlloc(ctx context.Context, allocate storiface.SectorFileType, spt abi.RegisteredSealProof, pathType storiface.PathType) ([]StorageInfo, error) { i.lk.RLock() defer i.lk.RUnlock() @@ -377,10 +378,10 @@ func (i *Index) StorageBestAlloc(ctx context.Context, allocate SectorFileType, s } for _, p := range i.stores { - if (pathType == PathSealing) && !p.info.CanSeal { + if (pathType == storiface.PathSealing) && !p.info.CanSeal { continue } - if (pathType == PathStorage) && !p.info.CanStore { + if (pathType == storiface.PathStorage) && !p.info.CanStore { continue } @@ -421,7 +422,7 @@ func (i *Index) StorageBestAlloc(ctx context.Context, allocate SectorFileType, s return out, nil } -func (i *Index) FindSector(id abi.SectorID, typ SectorFileType) ([]ID, error) { +func (i *Index) FindSector(id abi.SectorID, typ storiface.SectorFileType) ([]ID, error) { i.lk.RLock() defer i.lk.RUnlock() diff --git a/extern/sector-storage/stores/index_locks.go b/extern/sector-storage/stores/index_locks.go index 8bf15b950..2137436d2 100644 --- a/extern/sector-storage/stores/index_locks.go +++ b/extern/sector-storage/stores/index_locks.go @@ -2,6 +2,7 @@ package stores import ( "context" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "sync" "golang.org/x/xerrors" @@ -12,13 +13,13 @@ import ( type sectorLock struct { cond *ctxCond - r [FileTypes]uint - w SectorFileType + r [storiface.FileTypes]uint + w storiface.SectorFileType refs uint // access with indexLocks.lk } -func (l *sectorLock) canLock(read SectorFileType, write SectorFileType) bool { +func (l *sectorLock) canLock(read storiface.SectorFileType, write storiface.SectorFileType) bool { for i, b := range write.All() { if b && l.r[i] > 0 { return false @@ -29,7 +30,7 @@ func (l *sectorLock) canLock(read SectorFileType, write SectorFileType) bool { return l.w&read == 0 && l.w&write == 0 } -func (l *sectorLock) tryLock(read SectorFileType, write SectorFileType) bool { +func (l *sectorLock) tryLock(read storiface.SectorFileType, write storiface.SectorFileType) bool { if !l.canLock(read, write) { return false } @@ -45,16 +46,16 @@ func (l *sectorLock) tryLock(read SectorFileType, write SectorFileType) bool { return true } -type lockFn func(l *sectorLock, ctx context.Context, read SectorFileType, write SectorFileType) (bool, error) +type lockFn func(l *sectorLock, ctx context.Context, read storiface.SectorFileType, write storiface.SectorFileType) (bool, error) -func (l *sectorLock) tryLockSafe(ctx context.Context, read SectorFileType, write SectorFileType) (bool, error) { +func (l *sectorLock) tryLockSafe(ctx context.Context, read storiface.SectorFileType, write storiface.SectorFileType) (bool, error) { l.cond.L.Lock() defer l.cond.L.Unlock() return l.tryLock(read, write), nil } -func (l *sectorLock) lock(ctx context.Context, read SectorFileType, write SectorFileType) (bool, error) { +func (l *sectorLock) lock(ctx context.Context, read storiface.SectorFileType, write storiface.SectorFileType) (bool, error) { l.cond.L.Lock() defer l.cond.L.Unlock() @@ -67,7 +68,7 @@ func (l *sectorLock) lock(ctx context.Context, read SectorFileType, write Sector return true, nil } -func (l *sectorLock) unlock(read SectorFileType, write SectorFileType) { +func (l *sectorLock) unlock(read storiface.SectorFileType, write storiface.SectorFileType) { l.cond.L.Lock() defer l.cond.L.Unlock() @@ -88,12 +89,12 @@ type indexLocks struct { locks map[abi.SectorID]*sectorLock } -func (i *indexLocks) lockWith(ctx context.Context, lockFn lockFn, sector abi.SectorID, read SectorFileType, write SectorFileType) (bool, error) { +func (i *indexLocks) lockWith(ctx context.Context, lockFn lockFn, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) (bool, error) { if read|write == 0 { return false, nil } - if read|write > (1< (1< %s(se:%t; st:%t)", s, fileType, sst.ID, sst.CanSeal, sst.CanStore, dst.ID, dst.CanSeal, dst.CanStore) - if err := st.index.StorageDropSector(ctx, ID(PathByType(srcIds, fileType)), s, fileType); err != nil { + if err := st.index.StorageDropSector(ctx, ID(storiface.PathByType(srcIds, fileType)), s, fileType); err != nil { return xerrors.Errorf("dropping source sector from index: %w", err) } - if err := move(PathByType(src, fileType), PathByType(dest, fileType)); err != nil { + if err := move(storiface.PathByType(src, fileType), storiface.PathByType(dest, fileType)); err != nil { // TODO: attempt some recovery (check if src is still there, re-declare) return xerrors.Errorf("moving sector %v(%d): %w", s, fileType, err) } - if err := st.index.StorageDeclareSector(ctx, ID(PathByType(destIds, fileType)), s, fileType, true); err != nil { - return xerrors.Errorf("declare sector %d(t:%d) -> %s: %w", s, fileType, ID(PathByType(destIds, fileType)), err) + if err := st.index.StorageDeclareSector(ctx, ID(storiface.PathByType(destIds, fileType)), s, fileType, true); err != nil { + return xerrors.Errorf("declare sector %d(t:%d) -> %s: %w", s, fileType, ID(storiface.PathByType(destIds, fileType)), err) } } diff --git a/extern/sector-storage/stores/remote.go b/extern/sector-storage/stores/remote.go index a88e3b947..d9e1cf49f 100644 --- a/extern/sector-storage/stores/remote.go +++ b/extern/sector-storage/stores/remote.go @@ -38,7 +38,7 @@ type Remote struct { fetching map[abi.SectorID]chan struct{} } -func (r *Remote) RemoveCopies(ctx context.Context, s abi.SectorID, types SectorFileType) error { +func (r *Remote) RemoveCopies(ctx context.Context, s abi.SectorID, types storiface.SectorFileType) error { // TODO: do this on remotes too // (not that we really need to do that since it's always called by the // worker which pulled the copy) @@ -58,9 +58,9 @@ func NewRemote(local *Local, index SectorIndex, auth http.Header, fetchLimit int } } -func (r *Remote) AcquireSector(ctx context.Context, s abi.SectorID, spt abi.RegisteredSealProof, existing SectorFileType, allocate SectorFileType, pathType PathType, op AcquireMode) (SectorPaths, SectorPaths, error) { +func (r *Remote) AcquireSector(ctx context.Context, s abi.SectorID, spt abi.RegisteredSealProof, existing storiface.SectorFileType, allocate storiface.SectorFileType, pathType storiface.PathType, op storiface.AcquireMode) (storiface.SectorPaths, storiface.SectorPaths, error) { if existing|allocate != existing^allocate { - return SectorPaths{}, SectorPaths{}, xerrors.New("can't both find and allocate a sector") + return storiface.SectorPaths{}, storiface.SectorPaths{}, xerrors.New("can't both find and allocate a sector") } for { @@ -79,7 +79,7 @@ func (r *Remote) AcquireSector(ctx context.Context, s abi.SectorID, spt abi.Regi case <-c: continue case <-ctx.Done(): - return SectorPaths{}, SectorPaths{}, ctx.Err() + return storiface.SectorPaths{}, storiface.SectorPaths{}, ctx.Err() } } @@ -92,62 +92,62 @@ func (r *Remote) AcquireSector(ctx context.Context, s abi.SectorID, spt abi.Regi paths, stores, err := r.local.AcquireSector(ctx, s, spt, existing, allocate, pathType, op) if err != nil { - return SectorPaths{}, SectorPaths{}, xerrors.Errorf("local acquire error: %w", err) + return storiface.SectorPaths{}, storiface.SectorPaths{}, xerrors.Errorf("local acquire error: %w", err) } - var toFetch SectorFileType - for _, fileType := range PathTypes { + var toFetch storiface.SectorFileType + for _, fileType := range storiface.PathTypes { if fileType&existing == 0 { continue } - if PathByType(paths, fileType) == "" { + if storiface.PathByType(paths, fileType) == "" { toFetch |= fileType } } - apaths, ids, err := r.local.AcquireSector(ctx, s, spt, FTNone, toFetch, pathType, op) + apaths, ids, err := r.local.AcquireSector(ctx, s, spt, storiface.FTNone, toFetch, pathType, op) if err != nil { - return SectorPaths{}, SectorPaths{}, xerrors.Errorf("allocate local sector for fetching: %w", err) + return storiface.SectorPaths{}, storiface.SectorPaths{}, xerrors.Errorf("allocate local sector for fetching: %w", err) } - odt := FSOverheadSeal - if pathType == PathStorage { - odt = FsOverheadFinalized + odt := storiface.FSOverheadSeal + if pathType == storiface.PathStorage { + odt = storiface.FsOverheadFinalized } releaseStorage, err := r.local.Reserve(ctx, s, spt, toFetch, ids, odt) if err != nil { - return SectorPaths{}, SectorPaths{}, xerrors.Errorf("reserving storage space: %w", err) + return storiface.SectorPaths{}, storiface.SectorPaths{}, xerrors.Errorf("reserving storage space: %w", err) } defer releaseStorage() - for _, fileType := range PathTypes { + for _, fileType := range storiface.PathTypes { if fileType&existing == 0 { continue } - if PathByType(paths, fileType) != "" { + if storiface.PathByType(paths, fileType) != "" { continue } - dest := PathByType(apaths, fileType) - storageID := PathByType(ids, fileType) + dest := storiface.PathByType(apaths, fileType) + storageID := storiface.PathByType(ids, fileType) url, err := r.acquireFromRemote(ctx, s, fileType, dest) if err != nil { - return SectorPaths{}, SectorPaths{}, err + return storiface.SectorPaths{}, storiface.SectorPaths{}, err } - SetPathByType(&paths, fileType, dest) - SetPathByType(&stores, fileType, storageID) + storiface.SetPathByType(&paths, fileType, dest) + storiface.SetPathByType(&stores, fileType, storageID) - if err := r.index.StorageDeclareSector(ctx, ID(storageID), s, fileType, op == AcquireMove); err != nil { + if err := r.index.StorageDeclareSector(ctx, ID(storageID), s, fileType, op == storiface.AcquireMove); err != nil { log.Warnf("declaring sector %v in %s failed: %+v", s, storageID, err) continue } - if op == AcquireMove { + if op == storiface.AcquireMove { if err := r.deleteFromRemote(ctx, url); err != nil { log.Warnf("deleting sector %v from %s (delete %s): %+v", s, storageID, url, err) } @@ -169,7 +169,7 @@ func tempFetchDest(spath string, create bool) (string, error) { return filepath.Join(tempdir, b), nil } -func (r *Remote) acquireFromRemote(ctx context.Context, s abi.SectorID, fileType SectorFileType, dest string) (string, error) { +func (r *Remote) acquireFromRemote(ctx context.Context, s abi.SectorID, fileType storiface.SectorFileType, dest string) (string, error) { si, err := r.index.StorageFindSector(ctx, s, fileType, 0, false) if err != nil { return "", err @@ -281,9 +281,9 @@ func (r *Remote) fetch(ctx context.Context, url, outname string) error { } } -func (r *Remote) MoveStorage(ctx context.Context, s abi.SectorID, spt abi.RegisteredSealProof, types SectorFileType) error { +func (r *Remote) MoveStorage(ctx context.Context, s abi.SectorID, spt abi.RegisteredSealProof, types storiface.SectorFileType) error { // Make sure we have the data local - _, _, err := r.AcquireSector(ctx, s, spt, types, FTNone, PathStorage, AcquireMove) + _, _, err := r.AcquireSector(ctx, s, spt, types, storiface.FTNone, storiface.PathStorage, storiface.AcquireMove) if err != nil { return xerrors.Errorf("acquire src storage (remote): %w", err) } @@ -291,7 +291,7 @@ func (r *Remote) MoveStorage(ctx context.Context, s abi.SectorID, spt abi.Regist return r.local.MoveStorage(ctx, s, spt, types) } -func (r *Remote) Remove(ctx context.Context, sid abi.SectorID, typ SectorFileType, force bool) error { +func (r *Remote) Remove(ctx context.Context, sid abi.SectorID, typ storiface.SectorFileType, force bool) error { if bits.OnesCount(uint(typ)) != 1 { return xerrors.New("delete expects one file type") } diff --git a/extern/sector-storage/stores/filetype.go b/extern/sector-storage/storiface/filetype.go similarity index 96% rename from extern/sector-storage/stores/filetype.go rename to extern/sector-storage/storiface/filetype.go index 50417d968..6db5cf9ec 100644 --- a/extern/sector-storage/stores/filetype.go +++ b/extern/sector-storage/storiface/filetype.go @@ -1,4 +1,4 @@ -package stores +package storiface import ( "fmt" @@ -16,6 +16,8 @@ const ( FileTypes = iota ) +var PathTypes = []SectorFileType{FTUnsealed, FTSealed, FTCache} + const ( FTNone SectorFileType = 0 ) diff --git a/extern/sector-storage/storiface/storage.go b/extern/sector-storage/storiface/storage.go index f1de3656e..e836002d5 100644 --- a/extern/sector-storage/storiface/storage.go +++ b/extern/sector-storage/storiface/storage.go @@ -1 +1,15 @@ package storiface + +type PathType string + +const ( + PathStorage PathType = "storage" + PathSealing PathType = "sealing" +) + +type AcquireMode string + +const ( + AcquireMove AcquireMode = "move" + AcquireCopy AcquireMode = "copy" +) diff --git a/extern/sector-storage/storiface/worker.go b/extern/sector-storage/storiface/worker.go index 9f79e37be..dac22aba0 100644 --- a/extern/sector-storage/storiface/worker.go +++ b/extern/sector-storage/storiface/worker.go @@ -12,7 +12,6 @@ import ( "github.com/filecoin-project/specs-storage/storage" "github.com/filecoin-project/lotus/extern/sector-storage/sealtasks" - "github.com/filecoin-project/lotus/extern/sector-storage/stores" ) type WorkerInfo struct { @@ -64,10 +63,10 @@ type WorkerCalls interface { SealCommit2(ctx context.Context, sector abi.SectorID, c1o storage.Commit1Out) (CallID, error) FinalizeSector(ctx context.Context, sector abi.SectorID, keepUnsealed []storage.Range) (CallID, error) ReleaseUnsealed(ctx context.Context, sector abi.SectorID, safeToFree []storage.Range) (CallID, error) - MoveStorage(ctx context.Context, sector abi.SectorID, types stores.SectorFileType) (CallID, error) + MoveStorage(ctx context.Context, sector abi.SectorID, types SectorFileType) (CallID, error) UnsealPiece(context.Context, abi.SectorID, UnpaddedByteIndex, abi.UnpaddedPieceSize, abi.SealRandomness, cid.Cid) (CallID, error) ReadPiece(context.Context, io.Writer, abi.SectorID, UnpaddedByteIndex, abi.UnpaddedPieceSize) (CallID, error) - Fetch(context.Context, abi.SectorID, stores.SectorFileType, stores.PathType, stores.AcquireMode) (CallID, error) + Fetch(context.Context, abi.SectorID, SectorFileType, PathType, AcquireMode) (CallID, error) } type WorkerReturn interface { diff --git a/extern/sector-storage/testworker_test.go b/extern/sector-storage/testworker_test.go index 858b76f7c..cfa2bed06 100644 --- a/extern/sector-storage/testworker_test.go +++ b/extern/sector-storage/testworker_test.go @@ -85,11 +85,11 @@ func (t *testWorker) Remove(ctx context.Context, sector abi.SectorID) error { panic("implement me") } -func (t *testWorker) MoveStorage(ctx context.Context, sector abi.SectorID, types stores.SectorFileType) error { +func (t *testWorker) MoveStorage(ctx context.Context, sector abi.SectorID, types storiface.SectorFileType) error { panic("implement me") } -func (t *testWorker) Fetch(ctx context.Context, id abi.SectorID, fileType stores.SectorFileType, ptype stores.PathType, am stores.AcquireMode) error { +func (t *testWorker) Fetch(ctx context.Context, id abi.SectorID, fileType storiface.SectorFileType, ptype storiface.PathType, am storiface.AcquireMode) error { return nil } diff --git a/extern/sector-storage/work_tracker.go b/extern/sector-storage/work_tracker.go index fe176a7f7..53f79af90 100644 --- a/extern/sector-storage/work_tracker.go +++ b/extern/sector-storage/work_tracker.go @@ -12,7 +12,6 @@ import ( "github.com/filecoin-project/specs-storage/storage" "github.com/filecoin-project/lotus/extern/sector-storage/sealtasks" - "github.com/filecoin-project/lotus/extern/sector-storage/stores" "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) @@ -108,7 +107,7 @@ func (t *trackedWorker) AddPiece(ctx context.Context, sector abi.SectorID, piece return t.Worker.AddPiece(ctx, sector, pieceSizes, newPieceSize, pieceData) } -func (t *trackedWorker) Fetch(ctx context.Context, s abi.SectorID, ft stores.SectorFileType, ptype stores.PathType, am stores.AcquireMode) error { +func (t *trackedWorker) Fetch(ctx context.Context, s abi.SectorID, ft storiface.SectorFileType, ptype storiface.PathType, am storiface.AcquireMode) error { defer t.tracker.track(s, sealtasks.TTFetch)() return t.Worker.Fetch(ctx, s, ft, ptype, am) From 06e3852cef1a1a74ddd7352e72dddd10a6601dc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 7 Sep 2020 12:20:50 +0200 Subject: [PATCH 003/313] storage: Integrate async workers in sealing manager --- extern/sector-storage/manager.go | 178 +++++++++++++++++++++++++------ 1 file changed, 148 insertions(+), 30 deletions(-) diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index dacd3439f..da700cdc0 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -5,6 +5,7 @@ import ( "errors" "io" "net/http" + "sync" "github.com/hashicorp/go-multierror" "github.com/ipfs/go-cid" @@ -68,6 +69,15 @@ type Manager struct { sched *scheduler storage.Prover + + resLk sync.Mutex + results map[storiface.CallID]result + waitRes map[storiface.CallID]chan struct{} +} + +type result struct { + r interface{} + err error } type SealerConfig struct { @@ -191,9 +201,10 @@ func schedNop(context.Context, Worker) error { return nil } -func schedFetch(sector abi.SectorID, ft storiface.SectorFileType, ptype storiface.PathType, am storiface.AcquireMode) func(context.Context, Worker) error { +func schedFetch(wf waitFunc, sector abi.SectorID, ft storiface.SectorFileType, ptype storiface.PathType, am storiface.AcquireMode) func(context.Context, Worker) error { return func(ctx context.Context, worker Worker) error { - return worker.Fetch(ctx, sector, ft, ptype, am) + _, err := wf(ctx)(worker.Fetch(ctx, sector, ft, ptype, am)) + return err } } @@ -220,15 +231,21 @@ func (m *Manager) ReadPiece(ctx context.Context, sink io.Writer, sector abi.Sect var readOk bool + readPiece := func(ctx context.Context, w Worker) error { + r, err := m.waitResult(ctx)(w.ReadPiece(ctx, sink, sector, offset, size)) + if err != nil { + return err + } + readOk = r.(bool) + return nil + } + if len(best) > 0 { // There is unsealed sector, see if we can read from it selector = newExistingSelector(m.index, sector, storiface.FTUnsealed, false) - err = m.sched.Schedule(ctx, sector, sealtasks.TTReadUnsealed, selector, schedFetch(sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { - readOk, err = w.ReadPiece(ctx, sink, sector, offset, size) - return err - }) + err = m.sched.Schedule(ctx, sector, sealtasks.TTReadUnsealed, selector, schedFetch(m.waitResult, sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove), readPiece) if err != nil { return xerrors.Errorf("reading piece from sealed sector: %w", err) } @@ -239,12 +256,12 @@ func (m *Manager) ReadPiece(ctx context.Context, sink io.Writer, sector abi.Sect } unsealFetch := func(ctx context.Context, worker Worker) error { - if err := worker.Fetch(ctx, sector, storiface.FTSealed|storiface.FTCache, storiface.PathSealing, storiface.AcquireCopy); err != nil { + if _, err := m.waitResult(ctx)(worker.Fetch(ctx, sector, storiface.FTSealed|storiface.FTCache, storiface.PathSealing, storiface.AcquireCopy)); err != nil { return xerrors.Errorf("copy sealed/cache sector data: %w", err) } if len(best) > 0 { - if err := worker.Fetch(ctx, sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove); err != nil { + if _, err := m.waitResult(ctx)(worker.Fetch(ctx, sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove)); err != nil { return xerrors.Errorf("copy unsealed sector data: %w", err) } } @@ -252,7 +269,8 @@ func (m *Manager) ReadPiece(ctx context.Context, sink io.Writer, sector abi.Sect } err = m.sched.Schedule(ctx, sector, sealtasks.TTUnseal, selector, unsealFetch, func(ctx context.Context, w Worker) error { - return w.UnsealPiece(ctx, sector, offset, size, ticket, unsealed) + _, err := m.waitResult(ctx)(w.UnsealPiece(ctx, sector, offset, size, ticket, unsealed)) + return err }) if err != nil { return err @@ -260,10 +278,7 @@ func (m *Manager) ReadPiece(ctx context.Context, sink io.Writer, sector abi.Sect selector = newExistingSelector(m.index, sector, storiface.FTUnsealed, false) - err = m.sched.Schedule(ctx, sector, sealtasks.TTReadUnsealed, selector, schedFetch(sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { - readOk, err = w.ReadPiece(ctx, sink, sector, offset, size) - return err - }) + err = m.sched.Schedule(ctx, sector, sealtasks.TTReadUnsealed, selector, schedFetch(m.waitResult, sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove), readPiece) if err != nil { return xerrors.Errorf("reading piece from sealed sector: %w", err) } @@ -298,11 +313,11 @@ func (m *Manager) AddPiece(ctx context.Context, sector abi.SectorID, existingPie var out abi.PieceInfo err = m.sched.Schedule(ctx, sector, sealtasks.TTAddPiece, selector, schedNop, func(ctx context.Context, w Worker) error { - p, err := w.AddPiece(ctx, sector, existingPieces, sz, r) + p, err := m.waitResult(ctx)(w.AddPiece(ctx, sector, existingPieces, sz, r)) if err != nil { return err } - out = p + out = p.(abi.PieceInfo) return nil }) @@ -321,12 +336,12 @@ func (m *Manager) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticke selector := newAllocSelector(m.index, storiface.FTCache|storiface.FTSealed, storiface.PathSealing) - err = m.sched.Schedule(ctx, sector, sealtasks.TTPreCommit1, selector, schedFetch(sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { - p, err := w.SealPreCommit1(ctx, sector, ticket, pieces) + err = m.sched.Schedule(ctx, sector, sealtasks.TTPreCommit1, selector, schedFetch(m.waitResult, sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { + p, err := m.waitResult(ctx)(w.SealPreCommit1(ctx, sector, ticket, pieces)) if err != nil { return err } - out = p + out = p.(storage.PreCommit1Out) return nil }) @@ -343,12 +358,12 @@ func (m *Manager) SealPreCommit2(ctx context.Context, sector abi.SectorID, phase selector := newExistingSelector(m.index, sector, storiface.FTCache|storiface.FTSealed, true) - err = m.sched.Schedule(ctx, sector, sealtasks.TTPreCommit2, selector, schedFetch(sector, storiface.FTCache|storiface.FTSealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { - p, err := w.SealPreCommit2(ctx, sector, phase1Out) + err = m.sched.Schedule(ctx, sector, sealtasks.TTPreCommit2, selector, schedFetch(m.waitResult, sector, storiface.FTCache|storiface.FTSealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { + p, err := m.waitResult(ctx)(w.SealPreCommit2(ctx, sector, phase1Out)) if err != nil { return err } - out = p + out = p.(storage.SectorCids) return nil }) return out, err @@ -367,12 +382,12 @@ func (m *Manager) SealCommit1(ctx context.Context, sector abi.SectorID, ticket a // generally very cheap / fast, and transferring data is not worth the effort selector := newExistingSelector(m.index, sector, storiface.FTCache|storiface.FTSealed, false) - err = m.sched.Schedule(ctx, sector, sealtasks.TTCommit1, selector, schedFetch(sector, storiface.FTCache|storiface.FTSealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { - p, err := w.SealCommit1(ctx, sector, ticket, seed, pieces, cids) + err = m.sched.Schedule(ctx, sector, sealtasks.TTCommit1, selector, schedFetch(m.waitResult, sector, storiface.FTCache|storiface.FTSealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { + p, err := m.waitResult(ctx)(w.SealCommit1(ctx, sector, ticket, seed, pieces, cids)) if err != nil { return err } - out = p + out = p.(storage.Commit1Out) return nil }) return out, err @@ -382,11 +397,11 @@ func (m *Manager) SealCommit2(ctx context.Context, sector abi.SectorID, phase1Ou selector := newTaskSelector() err = m.sched.Schedule(ctx, sector, sealtasks.TTCommit2, selector, schedNop, func(ctx context.Context, w Worker) error { - p, err := w.SealCommit2(ctx, sector, phase1Out) + p, err := m.waitResult(ctx)(w.SealCommit2(ctx, sector, phase1Out)) if err != nil { return err } - out = p + out = p.(storage.Proof) return nil }) @@ -416,9 +431,10 @@ func (m *Manager) FinalizeSector(ctx context.Context, sector abi.SectorID, keepU selector := newExistingSelector(m.index, sector, storiface.FTCache|storiface.FTSealed, false) err := m.sched.Schedule(ctx, sector, sealtasks.TTFinalize, selector, - schedFetch(sector, storiface.FTCache|storiface.FTSealed|unsealed, storiface.PathSealing, storiface.AcquireMove), + schedFetch(m.waitResult, sector, storiface.FTCache|storiface.FTSealed|unsealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { - return w.FinalizeSector(ctx, sector, keepUnsealed) + _, err := m.waitResult(ctx)(w.FinalizeSector(ctx, sector, keepUnsealed)) + return err }) if err != nil { return err @@ -433,9 +449,10 @@ func (m *Manager) FinalizeSector(ctx context.Context, sector abi.SectorID, keepU } err = m.sched.Schedule(ctx, sector, sealtasks.TTFetch, fetchSel, - schedFetch(sector, storiface.FTCache|storiface.FTSealed|moveUnsealed, storiface.PathStorage, storiface.AcquireMove), + schedFetch(m.waitResult, sector, storiface.FTCache|storiface.FTSealed|moveUnsealed, storiface.PathStorage, storiface.AcquireMove), func(ctx context.Context, w Worker) error { - return w.MoveStorage(ctx, sector, storiface.FTCache|storiface.FTSealed|moveUnsealed) + _, err := m.waitResult(ctx)(w.MoveStorage(ctx, sector, storiface.FTCache|storiface.FTSealed|moveUnsealed)) + return err }) if err != nil { return xerrors.Errorf("moving sector to storage: %w", err) @@ -472,6 +489,107 @@ func (m *Manager) Remove(ctx context.Context, sector abi.SectorID) error { return err } +type waitFunc func(ctx context.Context) func(callID storiface.CallID, err error) (interface{}, error) + +func (m *Manager) waitResult(ctx context.Context) func(callID storiface.CallID, err error) (interface{}, error) { + return func(callID storiface.CallID, err error) (interface{}, error) { + if err != nil { + return nil, err + } + + m.resLk.Lock() + res, ok := m.results[callID] + if ok { + m.resLk.Unlock() + return res.r, res.err + } + + ch, ok := m.waitRes[callID] + if !ok { + ch = make(chan struct{}) + m.waitRes[callID] = ch + } + m.resLk.Unlock() + + select { + case <-ch: + m.resLk.Lock() + defer m.resLk.Unlock() + + res := m.results[callID] + delete(m.results, callID) + + return res.r, res.err + case <-ctx.Done(): + return nil, xerrors.Errorf("waiting for result: %w", ctx.Err()) + } + } +} + +func (m *Manager) returnResult(callID storiface.CallID, r interface{}, err string) error { + m.resLk.Lock() + defer m.resLk.Unlock() + + _, ok := m.results[callID] + if ok { + return xerrors.Errorf("result for call %v already reported") + } + + m.results[callID] = result{ + r: r, + err: errors.New(err), + } + + close(m.waitRes[callID]) + delete(m.waitRes, callID) + + return nil +} + +func (m *Manager) ReturnAddPiece(ctx context.Context, callID storiface.CallID, pi abi.PieceInfo, err string) error { + return m.returnResult(callID, pi, err) +} + +func (m *Manager) ReturnSealPreCommit1(ctx context.Context, callID storiface.CallID, p1o storage.PreCommit1Out, err string) error { + return m.returnResult(callID, p1o, err) +} + +func (m *Manager) ReturnSealPreCommit2(ctx context.Context, callID storiface.CallID, sealed storage.SectorCids, err string) error { + return m.returnResult(callID, sealed, err) +} + +func (m *Manager) ReturnSealCommit1(ctx context.Context, callID storiface.CallID, out storage.Commit1Out, err string) error { + return m.returnResult(callID, out, err) +} + +func (m *Manager) ReturnSealCommit2(ctx context.Context, callID storiface.CallID, proof storage.Proof, err string) error { + return m.returnResult(callID, proof, err) +} + +func (m *Manager) ReturnFinalizeSector(ctx context.Context, callID storiface.CallID, err string) error { + return m.returnResult(callID, nil, err) +} + +func (m *Manager) ReturnReleaseUnsealed(ctx context.Context, callID storiface.CallID, err string) error { + return m.returnResult(callID, nil, err) +} + +func (m *Manager) ReturnMoveStorage(ctx context.Context, callID storiface.CallID, err string) error { + return m.returnResult(callID, nil, err) +} + +func (m *Manager) ReturnUnsealPiece(ctx context.Context, callID storiface.CallID, err string) error { + return m.returnResult(callID, nil, err) +} + +func (m *Manager) ReturnReadPiece(ctx context.Context, callID storiface.CallID, ok bool, err string) error { + return m.returnResult(callID, ok, err) +} + +func (m *Manager) ReturnFetch(ctx context.Context, callID storiface.CallID, err string) error { + return m.returnResult(callID, nil, err) +} + func (m *Manager) StorageLocal(ctx context.Context) (map[stores.ID]string, error) { l, err := m.localStore.Local(ctx) if err != nil { From 9e6f974f3c2bbb28c0258a5bbbd01c1034c074a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 7 Sep 2020 16:12:46 +0200 Subject: [PATCH 004/313] storage: Fix build --- cmd/lotus-seal-worker/rpc.go | 5 +- extern/sector-storage/manager.go | 8 +- extern/sector-storage/sched_test.go | 3 +- extern/sector-storage/stats.go | 2 +- extern/sector-storage/storiface/worker.go | 2 +- extern/sector-storage/work_tracker.go | 107 ++++++++++++---------- node/builder.go | 2 + node/impl/storminer.go | 1 + 8 files changed, 72 insertions(+), 58 deletions(-) diff --git a/cmd/lotus-seal-worker/rpc.go b/cmd/lotus-seal-worker/rpc.go index 5380fe432..3c0a1f2ce 100644 --- a/cmd/lotus-seal-worker/rpc.go +++ b/cmd/lotus-seal-worker/rpc.go @@ -6,11 +6,10 @@ import ( "github.com/mitchellh/go-homedir" "golang.org/x/xerrors" - "github.com/filecoin-project/specs-storage/storage" - "github.com/filecoin-project/lotus/build" sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage" "github.com/filecoin-project/lotus/extern/sector-storage/stores" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) type worker struct { @@ -43,4 +42,4 @@ func (w *worker) StorageAddLocal(ctx context.Context, path string) error { return nil } -var _ storage.Sealer = &worker{} +var _ storiface.WorkerCalls = &worker{} diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index da700cdc0..8891d83ab 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -52,6 +52,7 @@ type SectorManager interface { ffiwrapper.StorageSealer storage.Prover + storiface.WorkerReturn FaultTracker } @@ -70,13 +71,13 @@ type Manager struct { storage.Prover - resLk sync.Mutex + resLk sync.Mutex results map[storiface.CallID]result waitRes map[storiface.CallID]chan struct{} } type result struct { - r interface{} + r interface{} err error } @@ -179,7 +180,8 @@ func (m *Manager) AddWorker(ctx context.Context, w Worker) error { m.sched.newWorkers <- &workerHandle{ w: w, wt: &workTracker{ - running: map[uint64]storiface.WorkerJob{}, + done: map[storiface.CallID]struct{}{}, + running: map[storiface.CallID]storiface.WorkerJob{}, }, info: info, preparing: &activeResources{}, diff --git a/extern/sector-storage/sched_test.go b/extern/sector-storage/sched_test.go index 834a9f6dd..a95d4b3fa 100644 --- a/extern/sector-storage/sched_test.go +++ b/extern/sector-storage/sched_test.go @@ -166,7 +166,8 @@ func addTestWorker(t *testing.T, sched *scheduler, index *stores.Index, name str sched.newWorkers <- &workerHandle{ w: w, wt: &workTracker{ - running: map[uint64]storiface.WorkerJob{}, + done: map[storiface.CallID]struct{}{}, + running: map[storiface.CallID]storiface.WorkerJob{}, }, info: info, preparing: &activeResources{}, diff --git a/extern/sector-storage/stats.go b/extern/sector-storage/stats.go index 7f95e3bc3..f9063cbec 100644 --- a/extern/sector-storage/stats.go +++ b/extern/sector-storage/stats.go @@ -36,7 +36,7 @@ func (m *Manager) WorkerJobs() map[uint64][]storiface.WorkerJob { for wi, window := range handle.activeWindows { for _, request := range window.todo { out[uint64(id)] = append(out[uint64(id)], storiface.WorkerJob{ - ID: 0, + ID: storiface.UndefCall, Sector: request.sector, Task: request.taskType, RunWait: wi + 1, diff --git a/extern/sector-storage/storiface/worker.go b/extern/sector-storage/storiface/worker.go index dac22aba0..839ac14ad 100644 --- a/extern/sector-storage/storiface/worker.go +++ b/extern/sector-storage/storiface/worker.go @@ -40,7 +40,7 @@ type WorkerStats struct { } type WorkerJob struct { - ID uint64 + ID CallID Sector abi.SectorID Task sealtasks.TaskType diff --git a/extern/sector-storage/work_tracker.go b/extern/sector-storage/work_tracker.go index 53f79af90..57e136af0 100644 --- a/extern/sector-storage/work_tracker.go +++ b/extern/sector-storage/work_tracker.go @@ -18,31 +18,58 @@ import ( type workTracker struct { lk sync.Mutex - ctr uint64 - running map[uint64]storiface.WorkerJob + done map[storiface.CallID]struct{} + running map[storiface.CallID]storiface.WorkerJob // TODO: done, aggregate stats, queue stats, scheduler feedback } -func (wt *workTracker) track(sid abi.SectorID, task sealtasks.TaskType) func() { +// TODO: CALL THIS! +// TODO: CALL THIS! +// TODO: CALL THIS! +// TODO: CALL THIS! +// TODO: CALL THIS! +// TODO: CALL THIS! +// TODO: CALL THIS! +// TODO: CALL THIS! +// TODO: CALL THIS! +// TODO: CALL THIS! +func (wt *workTracker) onDone(callID storiface.CallID) { wt.lk.Lock() defer wt.lk.Unlock() - id := wt.ctr - wt.ctr++ - - wt.running[id] = storiface.WorkerJob{ - ID: id, - Sector: sid, - Task: task, - Start: time.Now(), + _, ok := wt.running[callID] + if !ok { + wt.done[callID] = struct{}{} + return } - return func() { + delete(wt.running, callID) +} + +func (wt *workTracker) track(sid abi.SectorID, task sealtasks.TaskType) func(storiface.CallID, error) (storiface.CallID, error) { + return func(callID storiface.CallID, err error) (storiface.CallID, error) { + if err != nil { + return callID, err + } + wt.lk.Lock() defer wt.lk.Unlock() - delete(wt.running, id) + _, done := wt.done[callID] + if done { + delete(wt.done, callID) + return callID, err + } + + wt.running[callID] = storiface.WorkerJob{ + ID: callID, + Sector: sid, + Task: task, + Start: time.Now(), + } + + return callID, err } } @@ -71,58 +98,40 @@ type trackedWorker struct { tracker *workTracker } -func (t *trackedWorker) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storage.PreCommit1Out, error) { - defer t.tracker.track(sector, sealtasks.TTPreCommit1)() - - return t.Worker.SealPreCommit1(ctx, sector, ticket, pieces) +func (t *trackedWorker) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storiface.CallID, error) { + return t.tracker.track(sector, sealtasks.TTPreCommit1)(t.Worker.SealPreCommit1(ctx, sector, ticket, pieces)) } -func (t *trackedWorker) SealPreCommit2(ctx context.Context, sector abi.SectorID, pc1o storage.PreCommit1Out) (storage.SectorCids, error) { - defer t.tracker.track(sector, sealtasks.TTPreCommit2)() - - return t.Worker.SealPreCommit2(ctx, sector, pc1o) +func (t *trackedWorker) SealPreCommit2(ctx context.Context, sector abi.SectorID, pc1o storage.PreCommit1Out) (storiface.CallID, error) { + return t.tracker.track(sector, sealtasks.TTPreCommit2)(t.Worker.SealPreCommit2(ctx, sector, pc1o)) } -func (t *trackedWorker) SealCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storage.Commit1Out, error) { - defer t.tracker.track(sector, sealtasks.TTCommit1)() - - return t.Worker.SealCommit1(ctx, sector, ticket, seed, pieces, cids) +func (t *trackedWorker) SealCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storiface.CallID, error) { + return t.tracker.track(sector, sealtasks.TTCommit1)(t.Worker.SealCommit1(ctx, sector, ticket, seed, pieces, cids)) } -func (t *trackedWorker) SealCommit2(ctx context.Context, sector abi.SectorID, c1o storage.Commit1Out) (storage.Proof, error) { - defer t.tracker.track(sector, sealtasks.TTCommit2)() - - return t.Worker.SealCommit2(ctx, sector, c1o) +func (t *trackedWorker) SealCommit2(ctx context.Context, sector abi.SectorID, c1o storage.Commit1Out) (storiface.CallID, error) { + return t.tracker.track(sector, sealtasks.TTCommit2)(t.Worker.SealCommit2(ctx, sector, c1o)) } -func (t *trackedWorker) FinalizeSector(ctx context.Context, sector abi.SectorID, keepUnsealed []storage.Range) error { - defer t.tracker.track(sector, sealtasks.TTFinalize)() - - return t.Worker.FinalizeSector(ctx, sector, keepUnsealed) +func (t *trackedWorker) FinalizeSector(ctx context.Context, sector abi.SectorID, keepUnsealed []storage.Range) (storiface.CallID, error) { + return t.tracker.track(sector, sealtasks.TTFinalize)(t.Worker.FinalizeSector(ctx, sector, keepUnsealed)) } -func (t *trackedWorker) AddPiece(ctx context.Context, sector abi.SectorID, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage.Data) (abi.PieceInfo, error) { - defer t.tracker.track(sector, sealtasks.TTAddPiece)() - - return t.Worker.AddPiece(ctx, sector, pieceSizes, newPieceSize, pieceData) +func (t *trackedWorker) AddPiece(ctx context.Context, sector abi.SectorID, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage.Data) (storiface.CallID, error) { + return t.tracker.track(sector, sealtasks.TTAddPiece)(t.Worker.AddPiece(ctx, sector, pieceSizes, newPieceSize, pieceData)) } -func (t *trackedWorker) Fetch(ctx context.Context, s abi.SectorID, ft storiface.SectorFileType, ptype storiface.PathType, am storiface.AcquireMode) error { - defer t.tracker.track(s, sealtasks.TTFetch)() - - return t.Worker.Fetch(ctx, s, ft, ptype, am) +func (t *trackedWorker) Fetch(ctx context.Context, s abi.SectorID, ft storiface.SectorFileType, ptype storiface.PathType, am storiface.AcquireMode) (storiface.CallID, error) { + return t.tracker.track(s, sealtasks.TTFetch)(t.Worker.Fetch(ctx, s, ft, ptype, am)) } -func (t *trackedWorker) UnsealPiece(ctx context.Context, id abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, randomness abi.SealRandomness, cid cid.Cid) error { - defer t.tracker.track(id, sealtasks.TTUnseal)() - - return t.Worker.UnsealPiece(ctx, id, index, size, randomness, cid) +func (t *trackedWorker) UnsealPiece(ctx context.Context, id abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, randomness abi.SealRandomness, cid cid.Cid) (storiface.CallID, error) { + return t.tracker.track(id, sealtasks.TTUnseal)(t.Worker.UnsealPiece(ctx, id, index, size, randomness, cid)) } -func (t *trackedWorker) ReadPiece(ctx context.Context, writer io.Writer, id abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize) (bool, error) { - defer t.tracker.track(id, sealtasks.TTReadUnsealed)() - - return t.Worker.ReadPiece(ctx, writer, id, index, size) +func (t *trackedWorker) ReadPiece(ctx context.Context, writer io.Writer, id abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize) (storiface.CallID, error) { + return t.tracker.track(id, sealtasks.TTReadUnsealed)(t.Worker.ReadPiece(ctx, writer, id, index, size)) } var _ Worker = &trackedWorker{} diff --git a/node/builder.go b/node/builder.go index 5b6966cd4..5c21a155d 100644 --- a/node/builder.go +++ b/node/builder.go @@ -43,6 +43,7 @@ import ( sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" "github.com/filecoin-project/lotus/extern/sector-storage/stores" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" sealing "github.com/filecoin-project/lotus/extern/storage-sealing" "github.com/filecoin-project/lotus/lib/blockstore" "github.com/filecoin-project/lotus/lib/peermgr" @@ -298,6 +299,7 @@ func Online() Option { Override(new(sectorstorage.SectorManager), From(new(*sectorstorage.Manager))), Override(new(storage2.Prover), From(new(sectorstorage.SectorManager))), + Override(new(storiface.WorkerReturn), From(new(sectorstorage.SectorManager))), Override(new(*sectorblocks.SectorBlocks), sectorblocks.NewSectorBlocks), Override(new(*storage.Miner), modules.StorageMiner(config.DefaultStorageMiner().Fees)), diff --git a/node/impl/storminer.go b/node/impl/storminer.go index c688ff677..73e8eea06 100644 --- a/node/impl/storminer.go +++ b/node/impl/storminer.go @@ -53,6 +53,7 @@ type StorageMinerAPI struct { StorageMgr *sectorstorage.Manager `optional:"true"` IStorageMgr sectorstorage.SectorManager *stores.Index + storiface.WorkerReturn DataTransfer dtypes.ProviderDataTransfer Host host.Host From 231a9e40512827bd537901606660b560c5f26deb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 7 Sep 2020 16:35:54 +0200 Subject: [PATCH 005/313] Fix sealing sched tests --- cmd/lotus-seal-worker/main.go | 2 +- extern/sector-storage/localworker.go | 3 +- extern/sector-storage/manager.go | 14 ++++-- extern/sector-storage/manager_test.go | 6 ++- extern/sector-storage/mock/mock.go | 44 +++++++++++++++++ extern/sector-storage/sched_test.go | 26 +++++----- extern/sector-storage/testworker_test.go | 60 +++++++++++++++++------- 7 files changed, 120 insertions(+), 35 deletions(-) diff --git a/cmd/lotus-seal-worker/main.go b/cmd/lotus-seal-worker/main.go index e6361d3cf..b7fdfef2a 100644 --- a/cmd/lotus-seal-worker/main.go +++ b/cmd/lotus-seal-worker/main.go @@ -344,7 +344,7 @@ var runCmd = &cli.Command{ LocalWorker: sectorstorage.NewLocalWorker(sectorstorage.WorkerConfig{ SealProof: spt, TaskTypes: taskTypes, - }, remote, localStore, nodeApi), + }, remote, localStore, nodeApi, nodeApi), localStore: localStore, ls: lr, } diff --git a/extern/sector-storage/localworker.go b/extern/sector-storage/localworker.go index 1a2232dd1..c20179578 100644 --- a/extern/sector-storage/localworker.go +++ b/extern/sector-storage/localworker.go @@ -39,7 +39,7 @@ type LocalWorker struct { acceptTasks map[sealtasks.TaskType]struct{} } -func NewLocalWorker(wcfg WorkerConfig, store stores.Store, local *stores.Local, sindex stores.SectorIndex) *LocalWorker { +func NewLocalWorker(wcfg WorkerConfig, store stores.Store, local *stores.Local, sindex stores.SectorIndex, ret storiface.WorkerReturn) *LocalWorker { acceptTasks := map[sealtasks.TaskType]struct{}{} for _, taskType := range wcfg.TaskTypes { acceptTasks[taskType] = struct{}{} @@ -52,6 +52,7 @@ func NewLocalWorker(wcfg WorkerConfig, store stores.Store, local *stores.Local, storage: store, localStore: local, sindex: sindex, + ret: ret, acceptTasks: acceptTasks, } diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index 8891d83ab..91381113c 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -119,6 +119,9 @@ func New(ctx context.Context, ls stores.LocalStorage, si stores.SectorIndex, cfg sched: newScheduler(cfg.SealProofType), Prover: prover, + + results: map[storiface.CallID]result{}, + waitRes: map[storiface.CallID]chan struct{}{}, } go m.sched.runSched() @@ -145,7 +148,7 @@ func New(ctx context.Context, ls stores.LocalStorage, si stores.SectorIndex, cfg err = m.AddWorker(ctx, NewLocalWorker(WorkerConfig{ SealProof: cfg.SealProofType, TaskTypes: localTasks, - }, stor, lstor, si)) + }, stor, lstor, si, m)) if err != nil { return nil, xerrors.Errorf("adding local worker: %w", err) } @@ -528,7 +531,7 @@ func (m *Manager) waitResult(ctx context.Context) func(callID storiface.CallID, } } -func (m *Manager) returnResult(callID storiface.CallID, r interface{}, err string) error { +func (m *Manager) returnResult(callID storiface.CallID, r interface{}, serr string) error { m.resLk.Lock() defer m.resLk.Unlock() @@ -537,9 +540,14 @@ func (m *Manager) returnResult(callID storiface.CallID, r interface{}, err strin return xerrors.Errorf("result for call %v already reported") } + var err error + if serr != "" { + err = errors.New(serr) + } + m.results[callID] = result{ r: r, - err: errors.New(err), + err: err, } close(m.waitRes[callID]) diff --git a/extern/sector-storage/manager_test.go b/extern/sector-storage/manager_test.go index 13ad9f8bf..bab9a4657 100644 --- a/extern/sector-storage/manager_test.go +++ b/extern/sector-storage/manager_test.go @@ -15,6 +15,7 @@ import ( "github.com/filecoin-project/lotus/extern/sector-storage/fsutil" "github.com/filecoin-project/lotus/extern/sector-storage/sealtasks" "github.com/filecoin-project/lotus/extern/sector-storage/stores" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "github.com/filecoin-project/specs-actors/actors/abi" @@ -109,6 +110,9 @@ func newTestMgr(ctx context.Context, t *testing.T) (*Manager, *stores.Local, *st sched: newScheduler(cfg.SealProofType), Prover: prover, + + results: map[storiface.CallID]result{}, + waitRes: map[storiface.CallID]chan struct{}{}, } go m.sched.runSched() @@ -129,7 +133,7 @@ func TestSimple(t *testing.T) { err := m.AddWorker(ctx, newTestWorker(WorkerConfig{ SealProof: abi.RegisteredSealProof_StackedDrg2KiBV1, TaskTypes: localTasks, - }, lstor)) + }, lstor, m)) require.NoError(t, err) sid := abi.SectorID{Miner: 1000, Number: 1} diff --git a/extern/sector-storage/mock/mock.go b/extern/sector-storage/mock/mock.go index 4afe5f096..aa3f24197 100644 --- a/extern/sector-storage/mock/mock.go +++ b/extern/sector-storage/mock/mock.go @@ -384,6 +384,50 @@ func (mgr *SectorMgr) CheckProvable(ctx context.Context, spt abi.RegisteredSealP return bad, nil } +func (mgr *SectorMgr) ReturnAddPiece(ctx context.Context, callID storiface.CallID, pi abi.PieceInfo, err string) error { + panic("not supported") +} + +func (mgr *SectorMgr) ReturnSealPreCommit1(ctx context.Context, callID storiface.CallID, p1o storage.PreCommit1Out, err string) error { + panic("not supported") +} + +func (mgr *SectorMgr) ReturnSealPreCommit2(ctx context.Context, callID storiface.CallID, sealed storage.SectorCids, err string) error { + panic("not supported") +} + +func (mgr *SectorMgr) ReturnSealCommit1(ctx context.Context, callID storiface.CallID, out storage.Commit1Out, err string) error { + panic("not supported") +} + +func (mgr *SectorMgr) ReturnSealCommit2(ctx context.Context, callID storiface.CallID, proof storage.Proof, err string) error { + panic("not supported") +} + +func (mgr *SectorMgr) ReturnFinalizeSector(ctx context.Context, callID storiface.CallID, err string) error { + panic("not supported") +} + +func (mgr *SectorMgr) ReturnReleaseUnsealed(ctx context.Context, callID storiface.CallID, err string) error { + panic("not supported") +} + +func (mgr *SectorMgr) ReturnMoveStorage(ctx context.Context, callID storiface.CallID, err string) error { + panic("not supported") +} + +func (mgr *SectorMgr) ReturnUnsealPiece(ctx context.Context, callID storiface.CallID, err string) error { + panic("not supported") +} + +func (mgr *SectorMgr) ReturnReadPiece(ctx context.Context, callID storiface.CallID, ok bool, err string) error { + panic("not supported") +} + +func (mgr *SectorMgr) ReturnFetch(ctx context.Context, callID storiface.CallID, err string) error { + panic("not supported") +} + func (m mockVerif) VerifySeal(svi abi.SealVerifyInfo) (bool, error) { if len(svi.Proof) != 32 { // Real ones are longer, but this should be fine return false, nil diff --git a/extern/sector-storage/sched_test.go b/extern/sector-storage/sched_test.go index a95d4b3fa..47da92217 100644 --- a/extern/sector-storage/sched_test.go +++ b/extern/sector-storage/sched_test.go @@ -46,55 +46,55 @@ type schedTestWorker struct { closing chan struct{} } -func (s *schedTestWorker) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storage.PreCommit1Out, error) { +func (s *schedTestWorker) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storiface.CallID, error) { panic("implement me") } -func (s *schedTestWorker) SealPreCommit2(ctx context.Context, sector abi.SectorID, pc1o storage.PreCommit1Out) (storage.SectorCids, error) { +func (s *schedTestWorker) SealPreCommit2(ctx context.Context, sector abi.SectorID, pc1o storage.PreCommit1Out) (storiface.CallID, error) { panic("implement me") } -func (s *schedTestWorker) SealCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storage.Commit1Out, error) { +func (s *schedTestWorker) SealCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storiface.CallID, error) { panic("implement me") } -func (s *schedTestWorker) SealCommit2(ctx context.Context, sector abi.SectorID, c1o storage.Commit1Out) (storage.Proof, error) { +func (s *schedTestWorker) SealCommit2(ctx context.Context, sector abi.SectorID, c1o storage.Commit1Out) (storiface.CallID, error) { panic("implement me") } -func (s *schedTestWorker) FinalizeSector(ctx context.Context, sector abi.SectorID, keepUnsealed []storage.Range) error { +func (s *schedTestWorker) FinalizeSector(ctx context.Context, sector abi.SectorID, keepUnsealed []storage.Range) (storiface.CallID, error) { panic("implement me") } -func (s *schedTestWorker) ReleaseUnsealed(ctx context.Context, sector abi.SectorID, safeToFree []storage.Range) error { +func (s *schedTestWorker) ReleaseUnsealed(ctx context.Context, sector abi.SectorID, safeToFree []storage.Range) (storiface.CallID, error) { panic("implement me") } -func (s *schedTestWorker) Remove(ctx context.Context, sector abi.SectorID) error { +func (s *schedTestWorker) Remove(ctx context.Context, sector abi.SectorID) (storiface.CallID, error) { panic("implement me") } -func (s *schedTestWorker) NewSector(ctx context.Context, sector abi.SectorID) error { +func (s *schedTestWorker) NewSector(ctx context.Context, sector abi.SectorID) (storiface.CallID, error) { panic("implement me") } -func (s *schedTestWorker) AddPiece(ctx context.Context, sector abi.SectorID, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage.Data) (abi.PieceInfo, error) { +func (s *schedTestWorker) AddPiece(ctx context.Context, sector abi.SectorID, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage.Data) (storiface.CallID, error) { panic("implement me") } -func (s *schedTestWorker) MoveStorage(ctx context.Context, sector abi.SectorID, types storiface.SectorFileType) error { +func (s *schedTestWorker) MoveStorage(ctx context.Context, sector abi.SectorID, types storiface.SectorFileType) (storiface.CallID, error) { panic("implement me") } -func (s *schedTestWorker) Fetch(ctx context.Context, id abi.SectorID, ft storiface.SectorFileType, ptype storiface.PathType, am storiface.AcquireMode) error { +func (s *schedTestWorker) Fetch(ctx context.Context, id abi.SectorID, ft storiface.SectorFileType, ptype storiface.PathType, am storiface.AcquireMode) (storiface.CallID, error) { panic("implement me") } -func (s *schedTestWorker) UnsealPiece(ctx context.Context, id abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, randomness abi.SealRandomness, cid cid.Cid) error { +func (s *schedTestWorker) UnsealPiece(ctx context.Context, id abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, randomness abi.SealRandomness, cid cid.Cid) (storiface.CallID, error) { panic("implement me") } -func (s *schedTestWorker) ReadPiece(ctx context.Context, writer io.Writer, id abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize) (bool, error) { +func (s *schedTestWorker) ReadPiece(ctx context.Context, writer io.Writer, id abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize) (storiface.CallID, error) { panic("implement me") } diff --git a/extern/sector-storage/testworker_test.go b/extern/sector-storage/testworker_test.go index cfa2bed06..a212271a7 100644 --- a/extern/sector-storage/testworker_test.go +++ b/extern/sector-storage/testworker_test.go @@ -4,6 +4,7 @@ import ( "context" "io" + "github.com/google/uuid" "github.com/ipfs/go-cid" "github.com/filecoin-project/specs-actors/actors/abi" @@ -18,11 +19,12 @@ import ( type testWorker struct { acceptTasks map[sealtasks.TaskType]struct{} lstor *stores.Local + ret storiface.WorkerReturn mockSeal *mock.SectorMgr } -func newTestWorker(wcfg WorkerConfig, lstor *stores.Local) *testWorker { +func newTestWorker(wcfg WorkerConfig, lstor *stores.Local, ret storiface.WorkerReturn) *testWorker { ssize, err := wcfg.SealProof.SectorSize() if err != nil { panic(err) @@ -36,61 +38,87 @@ func newTestWorker(wcfg WorkerConfig, lstor *stores.Local) *testWorker { return &testWorker{ acceptTasks: acceptTasks, lstor: lstor, + ret: ret, mockSeal: mock.NewMockSectorMgr(ssize, nil), } } -func (t *testWorker) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storage.PreCommit1Out, error) { - return t.mockSeal.SealPreCommit1(ctx, sector, ticket, pieces) +func (t *testWorker) asyncCall(sector abi.SectorID, work func(ci storiface.CallID)) (storiface.CallID, error) { + ci := storiface.CallID{ + Sector: sector, + ID: uuid.New(), + } + + go work(ci) + + return ci, nil +} + +func (t *testWorker) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storiface.CallID, error) { + return t.asyncCall(sector, func(ci storiface.CallID) { + p1o, err := t.mockSeal.SealPreCommit1(ctx, sector, ticket, pieces) + if err := t.ret.ReturnSealPreCommit1(ctx, ci, p1o, errstr(err)); err != nil { + log.Error(err) + } + }) } func (t *testWorker) NewSector(ctx context.Context, sector abi.SectorID) error { panic("implement me") } -func (t *testWorker) UnsealPiece(ctx context.Context, id abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, randomness abi.SealRandomness, cid cid.Cid) error { +func (t *testWorker) UnsealPiece(ctx context.Context, id abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, randomness abi.SealRandomness, cid cid.Cid) (storiface.CallID, error) { panic("implement me") } -func (t *testWorker) ReadPiece(ctx context.Context, writer io.Writer, id abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize) (bool, error) { +func (t *testWorker) ReadPiece(ctx context.Context, writer io.Writer, id abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize) (storiface.CallID, error) { panic("implement me") } -func (t *testWorker) AddPiece(ctx context.Context, sector abi.SectorID, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage.Data) (abi.PieceInfo, error) { - return t.mockSeal.AddPiece(ctx, sector, pieceSizes, newPieceSize, pieceData) +func (t *testWorker) AddPiece(ctx context.Context, sector abi.SectorID, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage.Data) (storiface.CallID, error) { + return t.asyncCall(sector, func(ci storiface.CallID) { + p, err := t.mockSeal.AddPiece(ctx, sector, pieceSizes, newPieceSize, pieceData) + if err := t.ret.ReturnAddPiece(ctx, ci, p, errstr(err)); err != nil { + log.Error(err) + } + }) } -func (t *testWorker) SealPreCommit2(ctx context.Context, sector abi.SectorID, pc1o storage.PreCommit1Out) (storage.SectorCids, error) { +func (t *testWorker) SealPreCommit2(ctx context.Context, sector abi.SectorID, pc1o storage.PreCommit1Out) (storiface.CallID, error) { panic("implement me") } -func (t *testWorker) SealCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storage.Commit1Out, error) { +func (t *testWorker) SealCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storiface.CallID, error) { panic("implement me") } -func (t *testWorker) SealCommit2(ctx context.Context, sector abi.SectorID, c1o storage.Commit1Out) (storage.Proof, error) { +func (t *testWorker) SealCommit2(ctx context.Context, sector abi.SectorID, c1o storage.Commit1Out) (storiface.CallID, error) { panic("implement me") } -func (t *testWorker) FinalizeSector(ctx context.Context, sector abi.SectorID, keepUnsealed []storage.Range) error { +func (t *testWorker) FinalizeSector(ctx context.Context, sector abi.SectorID, keepUnsealed []storage.Range) (storiface.CallID, error) { panic("implement me") } -func (t *testWorker) ReleaseUnsealed(ctx context.Context, sector abi.SectorID, safeToFree []storage.Range) error { +func (t *testWorker) ReleaseUnsealed(ctx context.Context, sector abi.SectorID, safeToFree []storage.Range) (storiface.CallID, error) { panic("implement me") } -func (t *testWorker) Remove(ctx context.Context, sector abi.SectorID) error { +func (t *testWorker) Remove(ctx context.Context, sector abi.SectorID) (storiface.CallID, error) { panic("implement me") } -func (t *testWorker) MoveStorage(ctx context.Context, sector abi.SectorID, types storiface.SectorFileType) error { +func (t *testWorker) MoveStorage(ctx context.Context, sector abi.SectorID, types storiface.SectorFileType) (storiface.CallID, error) { panic("implement me") } -func (t *testWorker) Fetch(ctx context.Context, id abi.SectorID, fileType storiface.SectorFileType, ptype storiface.PathType, am storiface.AcquireMode) error { - return nil +func (t *testWorker) Fetch(ctx context.Context, sector abi.SectorID, fileType storiface.SectorFileType, ptype storiface.PathType, am storiface.AcquireMode) (storiface.CallID, error) { + return t.asyncCall(sector, func(ci storiface.CallID) { + if err := t.ret.ReturnFetch(ctx, ci, ""); err != nil { + log.Error(err) + } + }) } func (t *testWorker) TaskTypes(ctx context.Context) (map[sealtasks.TaskType]struct{}, error) { From 554570f884f2530f4a5c8f3719d120f638b1ce52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 7 Sep 2020 17:57:23 +0200 Subject: [PATCH 006/313] docsgen --- documentation/en/api-methods.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index dd5c13815..050e142b6 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -204,7 +204,7 @@ Response: ```json { "Version": "string value", - "APIVersion": 3584, + "APIVersion": 3840, "BlockDelay": 42 } ``` From 1ebca8f7321d302c3c6776d7e5405c633b0bc6e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 14 Sep 2020 09:44:55 +0200 Subject: [PATCH 007/313] more working code --- cmd/lotus-seal-worker/main.go | 8 +- cmd/lotus-storage-miner/init.go | 9 +- extern/sector-storage/calltracker.go | 46 ++++++ extern/sector-storage/cbor_gen.go | 119 +++++++++++++++ extern/sector-storage/localworker.go | 176 +++++++++++----------- extern/sector-storage/manager.go | 7 +- extern/sector-storage/storiface/worker.go | 7 + gen/main.go | 8 + node/modules/storageminer.go | 9 +- 9 files changed, 296 insertions(+), 93 deletions(-) create mode 100644 extern/sector-storage/calltracker.go create mode 100644 extern/sector-storage/cbor_gen.go diff --git a/cmd/lotus-seal-worker/main.go b/cmd/lotus-seal-worker/main.go index 31ef2917d..9739acb68 100644 --- a/cmd/lotus-seal-worker/main.go +++ b/cmd/lotus-seal-worker/main.go @@ -15,6 +15,8 @@ import ( "github.com/google/uuid" "github.com/gorilla/mux" + "github.com/ipfs/go-datastore" + "github.com/ipfs/go-datastore/namespace" logging "github.com/ipfs/go-log/v2" manet "github.com/multiformats/go-multiaddr/net" "github.com/urfave/cli/v2" @@ -23,6 +25,7 @@ import ( "github.com/filecoin-project/go-jsonrpc" "github.com/filecoin-project/go-jsonrpc/auth" paramfetch "github.com/filecoin-project/go-paramfetch" + "github.com/filecoin-project/go-statestore" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api/apistruct" @@ -34,6 +37,7 @@ import ( "github.com/filecoin-project/lotus/extern/sector-storage/stores" "github.com/filecoin-project/lotus/lib/lotuslog" "github.com/filecoin-project/lotus/lib/rpcenc" + "github.com/filecoin-project/lotus/node/modules" "github.com/filecoin-project/lotus/node/repo" ) @@ -342,11 +346,13 @@ var runCmd = &cli.Command{ // Create / expose the worker + wsts := statestore.New(namespace.Wrap(datastore.NewMapDatastore(), modules.WorkerCallsPrefix)) // TODO: USE A REAL DATASTORE + workerApi := &worker{ LocalWorker: sectorstorage.NewLocalWorker(sectorstorage.WorkerConfig{ SealProof: spt, TaskTypes: taskTypes, - }, remote, localStore, nodeApi, nodeApi), + }, remote, localStore, nodeApi, nodeApi, wsts), localStore: localStore, ls: lr, } diff --git a/cmd/lotus-storage-miner/init.go b/cmd/lotus-storage-miner/init.go index ba9460dab..4009c74f7 100644 --- a/cmd/lotus-storage-miner/init.go +++ b/cmd/lotus-storage-miner/init.go @@ -12,11 +12,10 @@ import ( "path/filepath" "strconv" - "github.com/filecoin-project/go-state-types/big" - "github.com/docker/go-units" "github.com/google/uuid" "github.com/ipfs/go-datastore" + "github.com/ipfs/go-datastore/namespace" "github.com/libp2p/go-libp2p-core/crypto" "github.com/libp2p/go-libp2p-core/peer" "github.com/mitchellh/go-homedir" @@ -27,7 +26,9 @@ import ( cborutil "github.com/filecoin-project/go-cbor-util" paramfetch "github.com/filecoin-project/go-paramfetch" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/big" crypto2 "github.com/filecoin-project/go-state-types/crypto" + "github.com/filecoin-project/go-statestore" sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" "github.com/filecoin-project/lotus/extern/sector-storage/stores" @@ -441,6 +442,8 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api lapi.FullNode, return err } + wsts := statestore.New(namespace.Wrap(mds, modules.WorkerCallsPrefix)) + smgr, err := sectorstorage.New(ctx, lr, stores.NewIndex(), &ffiwrapper.Config{ SealProofType: spt, }, sectorstorage.SealerConfig{ @@ -450,7 +453,7 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api lapi.FullNode, AllowPreCommit2: true, AllowCommit: true, AllowUnseal: true, - }, nil, sa) + }, nil, sa, wsts) if err != nil { return err } diff --git a/extern/sector-storage/calltracker.go b/extern/sector-storage/calltracker.go new file mode 100644 index 000000000..8c5aff577 --- /dev/null +++ b/extern/sector-storage/calltracker.go @@ -0,0 +1,46 @@ +package sectorstorage + +import ( + "github.com/filecoin-project/go-statestore" + + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" +) + +type callTracker struct { + st *statestore.StateStore // by CallID +} + +type CallState uint64 + +const ( + CallStarted CallState = iota + CallDone + // returned -> remove +) + +type Call struct { + State CallState + + // Params cbg.Deferred // TODO: support once useful + Result []byte +} + +func (wt *callTracker) onStart(ci storiface.CallID) error { + return wt.st.Begin(ci, &Call{ + State: CallStarted, + }) +} + +func (wt *callTracker) onDone(ci storiface.CallID, ret []byte) error { + st := wt.st.Get(ci) + return st.Mutate(func(cs *Call) error { + cs.State = CallDone + cs.Result = ret + return nil + }) +} + +func (wt *callTracker) onReturned(ci storiface.CallID) error { + st := wt.st.Get(ci) + return st.End() +} diff --git a/extern/sector-storage/cbor_gen.go b/extern/sector-storage/cbor_gen.go new file mode 100644 index 000000000..c532a9700 --- /dev/null +++ b/extern/sector-storage/cbor_gen.go @@ -0,0 +1,119 @@ +// Code generated by github.com/whyrusleeping/cbor-gen. DO NOT EDIT. + +package sectorstorage + +import ( + "fmt" + "io" + + cbg "github.com/whyrusleeping/cbor-gen" + xerrors "golang.org/x/xerrors" +) + +var _ = xerrors.Errorf + +func (t *Call) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + panic("cbg") + if _, err := w.Write([]byte{162}); err != nil { + return err + } + + scratch := make([]byte, 9) + + // t.State (sectorstorage.CallState) (uint64) + if len("State") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"State\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("State"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("State")); err != nil { + return err + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.State)); err != nil { + return err + } + + // t.Result (typegen.Deferred) (struct) + if len("Result") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"Result\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("Result"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("Result")); err != nil { + return err + } + + return nil +} + +func (t *Call) UnmarshalCBOR(r io.Reader) error { + *t = Call{} + + br := cbg.GetPeeker(r) + scratch := make([]byte, 8) + + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("Call: map struct too large (%d)", extra) + } + + var name string + n := extra + + for i := uint64(0); i < n; i++ { + + { + sval, err := cbg.ReadStringBuf(br, scratch) + if err != nil { + return err + } + + name = string(sval) + } + + switch name { + // t.State (sectorstorage.CallState) (uint64) + case "State": + + { + + maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.State = CallState(extra) + + } + // t.Result (typegen.Deferred) (struct) + case "Result": + + { + + } + + default: + return fmt.Errorf("unknown struct field %d: '%s'", i, name) + } + } + + return nil +} diff --git a/extern/sector-storage/localworker.go b/extern/sector-storage/localworker.go index 5b81f297c..b2e264a15 100644 --- a/extern/sector-storage/localworker.go +++ b/extern/sector-storage/localworker.go @@ -4,6 +4,7 @@ import ( "context" "io" "os" + "reflect" "runtime" "github.com/elastic/go-sysinfo" @@ -14,6 +15,7 @@ import ( ffi "github.com/filecoin-project/filecoin-ffi" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-statestore" storage2 "github.com/filecoin-project/specs-storage/storage" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" @@ -36,10 +38,11 @@ type LocalWorker struct { sindex stores.SectorIndex ret storiface.WorkerReturn + ct *callTracker acceptTasks map[sealtasks.TaskType]struct{} } -func NewLocalWorker(wcfg WorkerConfig, store stores.Store, local *stores.Local, sindex stores.SectorIndex, ret storiface.WorkerReturn) *LocalWorker { +func NewLocalWorker(wcfg WorkerConfig, store stores.Store, local *stores.Local, sindex stores.SectorIndex, ret storiface.WorkerReturn, cst *statestore.StateStore) *LocalWorker { acceptTasks := map[sealtasks.TaskType]struct{}{} for _, taskType := range wcfg.TaskTypes { acceptTasks[taskType] = struct{}{} @@ -54,6 +57,9 @@ func NewLocalWorker(wcfg WorkerConfig, store stores.Store, local *stores.Local, sindex: sindex, ret: ret, + ct: &callTracker{ + st: cst, + }, acceptTasks: acceptTasks, } } @@ -98,13 +104,62 @@ func (l *LocalWorker) sb() (ffiwrapper.Storage, error) { return ffiwrapper.New(&localWorkerPathProvider{w: l}, l.scfg) } -func (l *LocalWorker) asyncCall(sector abi.SectorID, work func(ci storiface.CallID)) (storiface.CallID, error) { +type returnType string + +// in: func(WorkerReturn, context.Context, CallID, err string) +// in: func(WorkerReturn, context.Context, CallID, ret T, err string) +func rfunc(in interface{}) func(context.Context, storiface.WorkerReturn, interface{}, error) error { + rf := reflect.ValueOf(in) + ft := rf.Type() + withRet := ft.NumIn() == 4 + + return func(ctx context.Context, wr storiface.WorkerReturn, i interface{}, err error) error { + rctx := reflect.ValueOf(ctx) + rwr := reflect.ValueOf(wr) + rerr := reflect.ValueOf(errstr(err)) + + var ro []reflect.Value + + if withRet { + ro = rf.Call([]reflect.Value{rwr, rctx, reflect.ValueOf(i), rerr}) + } else { + ro = rf.Call([]reflect.Value{rwr, rctx, rerr}) + } + + return ro[0].Interface().(error) + } +} + +var returnFunc = map[returnType]func(context.Context, storiface.WorkerReturn, interface{}, error) error{ + "AddPiece": rfunc(storiface.WorkerReturn.ReturnAddPiece), + "SealPreCommit1": rfunc(storiface.WorkerReturn.ReturnSealPreCommit1), + "SealPreCommit2": rfunc(storiface.WorkerReturn.ReturnSealPreCommit2), + "SealCommit1": rfunc(storiface.WorkerReturn.ReturnSealCommit1), + "SealCommit2": rfunc(storiface.WorkerReturn.ReturnSealCommit2), + "FinalizeSector": rfunc(storiface.WorkerReturn.ReturnFinalizeSector), + "ReleaseUnsealed": rfunc(storiface.WorkerReturn.ReturnReleaseUnsealed), + "MoveStorage": rfunc(storiface.WorkerReturn.ReturnMoveStorage), + "UnsealPiece": rfunc(storiface.WorkerReturn.ReturnUnsealPiece), + "ReadPiece": rfunc(storiface.WorkerReturn.ReturnReadPiece), + "Fetch": rfunc(storiface.WorkerReturn.ReturnFetch), +} + +func (l *LocalWorker) asyncCall(ctx context.Context, sector abi.SectorID, rt returnType, work func(ci storiface.CallID) (interface{}, error)) (storiface.CallID, error) { ci := storiface.CallID{ Sector: sector, ID: uuid.New(), } - go work(ci) + if err := l.ct.onStart(ci); err != nil { + log.Errorf("tracking call (start): %+v", err) + } + + go func() { + res, err := work(ci) + if err := returnFunc[rt](ctx, l.ret, res, err); err != nil { + log.Errorf("return error: %s: %+v", rt, err) + } + }() return ci, nil } @@ -132,58 +187,42 @@ func (l *LocalWorker) AddPiece(ctx context.Context, sector abi.SectorID, epcs [] return storiface.UndefCall, err } - return l.asyncCall(sector, func(ci storiface.CallID) { - pi, err := sb.AddPiece(ctx, sector, epcs, sz, r) - - if err := l.ret.ReturnAddPiece(ctx, ci, pi, errstr(err)); err != nil { - log.Errorf("ReturnAddPiece: %+v", err) - } + return l.asyncCall(ctx, sector, "AddPiece", func(ci storiface.CallID) (interface{}, error) { + return sb.AddPiece(ctx, sector, epcs, sz, r) }) } func (l *LocalWorker) Fetch(ctx context.Context, sector abi.SectorID, fileType storiface.SectorFileType, ptype storiface.PathType, am storiface.AcquireMode) (storiface.CallID, error) { - return l.asyncCall(sector, func(ci storiface.CallID) { + return l.asyncCall(ctx, sector, "Fetch", func(ci storiface.CallID) (interface{}, error) { _, done, err := (&localWorkerPathProvider{w: l, op: am}).AcquireSector(ctx, sector, fileType, storiface.FTNone, ptype) if err == nil { done() } - if err := l.ret.ReturnFetch(ctx, ci, errstr(err)); err != nil { - log.Errorf("ReturnFetch: %+v", err) - } + return nil, err }) } func (l *LocalWorker) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storiface.CallID, error) { - return l.asyncCall(sector, func(ci storiface.CallID) { - var err error - var p1o storage2.PreCommit1Out - defer func() { - if err := l.ret.ReturnSealPreCommit1(ctx, ci, p1o, errstr(err)); err != nil { - log.Errorf("ReturnSealPreCommit1: %+v", err) - } - }() + return l.asyncCall(ctx, sector, "SealPreCommit1", func(ci storiface.CallID) (interface{}, error) { { // cleanup previous failed attempts if they exist - if err = l.storage.Remove(ctx, sector, storiface.FTSealed, true); err != nil { - err = xerrors.Errorf("cleaning up sealed data: %w", err) - return + if err := l.storage.Remove(ctx, sector, storiface.FTSealed, true); err != nil { + return nil, xerrors.Errorf("cleaning up sealed data: %w", err) } - if err = l.storage.Remove(ctx, sector, storiface.FTCache, true); err != nil { - err = xerrors.Errorf("cleaning up cache data: %w", err) - return + if err := l.storage.Remove(ctx, sector, storiface.FTCache, true); err != nil { + return nil, xerrors.Errorf("cleaning up cache data: %w", err) } } - var sb ffiwrapper.Storage - sb, err = l.sb() + sb, err := l.sb() if err != nil { - return + return nil, err } - p1o, err = sb.SealPreCommit1(ctx, sector, ticket, pieces) + return sb.SealPreCommit1(ctx, sector, ticket, pieces) }) } @@ -193,12 +232,8 @@ func (l *LocalWorker) SealPreCommit2(ctx context.Context, sector abi.SectorID, p return storiface.UndefCall, err } - return l.asyncCall(sector, func(ci storiface.CallID) { - cs, err := sb.SealPreCommit2(ctx, sector, phase1Out) - - if err := l.ret.ReturnSealPreCommit2(ctx, ci, cs, errstr(err)); err != nil { - log.Errorf("ReturnSealPreCommit2: %+v", err) - } + return l.asyncCall(ctx, sector, "SealPreCommit2", func(ci storiface.CallID) (interface{}, error) { + return sb.SealPreCommit2(ctx, sector, phase1Out) }) } @@ -208,12 +243,8 @@ func (l *LocalWorker) SealCommit1(ctx context.Context, sector abi.SectorID, tick return storiface.UndefCall, err } - return l.asyncCall(sector, func(ci storiface.CallID) { - c1o, err := sb.SealCommit1(ctx, sector, ticket, seed, pieces, cids) - - if err := l.ret.ReturnSealCommit1(ctx, ci, c1o, errstr(err)); err != nil { - log.Errorf("ReturnSealCommit1: %+v", err) - } + return l.asyncCall(ctx, sector, "SealCommit1", func(ci storiface.CallID) (interface{}, error) { + return sb.SealCommit1(ctx, sector, ticket, seed, pieces, cids) }) } @@ -223,12 +254,8 @@ func (l *LocalWorker) SealCommit2(ctx context.Context, sector abi.SectorID, phas return storiface.UndefCall, err } - return l.asyncCall(sector, func(ci storiface.CallID) { - proof, err := sb.SealCommit2(ctx, sector, phase1Out) - - if err := l.ret.ReturnSealCommit2(ctx, ci, proof, errstr(err)); err != nil { - log.Errorf("ReturnSealCommit2: %+v", err) - } + return l.asyncCall(ctx, sector, "SealCommit2", func(ci storiface.CallID) (interface{}, error) { + return sb.SealCommit2(ctx, sector, phase1Out) }) } @@ -238,23 +265,18 @@ func (l *LocalWorker) FinalizeSector(ctx context.Context, sector abi.SectorID, k return storiface.UndefCall, err } - return l.asyncCall(sector, func(ci storiface.CallID) { + return l.asyncCall(ctx, sector, "FinalizeSector", func(ci storiface.CallID) (interface{}, error) { if err := sb.FinalizeSector(ctx, sector, keepUnsealed); err != nil { - if err := l.ret.ReturnFinalizeSector(ctx, ci, errstr(xerrors.Errorf("finalizing sector: %w", err))); err != nil { - log.Errorf("ReturnFinalizeSector: %+v", err) - } + return nil, xerrors.Errorf("finalizing sector: %w", err) } if len(keepUnsealed) == 0 { - err = xerrors.Errorf("removing unsealed data: %w", err) - if err := l.ret.ReturnFinalizeSector(ctx, ci, errstr(err)); err != nil { - log.Errorf("ReturnFinalizeSector: %+v", err) + if err := l.storage.Remove(ctx, sector, storiface.FTUnsealed, true); err != nil { + return nil, xerrors.Errorf("removing unsealed data: %w", err) } } - if err := l.ret.ReturnFinalizeSector(ctx, ci, errstr(err)); err != nil { - log.Errorf("ReturnFinalizeSector: %+v", err) - } + return nil, err }) } @@ -279,12 +301,8 @@ func (l *LocalWorker) Remove(ctx context.Context, sector abi.SectorID) error { } func (l *LocalWorker) MoveStorage(ctx context.Context, sector abi.SectorID, types storiface.SectorFileType) (storiface.CallID, error) { - return l.asyncCall(sector, func(ci storiface.CallID) { - err := l.storage.MoveStorage(ctx, sector, l.scfg.SealProofType, types) - - if err := l.ret.ReturnMoveStorage(ctx, ci, errstr(err)); err != nil { - log.Errorf("ReturnMoveStorage: %+v", err) - } + return l.asyncCall(ctx, sector, "MoveStorage", func(ci storiface.CallID) (interface{}, error) { + return nil, l.storage.MoveStorage(ctx, sector, l.scfg.SealProofType, types) }) } @@ -294,28 +312,20 @@ func (l *LocalWorker) UnsealPiece(ctx context.Context, sector abi.SectorID, inde return storiface.UndefCall, err } - return l.asyncCall(sector, func(ci storiface.CallID) { - var err error - defer func() { - if err := l.ret.ReturnUnsealPiece(ctx, ci, errstr(err)); err != nil { - log.Errorf("ReturnUnsealPiece: %+v", err) - } - }() - + return l.asyncCall(ctx, sector, "UnsealPiece", func(ci storiface.CallID) (interface{}, error) { if err = sb.UnsealPiece(ctx, sector, index, size, randomness, cid); err != nil { - err = xerrors.Errorf("unsealing sector: %w", err) - return + return nil, xerrors.Errorf("unsealing sector: %w", err) } if err = l.storage.RemoveCopies(ctx, sector, storiface.FTSealed); err != nil { - err = xerrors.Errorf("removing source data: %w", err) - return + return nil, xerrors.Errorf("removing source data: %w", err) } if err = l.storage.RemoveCopies(ctx, sector, storiface.FTCache); err != nil { - err = xerrors.Errorf("removing source data: %w", err) - return + return nil, xerrors.Errorf("removing source data: %w", err) } + + return nil, nil }) } @@ -325,12 +335,8 @@ func (l *LocalWorker) ReadPiece(ctx context.Context, writer io.Writer, sector ab return storiface.UndefCall, err } - return l.asyncCall(sector, func(ci storiface.CallID) { - ok, err := sb.ReadPiece(ctx, writer, sector, index, size) - - if err := l.ret.ReturnReadPiece(ctx, ci, ok, errstr(err)); err != nil { - log.Errorf("ReturnReadPiece: %+v", err) - } + return l.asyncCall(ctx, sector, "ReadPiece", func(ci storiface.CallID) (interface{}, error) { + return sb.ReadPiece(ctx, writer, sector, index, size) }) } diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index cdc8fc3ce..f51cd713a 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -3,6 +3,7 @@ package sectorstorage import ( "context" "errors" + "github.com/filecoin-project/go-statestore" "io" "net/http" "sync" @@ -94,7 +95,9 @@ type SealerConfig struct { type StorageAuth http.Header -func New(ctx context.Context, ls stores.LocalStorage, si stores.SectorIndex, cfg *ffiwrapper.Config, sc SealerConfig, urls URLs, sa StorageAuth) (*Manager, error) { +type WorkerStateStore *statestore.StateStore + +func New(ctx context.Context, ls stores.LocalStorage, si stores.SectorIndex, cfg *ffiwrapper.Config, sc SealerConfig, urls URLs, sa StorageAuth, wss WorkerStateStore) (*Manager, error) { lstor, err := stores.NewLocal(ctx, ls, si, urls) if err != nil { return nil, err @@ -148,7 +151,7 @@ func New(ctx context.Context, ls stores.LocalStorage, si stores.SectorIndex, cfg err = m.AddWorker(ctx, NewLocalWorker(WorkerConfig{ SealProof: cfg.SealProofType, TaskTypes: localTasks, - }, stor, lstor, si, m)) + }, stor, lstor, si, m, wss)) if err != nil { return nil, xerrors.Errorf("adding local worker: %w", err) } diff --git a/extern/sector-storage/storiface/worker.go b/extern/sector-storage/storiface/worker.go index 30587007a..ead770524 100644 --- a/extern/sector-storage/storiface/worker.go +++ b/extern/sector-storage/storiface/worker.go @@ -2,6 +2,7 @@ package storiface import ( "context" + "fmt" "io" "time" @@ -53,6 +54,12 @@ type CallID struct { ID uuid.UUID } +func (c CallID) String() string { + return fmt.Sprintf("%d-%d-%s", c.Sector.Miner, c.Sector.Number, c.ID) +} + +var _ fmt.Stringer = &CallID{} + var UndefCall CallID type WorkerCalls interface { diff --git a/gen/main.go b/gen/main.go index e7586a92a..c7ae5bd57 100644 --- a/gen/main.go +++ b/gen/main.go @@ -2,6 +2,7 @@ package main import ( "fmt" + sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage" "os" gen "github.com/whyrusleeping/cbor-gen" @@ -74,4 +75,11 @@ func main() { os.Exit(1) } + err = gen.WriteMapEncodersToFile("./extern/sector-storage/cbor_gen.go", "sectorstorage", + sectorstorage.Call{}, + ) + if err != nil { + fmt.Println(err) + os.Exit(1) + } } diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 773df78fe..b28d3e3f4 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "github.com/filecoin-project/go-statestore" "net/http" "time" @@ -479,10 +480,14 @@ func RetrievalProvider(h host.Host, miner *storage.Miner, sealer sectorstorage.S return retrievalimpl.NewProvider(maddr, adapter, netwk, pieceStore, mds, dt, namespace.Wrap(ds, datastore.NewKey("/retrievals/provider")), opt) } -func SectorStorage(mctx helpers.MetricsCtx, lc fx.Lifecycle, ls stores.LocalStorage, si stores.SectorIndex, cfg *ffiwrapper.Config, sc sectorstorage.SealerConfig, urls sectorstorage.URLs, sa sectorstorage.StorageAuth) (*sectorstorage.Manager, error) { +var WorkerCallsPrefix = datastore.NewKey("/worker/calls") + +func SectorStorage(mctx helpers.MetricsCtx, lc fx.Lifecycle, ls stores.LocalStorage, si stores.SectorIndex, cfg *ffiwrapper.Config, sc sectorstorage.SealerConfig, urls sectorstorage.URLs, sa sectorstorage.StorageAuth, ds dtypes.MetadataDS) (*sectorstorage.Manager, error) { ctx := helpers.LifecycleCtx(mctx, lc) - sst, err := sectorstorage.New(ctx, ls, si, cfg, sc, urls, sa) + wsts := statestore.New(namespace.Wrap(ds, WorkerCallsPrefix)) + + sst, err := sectorstorage.New(ctx, ls, si, cfg, sc, urls, sa, wsts) if err != nil { return nil, err } From e9d25e591912c0e3ef6914ae87928dd9bd9aafef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 14 Sep 2020 20:28:47 +0200 Subject: [PATCH 008/313] More fixes --- chain/exchange/cbor_gen.go | 12 +++---- extern/sector-storage/cbor_gen.go | 34 ++++++++++++++++--- .../sector-storage/ffiwrapper/sealer_test.go | 4 +-- extern/sector-storage/localworker.go | 21 +++++++----- markets/storageadapter/provider.go | 4 ++- 5 files changed, 54 insertions(+), 21 deletions(-) diff --git a/chain/exchange/cbor_gen.go b/chain/exchange/cbor_gen.go index dc91babe3..29b258081 100644 --- a/chain/exchange/cbor_gen.go +++ b/chain/exchange/cbor_gen.go @@ -146,7 +146,7 @@ func (t *Response) MarshalCBOR(w io.Writer) error { scratch := make([]byte, 9) - // t.Status (blocksync.status) (uint64) + // t.Status (exchange.status) (uint64) if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.Status)); err != nil { return err @@ -164,7 +164,7 @@ func (t *Response) MarshalCBOR(w io.Writer) error { return err } - // t.Chain ([]*blocksync.BSTipSet) (slice) + // t.Chain ([]*exchange.BSTipSet) (slice) if len(t.Chain) > cbg.MaxLength { return xerrors.Errorf("Slice value in field t.Chain was too long") } @@ -198,7 +198,7 @@ func (t *Response) UnmarshalCBOR(r io.Reader) error { return fmt.Errorf("cbor input had wrong number of fields") } - // t.Status (blocksync.status) (uint64) + // t.Status (exchange.status) (uint64) { @@ -222,7 +222,7 @@ func (t *Response) UnmarshalCBOR(r io.Reader) error { t.ErrorMessage = string(sval) } - // t.Chain ([]*blocksync.BSTipSet) (slice) + // t.Chain ([]*exchange.BSTipSet) (slice) maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) if err != nil { @@ -567,7 +567,7 @@ func (t *BSTipSet) MarshalCBOR(w io.Writer) error { } } - // t.Messages (blocksync.CompactedMessages) (struct) + // t.Messages (exchange.CompactedMessages) (struct) if err := t.Messages.MarshalCBOR(w); err != nil { return err } @@ -621,7 +621,7 @@ func (t *BSTipSet) UnmarshalCBOR(r io.Reader) error { t.Blocks[i] = &v } - // t.Messages (blocksync.CompactedMessages) (struct) + // t.Messages (exchange.CompactedMessages) (struct) { diff --git a/extern/sector-storage/cbor_gen.go b/extern/sector-storage/cbor_gen.go index c532a9700..c20df2157 100644 --- a/extern/sector-storage/cbor_gen.go +++ b/extern/sector-storage/cbor_gen.go @@ -17,7 +17,6 @@ func (t *Call) MarshalCBOR(w io.Writer) error { _, err := w.Write(cbg.CborNull) return err } - panic("cbg") if _, err := w.Write([]byte{162}); err != nil { return err } @@ -40,7 +39,7 @@ func (t *Call) MarshalCBOR(w io.Writer) error { return err } - // t.Result (typegen.Deferred) (struct) + // t.Result ([]uint8) (slice) if len("Result") > cbg.MaxLength { return xerrors.Errorf("Value in field \"Result\" was too long") } @@ -52,6 +51,17 @@ func (t *Call) MarshalCBOR(w io.Writer) error { return err } + if len(t.Result) > cbg.ByteArrayMaxLen { + return xerrors.Errorf("Byte array in field t.Result was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajByteString, uint64(len(t.Result))); err != nil { + return err + } + + if _, err := w.Write(t.Result[:]); err != nil { + return err + } return nil } @@ -103,11 +113,27 @@ func (t *Call) UnmarshalCBOR(r io.Reader) error { t.State = CallState(extra) } - // t.Result (typegen.Deferred) (struct) + // t.Result ([]uint8) (slice) case "Result": - { + maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if extra > cbg.ByteArrayMaxLen { + return fmt.Errorf("t.Result: byte array too large (%d)", extra) + } + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + + if extra > 0 { + t.Result = make([]uint8, extra) + } + + if _, err := io.ReadFull(br, t.Result[:]); err != nil { + return err } default: diff --git a/extern/sector-storage/ffiwrapper/sealer_test.go b/extern/sector-storage/ffiwrapper/sealer_test.go index caa70c554..35d5d586c 100644 --- a/extern/sector-storage/ffiwrapper/sealer_test.go +++ b/extern/sector-storage/ffiwrapper/sealer_test.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "fmt" - "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "io" "io/ioutil" "math/rand" @@ -31,6 +30,7 @@ import ( ffi "github.com/filecoin-project/filecoin-ffi" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper/basicfs" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) func init() { @@ -206,7 +206,7 @@ func post(t *testing.T, sealer *Sealer, skipped []abi.SectorID, seals ...seal) { } func corrupt(t *testing.T, sealer *Sealer, id abi.SectorID) { - paths, done, err := sealer.sectors.AcquireSector(context.Background(), id, stores.FTSealed, 0, stores.PathStorage) + paths, done, err := sealer.sectors.AcquireSector(context.Background(), id, storiface.FTSealed, 0, storiface.PathStorage) require.NoError(t, err) defer done() diff --git a/extern/sector-storage/localworker.go b/extern/sector-storage/localworker.go index b2e264a15..0a1a02397 100644 --- a/extern/sector-storage/localworker.go +++ b/extern/sector-storage/localworker.go @@ -108,29 +108,34 @@ type returnType string // in: func(WorkerReturn, context.Context, CallID, err string) // in: func(WorkerReturn, context.Context, CallID, ret T, err string) -func rfunc(in interface{}) func(context.Context, storiface.WorkerReturn, interface{}, error) error { +func rfunc(in interface{}) func(context.Context, storiface.CallID, storiface.WorkerReturn, interface{}, error) error { rf := reflect.ValueOf(in) ft := rf.Type() - withRet := ft.NumIn() == 4 + withRet := ft.NumIn() == 5 - return func(ctx context.Context, wr storiface.WorkerReturn, i interface{}, err error) error { + return func(ctx context.Context, ci storiface.CallID, wr storiface.WorkerReturn, i interface{}, err error) error { rctx := reflect.ValueOf(ctx) rwr := reflect.ValueOf(wr) rerr := reflect.ValueOf(errstr(err)) + rci := reflect.ValueOf(ci) var ro []reflect.Value if withRet { - ro = rf.Call([]reflect.Value{rwr, rctx, reflect.ValueOf(i), rerr}) + ro = rf.Call([]reflect.Value{rwr, rctx, rci, reflect.ValueOf(i), rerr}) } else { - ro = rf.Call([]reflect.Value{rwr, rctx, rerr}) + ro = rf.Call([]reflect.Value{rwr, rctx, rci, rerr}) } - return ro[0].Interface().(error) + if !ro[0].IsNil() { + return ro[0].Interface().(error) + } + + return nil } } -var returnFunc = map[returnType]func(context.Context, storiface.WorkerReturn, interface{}, error) error{ +var returnFunc = map[returnType]func(context.Context, storiface.CallID, storiface.WorkerReturn, interface{}, error) error{ "AddPiece": rfunc(storiface.WorkerReturn.ReturnAddPiece), "SealPreCommit1": rfunc(storiface.WorkerReturn.ReturnSealPreCommit1), "SealPreCommit2": rfunc(storiface.WorkerReturn.ReturnSealPreCommit2), @@ -156,7 +161,7 @@ func (l *LocalWorker) asyncCall(ctx context.Context, sector abi.SectorID, rt ret go func() { res, err := work(ci) - if err := returnFunc[rt](ctx, l.ret, res, err); err != nil { + if err := returnFunc[rt](ctx, ci, l.ret, res, err); err != nil { log.Errorf("return error: %s: %+v", rt, err) } }() diff --git a/markets/storageadapter/provider.go b/markets/storageadapter/provider.go index 7af1808c1..612504afc 100644 --- a/markets/storageadapter/provider.go +++ b/markets/storageadapter/provider.go @@ -108,7 +108,9 @@ func (n *ProviderNodeAdapter) OnDealComplete(ctx context.Context, deal storagema curTime := time.Now() for time.Since(curTime) < addPieceRetryTimeout { if !xerrors.Is(err, sealing.ErrTooManySectorsSealing) { - log.Errorf("failed to addPiece for deal %d, err: %w", deal.DealID, err) + if err != nil { + log.Errorf("failed to addPiece for deal %d, err: %w", deal.DealID, err) + } break } select { From b1361aaf8bc6f3a6ea0bcfeab4f84493dbab9bec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 16 Sep 2020 17:08:05 +0200 Subject: [PATCH 009/313] sectorstorage: wip manager work tracker --- extern/sector-storage/manager.go | 148 ++++------ extern/sector-storage/manager_calltracker.go | 271 ++++++++++++++++++ .../{calltracker.go => worker_calltracker.go} | 8 +- .../{localworker.go => worker_local.go} | 4 +- .../{work_tracker.go => worker_tracked.go} | 0 gen/main.go | 1 + 6 files changed, 337 insertions(+), 95 deletions(-) create mode 100644 extern/sector-storage/manager_calltracker.go rename extern/sector-storage/{calltracker.go => worker_calltracker.go} (71%) rename extern/sector-storage/{localworker.go => worker_local.go} (99%) rename extern/sector-storage/{work_tracker.go => worker_tracked.go} (100%) diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index 3b2c7e994..14ec875e9 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -72,9 +72,15 @@ type Manager struct { storage.Prover - resLk sync.Mutex - results map[storiface.CallID]result - waitRes map[storiface.CallID]chan struct{} + workLk sync.Mutex + work *statestore.StateStore + + callToWork map[storiface.CallID]workID + // used when we get an early return and there's no callToWork mapping + callRes map[storiface.CallID]chan result + + results map[workID]result + waitRes map[workID]chan struct{} } type result struct { @@ -96,8 +102,9 @@ type SealerConfig struct { type StorageAuth http.Header type WorkerStateStore *statestore.StateStore +type ManagerStateStore *statestore.StateStore -func New(ctx context.Context, ls stores.LocalStorage, si stores.SectorIndex, cfg *ffiwrapper.Config, sc SealerConfig, urls URLs, sa StorageAuth, wss WorkerStateStore) (*Manager, error) { +func New(ctx context.Context, ls stores.LocalStorage, si stores.SectorIndex, cfg *ffiwrapper.Config, sc SealerConfig, urls URLs, sa StorageAuth, wss WorkerStateStore, mss ManagerStateStore) (*Manager, error) { lstor, err := stores.NewLocal(ctx, ls, si, urls) if err != nil { return nil, err @@ -123,10 +130,15 @@ func New(ctx context.Context, ls stores.LocalStorage, si stores.SectorIndex, cfg Prover: prover, - results: map[storiface.CallID]result{}, - waitRes: map[storiface.CallID]chan struct{}{}, + work: mss, + workWait: map[workID]*sync.Cond{}, + callToWork: map[storiface.CallID]workID{}, + results: map[workID]result{}, + waitRes: map[workID]chan struct{}{}, } + // TODO: remove all non-running work from the work tracker + go m.sched.runSched() localTasks := []sealtasks.TaskType{ @@ -209,16 +221,16 @@ func schedNop(context.Context, Worker) error { return nil } -func schedFetch(wf waitFunc, sector abi.SectorID, ft storiface.SectorFileType, ptype storiface.PathType, am storiface.AcquireMode) func(context.Context, Worker) error { +func (m *Manager) schedFetch(sector abi.SectorID, ft storiface.SectorFileType, ptype storiface.PathType, am storiface.AcquireMode) func(context.Context, Worker) error { return func(ctx context.Context, worker Worker) error { - _, err := wf(ctx)(worker.Fetch(ctx, sector, ft, ptype, am)) + _, err := m.startWork(ctx)(worker.Fetch(ctx, sector, ft, ptype, am)) return err } } func (m *Manager) readPiece(sink io.Writer, sector abi.SectorID, offset storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, rok *bool) func(ctx context.Context, w Worker) error { return func(ctx context.Context, w Worker) error { - r, err := m.waitResult(ctx)(w.ReadPiece(ctx, sink, sector, offset, size)) + r, err := m.startWork(ctx)(w.ReadPiece(ctx, sink, sector, offset, size)) if err != nil { return err } @@ -251,7 +263,7 @@ func (m *Manager) tryReadUnsealedPiece(ctx context.Context, sink io.Writer, sect selector = newExistingSelector(m.index, sector, storiface.FTUnsealed, false) - err = m.sched.Schedule(ctx, sector, sealtasks.TTReadUnsealed, selector, schedFetch(m.waitResult, sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove), + err = m.sched.Schedule(ctx, sector, sealtasks.TTReadUnsealed, selector, schedFetch(m.startWork, sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove), m.readPiece(sink, sector, offset, size, &readOk)) if err != nil { returnErr = xerrors.Errorf("reading piece from sealed sector: %w", err) @@ -278,12 +290,12 @@ func (m *Manager) ReadPiece(ctx context.Context, sink io.Writer, sector abi.Sect } unsealFetch := func(ctx context.Context, worker Worker) error { - if _, err := m.waitResult(ctx)(worker.Fetch(ctx, sector, storiface.FTSealed|storiface.FTCache, storiface.PathSealing, storiface.AcquireCopy)); err != nil { + if _, err := m.startWork(ctx)(worker.Fetch(ctx, sector, storiface.FTSealed|storiface.FTCache, storiface.PathSealing, storiface.AcquireCopy)); err != nil { return xerrors.Errorf("copy sealed/cache sector data: %w", err) } if foundUnsealed { - if _, err := m.waitResult(ctx)(worker.Fetch(ctx, sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove)); err != nil { + if _, err := m.startWork(ctx)(worker.Fetch(ctx, sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove)); err != nil { return xerrors.Errorf("copy unsealed sector data: %w", err) } } @@ -294,7 +306,7 @@ func (m *Manager) ReadPiece(ctx context.Context, sink io.Writer, sector abi.Sect return xerrors.Errorf("cannot unseal piece (sector: %d, offset: %d size: %d) - unsealed cid is undefined", sector, offset, size) } err = m.sched.Schedule(ctx, sector, sealtasks.TTUnseal, selector, unsealFetch, func(ctx context.Context, w Worker) error { - _, err := m.waitResult(ctx)(w.UnsealPiece(ctx, sector, offset, size, ticket, unsealed)) + _, err := m.startWork(ctx)(w.UnsealPiece(ctx, sector, offset, size, ticket, unsealed)) return err }) if err != nil { @@ -303,7 +315,7 @@ func (m *Manager) ReadPiece(ctx context.Context, sink io.Writer, sector abi.Sect selector = newExistingSelector(m.index, sector, storiface.FTUnsealed, false) - err = m.sched.Schedule(ctx, sector, sealtasks.TTReadUnsealed, selector, schedFetch(m.waitResult, sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove), + err = m.sched.Schedule(ctx, sector, sealtasks.TTReadUnsealed, selector, schedFetch(m.startWork, sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove), m.readPiece(sink, sector, offset, size, &readOk)) if err != nil { return xerrors.Errorf("reading piece from sealed sector: %w", err) @@ -339,7 +351,7 @@ func (m *Manager) AddPiece(ctx context.Context, sector abi.SectorID, existingPie var out abi.PieceInfo err = m.sched.Schedule(ctx, sector, sealtasks.TTAddPiece, selector, schedNop, func(ctx context.Context, w Worker) error { - p, err := m.waitResult(ctx)(w.AddPiece(ctx, sector, existingPieces, sz, r)) + p, err := m.startWork(ctx)(w.AddPiece(ctx, sector, existingPieces, sz, r)) if err != nil { return err } @@ -354,6 +366,25 @@ func (m *Manager) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticke ctx, cancel := context.WithCancel(ctx) defer cancel() + wk, wait, err := m.getWork(ctx, "PreCommit1", sector, ticket, pieces) + if err != nil { + return nil, xerrors.Errorf("getWork: %w", err) + } + + waitRes := func() { + p, werr := m.waitWork(ctx, wk) + if werr != nil { + err = werr + return + } + out = p.(storage.PreCommit1Out) + } + + if wait { // already in progress + waitRes() + return + } + if err := m.index.StorageLock(ctx, sector, storiface.FTUnsealed, storiface.FTSealed|storiface.FTCache); err != nil { return nil, xerrors.Errorf("acquiring sector lock: %w", err) } @@ -362,12 +393,13 @@ func (m *Manager) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticke selector := newAllocSelector(m.index, storiface.FTCache|storiface.FTSealed, storiface.PathSealing) - err = m.sched.Schedule(ctx, sector, sealtasks.TTPreCommit1, selector, schedFetch(m.waitResult, sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { - p, err := m.waitResult(ctx)(w.SealPreCommit1(ctx, sector, ticket, pieces)) + err = m.sched.Schedule(ctx, sector, sealtasks.TTPreCommit1, selector, m.schedFetch(sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { + err := m.startWork(ctx, wk)(w.SealPreCommit1(ctx, sector, ticket, pieces)) if err != nil { return err } - out = p.(storage.PreCommit1Out) + waitRes() + return nil }) @@ -384,8 +416,8 @@ func (m *Manager) SealPreCommit2(ctx context.Context, sector abi.SectorID, phase selector := newExistingSelector(m.index, sector, storiface.FTCache|storiface.FTSealed, true) - err = m.sched.Schedule(ctx, sector, sealtasks.TTPreCommit2, selector, schedFetch(m.waitResult, sector, storiface.FTCache|storiface.FTSealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { - p, err := m.waitResult(ctx)(w.SealPreCommit2(ctx, sector, phase1Out)) + err = m.sched.Schedule(ctx, sector, sealtasks.TTPreCommit2, selector, schedFetch(m.startWork, sector, storiface.FTCache|storiface.FTSealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { + p, err := m.startWork(ctx)(w.SealPreCommit2(ctx, sector, phase1Out)) if err != nil { return err } @@ -408,8 +440,8 @@ func (m *Manager) SealCommit1(ctx context.Context, sector abi.SectorID, ticket a // generally very cheap / fast, and transferring data is not worth the effort selector := newExistingSelector(m.index, sector, storiface.FTCache|storiface.FTSealed, false) - err = m.sched.Schedule(ctx, sector, sealtasks.TTCommit1, selector, schedFetch(m.waitResult, sector, storiface.FTCache|storiface.FTSealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { - p, err := m.waitResult(ctx)(w.SealCommit1(ctx, sector, ticket, seed, pieces, cids)) + err = m.sched.Schedule(ctx, sector, sealtasks.TTCommit1, selector, schedFetch(m.startWork, sector, storiface.FTCache|storiface.FTSealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { + p, err := m.startWork(ctx)(w.SealCommit1(ctx, sector, ticket, seed, pieces, cids)) if err != nil { return err } @@ -423,7 +455,7 @@ func (m *Manager) SealCommit2(ctx context.Context, sector abi.SectorID, phase1Ou selector := newTaskSelector() err = m.sched.Schedule(ctx, sector, sealtasks.TTCommit2, selector, schedNop, func(ctx context.Context, w Worker) error { - p, err := m.waitResult(ctx)(w.SealCommit2(ctx, sector, phase1Out)) + p, err := m.startWork(ctx)(w.SealCommit2(ctx, sector, phase1Out)) if err != nil { return err } @@ -457,9 +489,9 @@ func (m *Manager) FinalizeSector(ctx context.Context, sector abi.SectorID, keepU selector := newExistingSelector(m.index, sector, storiface.FTCache|storiface.FTSealed, false) err := m.sched.Schedule(ctx, sector, sealtasks.TTFinalize, selector, - schedFetch(m.waitResult, sector, storiface.FTCache|storiface.FTSealed|unsealed, storiface.PathSealing, storiface.AcquireMove), + schedFetch(m.startWork, sector, storiface.FTCache|storiface.FTSealed|unsealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { - _, err := m.waitResult(ctx)(w.FinalizeSector(ctx, sector, keepUnsealed)) + _, err := m.startWork(ctx)(w.FinalizeSector(ctx, sector, keepUnsealed)) return err }) if err != nil { @@ -475,9 +507,9 @@ func (m *Manager) FinalizeSector(ctx context.Context, sector abi.SectorID, keepU } err = m.sched.Schedule(ctx, sector, sealtasks.TTFetch, fetchSel, - schedFetch(m.waitResult, sector, storiface.FTCache|storiface.FTSealed|moveUnsealed, storiface.PathStorage, storiface.AcquireMove), + schedFetch(m.startWork, sector, storiface.FTCache|storiface.FTSealed|moveUnsealed, storiface.PathStorage, storiface.AcquireMove), func(ctx context.Context, w Worker) error { - _, err := m.waitResult(ctx)(w.MoveStorage(ctx, sector, storiface.FTCache|storiface.FTSealed|moveUnsealed)) + _, err := m.startWork(ctx)(w.MoveStorage(ctx, sector, storiface.FTCache|storiface.FTSealed|moveUnsealed)) return err }) if err != nil { @@ -515,68 +547,6 @@ func (m *Manager) Remove(ctx context.Context, sector abi.SectorID) error { return err } -type waitFunc func(ctx context.Context) func(callID storiface.CallID, err error) (interface{}, error) - -func (m *Manager) waitResult(ctx context.Context) func(callID storiface.CallID, err error) (interface{}, error) { - return func(callID storiface.CallID, err error) (interface{}, error) { - if err != nil { - return nil, err - } - - m.resLk.Lock() - res, ok := m.results[callID] - if ok { - m.resLk.Unlock() - return res.r, res.err - } - - ch, ok := m.waitRes[callID] - if !ok { - ch = make(chan struct{}) - m.waitRes[callID] = ch - } - m.resLk.Unlock() - - select { - case <-ch: - m.resLk.Lock() - defer m.resLk.Unlock() - - res := m.results[callID] - delete(m.results, callID) - - return res.r, res.err - case <-ctx.Done(): - return nil, xerrors.Errorf("waiting for result: %w", ctx.Err()) - } - } -} - -func (m *Manager) returnResult(callID storiface.CallID, r interface{}, serr string) error { - m.resLk.Lock() - defer m.resLk.Unlock() - - _, ok := m.results[callID] - if ok { - return xerrors.Errorf("result for call %v already reported") - } - - var err error - if serr != "" { - err = errors.New(serr) - } - - m.results[callID] = result{ - r: r, - err: err, - } - - close(m.waitRes[callID]) - delete(m.waitRes, callID) - - return nil -} - func (m *Manager) ReturnAddPiece(ctx context.Context, callID storiface.CallID, pi abi.PieceInfo, err string) error { return m.returnResult(callID, pi, err) } diff --git a/extern/sector-storage/manager_calltracker.go b/extern/sector-storage/manager_calltracker.go new file mode 100644 index 000000000..d209cc1f0 --- /dev/null +++ b/extern/sector-storage/manager_calltracker.go @@ -0,0 +1,271 @@ +package sectorstorage + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "golang.org/x/xerrors" + "io" + + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" +) + +type workID struct { + Method string + Params string // json [...params] +} + +func (w *workID) String() string { + return fmt.Sprintf("%s(%s)", w.Method, w.Params) +} + +var _ fmt.Stringer = &workID{} + +type WorkStatus string +const ( + wsStarted WorkStatus = "started" // task started, not scheduled/running on a worker yet + wsRunning WorkStatus = "running" // task running on a worker, waiting for worker return + wsDone WorkStatus = "done" // task returned from the worker, results available +) + +type WorkState struct { + Status WorkStatus + + WorkerCall storiface.CallID // Set when entering wsRunning + WorkError string // Status = wsDone, set when failed to start work +} + +func (w *WorkState) UnmarshalCBOR(reader io.Reader) error { + panic("implement me") +} + +func newWorkID(method string, params ...interface{}) (workID, error) { + pb, err := json.Marshal(params) + if err != nil { + return workID{}, xerrors.Errorf("marshaling work params: %w", err) + } + + return workID{ + Method: method, + Params: string(pb), + }, nil +} + +// returns wait=true when the task is already tracked/running +func (m *Manager) getWork(ctx context.Context, method string, params ...interface{}) (wid workID, wait bool, err error) { + wid, err = newWorkID(method, params) + if err != nil { + return workID{}, false, xerrors.Errorf("creating workID: %w", err) + } + + m.workLk.Lock() + defer m.workLk.Unlock() + + have, err := m.work.Has(wid) + if err != nil { + return workID{}, false, xerrors.Errorf("failed to check if the task is already tracked: %w", err) + } + + if !have { + err := m.work.Begin(wid, WorkState{ + Status: wsStarted, + }) + if err != nil { + return workID{}, false, xerrors.Errorf("failed to track task start: %w", err) + } + + return wid, false, nil + } + + // already started + + return wid, true, nil +} + +func (m *Manager) startWork(ctx context.Context, wk workID) func(callID storiface.CallID, err error) error { + return func(callID storiface.CallID, err error) error { + m.workLk.Lock() + defer m.workLk.Unlock() + + if err != nil { + merr := m.work.Get(wk).Mutate(func(ws *WorkState) error { + ws.Status = wsDone + ws.WorkError = err.Error() + return nil + }) + + if merr != nil { + return xerrors.Errorf("failed to start work and to track the error; merr: %+v, err: %w", merr, err) + } + return err + } + + err = m.work.Get(wk).Mutate(func(ws *WorkState) error { + _, ok := m.results[wk] + if ok { + log.Warn("work returned before we started tracking it") + ws.Status = wsDone + } else { + ws.Status = wsRunning + } + ws.WorkerCall = callID + return nil + }) + if err != nil { + return xerrors.Errorf("registering running work: %w", err) + } + + m.callToWork[callID] = wk + + return nil + } +} + +func (m *Manager) waitWork(ctx context.Context, wid workID) (interface{}, error) { + m.workLk.Lock() + + var ws WorkState + if err := m.work.Get(wid).Get(&ws); err != nil { + m.workLk.Unlock() + return nil, xerrors.Errorf("getting work status: %w", err) + } + + if ws.Status == wsStarted { + m.workLk.Unlock() + return nil, xerrors.Errorf("waitWork called for work in 'started' state") + } + + // sanity check + wk := m.callToWork[ws.WorkerCall] + if wk != wid { + m.workLk.Unlock() + return nil, xerrors.Errorf("wrong callToWork mapping for call %s; expected %s, got %s", ws.WorkerCall, wid, wk) + } + + // make sure we don't have the result ready + cr, ok := m.callRes[ws.WorkerCall] + if ok { + delete(m.callToWork, ws.WorkerCall) + + if len(cr) == 1 { + err := m.work.Get(wk).End() + if err != nil { + m.workLk.Unlock() + // Not great, but not worth discarding potentially multi-hour computation over this + log.Errorf("marking work as done: %+v", err) + } + + res := <- cr + delete(m.callRes, ws.WorkerCall) + + m.workLk.Unlock() + return res.r, res.err + } + + m.workLk.Unlock() + return nil, xerrors.Errorf("something else in waiting on callRes") + } + + ch, ok := m.waitRes[wid] + if !ok { + ch = make(chan struct{}) + m.waitRes[wid] = ch + } + m.workLk.Unlock() + + select { + case <-ch: + m.workLk.Lock() + defer m.workLk.Unlock() + + res := m.results[wid] + delete(m.results, wid) + + err := m.work.Get(wk).End() + if err != nil { + // Not great, but not worth discarding potentially multi-hour computation over this + log.Errorf("marking work as done: %+v", err) + } + + return res.r, res.err + case <-ctx.Done(): + return nil, xerrors.Errorf("waiting for work result: %w", ctx.Err()) + } +} + +func (m *Manager) waitCall(ctx context.Context, callID storiface.CallID) (interface{}, error) { + m.workLk.Lock() + _, ok := m.callToWork[callID] + if ok { + m.workLk.Unlock() + return nil, xerrors.Errorf("can't wait for calls related to work") + } + + ch, ok := m.callRes[callID] + if !ok { + ch = make(chan result) + m.callRes[callID] = ch + } + m.workLk.Unlock() + + defer func() { + m.workLk.Lock() + defer m.workLk.Unlock() + + delete(m.callRes, callID) + }() + + select { + case res := <-ch: + return res.r, res.err + case <-ctx.Done(): + return nil, xerrors.Errorf("waiting for call result: %w", ctx.Err()) + } +} + +func (m *Manager) returnResult(callID storiface.CallID, r interface{}, serr string) error { + var err error + if serr != "" { + err = errors.New(serr) + } + + res := result{ + r: r, + err: err, + } + + m.workLk.Lock() + defer m.workLk.Unlock() + + wid, ok := m.callToWork[callID] + if !ok { + rch, ok := m.callRes[callID] + if !ok { + rch = make(chan result, 1) + m.callRes[callID] = rch + } + + if len(rch) > 0 { + return xerrors.Errorf("callRes channel already has a response") + } + if cap(rch) == 0 { + return xerrors.Errorf("expected rch to be buffered") + } + + rch <- res + return nil + } + + _, ok = m.results[wid] + if ok { + return xerrors.Errorf("result for call %v already reported") + } + + m.results[wid] = res + + close(m.waitRes[wid]) + delete(m.waitRes, wid) + + return nil +} diff --git a/extern/sector-storage/calltracker.go b/extern/sector-storage/worker_calltracker.go similarity index 71% rename from extern/sector-storage/calltracker.go rename to extern/sector-storage/worker_calltracker.go index 8c5aff577..56909e68c 100644 --- a/extern/sector-storage/calltracker.go +++ b/extern/sector-storage/worker_calltracker.go @@ -6,7 +6,7 @@ import ( "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) -type callTracker struct { +type workerCallTracker struct { st *statestore.StateStore // by CallID } @@ -25,13 +25,13 @@ type Call struct { Result []byte } -func (wt *callTracker) onStart(ci storiface.CallID) error { +func (wt *workerCallTracker) onStart(ci storiface.CallID) error { return wt.st.Begin(ci, &Call{ State: CallStarted, }) } -func (wt *callTracker) onDone(ci storiface.CallID, ret []byte) error { +func (wt *workerCallTracker) onDone(ci storiface.CallID, ret []byte) error { st := wt.st.Get(ci) return st.Mutate(func(cs *Call) error { cs.State = CallDone @@ -40,7 +40,7 @@ func (wt *callTracker) onDone(ci storiface.CallID, ret []byte) error { }) } -func (wt *callTracker) onReturned(ci storiface.CallID) error { +func (wt *workerCallTracker) onReturned(ci storiface.CallID) error { st := wt.st.Get(ci) return st.End() } diff --git a/extern/sector-storage/localworker.go b/extern/sector-storage/worker_local.go similarity index 99% rename from extern/sector-storage/localworker.go rename to extern/sector-storage/worker_local.go index 0a1a02397..67b9df5e1 100644 --- a/extern/sector-storage/localworker.go +++ b/extern/sector-storage/worker_local.go @@ -38,7 +38,7 @@ type LocalWorker struct { sindex stores.SectorIndex ret storiface.WorkerReturn - ct *callTracker + ct *workerCallTracker acceptTasks map[sealtasks.TaskType]struct{} } @@ -57,7 +57,7 @@ func NewLocalWorker(wcfg WorkerConfig, store stores.Store, local *stores.Local, sindex: sindex, ret: ret, - ct: &callTracker{ + ct: &workerCallTracker{ st: cst, }, acceptTasks: acceptTasks, diff --git a/extern/sector-storage/work_tracker.go b/extern/sector-storage/worker_tracked.go similarity index 100% rename from extern/sector-storage/work_tracker.go rename to extern/sector-storage/worker_tracked.go diff --git a/gen/main.go b/gen/main.go index c7ae5bd57..95ace5583 100644 --- a/gen/main.go +++ b/gen/main.go @@ -77,6 +77,7 @@ func main() { err = gen.WriteMapEncodersToFile("./extern/sector-storage/cbor_gen.go", "sectorstorage", sectorstorage.Call{}, + sectorstorage.WorkState{}, ) if err != nil { fmt.Println(err) From 5e09581256ee57deab2d71df2d5052d80e311e24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 16 Sep 2020 22:33:49 +0200 Subject: [PATCH 010/313] sectorstorage: get new work tracker to run --- cmd/lotus-storage-miner/init.go | 3 +- extern/sector-storage/cbor_gen.go | 148 +++++++++++++++++++ extern/sector-storage/manager.go | 111 ++++++++++---- extern/sector-storage/manager_calltracker.go | 27 +++- extern/sector-storage/manager_test.go | 21 ++- extern/sector-storage/storiface/cbor_gen.go | 142 ++++++++++++++++++ gen/main.go | 11 +- lotuspond/front/src/chain/methods.json | 3 +- node/modules/storageminer.go | 4 +- 9 files changed, 425 insertions(+), 45 deletions(-) create mode 100644 extern/sector-storage/storiface/cbor_gen.go diff --git a/cmd/lotus-storage-miner/init.go b/cmd/lotus-storage-miner/init.go index 462a54985..c7bbf09a7 100644 --- a/cmd/lotus-storage-miner/init.go +++ b/cmd/lotus-storage-miner/init.go @@ -444,6 +444,7 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api lapi.FullNode, } wsts := statestore.New(namespace.Wrap(mds, modules.WorkerCallsPrefix)) + smsts := statestore.New(namespace.Wrap(mds, modules.ManagerWorkPrefix)) smgr, err := sectorstorage.New(ctx, lr, stores.NewIndex(), &ffiwrapper.Config{ SealProofType: spt, @@ -454,7 +455,7 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api lapi.FullNode, AllowPreCommit2: true, AllowCommit: true, AllowUnseal: true, - }, nil, sa, wsts) + }, nil, sa, wsts, smsts) if err != nil { return err } diff --git a/extern/sector-storage/cbor_gen.go b/extern/sector-storage/cbor_gen.go index c20df2157..137e32650 100644 --- a/extern/sector-storage/cbor_gen.go +++ b/extern/sector-storage/cbor_gen.go @@ -143,3 +143,151 @@ func (t *Call) UnmarshalCBOR(r io.Reader) error { return nil } +func (t *WorkState) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write([]byte{163}); err != nil { + return err + } + + scratch := make([]byte, 9) + + // t.Status (sectorstorage.WorkStatus) (string) + if len("Status") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"Status\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("Status"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("Status")); err != nil { + return err + } + + if len(t.Status) > cbg.MaxLength { + return xerrors.Errorf("Value in field t.Status was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len(t.Status))); err != nil { + return err + } + if _, err := io.WriteString(w, string(t.Status)); err != nil { + return err + } + + // t.WorkerCall (storiface.CallID) (struct) + if len("WorkerCall") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"WorkerCall\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("WorkerCall"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("WorkerCall")); err != nil { + return err + } + + if err := t.WorkerCall.MarshalCBOR(w); err != nil { + return err + } + + // t.WorkError (string) (string) + if len("WorkError") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"WorkError\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("WorkError"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("WorkError")); err != nil { + return err + } + + if len(t.WorkError) > cbg.MaxLength { + return xerrors.Errorf("Value in field t.WorkError was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len(t.WorkError))); err != nil { + return err + } + if _, err := io.WriteString(w, string(t.WorkError)); err != nil { + return err + } + return nil +} + +func (t *WorkState) UnmarshalCBOR(r io.Reader) error { + *t = WorkState{} + + br := cbg.GetPeeker(r) + scratch := make([]byte, 8) + + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("WorkState: map struct too large (%d)", extra) + } + + var name string + n := extra + + for i := uint64(0); i < n; i++ { + + { + sval, err := cbg.ReadStringBuf(br, scratch) + if err != nil { + return err + } + + name = string(sval) + } + + switch name { + // t.Status (sectorstorage.WorkStatus) (string) + case "Status": + + { + sval, err := cbg.ReadStringBuf(br, scratch) + if err != nil { + return err + } + + t.Status = WorkStatus(sval) + } + // t.WorkerCall (storiface.CallID) (struct) + case "WorkerCall": + + { + + if err := t.WorkerCall.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.WorkerCall: %w", err) + } + + } + // t.WorkError (string) (string) + case "WorkError": + + { + sval, err := cbg.ReadStringBuf(br, scratch) + if err != nil { + return err + } + + t.WorkError = string(sval) + } + + default: + return fmt.Errorf("unknown struct field %d: '%s'", i, name) + } + } + + return nil +} diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index 14ec875e9..a3f04037d 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -130,11 +130,11 @@ func New(ctx context.Context, ls stores.LocalStorage, si stores.SectorIndex, cfg Prover: prover, - work: mss, - workWait: map[workID]*sync.Cond{}, + work: mss, callToWork: map[storiface.CallID]workID{}, - results: map[workID]result{}, - waitRes: map[workID]chan struct{}{}, + callRes: map[storiface.CallID]chan result{}, + results: map[workID]result{}, + waitRes: map[workID]chan struct{}{}, } // TODO: remove all non-running work from the work tracker @@ -223,14 +223,14 @@ func schedNop(context.Context, Worker) error { func (m *Manager) schedFetch(sector abi.SectorID, ft storiface.SectorFileType, ptype storiface.PathType, am storiface.AcquireMode) func(context.Context, Worker) error { return func(ctx context.Context, worker Worker) error { - _, err := m.startWork(ctx)(worker.Fetch(ctx, sector, ft, ptype, am)) + _, err := m.waitSimpleCall(ctx)(worker.Fetch(ctx, sector, ft, ptype, am)) return err } } func (m *Manager) readPiece(sink io.Writer, sector abi.SectorID, offset storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, rok *bool) func(ctx context.Context, w Worker) error { return func(ctx context.Context, w Worker) error { - r, err := m.startWork(ctx)(w.ReadPiece(ctx, sink, sector, offset, size)) + r, err := m.waitSimpleCall(ctx)(w.ReadPiece(ctx, sink, sector, offset, size)) if err != nil { return err } @@ -263,7 +263,7 @@ func (m *Manager) tryReadUnsealedPiece(ctx context.Context, sink io.Writer, sect selector = newExistingSelector(m.index, sector, storiface.FTUnsealed, false) - err = m.sched.Schedule(ctx, sector, sealtasks.TTReadUnsealed, selector, schedFetch(m.startWork, sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove), + err = m.sched.Schedule(ctx, sector, sealtasks.TTReadUnsealed, selector, m.schedFetch(sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove), m.readPiece(sink, sector, offset, size, &readOk)) if err != nil { returnErr = xerrors.Errorf("reading piece from sealed sector: %w", err) @@ -290,12 +290,12 @@ func (m *Manager) ReadPiece(ctx context.Context, sink io.Writer, sector abi.Sect } unsealFetch := func(ctx context.Context, worker Worker) error { - if _, err := m.startWork(ctx)(worker.Fetch(ctx, sector, storiface.FTSealed|storiface.FTCache, storiface.PathSealing, storiface.AcquireCopy)); err != nil { + if _, err := m.waitSimpleCall(ctx)(worker.Fetch(ctx, sector, storiface.FTSealed|storiface.FTCache, storiface.PathSealing, storiface.AcquireCopy)); err != nil { return xerrors.Errorf("copy sealed/cache sector data: %w", err) } if foundUnsealed { - if _, err := m.startWork(ctx)(worker.Fetch(ctx, sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove)); err != nil { + if _, err := m.waitSimpleCall(ctx)(worker.Fetch(ctx, sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove)); err != nil { return xerrors.Errorf("copy unsealed sector data: %w", err) } } @@ -306,7 +306,8 @@ func (m *Manager) ReadPiece(ctx context.Context, sink io.Writer, sector abi.Sect return xerrors.Errorf("cannot unseal piece (sector: %d, offset: %d size: %d) - unsealed cid is undefined", sector, offset, size) } err = m.sched.Schedule(ctx, sector, sealtasks.TTUnseal, selector, unsealFetch, func(ctx context.Context, w Worker) error { - _, err := m.startWork(ctx)(w.UnsealPiece(ctx, sector, offset, size, ticket, unsealed)) + // TODO: make restartable + _, err := m.waitSimpleCall(ctx)(w.UnsealPiece(ctx, sector, offset, size, ticket, unsealed)) return err }) if err != nil { @@ -315,7 +316,7 @@ func (m *Manager) ReadPiece(ctx context.Context, sink io.Writer, sector abi.Sect selector = newExistingSelector(m.index, sector, storiface.FTUnsealed, false) - err = m.sched.Schedule(ctx, sector, sealtasks.TTReadUnsealed, selector, schedFetch(m.startWork, sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove), + err = m.sched.Schedule(ctx, sector, sealtasks.TTReadUnsealed, selector, m.schedFetch(sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove), m.readPiece(sink, sector, offset, size, &readOk)) if err != nil { return xerrors.Errorf("reading piece from sealed sector: %w", err) @@ -351,7 +352,7 @@ func (m *Manager) AddPiece(ctx context.Context, sector abi.SectorID, existingPie var out abi.PieceInfo err = m.sched.Schedule(ctx, sector, sealtasks.TTAddPiece, selector, schedNop, func(ctx context.Context, w Worker) error { - p, err := m.startWork(ctx)(w.AddPiece(ctx, sector, existingPieces, sz, r)) + p, err := m.waitSimpleCall(ctx)(w.AddPiece(ctx, sector, existingPieces, sz, r)) if err != nil { return err } @@ -398,8 +399,8 @@ func (m *Manager) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticke if err != nil { return err } - waitRes() + waitRes() return nil }) @@ -410,18 +411,38 @@ func (m *Manager) SealPreCommit2(ctx context.Context, sector abi.SectorID, phase ctx, cancel := context.WithCancel(ctx) defer cancel() + wk, wait, err := m.getWork(ctx, "PreCommit2", sector, phase1Out) + if err != nil { + return storage.SectorCids{}, xerrors.Errorf("getWork: %w", err) + } + + waitRes := func() { + p, werr := m.waitWork(ctx, wk) + if werr != nil { + err = werr + return + } + out = p.(storage.SectorCids) + } + + if wait { // already in progress + waitRes() + return + } + if err := m.index.StorageLock(ctx, sector, storiface.FTSealed, storiface.FTCache); err != nil { return storage.SectorCids{}, xerrors.Errorf("acquiring sector lock: %w", err) } selector := newExistingSelector(m.index, sector, storiface.FTCache|storiface.FTSealed, true) - err = m.sched.Schedule(ctx, sector, sealtasks.TTPreCommit2, selector, schedFetch(m.startWork, sector, storiface.FTCache|storiface.FTSealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { - p, err := m.startWork(ctx)(w.SealPreCommit2(ctx, sector, phase1Out)) + err = m.sched.Schedule(ctx, sector, sealtasks.TTPreCommit2, selector, m.schedFetch(sector, storiface.FTCache|storiface.FTSealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { + err := m.startWork(ctx, wk)(w.SealPreCommit2(ctx, sector, phase1Out)) if err != nil { return err } - out = p.(storage.SectorCids) + + waitRes() return nil }) return out, err @@ -431,6 +452,25 @@ func (m *Manager) SealCommit1(ctx context.Context, sector abi.SectorID, ticket a ctx, cancel := context.WithCancel(ctx) defer cancel() + wk, wait, err := m.getWork(ctx, "Commit1", sector, ticket, seed, pieces, cids) + if err != nil { + return storage.Commit1Out{}, xerrors.Errorf("getWork: %w", err) + } + + waitRes := func() { + p, werr := m.waitWork(ctx, wk) + if werr != nil { + err = werr + return + } + out = p.(storage.Commit1Out) + } + + if wait { // already in progress + waitRes() + return + } + if err := m.index.StorageLock(ctx, sector, storiface.FTSealed, storiface.FTCache); err != nil { return storage.Commit1Out{}, xerrors.Errorf("acquiring sector lock: %w", err) } @@ -440,26 +480,47 @@ func (m *Manager) SealCommit1(ctx context.Context, sector abi.SectorID, ticket a // generally very cheap / fast, and transferring data is not worth the effort selector := newExistingSelector(m.index, sector, storiface.FTCache|storiface.FTSealed, false) - err = m.sched.Schedule(ctx, sector, sealtasks.TTCommit1, selector, schedFetch(m.startWork, sector, storiface.FTCache|storiface.FTSealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { - p, err := m.startWork(ctx)(w.SealCommit1(ctx, sector, ticket, seed, pieces, cids)) + err = m.sched.Schedule(ctx, sector, sealtasks.TTCommit1, selector, m.schedFetch(sector, storiface.FTCache|storiface.FTSealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { + err := m.startWork(ctx, wk)(w.SealCommit1(ctx, sector, ticket, seed, pieces, cids)) if err != nil { return err } - out = p.(storage.Commit1Out) + + waitRes() return nil }) return out, err } func (m *Manager) SealCommit2(ctx context.Context, sector abi.SectorID, phase1Out storage.Commit1Out) (out storage.Proof, err error) { + wk, wait, err := m.getWork(ctx, "Commit2", sector, phase1Out) + if err != nil { + return storage.Proof{}, xerrors.Errorf("getWork: %w", err) + } + + waitRes := func() { + p, werr := m.waitWork(ctx, wk) + if werr != nil { + err = werr + return + } + out = p.(storage.Proof) + } + + if wait { // already in progress + waitRes() + return + } + selector := newTaskSelector() err = m.sched.Schedule(ctx, sector, sealtasks.TTCommit2, selector, schedNop, func(ctx context.Context, w Worker) error { - p, err := m.startWork(ctx)(w.SealCommit2(ctx, sector, phase1Out)) + err := m.startWork(ctx, wk)(w.SealCommit2(ctx, sector, phase1Out)) if err != nil { return err } - out = p.(storage.Proof) + + waitRes() return nil }) @@ -489,9 +550,9 @@ func (m *Manager) FinalizeSector(ctx context.Context, sector abi.SectorID, keepU selector := newExistingSelector(m.index, sector, storiface.FTCache|storiface.FTSealed, false) err := m.sched.Schedule(ctx, sector, sealtasks.TTFinalize, selector, - schedFetch(m.startWork, sector, storiface.FTCache|storiface.FTSealed|unsealed, storiface.PathSealing, storiface.AcquireMove), + m.schedFetch(sector, storiface.FTCache|storiface.FTSealed|unsealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { - _, err := m.startWork(ctx)(w.FinalizeSector(ctx, sector, keepUnsealed)) + _, err := m.waitSimpleCall(ctx)(w.FinalizeSector(ctx, sector, keepUnsealed)) return err }) if err != nil { @@ -507,9 +568,9 @@ func (m *Manager) FinalizeSector(ctx context.Context, sector abi.SectorID, keepU } err = m.sched.Schedule(ctx, sector, sealtasks.TTFetch, fetchSel, - schedFetch(m.startWork, sector, storiface.FTCache|storiface.FTSealed|moveUnsealed, storiface.PathStorage, storiface.AcquireMove), + m.schedFetch(sector, storiface.FTCache|storiface.FTSealed|moveUnsealed, storiface.PathStorage, storiface.AcquireMove), func(ctx context.Context, w Worker) error { - _, err := m.startWork(ctx)(w.MoveStorage(ctx, sector, storiface.FTCache|storiface.FTSealed|moveUnsealed)) + _, err := m.waitSimpleCall(ctx)(w.MoveStorage(ctx, sector, storiface.FTCache|storiface.FTSealed|moveUnsealed)) return err }) if err != nil { diff --git a/extern/sector-storage/manager_calltracker.go b/extern/sector-storage/manager_calltracker.go index d209cc1f0..8092f514a 100644 --- a/extern/sector-storage/manager_calltracker.go +++ b/extern/sector-storage/manager_calltracker.go @@ -2,11 +2,11 @@ package sectorstorage import ( "context" + "crypto/sha256" "encoding/json" "errors" "fmt" "golang.org/x/xerrors" - "io" "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) @@ -16,7 +16,7 @@ type workID struct { Params string // json [...params] } -func (w *workID) String() string { +func (w workID) String() string { return fmt.Sprintf("%s(%s)", w.Method, w.Params) } @@ -36,16 +36,17 @@ type WorkState struct { WorkError string // Status = wsDone, set when failed to start work } -func (w *WorkState) UnmarshalCBOR(reader io.Reader) error { - panic("implement me") -} - func newWorkID(method string, params ...interface{}) (workID, error) { pb, err := json.Marshal(params) if err != nil { return workID{}, xerrors.Errorf("marshaling work params: %w", err) } + if len(pb) > 256 { + s := sha256.Sum256(pb) + pb = s[:] + } + return workID{ Method: method, Params: string(pb), @@ -68,7 +69,7 @@ func (m *Manager) getWork(ctx context.Context, method string, params ...interfac } if !have { - err := m.work.Begin(wid, WorkState{ + err := m.work.Begin(wid, &WorkState{ Status: wsStarted, }) if err != nil { @@ -194,6 +195,16 @@ func (m *Manager) waitWork(ctx context.Context, wid workID) (interface{}, error) } } +func (m *Manager) waitSimpleCall(ctx context.Context) func(callID storiface.CallID, err error) (interface{}, error) { + return func(callID storiface.CallID, err error) (interface{}, error) { + if err != nil { + return nil, err + } + + return m.waitCall(ctx, callID) + } +} + func (m *Manager) waitCall(ctx context.Context, callID storiface.CallID) (interface{}, error) { m.workLk.Lock() _, ok := m.callToWork[callID] @@ -204,7 +215,7 @@ func (m *Manager) waitCall(ctx context.Context, callID storiface.CallID) (interf ch, ok := m.callRes[callID] if !ok { - ch = make(chan result) + ch = make(chan result, 1) m.callRes[callID] = ch } m.workLk.Unlock() diff --git a/extern/sector-storage/manager_test.go b/extern/sector-storage/manager_test.go index db32d655e..a4015c132 100644 --- a/extern/sector-storage/manager_test.go +++ b/extern/sector-storage/manager_test.go @@ -11,17 +11,19 @@ import ( "strings" "testing" + "github.com/google/uuid" + "github.com/ipfs/go-datastore" + logging "github.com/ipfs/go-log" + "github.com/stretchr/testify/require" + + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-statestore" + "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" "github.com/filecoin-project/lotus/extern/sector-storage/fsutil" "github.com/filecoin-project/lotus/extern/sector-storage/sealtasks" "github.com/filecoin-project/lotus/extern/sector-storage/stores" "github.com/filecoin-project/lotus/extern/sector-storage/storiface" - - "github.com/filecoin-project/go-state-types/abi" - - "github.com/google/uuid" - logging "github.com/ipfs/go-log" - "github.com/stretchr/testify/require" ) func init() { @@ -111,8 +113,11 @@ func newTestMgr(ctx context.Context, t *testing.T) (*Manager, *stores.Local, *st Prover: prover, - results: map[storiface.CallID]result{}, - waitRes: map[storiface.CallID]chan struct{}{}, + work: statestore.New(datastore.NewMapDatastore()), + callToWork: map[storiface.CallID]workID{}, + callRes: map[storiface.CallID]chan result{}, + results: map[workID]result{}, + waitRes: map[workID]chan struct{}{}, } go m.sched.runSched() diff --git a/extern/sector-storage/storiface/cbor_gen.go b/extern/sector-storage/storiface/cbor_gen.go new file mode 100644 index 000000000..0efbc125b --- /dev/null +++ b/extern/sector-storage/storiface/cbor_gen.go @@ -0,0 +1,142 @@ +// Code generated by github.com/whyrusleeping/cbor-gen. DO NOT EDIT. + +package storiface + +import ( + "fmt" + "io" + + cbg "github.com/whyrusleeping/cbor-gen" + xerrors "golang.org/x/xerrors" +) + +var _ = xerrors.Errorf + +func (t *CallID) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write([]byte{162}); err != nil { + return err + } + + scratch := make([]byte, 9) + + // t.Sector (abi.SectorID) (struct) + if len("Sector") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"Sector\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("Sector"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("Sector")); err != nil { + return err + } + + if err := t.Sector.MarshalCBOR(w); err != nil { + return err + } + + // t.ID (uuid.UUID) (array) + if len("ID") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"ID\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("ID"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("ID")); err != nil { + return err + } + + if len(t.ID) > cbg.ByteArrayMaxLen { + return xerrors.Errorf("Byte array in field t.ID was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajByteString, uint64(len(t.ID))); err != nil { + return err + } + + if _, err := w.Write(t.ID[:]); err != nil { + return err + } + return nil +} + +func (t *CallID) UnmarshalCBOR(r io.Reader) error { + *t = CallID{} + + br := cbg.GetPeeker(r) + scratch := make([]byte, 8) + + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("CallID: map struct too large (%d)", extra) + } + + var name string + n := extra + + for i := uint64(0); i < n; i++ { + + { + sval, err := cbg.ReadStringBuf(br, scratch) + if err != nil { + return err + } + + name = string(sval) + } + + switch name { + // t.Sector (abi.SectorID) (struct) + case "Sector": + + { + + if err := t.Sector.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.Sector: %w", err) + } + + } + // t.ID (uuid.UUID) (array) + case "ID": + + maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + + if extra > cbg.ByteArrayMaxLen { + return fmt.Errorf("t.ID: byte array too large (%d)", extra) + } + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + + if extra != 16 { + return fmt.Errorf("expected array to have 16 elements") + } + + t.ID = [16]uint8{} + + if _, err := io.ReadFull(br, t.ID[:]); err != nil { + return err + } + + default: + return fmt.Errorf("unknown struct field %d: '%s'", i, name) + } + } + + return nil +} diff --git a/gen/main.go b/gen/main.go index 95ace5583..c2adbb7a0 100644 --- a/gen/main.go +++ b/gen/main.go @@ -2,7 +2,6 @@ package main import ( "fmt" - sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage" "os" gen "github.com/whyrusleeping/cbor-gen" @@ -10,6 +9,8 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/exchange" "github.com/filecoin-project/lotus/chain/types" + sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "github.com/filecoin-project/lotus/node/hello" "github.com/filecoin-project/lotus/paychmgr" ) @@ -75,6 +76,14 @@ func main() { os.Exit(1) } + err = gen.WriteMapEncodersToFile("./extern/sector-storage/storiface/cbor_gen.go", "storiface", + storiface.CallID{}, + ) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + err = gen.WriteMapEncodersToFile("./extern/sector-storage/cbor_gen.go", "sectorstorage", sectorstorage.Call{}, sectorstorage.WorkState{}, diff --git a/lotuspond/front/src/chain/methods.json b/lotuspond/front/src/chain/methods.json index ad1076c84..ce4919cc4 100644 --- a/lotuspond/front/src/chain/methods.json +++ b/lotuspond/front/src/chain/methods.json @@ -23,7 +23,8 @@ "AddSigner", "RemoveSigner", "SwapSigner", - "ChangeNumApprovalsThreshold" + "ChangeNumApprovalsThreshold", + "LockBalance" ], "fil/1/paymentchannel": [ "Send", diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index e73ac06c3..af76861c1 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -517,13 +517,15 @@ func RetrievalProvider(h host.Host, miner *storage.Miner, sealer sectorstorage.S } var WorkerCallsPrefix = datastore.NewKey("/worker/calls") +var ManagerWorkPrefix = datastore.NewKey("/stmgr/calls") func SectorStorage(mctx helpers.MetricsCtx, lc fx.Lifecycle, ls stores.LocalStorage, si stores.SectorIndex, cfg *ffiwrapper.Config, sc sectorstorage.SealerConfig, urls sectorstorage.URLs, sa sectorstorage.StorageAuth, ds dtypes.MetadataDS) (*sectorstorage.Manager, error) { ctx := helpers.LifecycleCtx(mctx, lc) wsts := statestore.New(namespace.Wrap(ds, WorkerCallsPrefix)) + smsts := statestore.New(namespace.Wrap(ds, ManagerWorkPrefix)) - sst, err := sectorstorage.New(ctx, ls, si, cfg, sc, urls, sa, wsts) + sst, err := sectorstorage.New(ctx, ls, si, cfg, sc, urls, sa, wsts, smsts) if err != nil { return nil, err } From d9d644b27fd3a0a6de24542ec0e1fa6857ba2bba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 17 Sep 2020 00:35:09 +0200 Subject: [PATCH 011/313] sectorstorage: handle restarting manager, test that --- extern/sector-storage/cbor_gen.go | 152 ++++++++++++++++++- extern/sector-storage/manager.go | 16 +- extern/sector-storage/manager_calltracker.go | 65 ++++++-- extern/sector-storage/manager_test.go | 125 ++++++++++++++- extern/sector-storage/sched.go | 4 +- extern/sector-storage/testworker_test.go | 32 ++-- extern/sector-storage/worker_calltracker.go | 3 +- extern/sector-storage/worker_local.go | 18 +++ gen/main.go | 1 + 9 files changed, 374 insertions(+), 42 deletions(-) diff --git a/extern/sector-storage/cbor_gen.go b/extern/sector-storage/cbor_gen.go index 137e32650..7ec29c795 100644 --- a/extern/sector-storage/cbor_gen.go +++ b/extern/sector-storage/cbor_gen.go @@ -148,12 +148,28 @@ func (t *WorkState) MarshalCBOR(w io.Writer) error { _, err := w.Write(cbg.CborNull) return err } - if _, err := w.Write([]byte{163}); err != nil { + if _, err := w.Write([]byte{164}); err != nil { return err } scratch := make([]byte, 9) + // t.ID (sectorstorage.WorkID) (struct) + if len("ID") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"ID\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("ID"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("ID")); err != nil { + return err + } + + if err := t.ID.MarshalCBOR(w); err != nil { + return err + } + // t.Status (sectorstorage.WorkStatus) (string) if len("Status") > cbg.MaxLength { return xerrors.Errorf("Value in field \"Status\" was too long") @@ -251,7 +267,17 @@ func (t *WorkState) UnmarshalCBOR(r io.Reader) error { } switch name { - // t.Status (sectorstorage.WorkStatus) (string) + // t.ID (sectorstorage.WorkID) (struct) + case "ID": + + { + + if err := t.ID.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.ID: %w", err) + } + + } + // t.Status (sectorstorage.WorkStatus) (string) case "Status": { @@ -291,3 +317,125 @@ func (t *WorkState) UnmarshalCBOR(r io.Reader) error { return nil } +func (t *WorkID) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write([]byte{162}); err != nil { + return err + } + + scratch := make([]byte, 9) + + // t.Method (string) (string) + if len("Method") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"Method\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("Method"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("Method")); err != nil { + return err + } + + if len(t.Method) > cbg.MaxLength { + return xerrors.Errorf("Value in field t.Method was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len(t.Method))); err != nil { + return err + } + if _, err := io.WriteString(w, string(t.Method)); err != nil { + return err + } + + // t.Params (string) (string) + if len("Params") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"Params\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("Params"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("Params")); err != nil { + return err + } + + if len(t.Params) > cbg.MaxLength { + return xerrors.Errorf("Value in field t.Params was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len(t.Params))); err != nil { + return err + } + if _, err := io.WriteString(w, string(t.Params)); err != nil { + return err + } + return nil +} + +func (t *WorkID) UnmarshalCBOR(r io.Reader) error { + *t = WorkID{} + + br := cbg.GetPeeker(r) + scratch := make([]byte, 8) + + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("WorkID: map struct too large (%d)", extra) + } + + var name string + n := extra + + for i := uint64(0); i < n; i++ { + + { + sval, err := cbg.ReadStringBuf(br, scratch) + if err != nil { + return err + } + + name = string(sval) + } + + switch name { + // t.Method (string) (string) + case "Method": + + { + sval, err := cbg.ReadStringBuf(br, scratch) + if err != nil { + return err + } + + t.Method = string(sval) + } + // t.Params (string) (string) + case "Params": + + { + sval, err := cbg.ReadStringBuf(br, scratch) + if err != nil { + return err + } + + t.Params = string(sval) + } + + default: + return fmt.Errorf("unknown struct field %d: '%s'", i, name) + } + } + + return nil +} diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index a3f04037d..b23b3d46f 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -43,7 +43,7 @@ type Worker interface { // returns channel signalling worker shutdown Closing(context.Context) (<-chan struct{}, error) - Close() error + Close() error // TODO: do we need this? } type SectorManager interface { @@ -75,12 +75,12 @@ type Manager struct { workLk sync.Mutex work *statestore.StateStore - callToWork map[storiface.CallID]workID + callToWork map[storiface.CallID]WorkID // used when we get an early return and there's no callToWork mapping callRes map[storiface.CallID]chan result - results map[workID]result - waitRes map[workID]chan struct{} + results map[WorkID]result + waitRes map[WorkID]chan struct{} } type result struct { @@ -131,13 +131,13 @@ func New(ctx context.Context, ls stores.LocalStorage, si stores.SectorIndex, cfg Prover: prover, work: mss, - callToWork: map[storiface.CallID]workID{}, + callToWork: map[storiface.CallID]WorkID{}, callRes: map[storiface.CallID]chan result{}, - results: map[workID]result{}, - waitRes: map[workID]chan struct{}{}, + results: map[WorkID]result{}, + waitRes: map[WorkID]chan struct{}{}, } - // TODO: remove all non-running work from the work tracker + m.setupWorkTracker() go m.sched.runSched() diff --git a/extern/sector-storage/manager_calltracker.go b/extern/sector-storage/manager_calltracker.go index 8092f514a..f0dafda38 100644 --- a/extern/sector-storage/manager_calltracker.go +++ b/extern/sector-storage/manager_calltracker.go @@ -11,16 +11,16 @@ import ( "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) -type workID struct { +type WorkID struct { Method string Params string // json [...params] } -func (w workID) String() string { +func (w WorkID) String() string { return fmt.Sprintf("%s(%s)", w.Method, w.Params) } -var _ fmt.Stringer = &workID{} +var _ fmt.Stringer = &WorkID{} type WorkStatus string const ( @@ -30,16 +30,18 @@ const ( ) type WorkState struct { + ID WorkID + Status WorkStatus WorkerCall storiface.CallID // Set when entering wsRunning WorkError string // Status = wsDone, set when failed to start work } -func newWorkID(method string, params ...interface{}) (workID, error) { +func newWorkID(method string, params ...interface{}) (WorkID, error) { pb, err := json.Marshal(params) if err != nil { - return workID{}, xerrors.Errorf("marshaling work params: %w", err) + return WorkID{}, xerrors.Errorf("marshaling work params: %w", err) } if len(pb) > 256 { @@ -47,17 +49,55 @@ func newWorkID(method string, params ...interface{}) (workID, error) { pb = s[:] } - return workID{ + return WorkID{ Method: method, Params: string(pb), }, nil } +func (m *Manager) setupWorkTracker() { + m.workLk.Lock() + defer m.workLk.Unlock() + + var ids []WorkState + if err := m.work.List(&ids); err != nil { + log.Error("getting work IDs") // quite bad + return + } + + for _, st := range ids { + wid := st.ID + if err := m.work.Get(wid).Get(&st); err != nil { + log.Errorf("getting work state for %s", wid) + continue + } + + switch st.Status { + case wsStarted: + log.Warnf("dropping non-running work %s", wid) + + if err := m.work.Get(wid).End(); err != nil { + log.Errorf("cleannig up work state for %s", wid) + } + case wsDone: + // realistically this shouldn't ever happen as we return results + // immediately after getting them + log.Warnf("dropping done work, no result, wid %s", wid) + + if err := m.work.Get(wid).End(); err != nil { + log.Errorf("cleannig up work state for %s", wid) + } + case wsRunning: + m.callToWork[st.WorkerCall] = wid + } + } +} + // returns wait=true when the task is already tracked/running -func (m *Manager) getWork(ctx context.Context, method string, params ...interface{}) (wid workID, wait bool, err error) { +func (m *Manager) getWork(ctx context.Context, method string, params ...interface{}) (wid WorkID, wait bool, err error) { wid, err = newWorkID(method, params) if err != nil { - return workID{}, false, xerrors.Errorf("creating workID: %w", err) + return WorkID{}, false, xerrors.Errorf("creating WorkID: %w", err) } m.workLk.Lock() @@ -65,15 +105,16 @@ func (m *Manager) getWork(ctx context.Context, method string, params ...interfac have, err := m.work.Has(wid) if err != nil { - return workID{}, false, xerrors.Errorf("failed to check if the task is already tracked: %w", err) + return WorkID{}, false, xerrors.Errorf("failed to check if the task is already tracked: %w", err) } if !have { err := m.work.Begin(wid, &WorkState{ + ID: wid, Status: wsStarted, }) if err != nil { - return workID{}, false, xerrors.Errorf("failed to track task start: %w", err) + return WorkID{}, false, xerrors.Errorf("failed to track task start: %w", err) } return wid, false, nil @@ -84,7 +125,7 @@ func (m *Manager) getWork(ctx context.Context, method string, params ...interfac return wid, true, nil } -func (m *Manager) startWork(ctx context.Context, wk workID) func(callID storiface.CallID, err error) error { +func (m *Manager) startWork(ctx context.Context, wk WorkID) func(callID storiface.CallID, err error) error { return func(callID storiface.CallID, err error) error { m.workLk.Lock() defer m.workLk.Unlock() @@ -123,7 +164,7 @@ func (m *Manager) startWork(ctx context.Context, wk workID) func(callID storifac } } -func (m *Manager) waitWork(ctx context.Context, wid workID) (interface{}, error) { +func (m *Manager) waitWork(ctx context.Context, wid WorkID) (interface{}, error) { m.workLk.Lock() var ws WorkState diff --git a/extern/sector-storage/manager_test.go b/extern/sector-storage/manager_test.go index a4015c132..8ddfd822e 100644 --- a/extern/sector-storage/manager_test.go +++ b/extern/sector-storage/manager_test.go @@ -9,6 +9,7 @@ import ( "os" "path/filepath" "strings" + "sync" "testing" "github.com/google/uuid" @@ -83,7 +84,7 @@ func (t *testStorage) Stat(path string) (fsutil.FsStat, error) { var _ stores.LocalStorage = &testStorage{} -func newTestMgr(ctx context.Context, t *testing.T) (*Manager, *stores.Local, *stores.Remote, *stores.Index) { +func newTestMgr(ctx context.Context, t *testing.T, ds datastore.Datastore) (*Manager, *stores.Local, *stores.Remote, *stores.Index) { st := newTestStorage(t) defer st.cleanup() @@ -113,13 +114,15 @@ func newTestMgr(ctx context.Context, t *testing.T) (*Manager, *stores.Local, *st Prover: prover, - work: statestore.New(datastore.NewMapDatastore()), - callToWork: map[storiface.CallID]workID{}, + work: statestore.New(ds), + callToWork: map[storiface.CallID]WorkID{}, callRes: map[storiface.CallID]chan result{}, - results: map[workID]result{}, - waitRes: map[workID]chan struct{}{}, + results: map[WorkID]result{}, + waitRes: map[WorkID]chan struct{}{}, } + m.setupWorkTracker() + go m.sched.runSched() return m, lstor, stor, si @@ -129,7 +132,7 @@ func TestSimple(t *testing.T) { logging.SetAllLoggers(logging.LevelDebug) ctx := context.Background() - m, lstor, _, _ := newTestMgr(ctx, t) + m, lstor, _, _ := newTestMgr(ctx, t, datastore.NewMapDatastore()) localTasks := []sealtasks.TaskType{ sealtasks.TTAddPiece, sealtasks.TTPreCommit1, sealtasks.TTCommit1, sealtasks.TTFinalize, sealtasks.TTFetch, @@ -157,5 +160,113 @@ func TestSimple(t *testing.T) { _, err = m.SealPreCommit1(ctx, sid, ticket, pieces) require.NoError(t, err) - +} + +func TestRedoPC1(t *testing.T) { + logging.SetAllLoggers(logging.LevelDebug) + + ctx := context.Background() + m, lstor, _, _ := newTestMgr(ctx, t, datastore.NewMapDatastore()) + + localTasks := []sealtasks.TaskType{ + sealtasks.TTAddPiece, sealtasks.TTPreCommit1, sealtasks.TTCommit1, sealtasks.TTFinalize, sealtasks.TTFetch, + } + + tw := newTestWorker(WorkerConfig{ + SealProof: abi.RegisteredSealProof_StackedDrg2KiBV1, + TaskTypes: localTasks, + }, lstor, m) + + err := m.AddWorker(ctx, tw) + require.NoError(t, err) + + sid := abi.SectorID{Miner: 1000, Number: 1} + + pi, err := m.AddPiece(ctx, sid, nil, 1016, strings.NewReader(strings.Repeat("testthis", 127))) + require.NoError(t, err) + require.Equal(t, abi.PaddedPieceSize(1024), pi.Size) + + piz, err := m.AddPiece(ctx, sid, nil, 1016, bytes.NewReader(make([]byte, 1016)[:])) + require.NoError(t, err) + require.Equal(t, abi.PaddedPieceSize(1024), piz.Size) + + pieces := []abi.PieceInfo{pi, piz} + + ticket := abi.SealRandomness{9, 9, 9, 9, 9, 9, 9, 9} + + _, err = m.SealPreCommit1(ctx, sid, ticket, pieces) + require.NoError(t, err) + + _, err = m.SealPreCommit1(ctx, sid, ticket, pieces) + require.NoError(t, err) + + require.Equal(t, 2, tw.pc1s) +} + +func TestRestartManager(t *testing.T) { + logging.SetAllLoggers(logging.LevelDebug) + + ctx, done := context.WithCancel(context.Background()) + defer done() + + ds := datastore.NewMapDatastore() + + m, lstor, _, _ := newTestMgr(ctx, t, ds) + + localTasks := []sealtasks.TaskType{ + sealtasks.TTAddPiece, sealtasks.TTPreCommit1, sealtasks.TTCommit1, sealtasks.TTFinalize, sealtasks.TTFetch, + } + + tw := newTestWorker(WorkerConfig{ + SealProof: abi.RegisteredSealProof_StackedDrg2KiBV1, + TaskTypes: localTasks, + }, lstor, m) + + err := m.AddWorker(ctx, tw) + require.NoError(t, err) + + sid := abi.SectorID{Miner: 1000, Number: 1} + + pi, err := m.AddPiece(ctx, sid, nil, 1016, strings.NewReader(strings.Repeat("testthis", 127))) + require.NoError(t, err) + require.Equal(t, abi.PaddedPieceSize(1024), pi.Size) + + piz, err := m.AddPiece(ctx, sid, nil, 1016, bytes.NewReader(make([]byte, 1016)[:])) + require.NoError(t, err) + require.Equal(t, abi.PaddedPieceSize(1024), piz.Size) + + pieces := []abi.PieceInfo{pi, piz} + + ticket := abi.SealRandomness{0, 9, 9, 9, 9, 9, 9, 9} + + tw.pc1lk.Lock() + tw.pc1wait = &sync.WaitGroup{} + tw.pc1wait.Add(1) + + var cwg sync.WaitGroup + cwg.Add(1) + + var perr error + go func() { + defer cwg.Done() + _, perr = m.SealPreCommit1(ctx, sid, ticket, pieces) + }() + + tw.pc1wait.Wait() + + require.NoError(t, m.Close(ctx)) + tw.ret = nil + + cwg.Wait() + require.Error(t, perr) + + m, lstor, _, _ = newTestMgr(ctx, t, ds) + tw.ret = m // simulate jsonrpc auto-reconnect + + tw.pc1lk.Unlock() + + _, err = m.SealPreCommit1(ctx, sid, ticket, pieces) + require.NoError(t, err) + + require.Equal(t, 1, tw.pc1s) } diff --git a/extern/sector-storage/sched.go b/extern/sector-storage/sched.go index 8b8ef6d46..d757140b9 100644 --- a/extern/sector-storage/sched.go +++ b/extern/sector-storage/sched.go @@ -801,11 +801,11 @@ func (sh *scheduler) workerCleanup(wid WorkerID, w *workerHandle) { log.Debugf("dropWorker %d", wid) - go func() { + /*go func() { // TODO: just remove? if err := w.w.Close(); err != nil { log.Warnf("closing worker %d: %+v", err) } - }() + }()*/ } } diff --git a/extern/sector-storage/testworker_test.go b/extern/sector-storage/testworker_test.go index 0740f91d3..3decf9288 100644 --- a/extern/sector-storage/testworker_test.go +++ b/extern/sector-storage/testworker_test.go @@ -3,6 +3,7 @@ package sectorstorage import ( "context" "io" + "sync" "github.com/google/uuid" "github.com/ipfs/go-cid" @@ -22,6 +23,10 @@ type testWorker struct { ret storiface.WorkerReturn mockSeal *mock.SectorMgr + + pc1s int + pc1lk sync.Mutex + pc1wait *sync.WaitGroup } func newTestWorker(wcfg WorkerConfig, lstor *stores.Local, ret storiface.WorkerReturn) *testWorker { @@ -55,15 +60,6 @@ func (t *testWorker) asyncCall(sector abi.SectorID, work func(ci storiface.CallI return ci, nil } -func (t *testWorker) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storiface.CallID, error) { - return t.asyncCall(sector, func(ci storiface.CallID) { - p1o, err := t.mockSeal.SealPreCommit1(ctx, sector, ticket, pieces) - if err := t.ret.ReturnSealPreCommit1(ctx, ci, p1o, errstr(err)); err != nil { - log.Error(err) - } - }) -} - func (t *testWorker) NewSector(ctx context.Context, sector abi.SectorID) error { panic("implement me") } @@ -85,6 +81,24 @@ func (t *testWorker) AddPiece(ctx context.Context, sector abi.SectorID, pieceSiz }) } +func (t *testWorker) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storiface.CallID, error) { + return t.asyncCall(sector, func(ci storiface.CallID) { + t.pc1s++ + + if t.pc1wait != nil { + t.pc1wait.Done() + } + + t.pc1lk.Lock() + defer t.pc1lk.Unlock() + + p1o, err := t.mockSeal.SealPreCommit1(ctx, sector, ticket, pieces) + if err := t.ret.ReturnSealPreCommit1(ctx, ci, p1o, errstr(err)); err != nil { + log.Error(err) + } + }) +} + func (t *testWorker) SealPreCommit2(ctx context.Context, sector abi.SectorID, pc1o storage.PreCommit1Out) (storiface.CallID, error) { panic("implement me") } diff --git a/extern/sector-storage/worker_calltracker.go b/extern/sector-storage/worker_calltracker.go index 56909e68c..a16ee33be 100644 --- a/extern/sector-storage/worker_calltracker.go +++ b/extern/sector-storage/worker_calltracker.go @@ -21,8 +21,7 @@ const ( type Call struct { State CallState - // Params cbg.Deferred // TODO: support once useful - Result []byte + Result []byte // json bytes } func (wt *workerCallTracker) onStart(ci storiface.CallID) error { diff --git a/extern/sector-storage/worker_local.go b/extern/sector-storage/worker_local.go index 67b9df5e1..210ea340c 100644 --- a/extern/sector-storage/worker_local.go +++ b/extern/sector-storage/worker_local.go @@ -2,6 +2,7 @@ package sectorstorage import ( "context" + "encoding/json" "io" "os" "reflect" @@ -161,9 +162,26 @@ func (l *LocalWorker) asyncCall(ctx context.Context, sector abi.SectorID, rt ret go func() { res, err := work(ci) + + { + rb, err := json.Marshal(res) + if err != nil { + log.Errorf("tracking call (marshaling results): %+v", err) + } else { + if err := l.ct.onDone(ci, rb); err != nil { + log.Errorf("tracking call (done): %+v", err) + } + } + + } + if err := returnFunc[rt](ctx, ci, l.ret, res, err); err != nil { log.Errorf("return error: %s: %+v", rt, err) } + + if err := l.ct.onReturned(ci); err != nil { + log.Errorf("tracking call (done): %+v", err) + } }() return ci, nil diff --git a/gen/main.go b/gen/main.go index c2adbb7a0..65d5726ab 100644 --- a/gen/main.go +++ b/gen/main.go @@ -87,6 +87,7 @@ func main() { err = gen.WriteMapEncodersToFile("./extern/sector-storage/cbor_gen.go", "sectorstorage", sectorstorage.Call{}, sectorstorage.WorkState{}, + sectorstorage.WorkID{}, ) if err != nil { fmt.Println(err) From 17680fff55f42a4c1494ce2e94151faff82cad61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 17 Sep 2020 00:35:30 +0200 Subject: [PATCH 012/313] gofmt --- documentation/en/api-methods.md | 2 +- extern/sector-storage/manager.go | 4 ++-- extern/sector-storage/manager_calltracker.go | 5 +++-- extern/sector-storage/testworker_test.go | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index bc28f453e..d72beca98 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -211,7 +211,7 @@ Response: ```json { "Version": "string value", - "APIVersion": 3840, + "APIVersion": 3584, "BlockDelay": 42 } ``` diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index b23b3d46f..eecfd1b55 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -72,8 +72,8 @@ type Manager struct { storage.Prover - workLk sync.Mutex - work *statestore.StateStore + workLk sync.Mutex + work *statestore.StateStore callToWork map[storiface.CallID]WorkID // used when we get an early return and there's no callToWork mapping diff --git a/extern/sector-storage/manager_calltracker.go b/extern/sector-storage/manager_calltracker.go index f0dafda38..8e3e20c6e 100644 --- a/extern/sector-storage/manager_calltracker.go +++ b/extern/sector-storage/manager_calltracker.go @@ -23,6 +23,7 @@ func (w WorkID) String() string { var _ fmt.Stringer = &WorkID{} type WorkStatus string + const ( wsStarted WorkStatus = "started" // task started, not scheduled/running on a worker yet wsRunning WorkStatus = "running" // task running on a worker, waiting for worker return @@ -35,7 +36,7 @@ type WorkState struct { Status WorkStatus WorkerCall storiface.CallID // Set when entering wsRunning - WorkError string // Status = wsDone, set when failed to start work + WorkError string // Status = wsDone, set when failed to start work } func newWorkID(method string, params ...interface{}) (WorkID, error) { @@ -198,7 +199,7 @@ func (m *Manager) waitWork(ctx context.Context, wid WorkID) (interface{}, error) log.Errorf("marking work as done: %+v", err) } - res := <- cr + res := <-cr delete(m.callRes, ws.WorkerCall) m.workLk.Unlock() diff --git a/extern/sector-storage/testworker_test.go b/extern/sector-storage/testworker_test.go index 3decf9288..94a87cdd2 100644 --- a/extern/sector-storage/testworker_test.go +++ b/extern/sector-storage/testworker_test.go @@ -24,8 +24,8 @@ type testWorker struct { mockSeal *mock.SectorMgr - pc1s int - pc1lk sync.Mutex + pc1s int + pc1lk sync.Mutex pc1wait *sync.WaitGroup } From 03c3d8bdb32d4a28211f1b30cc09d3894b27ffbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 22 Sep 2020 00:52:33 +0200 Subject: [PATCH 013/313] workers: Return unfinished tasks on restart --- extern/sector-storage/cbor_gen.go | 64 +++++++++++++++- extern/sector-storage/manager_test.go | 69 ++++++++++++++++++ extern/sector-storage/teststorage_test.go | 81 +++++++++++++++++++++ extern/sector-storage/worker_calltracker.go | 12 ++- extern/sector-storage/worker_local.go | 75 ++++++++++++++----- node/modules/storageminer.go | 6 +- 6 files changed, 283 insertions(+), 24 deletions(-) create mode 100644 extern/sector-storage/teststorage_test.go diff --git a/extern/sector-storage/cbor_gen.go b/extern/sector-storage/cbor_gen.go index 7ec29c795..a291487f0 100644 --- a/extern/sector-storage/cbor_gen.go +++ b/extern/sector-storage/cbor_gen.go @@ -17,12 +17,51 @@ func (t *Call) MarshalCBOR(w io.Writer) error { _, err := w.Write(cbg.CborNull) return err } - if _, err := w.Write([]byte{162}); err != nil { + if _, err := w.Write([]byte{164}); err != nil { return err } scratch := make([]byte, 9) + // t.ID (storiface.CallID) (struct) + if len("ID") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"ID\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("ID"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("ID")); err != nil { + return err + } + + if err := t.ID.MarshalCBOR(w); err != nil { + return err + } + + // t.RetType (sectorstorage.ReturnType) (string) + if len("RetType") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"RetType\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("RetType"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("RetType")); err != nil { + return err + } + + if len(t.RetType) > cbg.MaxLength { + return xerrors.Errorf("Value in field t.RetType was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len(t.RetType))); err != nil { + return err + } + if _, err := io.WriteString(w, string(t.RetType)); err != nil { + return err + } + // t.State (sectorstorage.CallState) (uint64) if len("State") > cbg.MaxLength { return xerrors.Errorf("Value in field \"State\" was too long") @@ -98,7 +137,28 @@ func (t *Call) UnmarshalCBOR(r io.Reader) error { } switch name { - // t.State (sectorstorage.CallState) (uint64) + // t.ID (storiface.CallID) (struct) + case "ID": + + { + + if err := t.ID.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.ID: %w", err) + } + + } + // t.RetType (sectorstorage.ReturnType) (string) + case "RetType": + + { + sval, err := cbg.ReadStringBuf(br, scratch) + if err != nil { + return err + } + + t.RetType = ReturnType(sval) + } + // t.State (sectorstorage.CallState) (uint64) case "State": { diff --git a/extern/sector-storage/manager_test.go b/extern/sector-storage/manager_test.go index 8ddfd822e..9a47c3b55 100644 --- a/extern/sector-storage/manager_test.go +++ b/extern/sector-storage/manager_test.go @@ -11,6 +11,7 @@ import ( "strings" "sync" "testing" + "time" "github.com/google/uuid" "github.com/ipfs/go-datastore" @@ -203,6 +204,7 @@ func TestRedoPC1(t *testing.T) { require.Equal(t, 2, tw.pc1s) } +// Manager restarts in the middle of a task, restarts it, it completes func TestRestartManager(t *testing.T) { logging.SetAllLoggers(logging.LevelDebug) @@ -262,6 +264,8 @@ func TestRestartManager(t *testing.T) { m, lstor, _, _ = newTestMgr(ctx, t, ds) tw.ret = m // simulate jsonrpc auto-reconnect + err = m.AddWorker(ctx, tw) + require.NoError(t, err) tw.pc1lk.Unlock() @@ -270,3 +274,68 @@ func TestRestartManager(t *testing.T) { require.Equal(t, 1, tw.pc1s) } + +// Worker restarts in the middle of a task, task fails after restart +func TestRestartWorker(t *testing.T) { + logging.SetAllLoggers(logging.LevelDebug) + + ctx, done := context.WithCancel(context.Background()) + defer done() + + ds := datastore.NewMapDatastore() + + m, lstor, stor, idx := newTestMgr(ctx, t, ds) + + localTasks := []sealtasks.TaskType{ + sealtasks.TTAddPiece, sealtasks.TTPreCommit1, sealtasks.TTCommit1, sealtasks.TTFinalize, sealtasks.TTFetch, + } + + wds := datastore.NewMapDatastore() + + arch := make(chan chan apres) + w := newLocalWorker(func() (ffiwrapper.Storage, error) { + return &testExec{apch: arch}, nil + }, WorkerConfig{ + SealProof: 0, + TaskTypes: localTasks, + }, stor, lstor, idx, m, statestore.New(wds)) + + err := m.AddWorker(ctx, w) + require.NoError(t, err) + + sid := abi.SectorID{Miner: 1000, Number: 1} + + apDone := make(chan struct{}) + + go func() { + defer close(apDone) + + _, err := m.AddPiece(ctx, sid, nil, 1016, strings.NewReader(strings.Repeat("testthis", 127))) + require.Error(t, err) + }() + + // kill the worker + <-arch + require.NoError(t, w.Close()) + + for { + if len(m.WorkerStats()) == 0 { + break + } + + time.Sleep(time.Millisecond * 3) + } + + // restart the worker + w = newLocalWorker(func() (ffiwrapper.Storage, error) { + return &testExec{apch: arch}, nil + }, WorkerConfig{ + SealProof: 0, + TaskTypes: localTasks, + }, stor, lstor, idx, m, statestore.New(wds)) + + err = m.AddWorker(ctx, w) + require.NoError(t, err) + + <-apDone +} diff --git a/extern/sector-storage/teststorage_test.go b/extern/sector-storage/teststorage_test.go new file mode 100644 index 000000000..da575a491 --- /dev/null +++ b/extern/sector-storage/teststorage_test.go @@ -0,0 +1,81 @@ +package sectorstorage + +import ( + "context" + "io" + + "github.com/ipfs/go-cid" + + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/specs-actors/actors/runtime/proof" + "github.com/filecoin-project/specs-storage/storage" + + "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" +) + +type apres struct { + pi abi.PieceInfo + err error +} + +type testExec struct { + apch chan chan apres +} + +func (t *testExec) GenerateWinningPoSt(ctx context.Context, minerID abi.ActorID, sectorInfo []proof.SectorInfo, randomness abi.PoStRandomness) ([]proof.PoStProof, error) { + panic("implement me") +} + +func (t *testExec) GenerateWindowPoSt(ctx context.Context, minerID abi.ActorID, sectorInfo []proof.SectorInfo, randomness abi.PoStRandomness) (proof []proof.PoStProof, skipped []abi.SectorID, err error) { + panic("implement me") +} + +func (t *testExec) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storage.PreCommit1Out, error) { + panic("implement me") +} + +func (t *testExec) SealPreCommit2(ctx context.Context, sector abi.SectorID, pc1o storage.PreCommit1Out) (storage.SectorCids, error) { + panic("implement me") +} + +func (t *testExec) SealCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storage.Commit1Out, error) { + panic("implement me") +} + +func (t *testExec) SealCommit2(ctx context.Context, sector abi.SectorID, c1o storage.Commit1Out) (storage.Proof, error) { + panic("implement me") +} + +func (t *testExec) FinalizeSector(ctx context.Context, sector abi.SectorID, keepUnsealed []storage.Range) error { + panic("implement me") +} + +func (t *testExec) ReleaseUnsealed(ctx context.Context, sector abi.SectorID, safeToFree []storage.Range) error { + panic("implement me") +} + +func (t *testExec) Remove(ctx context.Context, sector abi.SectorID) error { + panic("implement me") +} + +func (t *testExec) NewSector(ctx context.Context, sector abi.SectorID) error { + panic("implement me") +} + +func (t *testExec) AddPiece(ctx context.Context, sector abi.SectorID, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage.Data) (abi.PieceInfo, error) { + resp := make(chan apres) + t.apch <- resp + ar := <-resp + return ar.pi, ar.err +} + +func (t *testExec) UnsealPiece(ctx context.Context, sector abi.SectorID, offset storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, randomness abi.SealRandomness, commd cid.Cid) error { + panic("implement me") +} + +func (t *testExec) ReadPiece(ctx context.Context, writer io.Writer, sector abi.SectorID, offset storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize) (bool, error) { + panic("implement me") +} + +var _ ffiwrapper.Storage = &testExec{} \ No newline at end of file diff --git a/extern/sector-storage/worker_calltracker.go b/extern/sector-storage/worker_calltracker.go index a16ee33be..38fb39ee1 100644 --- a/extern/sector-storage/worker_calltracker.go +++ b/extern/sector-storage/worker_calltracker.go @@ -19,13 +19,18 @@ const ( ) type Call struct { + ID storiface.CallID + RetType ReturnType + State CallState Result []byte // json bytes } -func (wt *workerCallTracker) onStart(ci storiface.CallID) error { +func (wt *workerCallTracker) onStart(ci storiface.CallID, rt ReturnType) error { return wt.st.Begin(ci, &Call{ + ID: ci, + RetType:rt, State: CallStarted, }) } @@ -43,3 +48,8 @@ func (wt *workerCallTracker) onReturned(ci storiface.CallID) error { st := wt.st.Get(ci) return st.End() } + +func (wt *workerCallTracker) unfinished() ([]Call, error) { + var out []Call + return out, wt.st.List(&out) +} diff --git a/extern/sector-storage/worker_local.go b/extern/sector-storage/worker_local.go index 210ea340c..009e11921 100644 --- a/extern/sector-storage/worker_local.go +++ b/extern/sector-storage/worker_local.go @@ -38,18 +38,21 @@ type LocalWorker struct { localStore *stores.Local sindex stores.SectorIndex ret storiface.WorkerReturn + executor func() (ffiwrapper.Storage, error) ct *workerCallTracker acceptTasks map[sealtasks.TaskType]struct{} + + closing chan struct{} } -func NewLocalWorker(wcfg WorkerConfig, store stores.Store, local *stores.Local, sindex stores.SectorIndex, ret storiface.WorkerReturn, cst *statestore.StateStore) *LocalWorker { +func newLocalWorker(executor func() (ffiwrapper.Storage, error), wcfg WorkerConfig, store stores.Store, local *stores.Local, sindex stores.SectorIndex, ret storiface.WorkerReturn, cst *statestore.StateStore) *LocalWorker { acceptTasks := map[sealtasks.TaskType]struct{}{} for _, taskType := range wcfg.TaskTypes { acceptTasks[taskType] = struct{}{} } - return &LocalWorker{ + w := &LocalWorker{ scfg: &ffiwrapper.Config{ SealProofType: wcfg.SealProof, }, @@ -62,7 +65,37 @@ func NewLocalWorker(wcfg WorkerConfig, store stores.Store, local *stores.Local, st: cst, }, acceptTasks: acceptTasks, + executor: executor, + + closing: make(chan struct{}), } + + if w.executor == nil { + w.executor = w.ffiExec + } + + unfinished, err := w.ct.unfinished() + if err != nil { + log.Errorf("reading unfinished tasks: %+v", err) + return w + } + + go func() { + for _, call := range unfinished { + err := xerrors.Errorf("worker restarted") + + if err := returnFunc[call.RetType](context.TODO(), call.ID, ret, nil, err); err != nil { + log.Errorf("return error: %s: %+v", call.RetType, err) + } + } + }() + + + return w +} + +func NewLocalWorker(wcfg WorkerConfig, store stores.Store, local *stores.Local, sindex stores.SectorIndex, ret storiface.WorkerReturn, cst *statestore.StateStore) *LocalWorker { + return newLocalWorker(nil, wcfg, store, local, sindex, ret, cst) } type localWorkerPathProvider struct { @@ -101,11 +134,11 @@ func (l *localWorkerPathProvider) AcquireSector(ctx context.Context, sector abi. }, nil } -func (l *LocalWorker) sb() (ffiwrapper.Storage, error) { +func (l *LocalWorker) ffiExec() (ffiwrapper.Storage, error) { return ffiwrapper.New(&localWorkerPathProvider{w: l}, l.scfg) } -type returnType string +type ReturnType string // in: func(WorkerReturn, context.Context, CallID, err string) // in: func(WorkerReturn, context.Context, CallID, ret T, err string) @@ -123,7 +156,12 @@ func rfunc(in interface{}) func(context.Context, storiface.CallID, storiface.Wor var ro []reflect.Value if withRet { - ro = rf.Call([]reflect.Value{rwr, rctx, rci, reflect.ValueOf(i), rerr}) + ret := reflect.ValueOf(i) + if i == nil { + ret = reflect.Zero(rf.Type().In(3)) + } + + ro = rf.Call([]reflect.Value{rwr, rctx, rci, ret, rerr}) } else { ro = rf.Call([]reflect.Value{rwr, rctx, rci, rerr}) } @@ -136,7 +174,7 @@ func rfunc(in interface{}) func(context.Context, storiface.CallID, storiface.Wor } } -var returnFunc = map[returnType]func(context.Context, storiface.CallID, storiface.WorkerReturn, interface{}, error) error{ +var returnFunc = map[ReturnType]func(context.Context, storiface.CallID, storiface.WorkerReturn, interface{}, error) error{ "AddPiece": rfunc(storiface.WorkerReturn.ReturnAddPiece), "SealPreCommit1": rfunc(storiface.WorkerReturn.ReturnSealPreCommit1), "SealPreCommit2": rfunc(storiface.WorkerReturn.ReturnSealPreCommit2), @@ -150,13 +188,13 @@ var returnFunc = map[returnType]func(context.Context, storiface.CallID, storifac "Fetch": rfunc(storiface.WorkerReturn.ReturnFetch), } -func (l *LocalWorker) asyncCall(ctx context.Context, sector abi.SectorID, rt returnType, work func(ci storiface.CallID) (interface{}, error)) (storiface.CallID, error) { +func (l *LocalWorker) asyncCall(ctx context.Context, sector abi.SectorID, rt ReturnType, work func(ci storiface.CallID) (interface{}, error)) (storiface.CallID, error) { ci := storiface.CallID{ Sector: sector, ID: uuid.New(), } - if err := l.ct.onStart(ci); err != nil { + if err := l.ct.onStart(ci, rt); err != nil { log.Errorf("tracking call (start): %+v", err) } @@ -196,7 +234,7 @@ func errstr(err error) string { } func (l *LocalWorker) NewSector(ctx context.Context, sector abi.SectorID) error { - sb, err := l.sb() + sb, err := l.executor() if err != nil { return err } @@ -205,7 +243,7 @@ func (l *LocalWorker) NewSector(ctx context.Context, sector abi.SectorID) error } func (l *LocalWorker) AddPiece(ctx context.Context, sector abi.SectorID, epcs []abi.UnpaddedPieceSize, sz abi.UnpaddedPieceSize, r io.Reader) (storiface.CallID, error) { - sb, err := l.sb() + sb, err := l.executor() if err != nil { return storiface.UndefCall, err } @@ -240,7 +278,7 @@ func (l *LocalWorker) SealPreCommit1(ctx context.Context, sector abi.SectorID, t } } - sb, err := l.sb() + sb, err := l.executor() if err != nil { return nil, err } @@ -250,7 +288,7 @@ func (l *LocalWorker) SealPreCommit1(ctx context.Context, sector abi.SectorID, t } func (l *LocalWorker) SealPreCommit2(ctx context.Context, sector abi.SectorID, phase1Out storage2.PreCommit1Out) (storiface.CallID, error) { - sb, err := l.sb() + sb, err := l.executor() if err != nil { return storiface.UndefCall, err } @@ -261,7 +299,7 @@ func (l *LocalWorker) SealPreCommit2(ctx context.Context, sector abi.SectorID, p } func (l *LocalWorker) SealCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage2.SectorCids) (storiface.CallID, error) { - sb, err := l.sb() + sb, err := l.executor() if err != nil { return storiface.UndefCall, err } @@ -272,7 +310,7 @@ func (l *LocalWorker) SealCommit1(ctx context.Context, sector abi.SectorID, tick } func (l *LocalWorker) SealCommit2(ctx context.Context, sector abi.SectorID, phase1Out storage2.Commit1Out) (storiface.CallID, error) { - sb, err := l.sb() + sb, err := l.executor() if err != nil { return storiface.UndefCall, err } @@ -283,7 +321,7 @@ func (l *LocalWorker) SealCommit2(ctx context.Context, sector abi.SectorID, phas } func (l *LocalWorker) FinalizeSector(ctx context.Context, sector abi.SectorID, keepUnsealed []storage2.Range) (storiface.CallID, error) { - sb, err := l.sb() + sb, err := l.executor() if err != nil { return storiface.UndefCall, err } @@ -330,7 +368,7 @@ func (l *LocalWorker) MoveStorage(ctx context.Context, sector abi.SectorID, type } func (l *LocalWorker) UnsealPiece(ctx context.Context, sector abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, randomness abi.SealRandomness, cid cid.Cid) (storiface.CallID, error) { - sb, err := l.sb() + sb, err := l.executor() if err != nil { return storiface.UndefCall, err } @@ -353,7 +391,7 @@ func (l *LocalWorker) UnsealPiece(ctx context.Context, sector abi.SectorID, inde } func (l *LocalWorker) ReadPiece(ctx context.Context, writer io.Writer, sector abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize) (storiface.CallID, error) { - sb, err := l.sb() + sb, err := l.executor() if err != nil { return storiface.UndefCall, err } @@ -405,10 +443,11 @@ func (l *LocalWorker) Info(context.Context) (storiface.WorkerInfo, error) { } func (l *LocalWorker) Closing(ctx context.Context) (<-chan struct{}, error) { - return make(chan struct{}), nil + return l.closing, nil } func (l *LocalWorker) Close() error { + close(l.closing) return nil } diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index af76861c1..80bab7868 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "github.com/filecoin-project/go-statestore" "net/http" "time" @@ -43,6 +42,7 @@ import ( "github.com/filecoin-project/go-multistore" paramfetch "github.com/filecoin-project/go-paramfetch" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-statestore" "github.com/filecoin-project/go-storedcounter" sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage" @@ -50,15 +50,15 @@ import ( "github.com/filecoin-project/lotus/extern/sector-storage/stores" sealing "github.com/filecoin-project/lotus/extern/storage-sealing" "github.com/filecoin-project/lotus/extern/storage-sealing/sealiface" - "github.com/filecoin-project/lotus/journal" - "github.com/filecoin-project/lotus/markets" lapi "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/gen/slashfilter" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/journal" "github.com/filecoin-project/lotus/lib/blockstore" + "github.com/filecoin-project/lotus/markets" marketevents "github.com/filecoin-project/lotus/markets/loggers" "github.com/filecoin-project/lotus/markets/retrievaladapter" "github.com/filecoin-project/lotus/miner" From b8865fb182f700b04589d76e2324fdf90c131c43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 22 Sep 2020 01:00:17 +0200 Subject: [PATCH 014/313] workers: Mark on-restart-failed returned tasks as returned --- extern/sector-storage/manager_test.go | 5 +++++ extern/sector-storage/teststorage_test.go | 4 ++-- extern/sector-storage/worker_calltracker.go | 6 +++--- extern/sector-storage/worker_local.go | 8 ++++++-- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/extern/sector-storage/manager_test.go b/extern/sector-storage/manager_test.go index 9a47c3b55..d87ec0827 100644 --- a/extern/sector-storage/manager_test.go +++ b/extern/sector-storage/manager_test.go @@ -338,4 +338,9 @@ func TestRestartWorker(t *testing.T) { require.NoError(t, err) <-apDone + + time.Sleep(12 * time.Millisecond) + uf, err := w.ct.unfinished() + require.NoError(t, err) + require.Empty(t, uf) } diff --git a/extern/sector-storage/teststorage_test.go b/extern/sector-storage/teststorage_test.go index da575a491..0c8a240a3 100644 --- a/extern/sector-storage/teststorage_test.go +++ b/extern/sector-storage/teststorage_test.go @@ -15,7 +15,7 @@ import ( ) type apres struct { - pi abi.PieceInfo + pi abi.PieceInfo err error } @@ -78,4 +78,4 @@ func (t *testExec) ReadPiece(ctx context.Context, writer io.Writer, sector abi.S panic("implement me") } -var _ ffiwrapper.Storage = &testExec{} \ No newline at end of file +var _ ffiwrapper.Storage = &testExec{} diff --git a/extern/sector-storage/worker_calltracker.go b/extern/sector-storage/worker_calltracker.go index 38fb39ee1..1033822a5 100644 --- a/extern/sector-storage/worker_calltracker.go +++ b/extern/sector-storage/worker_calltracker.go @@ -29,9 +29,9 @@ type Call struct { func (wt *workerCallTracker) onStart(ci storiface.CallID, rt ReturnType) error { return wt.st.Begin(ci, &Call{ - ID: ci, - RetType:rt, - State: CallStarted, + ID: ci, + RetType: rt, + State: CallStarted, }) } diff --git a/extern/sector-storage/worker_local.go b/extern/sector-storage/worker_local.go index 009e11921..38b41ceb4 100644 --- a/extern/sector-storage/worker_local.go +++ b/extern/sector-storage/worker_local.go @@ -65,7 +65,7 @@ func newLocalWorker(executor func() (ffiwrapper.Storage, error), wcfg WorkerConf st: cst, }, acceptTasks: acceptTasks, - executor: executor, + executor: executor, closing: make(chan struct{}), } @@ -86,11 +86,15 @@ func newLocalWorker(executor func() (ffiwrapper.Storage, error), wcfg WorkerConf if err := returnFunc[call.RetType](context.TODO(), call.ID, ret, nil, err); err != nil { log.Errorf("return error: %s: %+v", call.RetType, err) + continue + } + + if err := w.ct.onReturned(call.ID); err != nil { + log.Errorf("marking call as returned failed: %s: %+v", call.RetType, err) } } }() - return w } From 706f4f2ef505cbbafda1f60212227f46682647d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 22 Sep 2020 18:36:44 +0200 Subject: [PATCH 015/313] worker: Don't die with the connection --- cmd/lotus-seal-worker/main.go | 86 +++++++++------------------ extern/sector-storage/worker_local.go | 11 ++++ 2 files changed, 40 insertions(+), 57 deletions(-) diff --git a/cmd/lotus-seal-worker/main.go b/cmd/lotus-seal-worker/main.go index 9739acb68..292590c2e 100644 --- a/cmd/lotus-seal-worker/main.go +++ b/cmd/lotus-seal-worker/main.go @@ -10,7 +10,6 @@ import ( "os" "path/filepath" "strings" - "syscall" "time" "github.com/google/uuid" @@ -198,8 +197,6 @@ var runCmd = &cli.Command{ } log.Infof("Remote version %s", v) - watchMinerConn(ctx, cctx, nodeApi) - // Check params act, err := nodeApi.ActorAddress(ctx) @@ -422,13 +419,36 @@ var runCmd = &cli.Command{ } } - log.Info("Waiting for tasks") - go func() { - if err := nodeApi.WorkerConnect(ctx, "ws://"+address+"/rpc/v0"); err != nil { - log.Errorf("Registering worker failed: %+v", err) - cancel() - return + for { + log.Info("Making sure no local tasks are running") + + // TODO: we could get rid of this, but that requires tracking resources for restarted tasks correctly + workerApi.LocalWorker.WaitQuiet() + + if err := nodeApi.WorkerConnect(ctx, "ws://"+address+"/rpc/v0"); err != nil { + log.Errorf("Registering worker failed: %+v", err) + cancel() + return + } + + log.Info("Worker registered successfully, waiting for tasks") + + closing, err := nodeApi.Closing(ctx) + if err != nil { + log.Errorf("failed to get remote closing channel: %+v", err) + } + + select { + case <-closing: + case <-ctx.Done(): + } + + if ctx.Err() != nil { + return // graceful shutdown + } + + log.Errorf("LOTUS-MINER CONNECTION LOST") } }() @@ -436,54 +456,6 @@ var runCmd = &cli.Command{ }, } -func watchMinerConn(ctx context.Context, cctx *cli.Context, nodeApi api.StorageMiner) { - go func() { - closing, err := nodeApi.Closing(ctx) - if err != nil { - log.Errorf("failed to get remote closing channel: %+v", err) - } - - select { - case <-closing: - case <-ctx.Done(): - } - - if ctx.Err() != nil { - return // graceful shutdown - } - - log.Warnf("Connection with miner node lost, restarting") - - exe, err := os.Executable() - if err != nil { - log.Errorf("getting executable for auto-restart: %+v", err) - } - - _ = log.Sync() - - // TODO: there are probably cleaner/more graceful ways to restart, - // but this is good enough for now (FSM can recover from the mess this creates) - //nolint:gosec - if err := syscall.Exec(exe, []string{exe, - fmt.Sprintf("--worker-repo=%s", cctx.String("worker-repo")), - fmt.Sprintf("--miner-repo=%s", cctx.String("miner-repo")), - fmt.Sprintf("--enable-gpu-proving=%t", cctx.Bool("enable-gpu-proving")), - "run", - fmt.Sprintf("--listen=%s", cctx.String("listen")), - fmt.Sprintf("--no-local-storage=%t", cctx.Bool("no-local-storage")), - fmt.Sprintf("--addpiece=%t", cctx.Bool("addpiece")), - fmt.Sprintf("--precommit1=%t", cctx.Bool("precommit1")), - fmt.Sprintf("--unseal=%t", cctx.Bool("unseal")), - fmt.Sprintf("--precommit2=%t", cctx.Bool("precommit2")), - fmt.Sprintf("--commit=%t", cctx.Bool("commit")), - fmt.Sprintf("--parallel-fetch-limit=%d", cctx.Int("parallel-fetch-limit")), - fmt.Sprintf("--timeout=%s", cctx.String("timeout")), - }, os.Environ()); err != nil { - fmt.Println(err) - } - }() -} - func extractRoutableIP(timeout time.Duration) (string, error) { minerMultiAddrKey := "MINER_API_INFO" deprecatedMinerMultiAddrKey := "STORAGE_API_INFO" diff --git a/extern/sector-storage/worker_local.go b/extern/sector-storage/worker_local.go index 38b41ceb4..46f0d65e2 100644 --- a/extern/sector-storage/worker_local.go +++ b/extern/sector-storage/worker_local.go @@ -7,6 +7,7 @@ import ( "os" "reflect" "runtime" + "sync" "github.com/elastic/go-sysinfo" "github.com/google/uuid" @@ -42,6 +43,7 @@ type LocalWorker struct { ct *workerCallTracker acceptTasks map[sealtasks.TaskType]struct{} + running sync.WaitGroup closing chan struct{} } @@ -202,7 +204,11 @@ func (l *LocalWorker) asyncCall(ctx context.Context, sector abi.SectorID, rt Ret log.Errorf("tracking call (start): %+v", err) } + l.running.Add(1) + go func() { + defer l.running.Done() + res, err := work(ci) { @@ -455,4 +461,9 @@ func (l *LocalWorker) Close() error { return nil } +// WaitQuiet blocks as long as there are tasks running +func (l *LocalWorker) WaitQuiet() { + l.running.Wait() +} + var _ Worker = &LocalWorker{} From bb5cc066771cf64b50fbd65a007199689f25e167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 22 Sep 2020 23:33:13 +0200 Subject: [PATCH 016/313] Fix workid param hash --- extern/sector-storage/manager_calltracker.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extern/sector-storage/manager_calltracker.go b/extern/sector-storage/manager_calltracker.go index 8e3e20c6e..13296a843 100644 --- a/extern/sector-storage/manager_calltracker.go +++ b/extern/sector-storage/manager_calltracker.go @@ -3,6 +3,7 @@ package sectorstorage import ( "context" "crypto/sha256" + "encoding/hex" "encoding/json" "errors" "fmt" @@ -47,7 +48,7 @@ func newWorkID(method string, params ...interface{}) (WorkID, error) { if len(pb) > 256 { s := sha256.Sum256(pb) - pb = s[:] + pb = []byte(hex.EncodeToString(s[:])) } return WorkID{ From 04ad1791b08da9008643caafd6760dfc714e1524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 23 Sep 2020 00:10:36 +0200 Subject: [PATCH 017/313] localworker: Fix contexts --- extern/sector-storage/worker_local.go | 56 +++++++++++++++++++++------ 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/extern/sector-storage/worker_local.go b/extern/sector-storage/worker_local.go index 46f0d65e2..495c9630d 100644 --- a/extern/sector-storage/worker_local.go +++ b/extern/sector-storage/worker_local.go @@ -8,6 +8,7 @@ import ( "reflect" "runtime" "sync" + "time" "github.com/elastic/go-sysinfo" "github.com/google/uuid" @@ -194,7 +195,7 @@ var returnFunc = map[ReturnType]func(context.Context, storiface.CallID, storifac "Fetch": rfunc(storiface.WorkerReturn.ReturnFetch), } -func (l *LocalWorker) asyncCall(ctx context.Context, sector abi.SectorID, rt ReturnType, work func(ci storiface.CallID) (interface{}, error)) (storiface.CallID, error) { +func (l *LocalWorker) asyncCall(ctx context.Context, sector abi.SectorID, rt ReturnType, work func(ctx context.Context, ci storiface.CallID) (interface{}, error)) (storiface.CallID, error) { ci := storiface.CallID{ Sector: sector, ID: uuid.New(), @@ -209,7 +210,10 @@ func (l *LocalWorker) asyncCall(ctx context.Context, sector abi.SectorID, rt Ret go func() { defer l.running.Done() - res, err := work(ci) + res, err := work(&wctx{ + vals: ctx, + closing: l.closing, + }, ci) { rb, err := json.Marshal(res) @@ -258,13 +262,13 @@ func (l *LocalWorker) AddPiece(ctx context.Context, sector abi.SectorID, epcs [] return storiface.UndefCall, err } - return l.asyncCall(ctx, sector, "AddPiece", func(ci storiface.CallID) (interface{}, error) { + return l.asyncCall(ctx, sector, "AddPiece", func(ctx context.Context, ci storiface.CallID) (interface{}, error) { return sb.AddPiece(ctx, sector, epcs, sz, r) }) } func (l *LocalWorker) Fetch(ctx context.Context, sector abi.SectorID, fileType storiface.SectorFileType, ptype storiface.PathType, am storiface.AcquireMode) (storiface.CallID, error) { - return l.asyncCall(ctx, sector, "Fetch", func(ci storiface.CallID) (interface{}, error) { + return l.asyncCall(ctx, sector, "Fetch", func(ctx context.Context, ci storiface.CallID) (interface{}, error) { _, done, err := (&localWorkerPathProvider{w: l, op: am}).AcquireSector(ctx, sector, fileType, storiface.FTNone, ptype) if err == nil { done() @@ -275,7 +279,7 @@ func (l *LocalWorker) Fetch(ctx context.Context, sector abi.SectorID, fileType s } func (l *LocalWorker) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storiface.CallID, error) { - return l.asyncCall(ctx, sector, "SealPreCommit1", func(ci storiface.CallID) (interface{}, error) { + return l.asyncCall(ctx, sector, "SealPreCommit1", func(ctx context.Context, ci storiface.CallID) (interface{}, error) { { // cleanup previous failed attempts if they exist @@ -303,7 +307,7 @@ func (l *LocalWorker) SealPreCommit2(ctx context.Context, sector abi.SectorID, p return storiface.UndefCall, err } - return l.asyncCall(ctx, sector, "SealPreCommit2", func(ci storiface.CallID) (interface{}, error) { + return l.asyncCall(ctx, sector, "SealPreCommit2", func(ctx context.Context, ci storiface.CallID) (interface{}, error) { return sb.SealPreCommit2(ctx, sector, phase1Out) }) } @@ -314,7 +318,7 @@ func (l *LocalWorker) SealCommit1(ctx context.Context, sector abi.SectorID, tick return storiface.UndefCall, err } - return l.asyncCall(ctx, sector, "SealCommit1", func(ci storiface.CallID) (interface{}, error) { + return l.asyncCall(ctx, sector, "SealCommit1", func(ctx context.Context, ci storiface.CallID) (interface{}, error) { return sb.SealCommit1(ctx, sector, ticket, seed, pieces, cids) }) } @@ -325,7 +329,7 @@ func (l *LocalWorker) SealCommit2(ctx context.Context, sector abi.SectorID, phas return storiface.UndefCall, err } - return l.asyncCall(ctx, sector, "SealCommit2", func(ci storiface.CallID) (interface{}, error) { + return l.asyncCall(ctx, sector, "SealCommit2", func(ctx context.Context, ci storiface.CallID) (interface{}, error) { return sb.SealCommit2(ctx, sector, phase1Out) }) } @@ -336,7 +340,7 @@ func (l *LocalWorker) FinalizeSector(ctx context.Context, sector abi.SectorID, k return storiface.UndefCall, err } - return l.asyncCall(ctx, sector, "FinalizeSector", func(ci storiface.CallID) (interface{}, error) { + return l.asyncCall(ctx, sector, "FinalizeSector", func(ctx context.Context, ci storiface.CallID) (interface{}, error) { if err := sb.FinalizeSector(ctx, sector, keepUnsealed); err != nil { return nil, xerrors.Errorf("finalizing sector: %w", err) } @@ -372,7 +376,7 @@ func (l *LocalWorker) Remove(ctx context.Context, sector abi.SectorID) error { } func (l *LocalWorker) MoveStorage(ctx context.Context, sector abi.SectorID, types storiface.SectorFileType) (storiface.CallID, error) { - return l.asyncCall(ctx, sector, "MoveStorage", func(ci storiface.CallID) (interface{}, error) { + return l.asyncCall(ctx, sector, "MoveStorage", func(ctx context.Context, ci storiface.CallID) (interface{}, error) { return nil, l.storage.MoveStorage(ctx, sector, l.scfg.SealProofType, types) }) } @@ -383,7 +387,7 @@ func (l *LocalWorker) UnsealPiece(ctx context.Context, sector abi.SectorID, inde return storiface.UndefCall, err } - return l.asyncCall(ctx, sector, "UnsealPiece", func(ci storiface.CallID) (interface{}, error) { + return l.asyncCall(ctx, sector, "UnsealPiece", func(ctx context.Context, ci storiface.CallID) (interface{}, error) { if err = sb.UnsealPiece(ctx, sector, index, size, randomness, cid); err != nil { return nil, xerrors.Errorf("unsealing sector: %w", err) } @@ -406,7 +410,7 @@ func (l *LocalWorker) ReadPiece(ctx context.Context, writer io.Writer, sector ab return storiface.UndefCall, err } - return l.asyncCall(ctx, sector, "ReadPiece", func(ci storiface.CallID) (interface{}, error) { + return l.asyncCall(ctx, sector, "ReadPiece", func(ctx context.Context, ci storiface.CallID) (interface{}, error) { return sb.ReadPiece(ctx, writer, sector, index, size) }) } @@ -466,4 +470,32 @@ func (l *LocalWorker) WaitQuiet() { l.running.Wait() } +type wctx struct { + vals context.Context + closing chan struct{} +} + +func (w *wctx) Deadline() (time.Time, bool) { + return time.Time{}, false +} + +func (w *wctx) Done() <-chan struct{} { + return w.closing +} + +func (w *wctx) Err() error { + select { + case <-w.closing: + return context.Canceled + default: + return nil + } +} + +func (w *wctx) Value(key interface{}) interface{} { + return w.vals.Value(key) +} + +var _ context.Context = &wctx{} + var _ Worker = &LocalWorker{} From 6185e157e91a265022ca2b56af6987965e29b3ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 23 Sep 2020 00:26:07 +0200 Subject: [PATCH 018/313] sectorstorage: calltracker: work around cbor-gen bytearray len limit --- extern/sector-storage/cbor_gen.go | 44 ++++++-------- extern/sector-storage/worker_calltracker.go | 66 ++++++++++++++++++++- 2 files changed, 81 insertions(+), 29 deletions(-) diff --git a/extern/sector-storage/cbor_gen.go b/extern/sector-storage/cbor_gen.go index a291487f0..51b82ef13 100644 --- a/extern/sector-storage/cbor_gen.go +++ b/extern/sector-storage/cbor_gen.go @@ -78,7 +78,7 @@ func (t *Call) MarshalCBOR(w io.Writer) error { return err } - // t.Result ([]uint8) (slice) + // t.Result (sectorstorage.ManyBytes) (struct) if len("Result") > cbg.MaxLength { return xerrors.Errorf("Value in field \"Result\" was too long") } @@ -90,15 +90,7 @@ func (t *Call) MarshalCBOR(w io.Writer) error { return err } - if len(t.Result) > cbg.ByteArrayMaxLen { - return xerrors.Errorf("Byte array in field t.Result was too long") - } - - if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajByteString, uint64(len(t.Result))); err != nil { - return err - } - - if _, err := w.Write(t.Result[:]); err != nil { + if err := t.Result.MarshalCBOR(w); err != nil { return err } return nil @@ -173,27 +165,25 @@ func (t *Call) UnmarshalCBOR(r io.Reader) error { t.State = CallState(extra) } - // t.Result ([]uint8) (slice) + // t.Result (sectorstorage.ManyBytes) (struct) case "Result": - maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) - if err != nil { - return err - } + { - if extra > cbg.ByteArrayMaxLen { - return fmt.Errorf("t.Result: byte array too large (%d)", extra) - } - if maj != cbg.MajByteString { - return fmt.Errorf("expected byte array") - } + b, err := br.ReadByte() + if err != nil { + return err + } + if b != cbg.CborNull[0] { + if err := br.UnreadByte(); err != nil { + return err + } + t.Result = new(ManyBytes) + if err := t.Result.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.Result pointer: %w", err) + } + } - if extra > 0 { - t.Result = make([]uint8, extra) - } - - if _, err := io.ReadFull(br, t.Result[:]); err != nil { - return err } default: diff --git a/extern/sector-storage/worker_calltracker.go b/extern/sector-storage/worker_calltracker.go index 1033822a5..6f03c72cc 100644 --- a/extern/sector-storage/worker_calltracker.go +++ b/extern/sector-storage/worker_calltracker.go @@ -1,7 +1,12 @@ package sectorstorage import ( + "fmt" + "io" + "github.com/filecoin-project/go-statestore" + cbg "github.com/whyrusleeping/cbor-gen" + "golang.org/x/xerrors" "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) @@ -24,7 +29,7 @@ type Call struct { State CallState - Result []byte // json bytes + Result *ManyBytes // json bytes } func (wt *workerCallTracker) onStart(ci storiface.CallID, rt ReturnType) error { @@ -39,7 +44,7 @@ func (wt *workerCallTracker) onDone(ci storiface.CallID, ret []byte) error { st := wt.st.Get(ci) return st.Mutate(func(cs *Call) error { cs.State = CallDone - cs.Result = ret + cs.Result = &ManyBytes{ret} return nil }) } @@ -53,3 +58,60 @@ func (wt *workerCallTracker) unfinished() ([]Call, error) { var out []Call return out, wt.st.List(&out) } + +// Ideally this would be a tag on the struct field telling cbor-gen to enforce higher max-len +type ManyBytes struct { + b []byte +} + +const many = 100 << 20 + +func (t *ManyBytes) MarshalCBOR(w io.Writer) error { + if t == nil { + t = &ManyBytes{} + } + + if len(t.b) > many { + return xerrors.Errorf("byte array in field t.Result was too long") + } + + scratch := make([]byte, 9) + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajByteString, uint64(len(t.b))); err != nil { + return err + } + + if _, err := w.Write(t.b[:]); err != nil { + return err + } + return nil +} + +func (t *ManyBytes) UnmarshalCBOR(r io.Reader) error { + *t = ManyBytes{} + + br := cbg.GetPeeker(r) + scratch := make([]byte, 9) + + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + + if extra > many { + return fmt.Errorf("byte array too large (%d)", extra) + } + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + + if extra > 0 { + t.b = make([]uint8, extra) + } + + if _, err := io.ReadFull(br, t.b[:]); err != nil { + return err + } + + return nil +} From 86c222ab58bc875400a3071ddf794274ff0eb322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 23 Sep 2020 14:56:37 +0200 Subject: [PATCH 019/313] sectorstorage: fix work tracking --- extern/sector-storage/manager.go | 5 +- extern/sector-storage/manager_calltracker.go | 2 + extern/sector-storage/manager_test.go | 5 ++ extern/sector-storage/sched.go | 14 +++-- extern/sector-storage/sched_test.go | 5 +- extern/sector-storage/stats.go | 6 +- extern/sector-storage/worker_tracked.go | 61 ++++++++++---------- 7 files changed, 53 insertions(+), 45 deletions(-) diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index eecfd1b55..d4db60806 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -197,10 +197,7 @@ func (m *Manager) AddWorker(ctx context.Context, w Worker) error { m.sched.newWorkers <- &workerHandle{ w: w, - wt: &workTracker{ - done: map[storiface.CallID]struct{}{}, - running: map[storiface.CallID]storiface.WorkerJob{}, - }, + info: info, preparing: &activeResources{}, active: &activeResources{}, diff --git a/extern/sector-storage/manager_calltracker.go b/extern/sector-storage/manager_calltracker.go index 13296a843..e62f964b3 100644 --- a/extern/sector-storage/manager_calltracker.go +++ b/extern/sector-storage/manager_calltracker.go @@ -289,6 +289,8 @@ func (m *Manager) returnResult(callID storiface.CallID, r interface{}, serr stri err: err, } + m.sched.wt.onDone(callID) + m.workLk.Lock() defer m.workLk.Unlock() diff --git a/extern/sector-storage/manager_test.go b/extern/sector-storage/manager_test.go index d87ec0827..0fada08bc 100644 --- a/extern/sector-storage/manager_test.go +++ b/extern/sector-storage/manager_test.go @@ -115,6 +115,11 @@ func newTestMgr(ctx context.Context, t *testing.T, ds datastore.Datastore) (*Man Prover: prover, + wt: &workTracker{ + done: map[storiface.CallID]struct{}{}, + running: map[storiface.CallID]trackedWork{}, + }, + work: statestore.New(ds), callToWork: map[storiface.CallID]WorkID{}, callRes: map[storiface.CallID]chan result{}, diff --git a/extern/sector-storage/sched.go b/extern/sector-storage/sched.go index d757140b9..760fe9cba 100644 --- a/extern/sector-storage/sched.go +++ b/extern/sector-storage/sched.go @@ -69,6 +69,8 @@ type scheduler struct { schedQueue *requestQueue openWindows []*schedWindowRequest + wt *workTracker + info chan func(interface{}) closing chan struct{} @@ -89,9 +91,6 @@ type workerHandle struct { wndLk sync.Mutex activeWindows []*schedWindow - // stats / tracking - wt *workTracker - // for sync manager goroutine closing cleanupStarted bool closedMgr chan struct{} @@ -157,6 +156,11 @@ func newScheduler(spt abi.RegisteredSealProof) *scheduler { schedQueue: &requestQueue{}, + wt: &workTracker{ + done: map[storiface.CallID]struct{}{}, + running: map[storiface.CallID]trackedWork{}, + }, + info: make(chan func(interface{})), closing: make(chan struct{}), @@ -680,7 +684,7 @@ func (sh *scheduler) assignWorker(taskDone chan struct{}, wid WorkerID, w *worke w.lk.Unlock() go func() { - err := req.prepare(req.ctx, w.wt.worker(w.w)) + err := req.prepare(req.ctx, sh.wt.worker(wid, w.w)) sh.workersLk.Lock() if err != nil { @@ -717,7 +721,7 @@ func (sh *scheduler) assignWorker(taskDone chan struct{}, wid WorkerID, w *worke case <-sh.closing: } - err = req.work(req.ctx, w.wt.worker(w.w)) + err = req.work(req.ctx, sh.wt.worker(wid, w.w)) select { case req.ret <- workerResponse{err: err}: diff --git a/extern/sector-storage/sched_test.go b/extern/sector-storage/sched_test.go index 55ef9bf02..f23be20c0 100644 --- a/extern/sector-storage/sched_test.go +++ b/extern/sector-storage/sched_test.go @@ -165,10 +165,7 @@ func addTestWorker(t *testing.T, sched *scheduler, index *stores.Index, name str sched.newWorkers <- &workerHandle{ w: w, - wt: &workTracker{ - done: map[storiface.CallID]struct{}{}, - running: map[storiface.CallID]storiface.WorkerJob{}, - }, + info: info, preparing: &activeResources{}, active: &activeResources{}, diff --git a/extern/sector-storage/stats.go b/extern/sector-storage/stats.go index f9063cbec..1ce415fd2 100644 --- a/extern/sector-storage/stats.go +++ b/extern/sector-storage/stats.go @@ -29,9 +29,11 @@ func (m *Manager) WorkerJobs() map[uint64][]storiface.WorkerJob { out := map[uint64][]storiface.WorkerJob{} - for id, handle := range m.sched.workers { - out[uint64(id)] = handle.wt.Running() + for _, t := range m.sched.wt.Running() { + out[uint64(t.worker)] = append(out[uint64(t.worker)], t.job) + } + for id, handle := range m.sched.workers { handle.wndLk.Lock() for wi, window := range handle.activeWindows { for _, request := range window.todo { diff --git a/extern/sector-storage/worker_tracked.go b/extern/sector-storage/worker_tracked.go index f5ad15360..4a22fcca7 100644 --- a/extern/sector-storage/worker_tracked.go +++ b/extern/sector-storage/worker_tracked.go @@ -15,25 +15,20 @@ import ( "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) +type trackedWork struct { + job storiface.WorkerJob + worker WorkerID +} + type workTracker struct { lk sync.Mutex done map[storiface.CallID]struct{} - running map[storiface.CallID]storiface.WorkerJob + running map[storiface.CallID]trackedWork // TODO: done, aggregate stats, queue stats, scheduler feedback } -// TODO: CALL THIS! -// TODO: CALL THIS! -// TODO: CALL THIS! -// TODO: CALL THIS! -// TODO: CALL THIS! -// TODO: CALL THIS! -// TODO: CALL THIS! -// TODO: CALL THIS! -// TODO: CALL THIS! -// TODO: CALL THIS! func (wt *workTracker) onDone(callID storiface.CallID) { wt.lk.Lock() defer wt.lk.Unlock() @@ -47,7 +42,7 @@ func (wt *workTracker) onDone(callID storiface.CallID) { delete(wt.running, callID) } -func (wt *workTracker) track(sid abi.SectorID, task sealtasks.TaskType) func(storiface.CallID, error) (storiface.CallID, error) { +func (wt *workTracker) track(wid WorkerID, sid abi.SectorID, task sealtasks.TaskType) func(storiface.CallID, error) (storiface.CallID, error) { return func(callID storiface.CallID, err error) (storiface.CallID, error) { if err != nil { return callID, err @@ -62,29 +57,34 @@ func (wt *workTracker) track(sid abi.SectorID, task sealtasks.TaskType) func(sto return callID, err } - wt.running[callID] = storiface.WorkerJob{ - ID: callID, - Sector: sid, - Task: task, - Start: time.Now(), + wt.running[callID] = trackedWork{ + job: storiface.WorkerJob{ + ID: callID, + Sector: sid, + Task: task, + Start: time.Now(), + }, + worker: wid, } return callID, err } } -func (wt *workTracker) worker(w Worker) Worker { +func (wt *workTracker) worker(wid WorkerID, w Worker) Worker { return &trackedWorker{ - Worker: w, + Worker: w, + wid: wid, + tracker: wt, } } -func (wt *workTracker) Running() []storiface.WorkerJob { +func (wt *workTracker) Running() []trackedWork { wt.lk.Lock() defer wt.lk.Unlock() - out := make([]storiface.WorkerJob, 0, len(wt.running)) + out := make([]trackedWork, 0, len(wt.running)) for _, job := range wt.running { out = append(out, job) } @@ -94,44 +94,45 @@ func (wt *workTracker) Running() []storiface.WorkerJob { type trackedWorker struct { Worker + wid WorkerID tracker *workTracker } func (t *trackedWorker) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storiface.CallID, error) { - return t.tracker.track(sector, sealtasks.TTPreCommit1)(t.Worker.SealPreCommit1(ctx, sector, ticket, pieces)) + return t.tracker.track(t.wid, sector, sealtasks.TTPreCommit1)(t.Worker.SealPreCommit1(ctx, sector, ticket, pieces)) } func (t *trackedWorker) SealPreCommit2(ctx context.Context, sector abi.SectorID, pc1o storage.PreCommit1Out) (storiface.CallID, error) { - return t.tracker.track(sector, sealtasks.TTPreCommit2)(t.Worker.SealPreCommit2(ctx, sector, pc1o)) + return t.tracker.track(t.wid, sector, sealtasks.TTPreCommit2)(t.Worker.SealPreCommit2(ctx, sector, pc1o)) } func (t *trackedWorker) SealCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storiface.CallID, error) { - return t.tracker.track(sector, sealtasks.TTCommit1)(t.Worker.SealCommit1(ctx, sector, ticket, seed, pieces, cids)) + return t.tracker.track(t.wid, sector, sealtasks.TTCommit1)(t.Worker.SealCommit1(ctx, sector, ticket, seed, pieces, cids)) } func (t *trackedWorker) SealCommit2(ctx context.Context, sector abi.SectorID, c1o storage.Commit1Out) (storiface.CallID, error) { - return t.tracker.track(sector, sealtasks.TTCommit2)(t.Worker.SealCommit2(ctx, sector, c1o)) + return t.tracker.track(t.wid, sector, sealtasks.TTCommit2)(t.Worker.SealCommit2(ctx, sector, c1o)) } func (t *trackedWorker) FinalizeSector(ctx context.Context, sector abi.SectorID, keepUnsealed []storage.Range) (storiface.CallID, error) { - return t.tracker.track(sector, sealtasks.TTFinalize)(t.Worker.FinalizeSector(ctx, sector, keepUnsealed)) + return t.tracker.track(t.wid, sector, sealtasks.TTFinalize)(t.Worker.FinalizeSector(ctx, sector, keepUnsealed)) } func (t *trackedWorker) AddPiece(ctx context.Context, sector abi.SectorID, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage.Data) (storiface.CallID, error) { - return t.tracker.track(sector, sealtasks.TTAddPiece)(t.Worker.AddPiece(ctx, sector, pieceSizes, newPieceSize, pieceData)) + return t.tracker.track(t.wid, sector, sealtasks.TTAddPiece)(t.Worker.AddPiece(ctx, sector, pieceSizes, newPieceSize, pieceData)) } func (t *trackedWorker) Fetch(ctx context.Context, s abi.SectorID, ft storiface.SectorFileType, ptype storiface.PathType, am storiface.AcquireMode) (storiface.CallID, error) { - return t.tracker.track(s, sealtasks.TTFetch)(t.Worker.Fetch(ctx, s, ft, ptype, am)) + return t.tracker.track(t.wid, s, sealtasks.TTFetch)(t.Worker.Fetch(ctx, s, ft, ptype, am)) } func (t *trackedWorker) UnsealPiece(ctx context.Context, id abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, randomness abi.SealRandomness, cid cid.Cid) (storiface.CallID, error) { - return t.tracker.track(id, sealtasks.TTUnseal)(t.Worker.UnsealPiece(ctx, id, index, size, randomness, cid)) + return t.tracker.track(t.wid, id, sealtasks.TTUnseal)(t.Worker.UnsealPiece(ctx, id, index, size, randomness, cid)) } func (t *trackedWorker) ReadPiece(ctx context.Context, writer io.Writer, id abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize) (storiface.CallID, error) { - return t.tracker.track(id, sealtasks.TTReadUnsealed)(t.Worker.ReadPiece(ctx, writer, id, index, size)) + return t.tracker.track(t.wid, id, sealtasks.TTReadUnsealed)(t.Worker.ReadPiece(ctx, writer, id, index, size)) } var _ Worker = &trackedWorker{} From 3003789288c25e428ef139e4765c0ca82af13b33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 23 Sep 2020 16:12:15 +0200 Subject: [PATCH 020/313] worker: Use a real datastore for keeping track of calls --- cmd/lotus-seal-worker/main.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/cmd/lotus-seal-worker/main.go b/cmd/lotus-seal-worker/main.go index 292590c2e..dc7ad4028 100644 --- a/cmd/lotus-seal-worker/main.go +++ b/cmd/lotus-seal-worker/main.go @@ -14,7 +14,6 @@ import ( "github.com/google/uuid" "github.com/gorilla/mux" - "github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore/namespace" logging "github.com/ipfs/go-log/v2" manet "github.com/multiformats/go-multiaddr/net" @@ -304,6 +303,15 @@ var runCmd = &cli.Command{ if err != nil { return err } + defer func() { + if err := lr.Close(); err != nil { + log.Error("closing repo", err) + } + }() + ds, err := lr.Datastore("/metadata") + if err != nil { + return err + } log.Info("Opening local storage; connecting to master") const unspecifiedAddress = "0.0.0.0" @@ -343,7 +351,7 @@ var runCmd = &cli.Command{ // Create / expose the worker - wsts := statestore.New(namespace.Wrap(datastore.NewMapDatastore(), modules.WorkerCallsPrefix)) // TODO: USE A REAL DATASTORE + wsts := statestore.New(namespace.Wrap(ds, modules.WorkerCallsPrefix)) workerApi := &worker{ LocalWorker: sectorstorage.NewLocalWorker(sectorstorage.WorkerConfig{ From c17f0d7e61fdbc4db05a8d1003ddbbb03f0e9dae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 23 Sep 2020 17:37:05 +0200 Subject: [PATCH 021/313] sectorstorage: Fix panic in returnResult --- extern/sector-storage/manager_calltracker.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/extern/sector-storage/manager_calltracker.go b/extern/sector-storage/manager_calltracker.go index e62f964b3..01bc7c38d 100644 --- a/extern/sector-storage/manager_calltracker.go +++ b/extern/sector-storage/manager_calltracker.go @@ -320,8 +320,11 @@ func (m *Manager) returnResult(callID storiface.CallID, r interface{}, serr stri m.results[wid] = res - close(m.waitRes[wid]) - delete(m.waitRes, wid) + _, found := m.waitRes[wid] + if found { + close(m.waitRes[wid]) + delete(m.waitRes, wid) + } return nil } From d817dceb05797c2d3706f9fa04c7f927932ba4eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 23 Sep 2020 19:26:26 +0200 Subject: [PATCH 022/313] Show lost calls in sealing jobs cli --- api/api_storage.go | 2 +- api/apistruct/struct.go | 4 +-- cmd/lotus-storage-miner/sealing.go | 22 +++++++++----- extern/sector-storage/manager.go | 2 +- extern/sector-storage/stats.go | 36 ++++++++++++++++++----- extern/sector-storage/storiface/worker.go | 2 +- node/impl/storminer.go | 2 +- 7 files changed, 50 insertions(+), 20 deletions(-) diff --git a/api/api_storage.go b/api/api_storage.go index aab4e364a..aee5b5b5b 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -63,7 +63,7 @@ type StorageMiner interface { // WorkerConnect tells the node to connect to workers RPC WorkerConnect(context.Context, string) error WorkerStats(context.Context) (map[uint64]storiface.WorkerStats, error) - WorkerJobs(context.Context) (map[uint64][]storiface.WorkerJob, error) + WorkerJobs(context.Context) (map[int64][]storiface.WorkerJob, error) storiface.WorkerReturn // SealingSchedDiag dumps internal sealing scheduler state diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 60e03f565..d4b48d66d 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -280,7 +280,7 @@ type StorageMinerStruct struct { WorkerConnect func(context.Context, string) error `perm:"admin"` // TODO: worker perm WorkerStats func(context.Context) (map[uint64]storiface.WorkerStats, error) `perm:"admin"` - WorkerJobs func(context.Context) (map[uint64][]storiface.WorkerJob, error) `perm:"admin"` + WorkerJobs func(context.Context) (map[int64][]storiface.WorkerJob, error) `perm:"admin"` ReturnAddPiece func(ctx context.Context, callID storiface.CallID, pi abi.PieceInfo, err string) error `perm:"admin"` ReturnSealPreCommit1 func(ctx context.Context, callID storiface.CallID, p1o storage.PreCommit1Out, err string) error `perm:"admin"` @@ -1093,7 +1093,7 @@ func (c *StorageMinerStruct) WorkerStats(ctx context.Context) (map[uint64]storif return c.Internal.WorkerStats(ctx) } -func (c *StorageMinerStruct) WorkerJobs(ctx context.Context) (map[uint64][]storiface.WorkerJob, error) { +func (c *StorageMinerStruct) WorkerJobs(ctx context.Context) (map[int64][]storiface.WorkerJob, error) { return c.Internal.WorkerJobs(ctx) } diff --git a/cmd/lotus-storage-miner/sealing.go b/cmd/lotus-storage-miner/sealing.go index 5cc5c419a..7d612a03a 100644 --- a/cmd/lotus-storage-miner/sealing.go +++ b/cmd/lotus-storage-miner/sealing.go @@ -1,6 +1,7 @@ package main import ( + "encoding/hex" "encoding/json" "fmt" "os" @@ -9,10 +10,9 @@ import ( "text/tabwriter" "time" - "golang.org/x/xerrors" - "github.com/fatih/color" "github.com/urfave/cli/v2" + "golang.org/x/xerrors" "github.com/filecoin-project/lotus/extern/sector-storage/storiface" @@ -139,7 +139,7 @@ var sealingJobsCmd = &cli.Command{ type line struct { storiface.WorkerJob - wid uint64 + wid int64 } lines := make([]line, 0) @@ -161,7 +161,7 @@ var sealingJobsCmd = &cli.Command{ return lines[i].Start.Before(lines[j].Start) }) - workerHostnames := map[uint64]string{} + workerHostnames := map[int64]string{} wst, err := nodeApi.WorkerStats(ctx) if err != nil { @@ -169,7 +169,7 @@ var sealingJobsCmd = &cli.Command{ } for wid, st := range wst { - workerHostnames[wid] = st.Info.Hostname + workerHostnames[int64(wid)] = st.Info.Hostname } tw := tabwriter.NewWriter(os.Stdout, 2, 4, 2, ' ', 0) @@ -177,10 +177,18 @@ var sealingJobsCmd = &cli.Command{ for _, l := range lines { state := "running" - if l.RunWait != 0 { + if l.RunWait > 0 { state = fmt.Sprintf("assigned(%d)", l.RunWait-1) } - _, _ = fmt.Fprintf(tw, "%d\t%d\t%d\t%s\t%s\t%s\t%s\n", l.ID, l.Sector.Number, l.wid, workerHostnames[l.wid], l.Task.Short(), state, time.Now().Sub(l.Start).Truncate(time.Millisecond*100)) + if l.RunWait == -1 { + state = "ret-wait" + } + dur := "n/a" + if !l.Start.IsZero() { + dur = time.Now().Sub(l.Start).Truncate(time.Millisecond * 100).String() + } + + _, _ = fmt.Fprintf(tw, "%s\t%d\t%d\t%s\t%s\t%s\t%s\n", hex.EncodeToString(l.ID.ID[10:]), l.Sector.Number, l.wid, workerHostnames[l.wid], l.Task.Short(), state, dur) } return tw.Flush() diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index d4db60806..c8553a4e9 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -57,7 +57,7 @@ type SectorManager interface { FaultTracker } -type WorkerID uint64 +type WorkerID int64 type Manager struct { scfg *ffiwrapper.Config diff --git a/extern/sector-storage/stats.go b/extern/sector-storage/stats.go index 1ce415fd2..9b8cbc24e 100644 --- a/extern/sector-storage/stats.go +++ b/extern/sector-storage/stats.go @@ -2,6 +2,7 @@ package sectorstorage import ( "github.com/filecoin-project/lotus/extern/sector-storage/storiface" + "time" ) func (m *Manager) WorkerStats() map[uint64]storiface.WorkerStats { @@ -23,21 +24,22 @@ func (m *Manager) WorkerStats() map[uint64]storiface.WorkerStats { return out } -func (m *Manager) WorkerJobs() map[uint64][]storiface.WorkerJob { - m.sched.workersLk.RLock() - defer m.sched.workersLk.RUnlock() - - out := map[uint64][]storiface.WorkerJob{} +func (m *Manager) WorkerJobs() map[int64][]storiface.WorkerJob { + out := map[int64][]storiface.WorkerJob{} + calls := map[storiface.CallID]struct{}{} for _, t := range m.sched.wt.Running() { - out[uint64(t.worker)] = append(out[uint64(t.worker)], t.job) + out[int64(t.worker)] = append(out[int64(t.worker)], t.job) + calls[t.job.ID] = struct{}{} } + m.sched.workersLk.RLock() + for id, handle := range m.sched.workers { handle.wndLk.Lock() for wi, window := range handle.activeWindows { for _, request := range window.todo { - out[uint64(id)] = append(out[uint64(id)], storiface.WorkerJob{ + out[int64(id)] = append(out[int64(id)], storiface.WorkerJob{ ID: storiface.UndefCall, Sector: request.sector, Task: request.taskType, @@ -49,5 +51,25 @@ func (m *Manager) WorkerJobs() map[uint64][]storiface.WorkerJob { handle.wndLk.Unlock() } + m.sched.workersLk.RUnlock() + + m.workLk.Lock() + defer m.workLk.Unlock() + + for id := range m.callToWork { + _, found := calls[id] + if found { + continue + } + + out[-1] = append(out[-1], storiface.WorkerJob{ + ID: id, + Sector: id.Sector, + Task: "???", + RunWait: -1, + Start: time.Time{}, + }) + } + return out } diff --git a/extern/sector-storage/storiface/worker.go b/extern/sector-storage/storiface/worker.go index ead770524..e6ab2246f 100644 --- a/extern/sector-storage/storiface/worker.go +++ b/extern/sector-storage/storiface/worker.go @@ -45,7 +45,7 @@ type WorkerJob struct { Sector abi.SectorID Task sealtasks.TaskType - RunWait int // 0 - running, 1+ - assigned + RunWait int // -1 - ret-wait, 0 - running, 1+ - assigned Start time.Time } diff --git a/node/impl/storminer.go b/node/impl/storminer.go index 337640027..ba0719078 100644 --- a/node/impl/storminer.go +++ b/node/impl/storminer.go @@ -87,7 +87,7 @@ func (sm *StorageMinerAPI) WorkerStats(context.Context) (map[uint64]storiface.Wo return sm.StorageMgr.WorkerStats(), nil } -func (sm *StorageMinerAPI) WorkerJobs(ctx context.Context) (map[uint64][]storiface.WorkerJob, error) { +func (sm *StorageMinerAPI) WorkerJobs(ctx context.Context) (map[int64][]storiface.WorkerJob, error) { return sm.StorageMgr.WorkerJobs(), nil } From 04ee53e0612a04dde59a2bf9dc509d3addef0a88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 24 Sep 2020 11:55:11 +0200 Subject: [PATCH 023/313] sectorstorage: Show task type of ret-wait jobs --- cmd/lotus-storage-miner/sealing.go | 3 +++ extern/sector-storage/cbor_gen.go | 7 ++++--- extern/sector-storage/manager.go | 8 ++++---- extern/sector-storage/manager_calltracker.go | 12 +++++++++--- extern/sector-storage/stats.go | 4 ++-- 5 files changed, 22 insertions(+), 12 deletions(-) diff --git a/cmd/lotus-storage-miner/sealing.go b/cmd/lotus-storage-miner/sealing.go index 7d612a03a..62276a0e3 100644 --- a/cmd/lotus-storage-miner/sealing.go +++ b/cmd/lotus-storage-miner/sealing.go @@ -158,6 +158,9 @@ var sealingJobsCmd = &cli.Command{ if lines[i].RunWait != lines[j].RunWait { return lines[i].RunWait < lines[j].RunWait } + if lines[i].Start.Equal(lines[j].Start) { + return lines[i].ID.ID.String() < lines[j].ID.ID.String() + } return lines[i].Start.Before(lines[j].Start) }) diff --git a/extern/sector-storage/cbor_gen.go b/extern/sector-storage/cbor_gen.go index 51b82ef13..0db97f2c9 100644 --- a/extern/sector-storage/cbor_gen.go +++ b/extern/sector-storage/cbor_gen.go @@ -6,6 +6,7 @@ import ( "fmt" "io" + sealtasks "github.com/filecoin-project/lotus/extern/sector-storage/sealtasks" cbg "github.com/whyrusleeping/cbor-gen" xerrors "golang.org/x/xerrors" ) @@ -378,7 +379,7 @@ func (t *WorkID) MarshalCBOR(w io.Writer) error { scratch := make([]byte, 9) - // t.Method (string) (string) + // t.Method (sealtasks.TaskType) (string) if len("Method") > cbg.MaxLength { return xerrors.Errorf("Value in field \"Method\" was too long") } @@ -459,7 +460,7 @@ func (t *WorkID) UnmarshalCBOR(r io.Reader) error { } switch name { - // t.Method (string) (string) + // t.Method (sealtasks.TaskType) (string) case "Method": { @@ -468,7 +469,7 @@ func (t *WorkID) UnmarshalCBOR(r io.Reader) error { return err } - t.Method = string(sval) + t.Method = sealtasks.TaskType(sval) } // t.Params (string) (string) case "Params": diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index c8553a4e9..7d49cc958 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -364,7 +364,7 @@ func (m *Manager) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticke ctx, cancel := context.WithCancel(ctx) defer cancel() - wk, wait, err := m.getWork(ctx, "PreCommit1", sector, ticket, pieces) + wk, wait, err := m.getWork(ctx, sealtasks.TTPreCommit1, sector, ticket, pieces) if err != nil { return nil, xerrors.Errorf("getWork: %w", err) } @@ -408,7 +408,7 @@ func (m *Manager) SealPreCommit2(ctx context.Context, sector abi.SectorID, phase ctx, cancel := context.WithCancel(ctx) defer cancel() - wk, wait, err := m.getWork(ctx, "PreCommit2", sector, phase1Out) + wk, wait, err := m.getWork(ctx, sealtasks.TTPreCommit2, sector, phase1Out) if err != nil { return storage.SectorCids{}, xerrors.Errorf("getWork: %w", err) } @@ -449,7 +449,7 @@ func (m *Manager) SealCommit1(ctx context.Context, sector abi.SectorID, ticket a ctx, cancel := context.WithCancel(ctx) defer cancel() - wk, wait, err := m.getWork(ctx, "Commit1", sector, ticket, seed, pieces, cids) + wk, wait, err := m.getWork(ctx, sealtasks.TTCommit1, sector, ticket, seed, pieces, cids) if err != nil { return storage.Commit1Out{}, xerrors.Errorf("getWork: %w", err) } @@ -490,7 +490,7 @@ func (m *Manager) SealCommit1(ctx context.Context, sector abi.SectorID, ticket a } func (m *Manager) SealCommit2(ctx context.Context, sector abi.SectorID, phase1Out storage.Commit1Out) (out storage.Proof, err error) { - wk, wait, err := m.getWork(ctx, "Commit2", sector, phase1Out) + wk, wait, err := m.getWork(ctx, sealtasks.TTCommit2, sector, phase1Out) if err != nil { return storage.Proof{}, xerrors.Errorf("getWork: %w", err) } diff --git a/extern/sector-storage/manager_calltracker.go b/extern/sector-storage/manager_calltracker.go index 01bc7c38d..865090467 100644 --- a/extern/sector-storage/manager_calltracker.go +++ b/extern/sector-storage/manager_calltracker.go @@ -8,12 +8,14 @@ import ( "errors" "fmt" "golang.org/x/xerrors" + "os" + "github.com/filecoin-project/lotus/extern/sector-storage/sealtasks" "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) type WorkID struct { - Method string + Method sealtasks.TaskType Params string // json [...params] } @@ -40,7 +42,7 @@ type WorkState struct { WorkError string // Status = wsDone, set when failed to start work } -func newWorkID(method string, params ...interface{}) (WorkID, error) { +func newWorkID(method sealtasks.TaskType, params ...interface{}) (WorkID, error) { pb, err := json.Marshal(params) if err != nil { return WorkID{}, xerrors.Errorf("marshaling work params: %w", err) @@ -74,6 +76,10 @@ func (m *Manager) setupWorkTracker() { continue } + if os.Getenv("LOTUS_MINER_ABORT_UNFINISHED_WORK") == "1" { + st.Status = wsDone + } + switch st.Status { case wsStarted: log.Warnf("dropping non-running work %s", wid) @@ -96,7 +102,7 @@ func (m *Manager) setupWorkTracker() { } // returns wait=true when the task is already tracked/running -func (m *Manager) getWork(ctx context.Context, method string, params ...interface{}) (wid WorkID, wait bool, err error) { +func (m *Manager) getWork(ctx context.Context, method sealtasks.TaskType, params ...interface{}) (wid WorkID, wait bool, err error) { wid, err = newWorkID(method, params) if err != nil { return WorkID{}, false, xerrors.Errorf("creating WorkID: %w", err) diff --git a/extern/sector-storage/stats.go b/extern/sector-storage/stats.go index 9b8cbc24e..849322be0 100644 --- a/extern/sector-storage/stats.go +++ b/extern/sector-storage/stats.go @@ -56,7 +56,7 @@ func (m *Manager) WorkerJobs() map[int64][]storiface.WorkerJob { m.workLk.Lock() defer m.workLk.Unlock() - for id := range m.callToWork { + for id, work := range m.callToWork { _, found := calls[id] if found { continue @@ -65,7 +65,7 @@ func (m *Manager) WorkerJobs() map[int64][]storiface.WorkerJob { out[-1] = append(out[-1], storiface.WorkerJob{ ID: id, Sector: id.Sector, - Task: "???", + Task: work.Method, RunWait: -1, Start: time.Time{}, }) From a8fcb86c10986839e700444e5f9705be8561bc61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 24 Sep 2020 22:17:20 +0200 Subject: [PATCH 024/313] miner allinfo: Don't fail if sector status fails --- cmd/lotus-storage-miner/info_all.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/lotus-storage-miner/info_all.go b/cmd/lotus-storage-miner/info_all.go index 265ba78a4..74f27fec5 100644 --- a/cmd/lotus-storage-miner/info_all.go +++ b/cmd/lotus-storage-miner/info_all.go @@ -135,7 +135,7 @@ var infoAllCmd = &cli.Command{ } if err := sectorsStatusCmd.Action(cli.NewContext(cctx.App, fs, cctx)); err != nil { - return err + fmt.Println("ERROR: ", err) } fmt.Printf("\n##: Sector %d Storage Location\n", s) @@ -146,7 +146,7 @@ var infoAllCmd = &cli.Command{ } if err := storageFindCmd.Action(cli.NewContext(cctx.App, fs, cctx)); err != nil { - return err + fmt.Println("ERROR: ", err) } } From a9d1ca4d83362e15b8fea113ec2733e52b5f2409 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 28 Sep 2020 12:08:09 +0200 Subject: [PATCH 025/313] Change order in miner sectors list --- cmd/lotus-storage-miner/sectors.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/lotus-storage-miner/sectors.go b/cmd/lotus-storage-miner/sectors.go index 370962bdc..67b14b382 100644 --- a/cmd/lotus-storage-miner/sectors.go +++ b/cmd/lotus-storage-miner/sectors.go @@ -205,15 +205,15 @@ var sectorsListCmd = &cli.Command{ _, inSSet := commitedIDs[s] _, inASet := activeIDs[s] - _, _ = fmt.Fprintf(w, "%d: %s\tsSet: %s\tactive: %s\ttktH: %d\tseedH: %d\tdeals: %v\t toUpgrade:%t\n", + _, _ = fmt.Fprintf(w, "%d: %s\tsSet: %s\tactive: %s\ttktH: %d\tseedH: %d\ttoUpgrade: %t\tdeals: %v\n", s, st.State, yesno(inSSet), yesno(inASet), st.Ticket.Epoch, st.Seed.Epoch, - st.Deals, st.ToUpgrade, + st.Deals, ) } } From 9e7d6823b1950f684242a899143597c31279d720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 28 Sep 2020 13:34:45 +0200 Subject: [PATCH 026/313] sectorstorage: Cleanup callToWork mapping after work is done --- extern/sector-storage/manager_calltracker.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/extern/sector-storage/manager_calltracker.go b/extern/sector-storage/manager_calltracker.go index 865090467..147e11b91 100644 --- a/extern/sector-storage/manager_calltracker.go +++ b/extern/sector-storage/manager_calltracker.go @@ -232,6 +232,11 @@ func (m *Manager) waitWork(ctx context.Context, wid WorkID) (interface{}, error) res := m.results[wid] delete(m.results, wid) + _, ok := m.callToWork[ws.WorkerCall] + if ok { + delete(m.callToWork, ws.WorkerCall) + } + err := m.work.Get(wk).End() if err != nil { // Not great, but not worth discarding potentially multi-hour computation over this From 86cf3c835ea36ac4e9b14679bd661b45bf3e394a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 28 Sep 2020 13:37:50 +0200 Subject: [PATCH 027/313] worker: Reconnect correctly --- cmd/lotus-seal-worker/main.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/lotus-seal-worker/main.go b/cmd/lotus-seal-worker/main.go index dc7ad4028..de2be716b 100644 --- a/cmd/lotus-seal-worker/main.go +++ b/cmd/lotus-seal-worker/main.go @@ -172,7 +172,6 @@ var runCmd = &cli.Command{ var err error for { nodeApi, closer, err = lcli.GetStorageMinerAPI(cctx, - jsonrpc.WithNoReconnect(), jsonrpc.WithTimeout(30*time.Second)) if err == nil { break From 4ba7af606192a71ec0f35f754a0e1f9afb460986 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 28 Sep 2020 20:46:44 +0200 Subject: [PATCH 028/313] worker: Mark return methods as retry-safe --- api/apistruct/struct.go | 24 ++++++++++++------------ cmd/lotus-seal-worker/main.go | 3 +-- extern/sector-storage/stores/local.go | 2 +- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 1122dd76b..07035221e 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -279,21 +279,21 @@ type StorageMinerStruct struct { SectorRemove func(context.Context, abi.SectorNumber) error `perm:"admin"` SectorMarkForUpgrade func(ctx context.Context, id abi.SectorNumber) error `perm:"admin"` - WorkerConnect func(context.Context, string) error `perm:"admin"` // TODO: worker perm + WorkerConnect func(context.Context, string) error `perm:"admin" retry:"true"` // TODO: worker perm WorkerStats func(context.Context) (map[uint64]storiface.WorkerStats, error) `perm:"admin"` WorkerJobs func(context.Context) (map[int64][]storiface.WorkerJob, error) `perm:"admin"` - ReturnAddPiece func(ctx context.Context, callID storiface.CallID, pi abi.PieceInfo, err string) error `perm:"admin"` - ReturnSealPreCommit1 func(ctx context.Context, callID storiface.CallID, p1o storage.PreCommit1Out, err string) error `perm:"admin"` - ReturnSealPreCommit2 func(ctx context.Context, callID storiface.CallID, sealed storage.SectorCids, err string) error `perm:"admin"` - ReturnSealCommit1 func(ctx context.Context, callID storiface.CallID, out storage.Commit1Out, err string) error `perm:"admin"` - ReturnSealCommit2 func(ctx context.Context, callID storiface.CallID, proof storage.Proof, err string) error `perm:"admin"` - ReturnFinalizeSector func(ctx context.Context, callID storiface.CallID, err string) error `perm:"admin"` - ReturnReleaseUnsealed func(ctx context.Context, callID storiface.CallID, err string) error `perm:"admin"` - ReturnMoveStorage func(ctx context.Context, callID storiface.CallID, err string) error `perm:"admin"` - ReturnUnsealPiece func(ctx context.Context, callID storiface.CallID, err string) error `perm:"admin"` - ReturnReadPiece func(ctx context.Context, callID storiface.CallID, ok bool, err string) error `perm:"admin"` - ReturnFetch func(ctx context.Context, callID storiface.CallID, err string) error `perm:"admin"` + ReturnAddPiece func(ctx context.Context, callID storiface.CallID, pi abi.PieceInfo, err string) error `perm:"admin" retry:"true"` + ReturnSealPreCommit1 func(ctx context.Context, callID storiface.CallID, p1o storage.PreCommit1Out, err string) error `perm:"admin" retry:"true"` + ReturnSealPreCommit2 func(ctx context.Context, callID storiface.CallID, sealed storage.SectorCids, err string) error `perm:"admin" retry:"true"` + ReturnSealCommit1 func(ctx context.Context, callID storiface.CallID, out storage.Commit1Out, err string) error `perm:"admin" retry:"true"` + ReturnSealCommit2 func(ctx context.Context, callID storiface.CallID, proof storage.Proof, err string) error `perm:"admin" retry:"true"` + ReturnFinalizeSector func(ctx context.Context, callID storiface.CallID, err string) error `perm:"admin" retry:"true"` + ReturnReleaseUnsealed func(ctx context.Context, callID storiface.CallID, err string) error `perm:"admin" retry:"true"` + ReturnMoveStorage func(ctx context.Context, callID storiface.CallID, err string) error `perm:"admin" retry:"true"` + ReturnUnsealPiece func(ctx context.Context, callID storiface.CallID, err string) error `perm:"admin" retry:"true"` + ReturnReadPiece func(ctx context.Context, callID storiface.CallID, ok bool, err string) error `perm:"admin" retry:"true"` + ReturnFetch func(ctx context.Context, callID storiface.CallID, err string) error `perm:"admin" retry:"true"` SealingSchedDiag func(context.Context) (interface{}, error) `perm:"admin"` diff --git a/cmd/lotus-seal-worker/main.go b/cmd/lotus-seal-worker/main.go index de2be716b..703f23055 100644 --- a/cmd/lotus-seal-worker/main.go +++ b/cmd/lotus-seal-worker/main.go @@ -171,8 +171,7 @@ var runCmd = &cli.Command{ var closer func() var err error for { - nodeApi, closer, err = lcli.GetStorageMinerAPI(cctx, - jsonrpc.WithTimeout(30*time.Second)) + nodeApi, closer, err = lcli.GetStorageMinerAPI(cctx, jsonrpc.WithTimeout(30*time.Second)) if err == nil { break } diff --git a/extern/sector-storage/stores/local.go b/extern/sector-storage/stores/local.go index ee8af3272..5ac92b337 100644 --- a/extern/sector-storage/stores/local.go +++ b/extern/sector-storage/stores/local.go @@ -257,7 +257,7 @@ func (st *Local) reportHealth(ctx context.Context) { for id, report := range toReport { if err := st.index.StorageReportHealth(ctx, id, report); err != nil { - log.Warnf("error reporting storage health for %s: %+v", id, report) + log.Warnf("error reporting storage health for %s (%+v): %+v", id, report, err) } } } From 810c76720034e7189eabc412555364df94128bf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 28 Sep 2020 21:06:49 +0200 Subject: [PATCH 029/313] worker: Redeclare storage on reconnect --- api/apistruct/struct.go | 2 +- cmd/lotus-seal-worker/main.go | 11 +++ extern/sector-storage/stores/local.go | 96 +++++++++++++++++++++------ 3 files changed, 86 insertions(+), 23 deletions(-) diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 07035221e..3abc5a18b 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -300,7 +300,7 @@ type StorageMinerStruct struct { StorageList func(context.Context) (map[stores.ID][]stores.Decl, error) `perm:"admin"` StorageLocal func(context.Context) (map[stores.ID]string, error) `perm:"admin"` StorageStat func(context.Context, stores.ID) (fsutil.FsStat, error) `perm:"admin"` - StorageAttach func(context.Context, stores.StorageInfo, fsutil.FsStat) error `perm:"admin"` + StorageAttach func(context.Context, stores.StorageInfo, fsutil.FsStat) error `perm:"admin" retry:"true"` StorageDeclareSector func(context.Context, stores.ID, abi.SectorID, storiface.SectorFileType, bool) error `perm:"admin"` StorageDropSector func(context.Context, stores.ID, abi.SectorID, storiface.SectorFileType) error `perm:"admin"` StorageFindSector func(context.Context, abi.SectorID, storiface.SectorFileType, abi.RegisteredSealProof, bool) ([]stores.SectorStorageInfo, error) `perm:"admin"` diff --git a/cmd/lotus-seal-worker/main.go b/cmd/lotus-seal-worker/main.go index 703f23055..b34e99994 100644 --- a/cmd/lotus-seal-worker/main.go +++ b/cmd/lotus-seal-worker/main.go @@ -426,12 +426,21 @@ var runCmd = &cli.Command{ } go func() { + var reconnect bool for { log.Info("Making sure no local tasks are running") // TODO: we could get rid of this, but that requires tracking resources for restarted tasks correctly workerApi.LocalWorker.WaitQuiet() + if reconnect { + if err := localStore.Redeclare(ctx); err != nil { + log.Errorf("Redeclaring local storage failed: %+v", err) + cancel() + return + } + } + if err := nodeApi.WorkerConnect(ctx, "ws://"+address+"/rpc/v0"); err != nil { log.Errorf("Registering worker failed: %+v", err) cancel() @@ -455,6 +464,8 @@ var runCmd = &cli.Command{ } log.Errorf("LOTUS-MINER CONNECTION LOST") + + reconnect = true } }() diff --git a/extern/sector-storage/stores/local.go b/extern/sector-storage/stores/local.go index 5ac92b337..216e88cba 100644 --- a/extern/sector-storage/stores/local.go +++ b/extern/sector-storage/stores/local.go @@ -178,6 +178,78 @@ func (st *Local) OpenPath(ctx context.Context, p string) error { return xerrors.Errorf("declaring storage in index: %w", err) } + if err := st.declareSectors(ctx, p, meta.ID, meta.CanStore); err != nil { + return err + } + + st.paths[meta.ID] = out + + return nil +} + +func (st *Local) open(ctx context.Context) error { + cfg, err := st.localStorage.GetStorage() + if err != nil { + return xerrors.Errorf("getting local storage config: %w", err) + } + + for _, path := range cfg.StoragePaths { + err := st.OpenPath(ctx, path.Path) + if err != nil { + return xerrors.Errorf("opening path %s: %w", path.Path, err) + } + } + + go st.reportHealth(ctx) + + return nil +} + +func (st *Local) Redeclare(ctx context.Context) error { + st.localLk.Lock() + defer st.localLk.Unlock() + + for id, p := range st.paths { + mb, err := ioutil.ReadFile(filepath.Join(p.local, MetaFile)) + if err != nil { + return xerrors.Errorf("reading storage metadata for %s: %w", p, err) + } + + var meta LocalStorageMeta + if err := json.Unmarshal(mb, &meta); err != nil { + return xerrors.Errorf("unmarshalling storage metadata for %s: %w", p, err) + } + + fst, err := p.stat(st.localStorage) + if err != nil { + return err + } + + if id != meta.ID { + log.Errorf("storage path ID changed: %s; %s -> %s", p.local, id, meta.ID) + continue + } + + err = st.index.StorageAttach(ctx, StorageInfo{ + ID: id, + URLs: st.urls, + Weight: meta.Weight, + CanSeal: meta.CanSeal, + CanStore: meta.CanStore, + }, fst) + if err != nil { + return xerrors.Errorf("redeclaring storage in index: %w", err) + } + + if err := st.declareSectors(ctx, p.local, meta.ID, meta.CanStore); err != nil { + return xerrors.Errorf("redeclaring sectors: %w", err) + } + } + + return nil +} + +func (st *Local) declareSectors(ctx context.Context, p string, id ID, primary bool) error { for _, t := range storiface.PathTypes { ents, err := ioutil.ReadDir(filepath.Join(p, t.String())) if err != nil { @@ -201,32 +273,12 @@ func (st *Local) OpenPath(ctx context.Context, p string) error { return xerrors.Errorf("parse sector id %s: %w", ent.Name(), err) } - if err := st.index.StorageDeclareSector(ctx, meta.ID, sid, t, meta.CanStore); err != nil { - return xerrors.Errorf("declare sector %d(t:%d) -> %s: %w", sid, t, meta.ID, err) + if err := st.index.StorageDeclareSector(ctx, id, sid, t, primary); err != nil { + return xerrors.Errorf("declare sector %d(t:%d) -> %s: %w", sid, t, id, err) } } } - st.paths[meta.ID] = out - - return nil -} - -func (st *Local) open(ctx context.Context) error { - cfg, err := st.localStorage.GetStorage() - if err != nil { - return xerrors.Errorf("getting local storage config: %w", err) - } - - for _, path := range cfg.StoragePaths { - err := st.OpenPath(ctx, path.Path) - if err != nil { - return xerrors.Errorf("opening path %s: %w", path.Path, err) - } - } - - go st.reportHealth(ctx) - return nil } From bf554d0e43bdeb34b9d62314b4f732929c0c92c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 28 Sep 2020 21:11:25 +0200 Subject: [PATCH 030/313] worker: Redeclare storage early on reconnect --- cmd/lotus-seal-worker/main.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/cmd/lotus-seal-worker/main.go b/cmd/lotus-seal-worker/main.go index b34e99994..fb576f874 100644 --- a/cmd/lotus-seal-worker/main.go +++ b/cmd/lotus-seal-worker/main.go @@ -428,12 +428,9 @@ var runCmd = &cli.Command{ go func() { var reconnect bool for { - log.Info("Making sure no local tasks are running") - - // TODO: we could get rid of this, but that requires tracking resources for restarted tasks correctly - workerApi.LocalWorker.WaitQuiet() - if reconnect { + log.Info("Redeclaring local storage") + if err := localStore.Redeclare(ctx); err != nil { log.Errorf("Redeclaring local storage failed: %+v", err) cancel() @@ -441,6 +438,12 @@ var runCmd = &cli.Command{ } } + log.Info("Making sure no local tasks are running") + + // TODO: we could get rid of this, but that requires tracking resources for restarted tasks correctly + workerApi.LocalWorker.WaitQuiet() + + if err := nodeApi.WorkerConnect(ctx, "ws://"+address+"/rpc/v0"); err != nil { log.Errorf("Registering worker failed: %+v", err) cancel() From 9bd25379711ce925c9e71d34c1313e2b933870e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 28 Sep 2020 22:05:51 +0200 Subject: [PATCH 031/313] stores: Fix error printing in http handler --- cmd/lotus-seal-worker/main.go | 1 - extern/sector-storage/stores/http_handler.go | 18 +++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/cmd/lotus-seal-worker/main.go b/cmd/lotus-seal-worker/main.go index fb576f874..0a88eacb4 100644 --- a/cmd/lotus-seal-worker/main.go +++ b/cmd/lotus-seal-worker/main.go @@ -443,7 +443,6 @@ var runCmd = &cli.Command{ // TODO: we could get rid of this, but that requires tracking resources for restarted tasks correctly workerApi.LocalWorker.WaitQuiet() - if err := nodeApi.WorkerConnect(ctx, "ws://"+address+"/rpc/v0"); err != nil { log.Errorf("Registering worker failed: %+v", err) cancel() diff --git a/extern/sector-storage/stores/http_handler.go b/extern/sector-storage/stores/http_handler.go index a5a2cd913..8891132ce 100644 --- a/extern/sector-storage/stores/http_handler.go +++ b/extern/sector-storage/stores/http_handler.go @@ -58,14 +58,14 @@ func (handler *FetchHandler) remoteGetSector(w http.ResponseWriter, r *http.Requ id, err := storiface.ParseSectorID(vars["id"]) if err != nil { - log.Error("%+v", err) + log.Errorf("%+v", err) w.WriteHeader(500) return } ft, err := ftFromString(vars["type"]) if err != nil { - log.Error("%+v", err) + log.Errorf("%+v", err) w.WriteHeader(500) return } @@ -75,7 +75,7 @@ func (handler *FetchHandler) remoteGetSector(w http.ResponseWriter, r *http.Requ // passing 0 spt because we don't allocate anything paths, _, err := handler.Local.AcquireSector(r.Context(), id, 0, ft, storiface.FTNone, storiface.PathStorage, storiface.AcquireMove) if err != nil { - log.Error("%+v", err) + log.Errorf("%+v", err) w.WriteHeader(500) return } @@ -91,7 +91,7 @@ func (handler *FetchHandler) remoteGetSector(w http.ResponseWriter, r *http.Requ stat, err := os.Stat(path) if err != nil { - log.Error("%+v", err) + log.Errorf("%+v", err) w.WriteHeader(500) return } @@ -105,14 +105,14 @@ func (handler *FetchHandler) remoteGetSector(w http.ResponseWriter, r *http.Requ w.Header().Set("Content-Type", "application/octet-stream") } if err != nil { - log.Error("%+v", err) + log.Errorf("%+v", err) w.WriteHeader(500) return } w.WriteHeader(200) if _, err := io.Copy(w, rd); err != nil { // TODO: default 32k buf may be too small - log.Error("%+v", err) + log.Errorf("%+v", err) return } } @@ -123,20 +123,20 @@ func (handler *FetchHandler) remoteDeleteSector(w http.ResponseWriter, r *http.R id, err := storiface.ParseSectorID(vars["id"]) if err != nil { - log.Error("%+v", err) + log.Errorf("%+v", err) w.WriteHeader(500) return } ft, err := ftFromString(vars["type"]) if err != nil { - log.Error("%+v", err) + log.Errorf("%+v", err) w.WriteHeader(500) return } if err := handler.Remove(r.Context(), id, ft, false); err != nil { - log.Error("%+v", err) + log.Errorf("%+v", err) w.WriteHeader(500) return } From 1e6a69f8aa76846f234534eec6003b00b9e733b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 28 Sep 2020 22:10:02 +0200 Subject: [PATCH 032/313] localworker: Don't mark calls as returned when returning fails --- extern/sector-storage/worker_local.go | 1 + 1 file changed, 1 insertion(+) diff --git a/extern/sector-storage/worker_local.go b/extern/sector-storage/worker_local.go index 495c9630d..68be481d9 100644 --- a/extern/sector-storage/worker_local.go +++ b/extern/sector-storage/worker_local.go @@ -229,6 +229,7 @@ func (l *LocalWorker) asyncCall(ctx context.Context, sector abi.SectorID, rt Ret if err := returnFunc[rt](ctx, ci, l.ret, res, err); err != nil { log.Errorf("return error: %s: %+v", rt, err) + return } if err := l.ct.onReturned(ci); err != nil { From 0f2dcf28b1f4da306ebd99e9792add208713716e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 29 Sep 2020 09:57:36 +0200 Subject: [PATCH 033/313] fsm: Reuse tickets in PC1 on retry --- extern/sector-storage/manager_test.go | 5 ----- extern/sector-storage/sched_test.go | 2 +- extern/storage-sealing/fsm.go | 9 +++++++- extern/storage-sealing/fsm_events.go | 18 ++++++++++++---- extern/storage-sealing/sector_state.go | 1 + extern/storage-sealing/states_sealing.go | 27 ++++++++++++++++++------ 6 files changed, 45 insertions(+), 17 deletions(-) diff --git a/extern/sector-storage/manager_test.go b/extern/sector-storage/manager_test.go index 0fada08bc..d87ec0827 100644 --- a/extern/sector-storage/manager_test.go +++ b/extern/sector-storage/manager_test.go @@ -115,11 +115,6 @@ func newTestMgr(ctx context.Context, t *testing.T, ds datastore.Datastore) (*Man Prover: prover, - wt: &workTracker{ - done: map[storiface.CallID]struct{}{}, - running: map[storiface.CallID]trackedWork{}, - }, - work: statestore.New(ds), callToWork: map[storiface.CallID]WorkID{}, callRes: map[storiface.CallID]chan result{}, diff --git a/extern/sector-storage/sched_test.go b/extern/sector-storage/sched_test.go index f23be20c0..a77576048 100644 --- a/extern/sector-storage/sched_test.go +++ b/extern/sector-storage/sched_test.go @@ -439,7 +439,7 @@ func TestSched(t *testing.T) { for _, job := range jobs { lines = append(lines, line{ WorkerJob: job, - wid: wid, + wid: uint64(wid), }) } } diff --git a/extern/storage-sealing/fsm.go b/extern/storage-sealing/fsm.go index 0d2e766fd..12af83f56 100644 --- a/extern/storage-sealing/fsm.go +++ b/extern/storage-sealing/fsm.go @@ -45,12 +45,14 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto on(SectorAddPiece{}, WaitDeals), on(SectorStartPacking{}, Packing), ), - Packing: planOne(on(SectorPacked{}, PreCommit1)), + Packing: planOne(on(SectorPacked{}, GetTicket)), + GetTicket: planOne(on(SectorTicket{}, PreCommit1)), PreCommit1: planOne( on(SectorPreCommit1{}, PreCommit2), on(SectorSealPreCommit1Failed{}, SealPreCommit1Failed), on(SectorDealsExpired{}, DealsExpired), on(SectorInvalidDealIDs{}, RecoverDealIDs), + on(SectorOldTicket{}, GetTicket), ), PreCommit2: planOne( on(SectorPreCommit2{}, PreCommitting), @@ -219,6 +221,9 @@ func (m *Sealing) plan(events []statemachine.Event, state *SectorInfo) (func(sta *<- Packing <- incoming committed capacity | | | v + | GetTicket + | | ^ + | v | *<- PreCommit1 <--> SealPreCommit1Failed | | ^ ^^ | | *----------++----\ @@ -267,6 +272,8 @@ func (m *Sealing) plan(events []statemachine.Event, state *SectorInfo) (func(sta log.Infof("Waiting for deals %d", state.SectorNumber) case Packing: return m.handlePacking, processed, nil + case GetTicket: + return m.handleGetTicket, processed, nil case PreCommit1: return m.handlePreCommit1, processed, nil case PreCommit2: diff --git a/extern/storage-sealing/fsm_events.go b/extern/storage-sealing/fsm_events.go index 3e597d761..aec2beb0a 100644 --- a/extern/storage-sealing/fsm_events.go +++ b/extern/storage-sealing/fsm_events.go @@ -101,16 +101,26 @@ func (evt SectorPacked) apply(state *SectorInfo) { } } +type SectorTicket struct { + TicketValue abi.SealRandomness + TicketEpoch abi.ChainEpoch +} + +func (evt SectorTicket) apply(state *SectorInfo) { + state.TicketEpoch = evt.TicketEpoch + state.TicketValue = evt.TicketValue +} + +type SectorOldTicket struct{} + +func (evt SectorOldTicket) apply(*SectorInfo) {} + type SectorPreCommit1 struct { PreCommit1Out storage.PreCommit1Out - TicketValue abi.SealRandomness - TicketEpoch abi.ChainEpoch } func (evt SectorPreCommit1) apply(state *SectorInfo) { state.PreCommit1Out = evt.PreCommit1Out - state.TicketEpoch = evt.TicketEpoch - state.TicketValue = evt.TicketValue state.PreCommit2Fails = 0 } diff --git a/extern/storage-sealing/sector_state.go b/extern/storage-sealing/sector_state.go index 10b96e504..8b0bff24a 100644 --- a/extern/storage-sealing/sector_state.go +++ b/extern/storage-sealing/sector_state.go @@ -41,6 +41,7 @@ const ( Empty SectorState = "Empty" WaitDeals SectorState = "WaitDeals" // waiting for more pieces (deals) to be added to the sector Packing SectorState = "Packing" // sector not in sealStore, and not on chain + GetTicket SectorState = "GetTicket" // generate ticket PreCommit1 SectorState = "PreCommit1" // do PreCommit1 PreCommit2 SectorState = "PreCommit2" // do PreCommit2 PreCommitting SectorState = "PreCommitting" // on chain pre-commit diff --git a/extern/storage-sealing/states_sealing.go b/extern/storage-sealing/states_sealing.go index a4e852454..55a3f27e8 100644 --- a/extern/storage-sealing/states_sealing.go +++ b/extern/storage-sealing/states_sealing.go @@ -21,6 +21,7 @@ import ( ) var DealSectorPriority = 1024 +var MaxTicketAge = abi.ChainEpoch(builtin.EpochsInDay * 2) func (m *Sealing) handlePacking(ctx statemachine.Context, sector SectorInfo) error { log.Infow("performing filling up rest of the sector...", "sector", sector.SectorNumber) @@ -83,6 +84,18 @@ func (m *Sealing) getTicket(ctx statemachine.Context, sector SectorInfo) (abi.Se return abi.SealRandomness(rand), ticketEpoch, nil } +func (m *Sealing) handleGetTicket(ctx statemachine.Context, sector SectorInfo) error { + ticketValue, ticketEpoch, err := m.getTicket(ctx, sector) + if err != nil { + return ctx.Send(SectorSealPreCommit1Failed{xerrors.Errorf("getting ticket failed: %w", err)}) + } + + return ctx.Send(SectorTicket{ + TicketValue: ticketValue, + TicketEpoch: ticketEpoch, + }) +} + func (m *Sealing) handlePreCommit1(ctx statemachine.Context, sector SectorInfo) error { if err := checkPieces(ctx.Context(), m.maddr, sector, m.api); err != nil { // Sanity check state switch err.(type) { @@ -99,21 +112,23 @@ func (m *Sealing) handlePreCommit1(ctx statemachine.Context, sector SectorInfo) } } - log.Infow("performing sector replication...", "sector", sector.SectorNumber) - ticketValue, ticketEpoch, err := m.getTicket(ctx, sector) + _, height, err := m.api.ChainHead(ctx.Context()) if err != nil { - return ctx.Send(SectorSealPreCommit1Failed{xerrors.Errorf("getting ticket failed: %w", err)}) + log.Errorf("handlePreCommit1: api error, not proceeding: %+v", err) + return nil } - pc1o, err := m.sealer.SealPreCommit1(sector.sealingCtx(ctx.Context()), m.minerSector(sector.SectorNumber), ticketValue, sector.pieceInfos()) + if height-sector.TicketEpoch > MaxTicketAge { + return ctx.Send(SectorOldTicket{}) + } + + pc1o, err := m.sealer.SealPreCommit1(sector.sealingCtx(ctx.Context()), m.minerSector(sector.SectorNumber), sector.TicketValue, sector.pieceInfos()) if err != nil { return ctx.Send(SectorSealPreCommit1Failed{xerrors.Errorf("seal pre commit(1) failed: %w", err)}) } return ctx.Send(SectorPreCommit1{ PreCommit1Out: pc1o, - TicketValue: ticketValue, - TicketEpoch: ticketEpoch, }) } From 46a5beafe45fa975758cbd9581cb6390eece6855 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 30 Sep 2020 15:17:29 +0200 Subject: [PATCH 034/313] shed: Datastore utils --- cmd/lotus-shed/datastore.go | 193 ++++++++++++++++++++++++++++++++++++ cmd/lotus-shed/main.go | 1 + go.mod | 1 + 3 files changed, 195 insertions(+) create mode 100644 cmd/lotus-shed/datastore.go diff --git a/cmd/lotus-shed/datastore.go b/cmd/lotus-shed/datastore.go new file mode 100644 index 000000000..dcd774a90 --- /dev/null +++ b/cmd/lotus-shed/datastore.go @@ -0,0 +1,193 @@ +package main + +import ( + "encoding/json" + "fmt" + "strings" + + "github.com/ipfs/go-datastore" + dsq "github.com/ipfs/go-datastore/query" + logging "github.com/ipfs/go-log" + "github.com/polydawn/refmt/cbor" + "github.com/urfave/cli/v2" + "golang.org/x/xerrors" + + "github.com/filecoin-project/lotus/node/repo" +) + +var datastoreCmd = &cli.Command{ + Name: "datastore", + Description: "access node datastores directly", + Subcommands: []*cli.Command{ + datastoreListCmd, + datastoreGetCmd, + }, +} + +var datastoreListCmd = &cli.Command{ + Name: "list", + Description: "list datastore keys", + Flags: []cli.Flag{ + &cli.IntFlag{ + Name: "repo-type", + Value: 1, + }, + &cli.BoolFlag{ + Name: "top-level", + Usage: "only print top-level keys", + }, + &cli.StringFlag{ + Name: "get-enc", + Usage: "print values [esc/hex/cbor]", + }, + }, + ArgsUsage: "[namespace prefix]", + Action: func(cctx *cli.Context) error { + logging.SetLogLevel("badger", "ERROR") // nolint:errchec + + r, err := repo.NewFS(cctx.String("repo")) + if err != nil { + return xerrors.Errorf("opening fs repo: %w", err) + } + + exists, err := r.Exists() + if err != nil { + return err + } + if !exists { + return xerrors.Errorf("lotus repo doesn't exist") + } + + lr, err := r.Lock(repo.RepoType(cctx.Int("repo-type"))) + if err != nil { + return err + } + defer lr.Close() //nolint:errcheck + + ds, err := lr.Datastore(datastore.NewKey(cctx.Args().First()).String()) + if err != nil { + return err + } + + genc := cctx.String("get-enc") + + q, err := ds.Query(dsq.Query{ + Prefix: datastore.NewKey(cctx.Args().Get(1)).String(), + KeysOnly: genc == "", + }) + if err != nil { + return xerrors.Errorf("datastore query: %w", err) + } + defer q.Close() //nolint:errcheck + + seen := map[string]struct{}{} + for res := range q.Next() { + s := res.Key + if cctx.Bool("top-level") { + k := datastore.NewKey(datastore.NewKey(s).List()[0]) + if k.Type() != "" { + s = k.Type() + } else { + s = k.String() + } + + _, has := seen[s] + if has { + continue + } + seen[s] = struct{}{} + } + + + s = fmt.Sprintf("%q", s) + s = strings.Trim(s, "\"") + fmt.Println(s) + + if genc != "" { + fmt.Print("\t") + if err := printVal(genc, res.Value); err != nil { + return err + } + } + } + + return nil + }, +} + +var datastoreGetCmd = &cli.Command{ + Name: "get", + Description: "list datastore keys", + Flags: []cli.Flag{ + &cli.IntFlag{ + Name: "repo-type", + Value: 1, + }, + &cli.StringFlag{ + Name: "enc", + Usage: "encoding (esc/hex/cbor)", + Value: "esc", + }, + }, + ArgsUsage: "[namespace key]", + Action: func(cctx *cli.Context) error { + logging.SetLogLevel("badger", "ERROR") // nolint:errchec + + r, err := repo.NewFS(cctx.String("repo")) + if err != nil { + return xerrors.Errorf("opening fs repo: %w", err) + } + + exists, err := r.Exists() + if err != nil { + return err + } + if !exists { + return xerrors.Errorf("lotus repo doesn't exist") + } + + lr, err := r.Lock(repo.RepoType(cctx.Int("repo-type"))) + if err != nil { + return err + } + defer lr.Close() //nolint:errcheck + + ds, err := lr.Datastore(datastore.NewKey(cctx.Args().First()).String()) + if err != nil { + return err + } + + val, err := ds.Get(datastore.NewKey(cctx.Args().Get(1))) + if err != nil { + return xerrors.Errorf("get: %w", err) + } + + return printVal(cctx.String("enc"), val) + }, +} + +func printVal(enc string, val []byte) error { + switch enc { + case "esc": + s := fmt.Sprintf("%q", string(val)) + s = strings.Trim(s, "\"") + fmt.Println(s) + case "hex": + fmt.Printf("%x\n", val) + case "cbor": + var out interface{} + if err := cbor.Unmarshal(cbor.DecodeOptions{}, val, &out); err != nil { + return xerrors.Errorf("unmarshaling cbor: %w", err) + } + s, err := json.Marshal(&out) + if err != nil { + return xerrors.Errorf("remarshaling as json: %w", err) + } + + fmt.Println(string(s)) + default: + return xerrors.New("unknown encoding") + } + + return nil +} diff --git a/cmd/lotus-shed/main.go b/cmd/lotus-shed/main.go index 118b4ea72..61e6967d6 100644 --- a/cmd/lotus-shed/main.go +++ b/cmd/lotus-shed/main.go @@ -37,6 +37,7 @@ func main() { exportChainCmd, consensusCmd, serveDealStatsCmd, + datastoreCmd, } app := &cli.App{ diff --git a/go.mod b/go.mod index 67d87347f..99f689f3d 100644 --- a/go.mod +++ b/go.mod @@ -106,6 +106,7 @@ require ( github.com/multiformats/go-multibase v0.0.3 github.com/multiformats/go-multihash v0.0.14 github.com/opentracing/opentracing-go v1.2.0 + github.com/polydawn/refmt v0.0.0-20190809202753-05966cbd336a github.com/raulk/clock v1.1.0 github.com/stretchr/testify v1.6.1 github.com/supranational/blst v0.1.1 From 6855284d88c8e19beed4c5bc8a7f374d1babd0da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 30 Sep 2020 17:26:09 +0200 Subject: [PATCH 035/313] sectorstorage: Cancel non-running work in case of abort in sched --- extern/sector-storage/manager.go | 12 +++-- extern/sector-storage/manager_calltracker.go | 49 +++++++++++++++++--- 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index 7d49cc958..afcc28ffd 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -364,10 +364,11 @@ func (m *Manager) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticke ctx, cancel := context.WithCancel(ctx) defer cancel() - wk, wait, err := m.getWork(ctx, sealtasks.TTPreCommit1, sector, ticket, pieces) + wk, wait, cancel, err := m.getWork(ctx, sealtasks.TTPreCommit1, sector, ticket, pieces) if err != nil { return nil, xerrors.Errorf("getWork: %w", err) } + defer cancel() waitRes := func() { p, werr := m.waitWork(ctx, wk) @@ -408,10 +409,11 @@ func (m *Manager) SealPreCommit2(ctx context.Context, sector abi.SectorID, phase ctx, cancel := context.WithCancel(ctx) defer cancel() - wk, wait, err := m.getWork(ctx, sealtasks.TTPreCommit2, sector, phase1Out) + wk, wait, cancel, err := m.getWork(ctx, sealtasks.TTPreCommit2, sector, phase1Out) if err != nil { return storage.SectorCids{}, xerrors.Errorf("getWork: %w", err) } + defer cancel() waitRes := func() { p, werr := m.waitWork(ctx, wk) @@ -449,10 +451,11 @@ func (m *Manager) SealCommit1(ctx context.Context, sector abi.SectorID, ticket a ctx, cancel := context.WithCancel(ctx) defer cancel() - wk, wait, err := m.getWork(ctx, sealtasks.TTCommit1, sector, ticket, seed, pieces, cids) + wk, wait, cancel, err := m.getWork(ctx, sealtasks.TTCommit1, sector, ticket, seed, pieces, cids) if err != nil { return storage.Commit1Out{}, xerrors.Errorf("getWork: %w", err) } + defer cancel() waitRes := func() { p, werr := m.waitWork(ctx, wk) @@ -490,10 +493,11 @@ func (m *Manager) SealCommit1(ctx context.Context, sector abi.SectorID, ticket a } func (m *Manager) SealCommit2(ctx context.Context, sector abi.SectorID, phase1Out storage.Commit1Out) (out storage.Proof, err error) { - wk, wait, err := m.getWork(ctx, sealtasks.TTCommit2, sector, phase1Out) + wk, wait, cancel, err := m.getWork(ctx, sealtasks.TTCommit2, sector, phase1Out) if err != nil { return storage.Proof{}, xerrors.Errorf("getWork: %w", err) } + defer cancel() waitRes := func() { p, werr := m.waitWork(ctx, wk) diff --git a/extern/sector-storage/manager_calltracker.go b/extern/sector-storage/manager_calltracker.go index 147e11b91..1135af4af 100644 --- a/extern/sector-storage/manager_calltracker.go +++ b/extern/sector-storage/manager_calltracker.go @@ -102,10 +102,10 @@ func (m *Manager) setupWorkTracker() { } // returns wait=true when the task is already tracked/running -func (m *Manager) getWork(ctx context.Context, method sealtasks.TaskType, params ...interface{}) (wid WorkID, wait bool, err error) { +func (m *Manager) getWork(ctx context.Context, method sealtasks.TaskType, params ...interface{}) (wid WorkID, wait bool, cancel func(), err error) { wid, err = newWorkID(method, params) if err != nil { - return WorkID{}, false, xerrors.Errorf("creating WorkID: %w", err) + return WorkID{}, false, nil, xerrors.Errorf("creating WorkID: %w", err) } m.workLk.Lock() @@ -113,7 +113,7 @@ func (m *Manager) getWork(ctx context.Context, method sealtasks.TaskType, params have, err := m.work.Has(wid) if err != nil { - return WorkID{}, false, xerrors.Errorf("failed to check if the task is already tracked: %w", err) + return WorkID{}, false, nil, xerrors.Errorf("failed to check if the task is already tracked: %w", err) } if !have { @@ -122,15 +122,52 @@ func (m *Manager) getWork(ctx context.Context, method sealtasks.TaskType, params Status: wsStarted, }) if err != nil { - return WorkID{}, false, xerrors.Errorf("failed to track task start: %w", err) + return WorkID{}, false, nil, xerrors.Errorf("failed to track task start: %w", err) } - return wid, false, nil + return wid, false, func() { + m.workLk.Lock() + defer m.workLk.Unlock() + + have, err := m.work.Has(wid) + if err != nil { + log.Errorf("cancel: work has error: %+v", err) + return + } + + if !have { + return // expected / happy path + } + + var ws WorkState + if err := m.work.Get(wid).Get(&ws); err != nil { + log.Errorf("cancel: get work %s: %+v", wid, err) + return + } + + switch ws.Status { + case wsStarted: + log.Warn("canceling started (not running) work %s", wid) + + if err := m.work.Get(wid).End(); err != nil { + log.Errorf("cancel: failed to cancel started work %s: %+v", wid, err) + return + } + case wsDone: + // TODO: still remove? + log.Warn("cancel called on work %s in 'done' state", wid) + case wsRunning: + log.Warn("cancel called on work %s in 'running' state (manager shutting down?)", wid) + } + + }, nil } // already started - return wid, true, nil + return wid, true, func() { + // TODO + }, nil } func (m *Manager) startWork(ctx context.Context, wk WorkID) func(callID storiface.CallID, err error) error { From 6ddea62d09992679b0fd8e9c0bcc91ccd0c06f9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 30 Sep 2020 17:26:24 +0200 Subject: [PATCH 036/313] shed: gofmt --- cmd/lotus-shed/datastore.go | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/cmd/lotus-shed/datastore.go b/cmd/lotus-shed/datastore.go index dcd774a90..5c668e081 100644 --- a/cmd/lotus-shed/datastore.go +++ b/cmd/lotus-shed/datastore.go @@ -16,7 +16,7 @@ import ( ) var datastoreCmd = &cli.Command{ - Name: "datastore", + Name: "datastore", Description: "access node datastores directly", Subcommands: []*cli.Command{ datastoreListCmd, @@ -25,19 +25,19 @@ var datastoreCmd = &cli.Command{ } var datastoreListCmd = &cli.Command{ - Name: "list", + Name: "list", Description: "list datastore keys", Flags: []cli.Flag{ &cli.IntFlag{ - Name: "repo-type", + Name: "repo-type", Value: 1, }, &cli.BoolFlag{ - Name: "top-level", + Name: "top-level", Usage: "only print top-level keys", }, &cli.StringFlag{ - Name: "get-enc", + Name: "get-enc", Usage: "print values [esc/hex/cbor]", }, }, @@ -72,8 +72,8 @@ var datastoreListCmd = &cli.Command{ genc := cctx.String("get-enc") q, err := ds.Query(dsq.Query{ - Prefix: datastore.NewKey(cctx.Args().Get(1)).String(), - KeysOnly: genc == "", + Prefix: datastore.NewKey(cctx.Args().Get(1)).String(), + KeysOnly: genc == "", }) if err != nil { return xerrors.Errorf("datastore query: %w", err) @@ -98,7 +98,6 @@ var datastoreListCmd = &cli.Command{ seen[s] = struct{}{} } - s = fmt.Sprintf("%q", s) s = strings.Trim(s, "\"") fmt.Println(s) @@ -116,15 +115,15 @@ var datastoreListCmd = &cli.Command{ } var datastoreGetCmd = &cli.Command{ - Name: "get", + Name: "get", Description: "list datastore keys", Flags: []cli.Flag{ &cli.IntFlag{ - Name: "repo-type", + Name: "repo-type", Value: 1, }, &cli.StringFlag{ - Name: "enc", + Name: "enc", Usage: "encoding (esc/hex/cbor)", Value: "esc", }, From 54fdd6ba5a24a2178bb9de410a74ab3fd71a0e49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 30 Sep 2020 17:48:48 +0200 Subject: [PATCH 037/313] sectorstorage: Variable scopes are hard --- extern/sector-storage/manager.go | 35 ++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index afcc28ffd..2eee50b1b 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -370,10 +370,11 @@ func (m *Manager) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticke } defer cancel() + var waitErr error waitRes := func() { p, werr := m.waitWork(ctx, wk) if werr != nil { - err = werr + waitErr = werr return } out = p.(storage.PreCommit1Out) @@ -401,8 +402,11 @@ func (m *Manager) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticke waitRes() return nil }) + if err != nil { + return nil, err + } - return out, err + return out, waitErr } func (m *Manager) SealPreCommit2(ctx context.Context, sector abi.SectorID, phase1Out storage.PreCommit1Out) (out storage.SectorCids, err error) { @@ -415,10 +419,11 @@ func (m *Manager) SealPreCommit2(ctx context.Context, sector abi.SectorID, phase } defer cancel() + var waitErr error waitRes := func() { p, werr := m.waitWork(ctx, wk) if werr != nil { - err = werr + waitErr = werr return } out = p.(storage.SectorCids) @@ -444,7 +449,11 @@ func (m *Manager) SealPreCommit2(ctx context.Context, sector abi.SectorID, phase waitRes() return nil }) - return out, err + if err != nil { + return storage.SectorCids{}, err + } + + return out, waitErr } func (m *Manager) SealCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (out storage.Commit1Out, err error) { @@ -457,10 +466,11 @@ func (m *Manager) SealCommit1(ctx context.Context, sector abi.SectorID, ticket a } defer cancel() + var waitErr error waitRes := func() { p, werr := m.waitWork(ctx, wk) if werr != nil { - err = werr + waitErr = werr return } out = p.(storage.Commit1Out) @@ -489,7 +499,11 @@ func (m *Manager) SealCommit1(ctx context.Context, sector abi.SectorID, ticket a waitRes() return nil }) - return out, err + if err != nil { + return nil, err + } + + return out, waitErr } func (m *Manager) SealCommit2(ctx context.Context, sector abi.SectorID, phase1Out storage.Commit1Out) (out storage.Proof, err error) { @@ -499,10 +513,11 @@ func (m *Manager) SealCommit2(ctx context.Context, sector abi.SectorID, phase1Ou } defer cancel() + var waitErr error waitRes := func() { p, werr := m.waitWork(ctx, wk) if werr != nil { - err = werr + waitErr = werr return } out = p.(storage.Proof) @@ -525,7 +540,11 @@ func (m *Manager) SealCommit2(ctx context.Context, sector abi.SectorID, phase1Ou return nil }) - return out, err + if err != nil { + return nil, err + } + + return out, waitErr } func (m *Manager) FinalizeSector(ctx context.Context, sector abi.SectorID, keepUnsealed []storage.Range) error { From a783bf9b8b1db350238212e351266eb8e684b772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 30 Sep 2020 17:53:15 +0200 Subject: [PATCH 038/313] storagefsm: Handle PC2 with missing replica --- extern/storage-sealing/fsm.go | 1 + extern/storage-sealing/states_sealing.go | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/extern/storage-sealing/fsm.go b/extern/storage-sealing/fsm.go index 12af83f56..a936e14b8 100644 --- a/extern/storage-sealing/fsm.go +++ b/extern/storage-sealing/fsm.go @@ -57,6 +57,7 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto PreCommit2: planOne( on(SectorPreCommit2{}, PreCommitting), on(SectorSealPreCommit2Failed{}, SealPreCommit2Failed), + on(SectorSealPreCommit1Failed{}, SealPreCommit1Failed), ), PreCommitting: planOne( on(SectorSealPreCommit1Failed{}, SealPreCommit1Failed), diff --git a/extern/storage-sealing/states_sealing.go b/extern/storage-sealing/states_sealing.go index 55a3f27e8..08371f7fa 100644 --- a/extern/storage-sealing/states_sealing.go +++ b/extern/storage-sealing/states_sealing.go @@ -3,6 +3,7 @@ package sealing import ( "bytes" "context" + "github.com/ipfs/go-cid" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" @@ -138,6 +139,10 @@ func (m *Sealing) handlePreCommit2(ctx statemachine.Context, sector SectorInfo) return ctx.Send(SectorSealPreCommit2Failed{xerrors.Errorf("seal pre commit(2) failed: %w", err)}) } + if cids.Unsealed == cid.Undef { + return ctx.Send(SectorSealPreCommit1Failed{xerrors.Errorf("seal pre commit(2) returned undefined CommD")}) + } + return ctx.Send(SectorPreCommit2{ Unsealed: cids.Unsealed, Sealed: cids.Sealed, From c22859809897c7096d4738b827d4a22901803e5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 30 Sep 2020 18:16:07 +0200 Subject: [PATCH 039/313] sectorstorage: Variable scopes are really hard --- extern/sector-storage/manager.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index 2eee50b1b..6ed7d9989 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -382,7 +382,7 @@ func (m *Manager) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticke if wait { // already in progress waitRes() - return + return out, waitErr } if err := m.index.StorageLock(ctx, sector, storiface.FTUnsealed, storiface.FTSealed|storiface.FTCache); err != nil { @@ -431,7 +431,7 @@ func (m *Manager) SealPreCommit2(ctx context.Context, sector abi.SectorID, phase if wait { // already in progress waitRes() - return + return out, waitErr } if err := m.index.StorageLock(ctx, sector, storiface.FTSealed, storiface.FTCache); err != nil { @@ -478,7 +478,7 @@ func (m *Manager) SealCommit1(ctx context.Context, sector abi.SectorID, ticket a if wait { // already in progress waitRes() - return + return out, waitErr } if err := m.index.StorageLock(ctx, sector, storiface.FTSealed, storiface.FTCache); err != nil { @@ -525,7 +525,7 @@ func (m *Manager) SealCommit2(ctx context.Context, sector abi.SectorID, phase1Ou if wait { // already in progress waitRes() - return + return out, waitErr } selector := newTaskSelector() From 4f97d9637ea667f35fcd78e2ab32e2f7ea2cb2b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 30 Sep 2020 19:11:58 +0200 Subject: [PATCH 040/313] Fix storage-fsm tests --- extern/storage-sealing/fsm_test.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/extern/storage-sealing/fsm_test.go b/extern/storage-sealing/fsm_test.go index 51fd2a37b..5b4541f75 100644 --- a/extern/storage-sealing/fsm_test.go +++ b/extern/storage-sealing/fsm_test.go @@ -44,6 +44,9 @@ func TestHappyPath(t *testing.T) { } m.planSingle(SectorPacked{}) + require.Equal(m.t, m.state.State, GetTicket) + + m.planSingle(SectorTicket{}) require.Equal(m.t, m.state.State, PreCommit1) m.planSingle(SectorPreCommit1{}) @@ -73,7 +76,7 @@ func TestHappyPath(t *testing.T) { m.planSingle(SectorFinalized{}) require.Equal(m.t, m.state.State, Proving) - expected := []SectorState{Packing, PreCommit1, PreCommit2, PreCommitting, PreCommitWait, WaitSeed, Committing, SubmitCommit, CommitWait, FinalizeSector, Proving} + expected := []SectorState{Packing, GetTicket, PreCommit1, PreCommit2, PreCommitting, PreCommitWait, WaitSeed, Committing, SubmitCommit, CommitWait, FinalizeSector, Proving} for i, n := range notif { if n.before.State != expected[i] { t.Fatalf("expected before state: %s, got: %s", expected[i], n.before.State) @@ -98,6 +101,9 @@ func TestSeedRevert(t *testing.T) { } m.planSingle(SectorPacked{}) + require.Equal(m.t, m.state.State, GetTicket) + + m.planSingle(SectorTicket{}) require.Equal(m.t, m.state.State, PreCommit1) m.planSingle(SectorPreCommit1{}) From 2d16af6ee60c75cf762c407152bcc62f8ccddf7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 30 Sep 2020 19:18:38 +0200 Subject: [PATCH 041/313] sectorstorage: Fix TestRedoPC1 --- extern/sector-storage/manager_test.go | 3 +++ extern/sector-storage/mock/mock.go | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/extern/sector-storage/manager_test.go b/extern/sector-storage/manager_test.go index d87ec0827..fe82c0ca0 100644 --- a/extern/sector-storage/manager_test.go +++ b/extern/sector-storage/manager_test.go @@ -198,6 +198,9 @@ func TestRedoPC1(t *testing.T) { _, err = m.SealPreCommit1(ctx, sid, ticket, pieces) require.NoError(t, err) + // tell mock ffi that we expect PC1 again + require.NoError(t, tw.mockSeal.ForceState(sid, 0)) // sectorPacking + _, err = m.SealPreCommit1(ctx, sid, ticket, pieces) require.NoError(t, err) diff --git a/extern/sector-storage/mock/mock.go b/extern/sector-storage/mock/mock.go index a292c2bbb..8eb65482d 100644 --- a/extern/sector-storage/mock/mock.go +++ b/extern/sector-storage/mock/mock.go @@ -127,6 +127,19 @@ func (mgr *SectorMgr) AcquireSectorNumber() (abi.SectorNumber, error) { return id, nil } +func (mgr *SectorMgr) ForceState(sid abi.SectorID, st int) error { + mgr.lk.Lock() + ss, ok := mgr.sectors[sid] + mgr.lk.Unlock() + if !ok { + return xerrors.Errorf("no sector with id %d in storage", sid) + } + + ss.state = st + + return nil +} + func (mgr *SectorMgr) SealPreCommit1(ctx context.Context, sid abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (out storage.PreCommit1Out, err error) { mgr.lk.Lock() ss, ok := mgr.sectors[sid] From e3ee4e4718b03e315e2dfda46010ceb0ba841bd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 30 Sep 2020 19:32:19 +0200 Subject: [PATCH 042/313] Fix lint errors --- chain/messagepool/selection.go | 1 + cmd/lotus-seed/seed/seed.go | 2 +- cmd/lotus-storage-miner/storage.go | 6 +++--- extern/sector-storage/ffiwrapper/verifier_cgo.go | 16 +++++++--------- extern/sector-storage/manager.go | 2 +- extern/sector-storage/manager_calltracker.go | 9 +++------ extern/sector-storage/manager_test.go | 2 +- extern/sector-storage/roprov.go | 2 +- extern/sector-storage/selector_alloc.go | 2 +- extern/sector-storage/selector_existing.go | 2 +- extern/sector-storage/stats.go | 3 ++- extern/sector-storage/stores/http_handler.go | 2 +- extern/sector-storage/stores/index.go | 6 +++--- extern/sector-storage/stores/index_locks.go | 3 ++- extern/sector-storage/stores/index_locks_test.go | 3 ++- extern/sector-storage/stores/local.go | 4 ++-- extern/storage-sealing/states_sealing.go | 12 ++++++------ 17 files changed, 38 insertions(+), 39 deletions(-) diff --git a/chain/messagepool/selection.go b/chain/messagepool/selection.go index 2ddbed0ad..4ade92a79 100644 --- a/chain/messagepool/selection.go +++ b/chain/messagepool/selection.go @@ -12,6 +12,7 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" tbig "github.com/filecoin-project/go-state-types/big" + "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/messagepool/gasguess" "github.com/filecoin-project/lotus/chain/types" diff --git a/cmd/lotus-seed/seed/seed.go b/cmd/lotus-seed/seed/seed.go index 32a7a68e1..92837cec5 100644 --- a/cmd/lotus-seed/seed/seed.go +++ b/cmd/lotus-seed/seed/seed.go @@ -6,7 +6,6 @@ import ( "encoding/hex" "encoding/json" "fmt" - "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "io/ioutil" "os" "path/filepath" @@ -31,6 +30,7 @@ import ( "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper/basicfs" "github.com/filecoin-project/lotus/extern/sector-storage/stores" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "github.com/filecoin-project/lotus/genesis" ) diff --git a/cmd/lotus-storage-miner/storage.go b/cmd/lotus-storage-miner/storage.go index ebc5d2fbe..cc91c9d6b 100644 --- a/cmd/lotus-storage-miner/storage.go +++ b/cmd/lotus-storage-miner/storage.go @@ -3,7 +3,6 @@ package main import ( "encoding/json" "fmt" - "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "io/ioutil" "os" "path/filepath" @@ -20,11 +19,12 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/lotus/extern/sector-storage/fsutil" - "github.com/filecoin-project/lotus/extern/sector-storage/stores" "github.com/filecoin-project/lotus/chain/types" lcli "github.com/filecoin-project/lotus/cli" + "github.com/filecoin-project/lotus/extern/sector-storage/fsutil" + "github.com/filecoin-project/lotus/extern/sector-storage/stores" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) const metaFile = "sectorstore.json" diff --git a/extern/sector-storage/ffiwrapper/verifier_cgo.go b/extern/sector-storage/ffiwrapper/verifier_cgo.go index c560d4328..8a9ac16d8 100644 --- a/extern/sector-storage/ffiwrapper/verifier_cgo.go +++ b/extern/sector-storage/ffiwrapper/verifier_cgo.go @@ -4,17 +4,15 @@ package ffiwrapper import ( "context" - "github.com/filecoin-project/lotus/extern/sector-storage/storiface" - - "github.com/filecoin-project/specs-actors/actors/runtime/proof" - - "golang.org/x/xerrors" - - "github.com/filecoin-project/go-state-types/abi" - - ffi "github.com/filecoin-project/filecoin-ffi" "go.opencensus.io/trace" + "golang.org/x/xerrors" + + ffi "github.com/filecoin-project/filecoin-ffi" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/specs-actors/actors/runtime/proof" + + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) func (sb *Sealer) GenerateWinningPoSt(ctx context.Context, minerID abi.ActorID, sectorInfo []proof.SectorInfo, randomness abi.PoStRandomness) ([]proof.PoStProof, error) { diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index 6ed7d9989..9445bdd2a 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -3,7 +3,6 @@ package sectorstorage import ( "context" "errors" - "github.com/filecoin-project/go-statestore" "io" "net/http" "sync" @@ -15,6 +14,7 @@ import ( "golang.org/x/xerrors" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-statestore" "github.com/filecoin-project/specs-storage/storage" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" diff --git a/extern/sector-storage/manager_calltracker.go b/extern/sector-storage/manager_calltracker.go index 1135af4af..8315c6fe6 100644 --- a/extern/sector-storage/manager_calltracker.go +++ b/extern/sector-storage/manager_calltracker.go @@ -7,9 +7,10 @@ import ( "encoding/json" "errors" "fmt" - "golang.org/x/xerrors" "os" + "golang.org/x/xerrors" + "github.com/filecoin-project/lotus/extern/sector-storage/sealtasks" "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) @@ -71,10 +72,6 @@ func (m *Manager) setupWorkTracker() { for _, st := range ids { wid := st.ID - if err := m.work.Get(wid).Get(&st); err != nil { - log.Errorf("getting work state for %s", wid) - continue - } if os.Getenv("LOTUS_MINER_ABORT_UNFINISHED_WORK") == "1" { st.Status = wsDone @@ -363,7 +360,7 @@ func (m *Manager) returnResult(callID storiface.CallID, r interface{}, serr stri _, ok = m.results[wid] if ok { - return xerrors.Errorf("result for call %v already reported") + return xerrors.Errorf("result for call %v already reported", wid) } m.results[wid] = res diff --git a/extern/sector-storage/manager_test.go b/extern/sector-storage/manager_test.go index fe82c0ca0..da89a0452 100644 --- a/extern/sector-storage/manager_test.go +++ b/extern/sector-storage/manager_test.go @@ -265,7 +265,7 @@ func TestRestartManager(t *testing.T) { cwg.Wait() require.Error(t, perr) - m, lstor, _, _ = newTestMgr(ctx, t, ds) + m, _, _, _ = newTestMgr(ctx, t, ds) tw.ret = m // simulate jsonrpc auto-reconnect err = m.AddWorker(ctx, tw) require.NoError(t, err) diff --git a/extern/sector-storage/roprov.go b/extern/sector-storage/roprov.go index b808bfd95..996d70721 100644 --- a/extern/sector-storage/roprov.go +++ b/extern/sector-storage/roprov.go @@ -2,13 +2,13 @@ package sectorstorage import ( "context" - "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "golang.org/x/xerrors" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/lotus/extern/sector-storage/stores" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) type readonlyProvider struct { diff --git a/extern/sector-storage/selector_alloc.go b/extern/sector-storage/selector_alloc.go index 800b8706b..77ed44708 100644 --- a/extern/sector-storage/selector_alloc.go +++ b/extern/sector-storage/selector_alloc.go @@ -2,7 +2,6 @@ package sectorstorage import ( "context" - "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "golang.org/x/xerrors" @@ -10,6 +9,7 @@ import ( "github.com/filecoin-project/lotus/extern/sector-storage/sealtasks" "github.com/filecoin-project/lotus/extern/sector-storage/stores" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) type allocSelector struct { diff --git a/extern/sector-storage/selector_existing.go b/extern/sector-storage/selector_existing.go index 298c3d3bd..100f6dc4d 100644 --- a/extern/sector-storage/selector_existing.go +++ b/extern/sector-storage/selector_existing.go @@ -2,7 +2,6 @@ package sectorstorage import ( "context" - "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "golang.org/x/xerrors" @@ -10,6 +9,7 @@ import ( "github.com/filecoin-project/lotus/extern/sector-storage/sealtasks" "github.com/filecoin-project/lotus/extern/sector-storage/stores" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) type existingSelector struct { diff --git a/extern/sector-storage/stats.go b/extern/sector-storage/stats.go index 849322be0..bba47d169 100644 --- a/extern/sector-storage/stats.go +++ b/extern/sector-storage/stats.go @@ -1,8 +1,9 @@ package sectorstorage import ( - "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "time" + + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) func (m *Manager) WorkerStats() map[uint64]storiface.WorkerStats { diff --git a/extern/sector-storage/stores/http_handler.go b/extern/sector-storage/stores/http_handler.go index 8891132ce..2237bd407 100644 --- a/extern/sector-storage/stores/http_handler.go +++ b/extern/sector-storage/stores/http_handler.go @@ -2,7 +2,6 @@ package stores import ( "encoding/json" - "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "io" "net/http" "os" @@ -11,6 +10,7 @@ import ( logging "github.com/ipfs/go-log/v2" "golang.org/x/xerrors" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "github.com/filecoin-project/lotus/extern/sector-storage/tarutil" ) diff --git a/extern/sector-storage/stores/index.go b/extern/sector-storage/stores/index.go index e65e52ab1..9b3798ae1 100644 --- a/extern/sector-storage/stores/index.go +++ b/extern/sector-storage/stores/index.go @@ -2,7 +2,6 @@ package stores import ( "context" - "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "net/url" gopath "path" "sort" @@ -11,10 +10,11 @@ import ( "golang.org/x/xerrors" - "github.com/filecoin-project/lotus/extern/sector-storage/fsutil" - "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" + + "github.com/filecoin-project/lotus/extern/sector-storage/fsutil" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) var HeartbeatInterval = 10 * time.Second diff --git a/extern/sector-storage/stores/index_locks.go b/extern/sector-storage/stores/index_locks.go index 59385e77c..3a5ff940e 100644 --- a/extern/sector-storage/stores/index_locks.go +++ b/extern/sector-storage/stores/index_locks.go @@ -2,12 +2,13 @@ package stores import ( "context" - "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "sync" "golang.org/x/xerrors" "github.com/filecoin-project/go-state-types/abi" + + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) type sectorLock struct { diff --git a/extern/sector-storage/stores/index_locks_test.go b/extern/sector-storage/stores/index_locks_test.go index 3b1ccbf44..ec7f34927 100644 --- a/extern/sector-storage/stores/index_locks_test.go +++ b/extern/sector-storage/stores/index_locks_test.go @@ -2,13 +2,14 @@ package stores import ( "context" - "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "testing" "time" "github.com/stretchr/testify/require" "github.com/filecoin-project/go-state-types/abi" + + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) var aSector = abi.SectorID{ diff --git a/extern/sector-storage/stores/local.go b/extern/sector-storage/stores/local.go index 216e88cba..e2dd9f174 100644 --- a/extern/sector-storage/stores/local.go +++ b/extern/sector-storage/stores/local.go @@ -212,12 +212,12 @@ func (st *Local) Redeclare(ctx context.Context) error { for id, p := range st.paths { mb, err := ioutil.ReadFile(filepath.Join(p.local, MetaFile)) if err != nil { - return xerrors.Errorf("reading storage metadata for %s: %w", p, err) + return xerrors.Errorf("reading storage metadata for %s: %w", p.local, err) } var meta LocalStorageMeta if err := json.Unmarshal(mb, &meta); err != nil { - return xerrors.Errorf("unmarshalling storage metadata for %s: %w", p, err) + return xerrors.Errorf("unmarshalling storage metadata for %s: %w", p.local, err) } fst, err := p.stat(st.localStorage) diff --git a/extern/storage-sealing/states_sealing.go b/extern/storage-sealing/states_sealing.go index 08371f7fa..545f023f7 100644 --- a/extern/storage-sealing/states_sealing.go +++ b/extern/storage-sealing/states_sealing.go @@ -3,13 +3,8 @@ package sealing import ( "bytes" "context" + "github.com/ipfs/go-cid" - - "github.com/filecoin-project/lotus/build" - "github.com/filecoin-project/lotus/chain/actors/builtin/miner" - "github.com/filecoin-project/lotus/chain/actors/policy" - miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" - "golang.org/x/xerrors" "github.com/filecoin-project/go-state-types/abi" @@ -18,7 +13,12 @@ import ( "github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/go-statemachine" "github.com/filecoin-project/specs-actors/actors/builtin" + miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" "github.com/filecoin-project/specs-storage/storage" + + "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/actors/builtin/miner" + "github.com/filecoin-project/lotus/chain/actors/policy" ) var DealSectorPriority = 1024 From 79d2ddf24ff452dc9c561c4f91d16e36a17bfc8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 30 Sep 2020 21:18:12 +0200 Subject: [PATCH 043/313] Review --- extern/sector-storage/sched.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/extern/sector-storage/sched.go b/extern/sector-storage/sched.go index 760fe9cba..e91c92525 100644 --- a/extern/sector-storage/sched.go +++ b/extern/sector-storage/sched.go @@ -803,13 +803,7 @@ func (sh *scheduler) workerCleanup(wid WorkerID, w *workerHandle) { } sh.openWindows = newWindows - log.Debugf("dropWorker %d", wid) - - /*go func() { // TODO: just remove? - if err := w.w.Close(); err != nil { - log.Warnf("closing worker %d: %+v", err) - } - }()*/ + log.Debugf("worker %d dropped", wid) } } From ef3987e2abbc38346974f9eba8b3d46a0c8b7dae Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Fri, 2 Oct 2020 14:51:32 -0700 Subject: [PATCH 044/313] decode parameters for multisig transactions in inspect --- cli/multisig.go | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/cli/multisig.go b/cli/multisig.go index 5b0977382..ade938f3d 100644 --- a/cli/multisig.go +++ b/cli/multisig.go @@ -3,13 +3,17 @@ package cli import ( "bytes" "encoding/hex" + "encoding/json" "fmt" "os" + "reflect" "sort" "strconv" "text/tabwriter" "github.com/filecoin-project/lotus/chain/actors" + "github.com/filecoin-project/lotus/chain/stmgr" + cbg "github.com/whyrusleeping/cbor-gen" "github.com/filecoin-project/go-state-types/big" @@ -171,6 +175,10 @@ var msigInspectCmd = &cli.Command{ Name: "vesting", Usage: "Include vesting details", }, + &cli.BoolFlag{ + Name: "decode-params", + Usage: "Decode parameters of transaction proposals", + }, }, Action: func(cctx *cli.Context) error { if !cctx.Args().Present() { @@ -201,6 +209,11 @@ var msigInspectCmd = &cli.Command{ return err } + ownId, err := api.StateLookupID(ctx, maddr, types.EmptyTSK) + if err != nil { + return err + } + mstate, err := multisig.Load(store, act) if err != nil { return err @@ -253,6 +266,7 @@ var msigInspectCmd = &cli.Command{ return xerrors.Errorf("reading pending transactions: %w", err) } + decParams := cctx.Bool("decode-params") fmt.Println("Transactions: ", len(pending)) if len(pending) > 0 { var txids []int64 @@ -263,11 +277,36 @@ var msigInspectCmd = &cli.Command{ return txids[i] < txids[j] }) - w := tabwriter.NewWriter(os.Stdout, 8, 4, 0, ' ', 0) + w := tabwriter.NewWriter(os.Stdout, 8, 4, 2, ' ', 0) fmt.Fprintf(w, "ID\tState\tApprovals\tTo\tValue\tMethod\tParams\n") for _, txid := range txids { tx := pending[txid] - fmt.Fprintf(w, "%d\t%s\t%d\t%s\t%s\t%d\t%x\n", txid, "pending", len(tx.Approved), tx.To, types.FIL(tx.Value), tx.Method, tx.Params) + target := tx.To.String() + if tx.To == ownId { + target += " (self)" + } + targAct, err := api.StateGetActor(ctx, tx.To, types.EmptyTSK) + if err != nil { + return xerrors.Errorf("failed to resolve 'To' address of multisig transaction %d: %w", txid, err) + } + method := stmgr.MethodsMap[targAct.Code][tx.Method] + + paramStr := fmt.Sprintf("%x", tx.Params) + if decParams && tx.Method != 0 { + ptyp := reflect.New(method.Params.Elem()).Interface().(cbg.CBORUnmarshaler) + if err := ptyp.UnmarshalCBOR(bytes.NewReader(tx.Params)); err != nil { + return xerrors.Errorf("failed to decode parameters of transaction %d: %w", txid, err) + } + + b, err := json.Marshal(ptyp) + if err != nil { + return xerrors.Errorf("could not json marshal parameter type: %w", err) + } + + paramStr = string(b) + } + + fmt.Fprintf(w, "%d\t%s\t%d\t%s\t%s\t%s(%d)\t%s\n", txid, "pending", len(tx.Approved), target, types.FIL(tx.Value), method.Name, tx.Method, paramStr) } if err := w.Flush(); err != nil { return xerrors.Errorf("flushing output: %+v", err) @@ -395,7 +434,7 @@ var msigProposeCmd = &cli.Command{ var msigApproveCmd = &cli.Command{ Name: "approve", Usage: "Approve a multisig message", - ArgsUsage: "[multisigAddress messageId proposerAddress destination value (optional)]", + ArgsUsage: " [proposerAddress destination value [methodId methodParams]]", Flags: []cli.Flag{ &cli.StringFlag{ Name: "from", From ce247bcab3edc758b9f6903e4e84224068d28c98 Mon Sep 17 00:00:00 2001 From: Animesh Date: Wed, 7 Oct 2020 10:27:51 +0530 Subject: [PATCH 045/313] Add api for getting status given a code --- api/api_full.go | 2 ++ api/apistruct/struct.go | 21 +++++++++++++-------- node/impl/client/client.go | 9 +++++++++ 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index 88f18943c..072d1cea6 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -271,6 +271,8 @@ type FullNode interface { ClientListDeals(ctx context.Context) ([]DealInfo, error) // ClientGetDealUpdates returns the status of updated deals ClientGetDealUpdates(ctx context.Context) (<-chan DealInfo, error) + // ClientGetDealStatus returns status given a code + ClientGetDealStatus(ctx context.Context, statusCode uint64) (string, error) // ClientHasLocal indicates whether a certain CID is locally stored. ClientHasLocal(ctx context.Context, root cid.Cid) (bool, error) // ClientFindData identifies peers that have a certain file, and returns QueryOffers (one per peer). diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index a09700eb9..dd47c79a4 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -146,14 +146,15 @@ type FullNodeStruct struct { WalletDelete func(context.Context, address.Address) error `perm:"write"` WalletValidateAddress func(context.Context, string) (address.Address, error) `perm:"read"` - ClientImport func(ctx context.Context, ref api.FileRef) (*api.ImportRes, error) `perm:"admin"` - ClientListImports func(ctx context.Context) ([]api.Import, error) `perm:"write"` - ClientRemoveImport func(ctx context.Context, importID multistore.StoreID) error `perm:"admin"` - ClientHasLocal func(ctx context.Context, root cid.Cid) (bool, error) `perm:"write"` - ClientFindData func(ctx context.Context, root cid.Cid, piece *cid.Cid) ([]api.QueryOffer, error) `perm:"read"` - ClientMinerQueryOffer func(ctx context.Context, miner address.Address, root cid.Cid, piece *cid.Cid) (api.QueryOffer, error) `perm:"read"` - ClientStartDeal func(ctx context.Context, params *api.StartDealParams) (*cid.Cid, error) `perm:"admin"` - ClientGetDealInfo func(context.Context, cid.Cid) (*api.DealInfo, error) `perm:"read"` + ClientImport func(ctx context.Context, ref api.FileRef) (*api.ImportRes, error) `perm:"admin"` + ClientListImports func(ctx context.Context) ([]api.Import, error) `perm:"write"` + ClientRemoveImport func(ctx context.Context, importID multistore.StoreID) error `perm:"admin"` + ClientHasLocal func(ctx context.Context, root cid.Cid) (bool, error) `perm:"write"` + ClientFindData func(ctx context.Context, root cid.Cid, piece *cid.Cid) ([]api.QueryOffer, error) `perm:"read"` + ClientMinerQueryOffer func(ctx context.Context, miner address.Address, root cid.Cid, piece *cid.Cid) (api.QueryOffer, error) `perm:"read"` + ClientStartDeal func(ctx context.Context, params *api.StartDealParams) (*cid.Cid, error) `perm:"admin"` + ClientGetDealInfo func(context.Context, cid.Cid) (*api.DealInfo, error) `perm:"read"` + ClientGetDealStatus func(context.Context, uint64) (string, error) ClientListDeals func(ctx context.Context) ([]api.DealInfo, error) `perm:"write"` ClientGetDealUpdates func(ctx context.Context) (<-chan api.DealInfo, error) `perm:"read"` ClientRetrieve func(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) error `perm:"admin"` @@ -478,6 +479,10 @@ func (c *FullNodeStruct) ClientGetDealInfo(ctx context.Context, deal cid.Cid) (* return c.Internal.ClientGetDealInfo(ctx, deal) } +func (c *FullNodeStruct) ClientGetDealStatus(ctx context.Context, statusCode uint64) (string, error) { + return c.Internal.ClientGetDealStatus(ctx, statusCode) +} + func (c *FullNodeStruct) ClientListDeals(ctx context.Context) ([]api.DealInfo, error) { return c.Internal.ClientListDeals(ctx) } diff --git a/node/impl/client/client.go b/node/impl/client/client.go index 5c1752154..6af266baa 100644 --- a/node/impl/client/client.go +++ b/node/impl/client/client.go @@ -863,3 +863,12 @@ func newDealInfo(v storagemarket.ClientDeal) api.DealInfo { func (a *API) ClientRetrieveTryRestartInsufficientFunds(ctx context.Context, paymentChannel address.Address) error { return a.Retrieval.TryRestartInsufficientFunds(paymentChannel) } + +func (a *API) ClientGetDealStatus(ctx context.Context, statusCode uint64) (string, error) { + ststr, ok := storagemarket.DealStates[statusCode] + if !ok { + return "", fmt.Errorf("no such deal state %d", statusCode) + } + + return ststr, nil +} From bf959e45fb5f1c5f9a406ffba407583af5517a21 Mon Sep 17 00:00:00 2001 From: Animesh Date: Wed, 7 Oct 2020 11:43:30 +0530 Subject: [PATCH 046/313] Add api for getting status given a code --- api/api_full.go | 2 ++ api/apistruct/struct.go | 21 +++++++++++++-------- node/impl/client/client.go | 9 +++++++++ 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index 88f18943c..072d1cea6 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -271,6 +271,8 @@ type FullNode interface { ClientListDeals(ctx context.Context) ([]DealInfo, error) // ClientGetDealUpdates returns the status of updated deals ClientGetDealUpdates(ctx context.Context) (<-chan DealInfo, error) + // ClientGetDealStatus returns status given a code + ClientGetDealStatus(ctx context.Context, statusCode uint64) (string, error) // ClientHasLocal indicates whether a certain CID is locally stored. ClientHasLocal(ctx context.Context, root cid.Cid) (bool, error) // ClientFindData identifies peers that have a certain file, and returns QueryOffers (one per peer). diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index a09700eb9..dd47c79a4 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -146,14 +146,15 @@ type FullNodeStruct struct { WalletDelete func(context.Context, address.Address) error `perm:"write"` WalletValidateAddress func(context.Context, string) (address.Address, error) `perm:"read"` - ClientImport func(ctx context.Context, ref api.FileRef) (*api.ImportRes, error) `perm:"admin"` - ClientListImports func(ctx context.Context) ([]api.Import, error) `perm:"write"` - ClientRemoveImport func(ctx context.Context, importID multistore.StoreID) error `perm:"admin"` - ClientHasLocal func(ctx context.Context, root cid.Cid) (bool, error) `perm:"write"` - ClientFindData func(ctx context.Context, root cid.Cid, piece *cid.Cid) ([]api.QueryOffer, error) `perm:"read"` - ClientMinerQueryOffer func(ctx context.Context, miner address.Address, root cid.Cid, piece *cid.Cid) (api.QueryOffer, error) `perm:"read"` - ClientStartDeal func(ctx context.Context, params *api.StartDealParams) (*cid.Cid, error) `perm:"admin"` - ClientGetDealInfo func(context.Context, cid.Cid) (*api.DealInfo, error) `perm:"read"` + ClientImport func(ctx context.Context, ref api.FileRef) (*api.ImportRes, error) `perm:"admin"` + ClientListImports func(ctx context.Context) ([]api.Import, error) `perm:"write"` + ClientRemoveImport func(ctx context.Context, importID multistore.StoreID) error `perm:"admin"` + ClientHasLocal func(ctx context.Context, root cid.Cid) (bool, error) `perm:"write"` + ClientFindData func(ctx context.Context, root cid.Cid, piece *cid.Cid) ([]api.QueryOffer, error) `perm:"read"` + ClientMinerQueryOffer func(ctx context.Context, miner address.Address, root cid.Cid, piece *cid.Cid) (api.QueryOffer, error) `perm:"read"` + ClientStartDeal func(ctx context.Context, params *api.StartDealParams) (*cid.Cid, error) `perm:"admin"` + ClientGetDealInfo func(context.Context, cid.Cid) (*api.DealInfo, error) `perm:"read"` + ClientGetDealStatus func(context.Context, uint64) (string, error) ClientListDeals func(ctx context.Context) ([]api.DealInfo, error) `perm:"write"` ClientGetDealUpdates func(ctx context.Context) (<-chan api.DealInfo, error) `perm:"read"` ClientRetrieve func(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) error `perm:"admin"` @@ -478,6 +479,10 @@ func (c *FullNodeStruct) ClientGetDealInfo(ctx context.Context, deal cid.Cid) (* return c.Internal.ClientGetDealInfo(ctx, deal) } +func (c *FullNodeStruct) ClientGetDealStatus(ctx context.Context, statusCode uint64) (string, error) { + return c.Internal.ClientGetDealStatus(ctx, statusCode) +} + func (c *FullNodeStruct) ClientListDeals(ctx context.Context) ([]api.DealInfo, error) { return c.Internal.ClientListDeals(ctx) } diff --git a/node/impl/client/client.go b/node/impl/client/client.go index 5c1752154..6af266baa 100644 --- a/node/impl/client/client.go +++ b/node/impl/client/client.go @@ -863,3 +863,12 @@ func newDealInfo(v storagemarket.ClientDeal) api.DealInfo { func (a *API) ClientRetrieveTryRestartInsufficientFunds(ctx context.Context, paymentChannel address.Address) error { return a.Retrieval.TryRestartInsufficientFunds(paymentChannel) } + +func (a *API) ClientGetDealStatus(ctx context.Context, statusCode uint64) (string, error) { + ststr, ok := storagemarket.DealStates[statusCode] + if !ok { + return "", fmt.Errorf("no such deal state %d", statusCode) + } + + return ststr, nil +} From 673de6aeb67eac8b0536b86cfe3c105a96ee8213 Mon Sep 17 00:00:00 2001 From: Animesh Date: Wed, 7 Oct 2020 12:35:42 +0530 Subject: [PATCH 047/313] Add perm tag to ClientGetDealStatus --- api/apistruct/struct.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index dd47c79a4..b27e9082c 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -146,15 +146,15 @@ type FullNodeStruct struct { WalletDelete func(context.Context, address.Address) error `perm:"write"` WalletValidateAddress func(context.Context, string) (address.Address, error) `perm:"read"` - ClientImport func(ctx context.Context, ref api.FileRef) (*api.ImportRes, error) `perm:"admin"` - ClientListImports func(ctx context.Context) ([]api.Import, error) `perm:"write"` - ClientRemoveImport func(ctx context.Context, importID multistore.StoreID) error `perm:"admin"` - ClientHasLocal func(ctx context.Context, root cid.Cid) (bool, error) `perm:"write"` - ClientFindData func(ctx context.Context, root cid.Cid, piece *cid.Cid) ([]api.QueryOffer, error) `perm:"read"` - ClientMinerQueryOffer func(ctx context.Context, miner address.Address, root cid.Cid, piece *cid.Cid) (api.QueryOffer, error) `perm:"read"` - ClientStartDeal func(ctx context.Context, params *api.StartDealParams) (*cid.Cid, error) `perm:"admin"` - ClientGetDealInfo func(context.Context, cid.Cid) (*api.DealInfo, error) `perm:"read"` - ClientGetDealStatus func(context.Context, uint64) (string, error) + ClientImport func(ctx context.Context, ref api.FileRef) (*api.ImportRes, error) `perm:"admin"` + ClientListImports func(ctx context.Context) ([]api.Import, error) `perm:"write"` + ClientRemoveImport func(ctx context.Context, importID multistore.StoreID) error `perm:"admin"` + ClientHasLocal func(ctx context.Context, root cid.Cid) (bool, error) `perm:"write"` + ClientFindData func(ctx context.Context, root cid.Cid, piece *cid.Cid) ([]api.QueryOffer, error) `perm:"read"` + ClientMinerQueryOffer func(ctx context.Context, miner address.Address, root cid.Cid, piece *cid.Cid) (api.QueryOffer, error) `perm:"read"` + ClientStartDeal func(ctx context.Context, params *api.StartDealParams) (*cid.Cid, error) `perm:"admin"` + ClientGetDealInfo func(context.Context, cid.Cid) (*api.DealInfo, error) `perm:"read"` + ClientGetDealStatus func(context.Context, uint64) (string, error) `perm:"read"` ClientListDeals func(ctx context.Context) ([]api.DealInfo, error) `perm:"write"` ClientGetDealUpdates func(ctx context.Context) (<-chan api.DealInfo, error) `perm:"read"` ClientRetrieve func(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) error `perm:"admin"` From 0f53eca88356acd3e087ef8ef57c41f08b64665a Mon Sep 17 00:00:00 2001 From: hunjixin <1084400399@qq.com> Date: Thu, 8 Oct 2020 10:04:43 +0800 Subject: [PATCH 048/313] add batch api for push messages --- api/api_full.go | 9 +++++++++ api/apistruct/struct.go | 16 ++++++++++++++++ node/impl/full/mpool.go | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) diff --git a/api/api_full.go b/api/api_full.go index 88f18943c..6696a9f92 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -203,6 +203,15 @@ type FullNode interface { // based on current chain conditions MpoolPushMessage(ctx context.Context, msg *types.Message, spec *MessageSendSpec) (*types.SignedMessage, error) + // MpoolBatchPush batch pushes a signed message to mempool. + MpoolBatchPush(context.Context, []*types.SignedMessage) ([]cid.Cid, error) + + // MpoolBatchPushUntrusted batch pushes a signed message to mempool from untrusted sources. + MpoolBatchPushUntrusted(context.Context, []*types.SignedMessage) ([]cid.Cid, error) + + // MpoolBatchPushMessage batch pushes a unsigned message to mempool. + MpoolBatchPushMessage(context.Context, []*types.Message, *MessageSendSpec) ([]*types.SignedMessage, error) + // MpoolGetNonce gets next nonce for the specified sender. // Note that this method may not be atomic. Use MpoolPushMessage instead. MpoolGetNonce(context.Context, address.Address) (uint64, error) diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index a09700eb9..e9e09606e 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -129,6 +129,10 @@ type FullNodeStruct struct { MpoolGetNonce func(context.Context, address.Address) (uint64, error) `perm:"read"` MpoolSub func(context.Context) (<-chan api.MpoolUpdate, error) `perm:"read"` + MpoolBatchPush func(ctx context.Context, smsgs []*types.SignedMessage) ([]cid.Cid, error) `perm:"write"` + MpoolBatchPushUntrusted func(ctx context.Context, smsgs []*types.SignedMessage) ([]cid.Cid, error) `perm:"write"` + MpoolBatchPushMessage func(ctx context.Context, msgs []*types.Message, spec *api.MessageSendSpec) ([]*types.SignedMessage, error) `perm:"sign"` + MinerGetBaseInfo func(context.Context, address.Address, abi.ChainEpoch, types.TipSetKey) (*api.MiningBaseInfo, error) `perm:"read"` MinerCreateBlock func(context.Context, *api.BlockTemplate) (*types.BlockMsg, error) `perm:"write"` @@ -569,6 +573,18 @@ func (c *FullNodeStruct) MpoolPushMessage(ctx context.Context, msg *types.Messag return c.Internal.MpoolPushMessage(ctx, msg, spec) } +func (c *FullNodeStruct) MpoolBatchPush(ctx context.Context, smsgs []*types.SignedMessage) ([]cid.Cid, error) { + return c.Internal.MpoolBatchPush(ctx, smsgs) +} + +func (c *FullNodeStruct) MpoolBatchPushUntrusted(ctx context.Context, smsgs []*types.SignedMessage) ([]cid.Cid, error) { + return c.Internal.MpoolBatchPushUntrusted(ctx, smsgs) +} + +func (c *FullNodeStruct) MpoolBatchPushMessage(ctx context.Context, msgs []*types.Message, spec *api.MessageSendSpec) ([]*types.SignedMessage, error) { + return c.Internal.MpoolBatchPushMessage(ctx, msgs, spec) +} + func (c *FullNodeStruct) MpoolSub(ctx context.Context) (<-chan api.MpoolUpdate, error) { return c.Internal.MpoolSub(ctx) } diff --git a/node/impl/full/mpool.go b/node/impl/full/mpool.go index 1f093606c..11c3fb045 100644 --- a/node/impl/full/mpool.go +++ b/node/impl/full/mpool.go @@ -169,6 +169,42 @@ func (a *MpoolAPI) MpoolPushMessage(ctx context.Context, msg *types.Message, spe }) } +func (a *MpoolAPI) MpoolBatchPush(ctx context.Context, smsgs []*types.SignedMessage) ([]cid.Cid, error) { + var messageCids []cid.Cid + for _, smsg := range smsgs { + smsgCid, err := a.Mpool.Push(smsg) + if err != nil { + return messageCids, err + } + messageCids = append(messageCids, smsgCid) + } + return messageCids, nil +} + +func (a *MpoolAPI) MpoolBatchPushUntrusted(ctx context.Context, smsgs []*types.SignedMessage) ([]cid.Cid, error) { + var messageCids []cid.Cid + for _, smsg := range smsgs { + smsgCid, err := a.Mpool.PushUntrusted(smsg) + if err != nil { + return messageCids, err + } + messageCids = append(messageCids, smsgCid) + } + return messageCids, nil +} + +func (a *MpoolAPI) MpoolBatchPushMessage(ctx context.Context, msgs []*types.Message, spec *api.MessageSendSpec) ([]*types.SignedMessage, error) { + var smsgs []*types.SignedMessage + for _, msg := range msgs { + smsg, err := a.MpoolPushMessage(ctx, msg, spec) + if err != nil { + return smsgs, err + } + smsgs = append(smsgs, smsg) + } + return smsgs, nil +} + func (a *MpoolAPI) MpoolGetNonce(ctx context.Context, addr address.Address) (uint64, error) { return a.Mpool.GetNonce(addr) } From d37389162e6ca2f03f1b198f05c88745784a57cf Mon Sep 17 00:00:00 2001 From: Animesh Date: Fri, 9 Oct 2020 09:55:38 +0530 Subject: [PATCH 049/313] Add docs --- documentation/en/api-methods.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index 630eae32e..f9678903b 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -37,6 +37,7 @@ * [ClientFindData](#ClientFindData) * [ClientGenCar](#ClientGenCar) * [ClientGetDealInfo](#ClientGetDealInfo) + * [ClientGetDealStatus](#ClientGetDealStatus) * [ClientGetDealUpdates](#ClientGetDealUpdates) * [ClientHasLocal](#ClientHasLocal) * [ClientImport](#ClientImport) @@ -963,6 +964,21 @@ Response: } ``` +### ClientGetDealStatus +ClientGetDealStatus returns status given a code + + +Perms: + +Inputs: +```json +[ + 42 +] +``` + +Response: `"string value"` + ### ClientGetDealUpdates ClientGetDealUpdates returns the status of updated deals From 4832cad1f1393cc57eb4f0407e3df6d3c5f29ca4 Mon Sep 17 00:00:00 2001 From: Animesh Date: Fri, 9 Oct 2020 10:18:32 +0530 Subject: [PATCH 050/313] sanity fix --- documentation/en/api-methods.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index f9678903b..ab298fe75 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -190,7 +190,7 @@ * [WalletSignMessage](#WalletSignMessage) * [WalletValidateAddress](#WalletValidateAddress) * [WalletVerify](#WalletVerify) -## +## ### Closing @@ -968,7 +968,7 @@ Response: ClientGetDealStatus returns status given a code -Perms: +Perms: Inputs: ```json From e0dcb0ec4930b465948af8ec04dc9ce6835c8087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Fri, 9 Oct 2020 22:20:15 +0100 Subject: [PATCH 051/313] tvx: trace puts to blockstore for inclusion in CAR. --- cmd/tvx/stores.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/cmd/tvx/stores.go b/cmd/tvx/stores.go index 93e0d215f..4f574c175 100644 --- a/cmd/tvx/stores.go +++ b/cmd/tvx/stores.go @@ -87,7 +87,7 @@ type proxyingBlockstore struct { ctx context.Context api api.FullNode - lk sync.RWMutex + lk sync.Mutex tracing bool traced map[cid.Cid]struct{} @@ -113,11 +113,11 @@ func (pb *proxyingBlockstore) FinishTracing() map[cid.Cid]struct{} { } func (pb *proxyingBlockstore) Get(cid cid.Cid) (blocks.Block, error) { - pb.lk.RLock() + pb.lk.Lock() if pb.tracing { pb.traced[cid] = struct{}{} } - pb.lk.RUnlock() + pb.lk.Unlock() if block, err := pb.Blockstore.Get(cid); err == nil { return block, err @@ -140,3 +140,12 @@ func (pb *proxyingBlockstore) Get(cid cid.Cid) (blocks.Block, error) { return block, nil } + +func (pb *proxyingBlockstore) Put(block blocks.Block) error { + pb.lk.Lock() + if pb.tracing { + pb.traced[block.Cid()] = struct{}{} + } + pb.lk.Unlock() + return pb.Blockstore.Put(block) +} From 85be11fb7515d997460b12cb91ed212d7e3dc3ac Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Sun, 11 Oct 2020 18:10:02 +0200 Subject: [PATCH 052/313] Add propose remove Signed-off-by: Jakub Sztandera --- chain/actors/builtin/multisig/message.go | 1 + cli/multisig.go | 79 ++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/chain/actors/builtin/multisig/message.go b/chain/actors/builtin/multisig/message.go index b19287432..5beb5319d 100644 --- a/chain/actors/builtin/multisig/message.go +++ b/chain/actors/builtin/multisig/message.go @@ -45,6 +45,7 @@ type MessageBuilder interface { // this type is the same between v0 and v2 type ProposalHashData = multisig2.ProposalHashData +type ProposeReturn = multisig2.ProposeReturn func txnParams(id uint64, data *ProposalHashData) ([]byte, error) { params := multisig2.TxnIDParams{ID: multisig2.TxnID(id)} diff --git a/cli/multisig.go b/cli/multisig.go index b692fad5a..90074c64d 100644 --- a/cli/multisig.go +++ b/cli/multisig.go @@ -41,6 +41,7 @@ var multisigCmd = &cli.Command{ msigCreateCmd, msigInspectCmd, msigProposeCmd, + msigRemoveProposeCmd, msigApproveCmd, msigAddProposeCmd, msigAddApproveCmd, @@ -504,6 +505,84 @@ var msigApproveCmd = &cli.Command{ }, } +var msigRemoveProposeCmd = &cli.Command{ + Name: "propose-remove", + Usage: "Propose to remove a signer", + ArgsUsage: "[multisigAddress signer]", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "decrease-threshold", + Usage: "whether the number of required signers should be decreased", + }, + &cli.StringFlag{ + Name: "from", + Usage: "account to send the propose message from", + }, + }, + Action: func(cctx *cli.Context) error { + if cctx.Args().Len() != 2 { + return ShowHelp(cctx, fmt.Errorf("must pass multisig address and signer address")) + } + + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + msig, err := address.NewFromString(cctx.Args().Get(0)) + if err != nil { + return err + } + + addr, err := address.NewFromString(cctx.Args().Get(1)) + if err != nil { + return err + } + + var from address.Address + if cctx.IsSet("from") { + f, err := address.NewFromString(cctx.String("from")) + if err != nil { + return err + } + from = f + } else { + defaddr, err := api.WalletDefaultAddress(ctx) + if err != nil { + return err + } + from = defaddr + } + + msgCid, err := api.MsigRemoveSigner(ctx, msig, from, addr, cctx.Bool("decrease-threshold")) + if err != nil { + return err + } + + fmt.Println("sent remove proposal in message: ", msgCid) + + wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence) + if err != nil { + return err + } + + if wait.Receipt.ExitCode != 0 { + return fmt.Errorf("add proposal returned exit %d", wait.Receipt.ExitCode) + } + + var ret multisig.ProposeReturn + err = ret.UnmarshalCBOR(bytes.NewReader(wait.Receipt.Return)) + if err != nil { + return xerrors.Errorf("decoding proposal return: %w", err) + } + fmt.Printf("TxnID: %d", ret.TxnID) + + return nil + }, +} + var msigAddProposeCmd = &cli.Command{ Name: "add-propose", Usage: "Propose to add a signer", From a36ec27230d1713aed62dcedaa6b1d19e9b2e723 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Sun, 11 Oct 2020 21:14:51 +0200 Subject: [PATCH 053/313] Look at block base fee Signed-off-by: Jakub Sztandera --- cmd/lotus-pcr/main.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cmd/lotus-pcr/main.go b/cmd/lotus-pcr/main.go index 5491e4af2..b5da05883 100644 --- a/cmd/lotus-pcr/main.go +++ b/cmd/lotus-pcr/main.go @@ -926,6 +926,11 @@ func (r *refunder) processTipsetStorageMinerActor(ctx context.Context, tipset *t return false, messageMethod, types.NewInt(0), nil } + if tipset.Blocks()[0].ParentBaseFee.GreaterThan(r.proveFeeCapMax) { + log.Debugw("skipping high base fee message", "method", messageMethod, "cid", msg.Cid, "miner", m.To, "basefee", tipset.Blocks()[0].ParentBaseFee, "fee_cap_max", r.proveFeeCapMax) + return false, messageMethod, types.NewInt(0), nil + } + var sn abi.SectorNumber var proveCommitSector miner0.ProveCommitSectorParams @@ -982,6 +987,11 @@ func (r *refunder) processTipsetStorageMinerActor(ctx context.Context, tipset *t return false, messageMethod, types.NewInt(0), nil } + if tipset.Blocks()[0].ParentBaseFee.GreaterThan(r.preFeeCapMax) { + log.Debugw("skipping high base fee message", "method", messageMethod, "cid", msg.Cid, "miner", m.To, "basefee", tipset.Blocks()[0].ParentBaseFee, "fee_cap_max", r.preFeeCapMax) + return false, messageMethod, types.NewInt(0), nil + } + var precommitInfo miner.SectorPreCommitInfo if err := precommitInfo.UnmarshalCBOR(bytes.NewBuffer(m.Params)); err != nil { log.Warnw("failed to decode precommit params", "err", err, "method", messageMethod, "cid", msg.Cid, "miner", m.To) From 23470bc38ff8502660c107418d323554d9d6fb83 Mon Sep 17 00:00:00 2001 From: Travis Person Date: Sun, 11 Oct 2020 20:27:36 +0000 Subject: [PATCH 054/313] lotus-stats: optmize getting miner power --- tools/stats/metrics.go | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/tools/stats/metrics.go b/tools/stats/metrics.go index aee61b2aa..8dc79ea44 100644 --- a/tools/stats/metrics.go +++ b/tools/stats/metrics.go @@ -16,6 +16,9 @@ import ( "github.com/filecoin-project/lotus/chain/actors/builtin/reward" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/specs-actors/actors/builtin" + "github.com/filecoin-project/specs-actors/actors/builtin/power" + "github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/ipfs/go-cid" "github.com/multiformats/go-multihash" @@ -269,22 +272,47 @@ func RecordTipsetStatePoints(ctx context.Context, api api.FullNode, pl *PointLis p = NewPoint("chain.power", totalPower.TotalPower.QualityAdjPower.Int64()) pl.AddPoint(p) - miners, err := api.StateListMiners(ctx, tipset.Key()) + powerActor, err := api.StateGetActor(ctx, builtin.StoragePowerActorAddr, tipset.Key()) if err != nil { return err } - for _, addr := range miners { - mp, err := api.StateMinerPower(ctx, addr, tipset.Key()) + powerRaw, err := api.ChainReadObj(ctx, powerActor.Head) + if err != nil { + return err + } + + var powerActorState power.State + + if err := powerActorState.UnmarshalCBOR(bytes.NewReader(powerRaw)); err != nil { + return fmt.Errorf("failed to unmarshal power actor state: %w", err) + } + + s := &ApiIpldStore{ctx, api} + mp, err := adt.AsMap(s, powerActorState.Claims) + if err != nil { + return err + } + + var claim power.Claim + err = mp.ForEach(&claim, func(key string) error { + addr, err := address.NewFromBytes([]byte(key)) if err != nil { return err } - if !mp.MinerPower.QualityAdjPower.IsZero() { - p = NewPoint("chain.miner_power", mp.MinerPower.QualityAdjPower.Int64()) - p.AddTag("miner", addr.String()) - pl.AddPoint(p) + if claim.QualityAdjPower.Int64() == 0 { + return nil } + + p = NewPoint("chain.miner_power", claim.QualityAdjPower.Int64()) + p.AddTag("miner", addr.String()) + pl.AddPoint(p) + + return nil + }) + if err != nil { + return err } return nil From b35f9b56b42ae7415284f5ced424af21923d693e Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Fri, 9 Oct 2020 20:17:04 -0700 Subject: [PATCH 055/313] WIP: adding in ledger support Signed-off-by: Jakub Sztandera --- chain/messagepool/messagepool.go | 3 + chain/wallet/ledger/ledger.go | 139 +++++++++++++++++++++ cmd/lotus-shed/ledger.go | 205 +++++++++++++++++++++++++++++++ cmd/lotus-shed/main.go | 1 + cmd/lotus-wallet/main.go | 11 +- go.mod | 1 + go.sum | 7 ++ 7 files changed, 366 insertions(+), 1 deletion(-) create mode 100644 chain/wallet/ledger/ledger.go create mode 100644 cmd/lotus-shed/ledger.go diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index d3c638b22..2a4704c3b 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -1249,6 +1249,9 @@ func (mp *MessagePool) Updates(ctx context.Context) (<-chan api.MpoolUpdate, err } func (mp *MessagePool) loadLocal() error { + return nil + // TODO: this causes super slow startup... + res, err := mp.localMsgs.Query(query.Query{}) if err != nil { return xerrors.Errorf("query local messages: %w", err) diff --git a/chain/wallet/ledger/ledger.go b/chain/wallet/ledger/ledger.go new file mode 100644 index 000000000..36b0fb040 --- /dev/null +++ b/chain/wallet/ledger/ledger.go @@ -0,0 +1,139 @@ +package ledgerwallet + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/crypto" + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/types" + "github.com/ipfs/go-datastore" + "github.com/ipfs/go-datastore/query" + ledgerfil "github.com/whyrusleeping/ledger-filecoin-go" +) + +type LedgerWallet struct { + ds datastore.Datastore +} + +func NewWallet(ds datastore.Datastore) *LedgerWallet { + return &LedgerWallet{ds} +} + +type LedgerKeyInfo struct { + Address address.Address + Path []uint32 +} + +var _ (api.WalletAPI) = (*LedgerWallet)(nil) + +func (lw LedgerWallet) WalletSign(ctx context.Context, signer address.Address, toSign []byte, meta api.MsgMeta) (*crypto.Signature, error) { + ki, err := lw.getKeyInfo(signer) + if err != nil { + return nil, err + } + + fl, err := ledgerfil.FindLedgerFilecoinApp() + if err != nil { + return nil, err + } + defer fl.Close() + if meta.Type != api.MTChainMsg { + return nil, fmt.Errorf("ledger can only sign chain messages") + } + + // TODO: assert meta matches the 'toSign' bits + + sig, err := fl.SignSECP256K1(ki.Path, meta.Extra) + if err != nil { + return nil, err + } + + return &crypto.Signature{ + Type: crypto.SigTypeSecp256k1, + Data: sig.SignatureBytes(), + }, nil +} + +func (lw LedgerWallet) getKeyInfo(addr address.Address) (*LedgerKeyInfo, error) { + kib, err := lw.ds.Get(keyForAddr(addr)) + if err != nil { + return nil, err + } + + var out LedgerKeyInfo + if err := json.Unmarshal(kib, &out); err != nil { + return nil, err + } + + return &out, nil +} + +func (lw LedgerWallet) WalletDelete(ctx context.Context, k address.Address) error { + return lw.ds.Delete(keyForAddr(k)) +} + +func (lw LedgerWallet) WalletExport(ctx context.Context, k address.Address) (*types.KeyInfo, error) { + return nil, fmt.Errorf("cannot export keys from ledger wallets") +} + +func (lw LedgerWallet) WalletHas(ctx context.Context, k address.Address) (bool, error) { + _, err := lw.ds.Get(keyForAddr(k)) + if err == nil { + return true, nil + } + if err == datastore.ErrNotFound { + return false, nil + } + return false, err +} + +func (lw LedgerWallet) WalletImport(ctx context.Context, kinfo *types.KeyInfo) (address.Address, error) { + var ki LedgerKeyInfo + if err := json.Unmarshal(kinfo.PrivateKey, &ki); err != nil { + return address.Undef, err + } + + if ki.Address == address.Undef { + return address.Undef, fmt.Errorf("no address given in imported key info") + } + + if err := lw.ds.Put(keyForAddr(ki.Address), kinfo.PrivateKey); err != nil { + return address.Undef, err + } + + return ki.Address, nil +} + +func (lw LedgerWallet) WalletList(ctx context.Context) ([]address.Address, error) { + res, err := lw.ds.Query(query.Query{Prefix: "ledgerkey/"}) + if err != nil { + return nil, err + } + + var out []address.Address + for { + res, ok := res.NextSync() + if !ok { + break + } + + var ki LedgerKeyInfo + if err := json.Unmarshal(res.Value, &ki); err != nil { + return nil, err + } + + out = append(out, ki.Address) + } + return out, nil +} + +func (lw LedgerWallet) WalletNew(ctx context.Context, t crypto.SigType) (address.Address, error) { + return address.Undef, fmt.Errorf("cannot create new address on ledger") +} + +func keyForAddr(addr address.Address) datastore.Key { + return datastore.NewKey("ledgerkey/" + addr.String()) +} diff --git a/cmd/lotus-shed/ledger.go b/cmd/lotus-shed/ledger.go new file mode 100644 index 000000000..4bb61e5e0 --- /dev/null +++ b/cmd/lotus-shed/ledger.go @@ -0,0 +1,205 @@ +package main + +import ( + "encoding/json" + "fmt" + "strconv" + "strings" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/chain/wallet" + ledgerwallet "github.com/filecoin-project/lotus/chain/wallet/ledger" + "github.com/urfave/cli/v2" + ledgerfil "github.com/whyrusleeping/ledger-filecoin-go" +) + +var ledgerCmd = &cli.Command{ + Name: "ledger", + Usage: "Ledger interactions", + Flags: []cli.Flag{}, + Subcommands: []*cli.Command{ + ledgerListAddressesCmd, + ledgerKeyInfoCmd, + ledgerSignTestCmd, + }, +} + +var ledgerListAddressesCmd = &cli.Command{ + Name: "list", + Action: func(cctx *cli.Context) error { + + fl, err := ledgerfil.FindLedgerFilecoinApp() + if err != nil { + return err + } + + for i := 0; i < 20; i++ { + p := []uint32{0x80000000 + 44, 0x80000000 + 461, 0x80000000, 0, uint32(i)} + pubk, err := fl.GetPublicKeySECP256K1(p) + if err != nil { + return err + } + + addr, err := address.NewSecp256k1Address(pubk) + if err != nil { + return err + } + + fmt.Printf("%s: %s\n", addr, printHDPath(p)) + } + + return nil + }, +} + +func parseHDPath(s string) ([]uint32, error) { + parts := strings.Split(s, "/") + if parts[0] != "m" { + return nil, fmt.Errorf("expected HD path to start with 'm'") + } + + var out []uint32 + for _, p := range parts[1:] { + var hard bool + if strings.HasSuffix(p, "'") { + p = p[:len(p)-1] + hard = true + } + + v, err := strconv.ParseUint(p, 10, 32) + if err != nil { + return nil, err + } + if v >= 0x80000000 { + return nil, fmt.Errorf("path element %s too large", p) + } + + if hard { + v += 0x80000000 + } + out = append(out, uint32(v)) + } + return out, nil +} + +func printHDPath(pth []uint32) string { + s := "m/" + for _, p := range pth { + var hard bool + if p >= 0x80000000 { + p -= 0x80000000 + } + s += fmt.Sprint(p) + if hard { + s += "'" + } + s += "/" + } + + return strings.TrimRight(s, "/") +} + +func numlist(p []uint32) string { + var out []string + for _, v := range p { + out = append(out, fmt.Sprint(v)) + } + return strings.Join(out, ",") +} + +var ledgerKeyInfoCmd = &cli.Command{ + Name: "key-info", + Action: func(cctx *cli.Context) error { + if !cctx.Args().Present() { + return cli.ShowCommandHelp(cctx, cctx.Command.Name) + } + + fl, err := ledgerfil.FindLedgerFilecoinApp() + if err != nil { + return err + } + + p, err := parseHDPath(cctx.Args().First()) + if err != nil { + return err + } + + pubk, _, addr, err := fl.GetAddressPubKeySECP256K1(p) + if err != nil { + return err + } + fmt.Println(addr) + fmt.Println(pubk) + + a, err := address.NewFromString(addr) + if err != nil { + return err + } + + var pd ledgerwallet.LedgerKeyInfo + pd.Address = a + pd.Path = p + + b, err := json.Marshal(pd) + if err != nil { + return err + } + + var ki types.KeyInfo + ki.Type = wallet.KTSecp256k1 + ki.PrivateKey = b + + out, err := json.Marshal(ki) + if err != nil { + return err + } + + fmt.Println(string(out)) + + return nil + }, +} + +var ledgerSignTestCmd = &cli.Command{ + Name: "sign", + Action: func(cctx *cli.Context) error { + if !cctx.Args().Present() { + return cli.ShowCommandHelp(cctx, cctx.Command.Name) + } + + fl, err := ledgerfil.FindLedgerFilecoinApp() + if err != nil { + return err + } + + p, err := parseHDPath(cctx.Args().First()) + if err != nil { + return err + } + + addr, err := address.NewFromString("f1xc3hws5n6y5m3m44gzb3gyjzhups6wzmhe663ji") + if err != nil { + return err + } + + m := &types.Message{ + To: addr, + From: addr, + } + + b, err := m.ToStorageBlock() + if err != nil { + return err + } + + sig, err := fl.SignSECP256K1(p, b.RawData()) + if err != nil { + return err + } + + fmt.Println(sig.SignatureBytes()) + + return nil + }, +} diff --git a/cmd/lotus-shed/main.go b/cmd/lotus-shed/main.go index 4542551db..29a105355 100644 --- a/cmd/lotus-shed/main.go +++ b/cmd/lotus-shed/main.go @@ -41,6 +41,7 @@ func main() { syncCmd, stateTreePruneCmd, datastoreCmd, + ledgerCmd, } app := &cli.App{ diff --git a/cmd/lotus-wallet/main.go b/cmd/lotus-wallet/main.go index ae3580a59..fbedffed0 100644 --- a/cmd/lotus-wallet/main.go +++ b/cmd/lotus-wallet/main.go @@ -13,6 +13,7 @@ import ( "github.com/filecoin-project/go-jsonrpc" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/wallet" + ledgerwallet "github.com/filecoin-project/lotus/chain/wallet/ledger" lcli "github.com/filecoin-project/lotus/cli" "github.com/filecoin-project/lotus/lib/lotuslog" "github.com/filecoin-project/lotus/node/repo" @@ -98,6 +99,14 @@ var runCmd = &cli.Command{ if err != nil { return err } + _ = w + + ds, err := lr.Datastore("/metadata") + if err != nil { + return err + } + + lw := ledgerwallet.NewWallet(ds) address := cctx.String("listen") mux := mux.NewRouter() @@ -105,7 +114,7 @@ var runCmd = &cli.Command{ log.Info("Setting up API endpoint at " + address) rpcServer := jsonrpc.NewServer() - rpcServer.Register("Filecoin", &LoggedWallet{under: w}) + rpcServer.Register("Filecoin", &LoggedWallet{under: lw}) mux.Handle("/rpc/v0", rpcServer) mux.PathPrefix("/").Handler(http.DefaultServeMux) // pprof diff --git a/go.mod b/go.mod index eb79a496c..d6a4768b7 100644 --- a/go.mod +++ b/go.mod @@ -120,6 +120,7 @@ require ( github.com/urfave/cli/v2 v2.2.0 github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba github.com/whyrusleeping/cbor-gen v0.0.0-20200826160007-0b9f6c5fb163 + github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4 github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 github.com/whyrusleeping/pubsub v0.0.0-20131020042734-02de8aa2db3d github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542 diff --git a/go.sum b/go.sum index e13359f6c..fe7aacbf9 100644 --- a/go.sum +++ b/go.sum @@ -1422,6 +1422,8 @@ github.com/whyrusleeping/go-smux-multiplex v3.0.16+incompatible/go.mod h1:34LEDb github.com/whyrusleeping/go-smux-multistream v2.0.2+incompatible/go.mod h1:dRWHHvc4HDQSHh9gbKEBbUZ+f2Q8iZTPG3UOGYODxSQ= github.com/whyrusleeping/go-smux-yamux v2.0.8+incompatible/go.mod h1:6qHUzBXUbB9MXmw3AUdB52L8sEb/hScCqOdW2kj/wuI= github.com/whyrusleeping/go-smux-yamux v2.0.9+incompatible/go.mod h1:6qHUzBXUbB9MXmw3AUdB52L8sEb/hScCqOdW2kj/wuI= +github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4 h1:NwiwjQDB3CzQ5XH0rdMh1oQqzJH7O2PSLWxif/w3zsY= +github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4/go.mod h1:K+EVq8d5QcQ2At5VECsA+SNZvWefyBXh8TnIsxo1OvQ= github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA= github.com/whyrusleeping/mdns v0.0.0-20180901202407-ef14215e6b30/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= @@ -1443,6 +1445,10 @@ github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542 h1:oWgZJmC1DorFZD github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542/go.mod h1:7T39/ZMvaSEZlBPoYfVFmsBLmUl3uz9IuzWj/U6FtvQ= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8= +github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +github.com/zondax/ledger-go v0.12.1 h1:hYRcyznPRJp+5mzF2sazTLP2nGvGjYDD2VzhHhFomLU= +github.com/zondax/ledger-go v0.12.1/go.mod h1:KatxXrVDzgWwbssUWsF5+cOJHXPvzQ09YSlzGNuhOEo= go.dedis.ch/fixbuf v1.0.3 h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs= go.dedis.ch/fixbuf v1.0.3/go.mod h1:yzJMt34Wa5xD37V5RTdmp38cz3QhMagdGoem9anUalw= go.dedis.ch/kyber/v3 v3.0.4/go.mod h1:OzvaEnPvKlyrWyp3kGXlFdp7ap1VC6RkZDTaPikqhsQ= @@ -1515,6 +1521,7 @@ golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= From 99791a695373c78ec93d985adb5895358406585b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sat, 10 Oct 2020 13:03:39 +0200 Subject: [PATCH 056/313] lotus-wallet: ledger flag Signed-off-by: Jakub Sztandera --- cmd/lotus-wallet/main.go | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/cmd/lotus-wallet/main.go b/cmd/lotus-wallet/main.go index fbedffed0..2d87998a4 100644 --- a/cmd/lotus-wallet/main.go +++ b/cmd/lotus-wallet/main.go @@ -2,6 +2,7 @@ package main import ( "context" + "github.com/filecoin-project/lotus/api" "net" "net/http" "os" @@ -61,6 +62,10 @@ var runCmd = &cli.Command{ Usage: "host address and port the wallet api will listen on", Value: "0.0.0.0:1777", }, + &cli.BoolFlag{ + Name: "ledger", + Usage: "use a ledger device instead of an on-disk wallet", + }, }, Action: func(cctx *cli.Context) error { log.Info("Starting lotus wallet") @@ -95,18 +100,21 @@ var runCmd = &cli.Command{ return err } - w, err := wallet.NewWallet(ks) - if err != nil { - return err - } - _ = w + var w api.WalletAPI + if !cctx.Bool("ledger") { + w, err = wallet.NewWallet(ks) + if err != nil { + return err + } + } else { + ds, err := lr.Datastore("/metadata") + if err != nil { + return err + } - ds, err := lr.Datastore("/metadata") - if err != nil { - return err + w = ledgerwallet.NewWallet(ds) } - lw := ledgerwallet.NewWallet(ds) address := cctx.String("listen") mux := mux.NewRouter() @@ -114,7 +122,7 @@ var runCmd = &cli.Command{ log.Info("Setting up API endpoint at " + address) rpcServer := jsonrpc.NewServer() - rpcServer.Register("Filecoin", &LoggedWallet{under: lw}) + rpcServer.Register("Filecoin", &LoggedWallet{under: w}) mux.Handle("/rpc/v0", rpcServer) mux.PathPrefix("/").Handler(http.DefaultServeMux) // pprof From 66d6113340e943fe9aca2b0227312ac521b059e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sat, 10 Oct 2020 13:06:02 +0200 Subject: [PATCH 057/313] ledgerwallet: Validate signing bytes Signed-off-by: Jakub Sztandera --- chain/wallet/ledger/ledger.go | 21 +++++++++++++++++++-- cmd/lotus-wallet/main.go | 6 +++--- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/chain/wallet/ledger/ledger.go b/chain/wallet/ledger/ledger.go index 36b0fb040..71ec067c8 100644 --- a/chain/wallet/ledger/ledger.go +++ b/chain/wallet/ledger/ledger.go @@ -1,9 +1,12 @@ package ledgerwallet import ( + "bytes" "context" "encoding/json" "fmt" + "github.com/ipfs/go-cid" + "golang.org/x/xerrors" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/crypto" @@ -27,7 +30,7 @@ type LedgerKeyInfo struct { Path []uint32 } -var _ (api.WalletAPI) = (*LedgerWallet)(nil) +var _ api.WalletAPI = (*LedgerWallet)(nil) func (lw LedgerWallet) WalletSign(ctx context.Context, signer address.Address, toSign []byte, meta api.MsgMeta) (*crypto.Signature, error) { ki, err := lw.getKeyInfo(signer) @@ -44,7 +47,21 @@ func (lw LedgerWallet) WalletSign(ctx context.Context, signer address.Address, t return nil, fmt.Errorf("ledger can only sign chain messages") } - // TODO: assert meta matches the 'toSign' bits + { + var cmsg types.Message + if err := cmsg.UnmarshalCBOR(bytes.NewReader(meta.Extra)); err != nil { + return nil, xerrors.Errorf("unmarshalling message: %w", err) + } + + _, bc, err := cid.CidFromBytes(toSign) + if err != nil { + return nil, xerrors.Errorf("getting cid from signing bytes: %w", err) + } + + if !cmsg.Cid().Equals(bc) { + return nil, xerrors.Errorf("cid(meta.Extra).bytes() != toSign") + } + } sig, err := fl.SignSECP256K1(ki.Path, meta.Extra) if err != nil { diff --git a/cmd/lotus-wallet/main.go b/cmd/lotus-wallet/main.go index 2d87998a4..ffaddc7e3 100644 --- a/cmd/lotus-wallet/main.go +++ b/cmd/lotus-wallet/main.go @@ -2,7 +2,6 @@ package main import ( "context" - "github.com/filecoin-project/lotus/api" "net" "net/http" "os" @@ -12,6 +11,8 @@ import ( "github.com/urfave/cli/v2" "github.com/filecoin-project/go-jsonrpc" + + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/wallet" ledgerwallet "github.com/filecoin-project/lotus/chain/wallet/ledger" @@ -63,7 +64,7 @@ var runCmd = &cli.Command{ Value: "0.0.0.0:1777", }, &cli.BoolFlag{ - Name: "ledger", + Name: "ledger", Usage: "use a ledger device instead of an on-disk wallet", }, }, @@ -115,7 +116,6 @@ var runCmd = &cli.Command{ w = ledgerwallet.NewWallet(ds) } - address := cctx.String("listen") mux := mux.NewRouter() From 2c9215723344c106f9508df7e7c13fde6def76d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sat, 10 Oct 2020 13:41:19 +0200 Subject: [PATCH 058/313] shed ledger: Some UX improvements Signed-off-by: Jakub Sztandera --- cmd/lotus-shed/ledger.go | 55 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/cmd/lotus-shed/ledger.go b/cmd/lotus-shed/ledger.go index 4bb61e5e0..fd7ac1b51 100644 --- a/cmd/lotus-shed/ledger.go +++ b/cmd/lotus-shed/ledger.go @@ -7,11 +7,15 @@ import ( "strings" "github.com/filecoin-project/go-address" + "github.com/urfave/cli/v2" + ledgerfil "github.com/whyrusleeping/ledger-filecoin-go" + "golang.org/x/xerrors" + + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/wallet" ledgerwallet "github.com/filecoin-project/lotus/chain/wallet/ledger" - "github.com/urfave/cli/v2" - ledgerfil "github.com/whyrusleeping/ledger-filecoin-go" + lcli "github.com/filecoin-project/lotus/cli" ) var ledgerCmd = &cli.Command{ @@ -27,7 +31,26 @@ var ledgerCmd = &cli.Command{ var ledgerListAddressesCmd = &cli.Command{ Name: "list", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "print-balances", + Usage: "print balances", + Aliases: []string{"b"}, + }, + }, Action: func(cctx *cli.Context) error { + var api api.FullNode + if cctx.Bool("print-balances") { + a, closer, err := lcli.GetFullNodeAPI(cctx) + if err != nil { + return err + } + + api = a + + defer closer() + } + ctx := lcli.ReqContext(cctx) fl, err := ledgerfil.FindLedgerFilecoinApp() if err != nil { @@ -35,6 +58,10 @@ var ledgerListAddressesCmd = &cli.Command{ } for i := 0; i < 20; i++ { + if err := ctx.Err(); err != nil { + return err + } + p := []uint32{0x80000000 + 44, 0x80000000 + 461, 0x80000000, 0, uint32(i)} pubk, err := fl.GetPublicKeySECP256K1(p) if err != nil { @@ -46,7 +73,17 @@ var ledgerListAddressesCmd = &cli.Command{ return err } - fmt.Printf("%s: %s\n", addr, printHDPath(p)) + if cctx.Bool("print-balances") && api != nil { // api check makes linter happier + b, err := api.WalletBalance(ctx, addr) + if err != nil { + return xerrors.Errorf("getting balance: %w", err) + } + + fmt.Printf("%s %s %s\n", addr, printHDPath(p), types.FIL(b)) + } else { + fmt.Printf("%s %s\n", addr, printHDPath(p)) + } + } return nil @@ -110,6 +147,12 @@ func numlist(p []uint32) string { var ledgerKeyInfoCmd = &cli.Command{ Name: "key-info", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "verbose", + Aliases: []string{"v"}, + }, + }, Action: func(cctx *cli.Context) error { if !cctx.Args().Present() { return cli.ShowCommandHelp(cctx, cctx.Command.Name) @@ -129,8 +172,10 @@ var ledgerKeyInfoCmd = &cli.Command{ if err != nil { return err } - fmt.Println(addr) - fmt.Println(pubk) + if cctx.Bool("verbose") { + fmt.Println(addr) + fmt.Println(pubk) + } a, err := address.NewFromString(addr) if err != nil { From 8ae66d6c6a2aa27105566bbdf41dd569b2e4a109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sat, 10 Oct 2020 14:06:03 +0200 Subject: [PATCH 059/313] Fix lint warnings Signed-off-by: Jakub Sztandera --- chain/wallet/ledger/ledger.go | 12 +++++++----- cmd/lotus-shed/ledger.go | 14 +++----------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/chain/wallet/ledger/ledger.go b/chain/wallet/ledger/ledger.go index 71ec067c8..94a828603 100644 --- a/chain/wallet/ledger/ledger.go +++ b/chain/wallet/ledger/ledger.go @@ -5,16 +5,18 @@ import ( "context" "encoding/json" "fmt" + "github.com/ipfs/go-cid" + "github.com/ipfs/go-datastore" + "github.com/ipfs/go-datastore/query" + ledgerfil "github.com/whyrusleeping/ledger-filecoin-go" "golang.org/x/xerrors" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/crypto" + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/types" - "github.com/ipfs/go-datastore" - "github.com/ipfs/go-datastore/query" - ledgerfil "github.com/whyrusleeping/ledger-filecoin-go" ) type LedgerWallet struct { @@ -42,7 +44,7 @@ func (lw LedgerWallet) WalletSign(ctx context.Context, signer address.Address, t if err != nil { return nil, err } - defer fl.Close() + defer fl.Close() // nolint:errcheck if meta.Type != api.MTChainMsg { return nil, fmt.Errorf("ledger can only sign chain messages") } @@ -82,7 +84,7 @@ func (lw LedgerWallet) getKeyInfo(addr address.Address) (*LedgerKeyInfo, error) var out LedgerKeyInfo if err := json.Unmarshal(kib, &out); err != nil { - return nil, err + return nil, xerrors.Errorf("unmarshalling ledger key info: %w", err) } return &out, nil diff --git a/cmd/lotus-shed/ledger.go b/cmd/lotus-shed/ledger.go index fd7ac1b51..8111cc6bf 100644 --- a/cmd/lotus-shed/ledger.go +++ b/cmd/lotus-shed/ledger.go @@ -33,8 +33,8 @@ var ledgerListAddressesCmd = &cli.Command{ Name: "list", Flags: []cli.Flag{ &cli.BoolFlag{ - Name: "print-balances", - Usage: "print balances", + Name: "print-balances", + Usage: "print balances", Aliases: []string{"b"}, }, }, @@ -137,19 +137,11 @@ func printHDPath(pth []uint32) string { return strings.TrimRight(s, "/") } -func numlist(p []uint32) string { - var out []string - for _, v := range p { - out = append(out, fmt.Sprint(v)) - } - return strings.Join(out, ",") -} - var ledgerKeyInfoCmd = &cli.Command{ Name: "key-info", Flags: []cli.Flag{ &cli.BoolFlag{ - Name: "verbose", + Name: "verbose", Aliases: []string{"v"}, }, }, From bb6a354b6269949529bc9791b62ec34c7562d74d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sat, 10 Oct 2020 14:17:44 +0200 Subject: [PATCH 060/313] chain cli: decode params command Signed-off-by: Jakub Sztandera --- cli/chain.go | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/cli/chain.go b/cli/chain.go index 763752f23..4dfcf3f36 100644 --- a/cli/chain.go +++ b/cli/chain.go @@ -3,6 +3,7 @@ package cli import ( "bytes" "context" + "encoding/hex" "encoding/json" "fmt" "os" @@ -53,6 +54,7 @@ var chainCmd = &cli.Command{ slashConsensusFault, chainGasPriceCmd, chainInspectUsage, + chainDecodeCmd, }, } @@ -1233,3 +1235,68 @@ var chainGasPriceCmd = &cli.Command{ return nil }, } + +var chainDecodeCmd = &cli.Command{ + Name: "decode", + Usage: "decode various types", + Subcommands: []*cli.Command{ + chainDecodeParamsCmd, + }, +} + +var chainDecodeParamsCmd = &cli.Command{ + Name: "params", + Usage: "Decode message params", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "tipset", + }, + }, + ArgsUsage: "[toAddr method hexParams]", + Action: func(cctx *cli.Context) error { + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + if cctx.Args().Len() != 3 { + return ShowHelp(cctx, fmt.Errorf("incorrect number of arguments")) + } + + to, err := address.NewFromString(cctx.Args().First()) + if err != nil { + return xerrors.Errorf("parsing toAddr: %w", err) + } + + method, err := strconv.ParseInt(cctx.Args().Get(1), 10, 64) + if err != nil { + return xerrors.Errorf("parsing method id: %w", err) + } + + params, err := hex.DecodeString(cctx.Args().Get(2)) + if err != nil { + return xerrors.Errorf("parsing hex params: %w", err) + } + + ts, err := LoadTipSet(ctx, cctx, api) + if err != nil { + return err + } + + act, err := api.StateGetActor(ctx, to, ts.Key()) + if err != nil { + return xerrors.Errorf("getting actor: %w", err) + } + + pstr, err := jsonParams(act.Code, abi.MethodNum(method), params) + if err != nil { + return err + } + + fmt.Println(pstr) + + return nil + }, +} From 753d7b71a9e3ac330ec29fd9c41a9eba824bd8ec Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Sat, 10 Oct 2020 22:59:40 +0200 Subject: [PATCH 061/313] Fix hardened path printing, show 20 addresses after empty Signed-off-by: Jakub Sztandera --- cmd/lotus-shed/ledger.go | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/cmd/lotus-shed/ledger.go b/cmd/lotus-shed/ledger.go index 8111cc6bf..84d582dea 100644 --- a/cmd/lotus-shed/ledger.go +++ b/cmd/lotus-shed/ledger.go @@ -29,6 +29,8 @@ var ledgerCmd = &cli.Command{ }, } +const hdHard = 0x80000000 + var ledgerListAddressesCmd = &cli.Command{ Name: "list", Flags: []cli.Flag{ @@ -57,12 +59,13 @@ var ledgerListAddressesCmd = &cli.Command{ return err } - for i := 0; i < 20; i++ { + end := 20 + for i := 0; i < end; i++ { if err := ctx.Err(); err != nil { return err } - p := []uint32{0x80000000 + 44, 0x80000000 + 461, 0x80000000, 0, uint32(i)} + p := []uint32{hdHard | 44, hdHard | 461, hdHard | 0, 0, uint32(i)} pubk, err := fl.GetPublicKeySECP256K1(p) if err != nil { return err @@ -78,6 +81,9 @@ var ledgerListAddressesCmd = &cli.Command{ if err != nil { return xerrors.Errorf("getting balance: %w", err) } + if !b.IsZero() { + end = i + 21 // BIP32 spec, stop after 20 empty addresses + } fmt.Printf("%s %s %s\n", addr, printHDPath(p), types.FIL(b)) } else { @@ -108,12 +114,12 @@ func parseHDPath(s string) ([]uint32, error) { if err != nil { return nil, err } - if v >= 0x80000000 { + if v >= hdHard { return nil, fmt.Errorf("path element %s too large", p) } if hard { - v += 0x80000000 + v += hdHard } out = append(out, uint32(v)) } @@ -121,20 +127,20 @@ func parseHDPath(s string) ([]uint32, error) { } func printHDPath(pth []uint32) string { - s := "m/" + s := "m" for _, p := range pth { - var hard bool - if p >= 0x80000000 { - p -= 0x80000000 - } + s += "/" + + hard := p&hdHard != 0 + p &^= hdHard // remove hdHard bit + s += fmt.Sprint(p) if hard { s += "'" } - s += "/" } - return strings.TrimRight(s, "/") + return s } var ledgerKeyInfoCmd = &cli.Command{ @@ -164,6 +170,7 @@ var ledgerKeyInfoCmd = &cli.Command{ if err != nil { return err } + if cctx.Bool("verbose") { fmt.Println(addr) fmt.Println(pubk) From 7ee6bafd2312f8894eee66bd2c57fe3015118ede Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Sat, 10 Oct 2020 23:13:22 +0200 Subject: [PATCH 062/313] Fix lint warn Signed-off-by: Jakub Sztandera --- cmd/lotus-shed/ledger.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/lotus-shed/ledger.go b/cmd/lotus-shed/ledger.go index 84d582dea..f8267ce12 100644 --- a/cmd/lotus-shed/ledger.go +++ b/cmd/lotus-shed/ledger.go @@ -65,7 +65,7 @@ var ledgerListAddressesCmd = &cli.Command{ return err } - p := []uint32{hdHard | 44, hdHard | 461, hdHard | 0, 0, uint32(i)} + p := []uint32{hdHard | 44, hdHard | 461, hdHard, 0, uint32(i)} pubk, err := fl.GetPublicKeySECP256K1(p) if err != nil { return err From 6a232e7214ae6e21c2b6c7f5ac5735b694cc47a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sun, 11 Oct 2020 00:08:12 +0200 Subject: [PATCH 063/313] Basic multi-wallet support Signed-off-by: Jakub Sztandera --- chain/wallet/ledger/ledger.go | 17 ++- chain/wallet/multi.go | 160 ++++++++++++++++++++++++++++ chain/wallet/remotewallet/remote.go | 8 ++ chain/wallet/wallet.go | 21 ++++ node/builder.go | 13 ++- node/config/def.go | 2 + 6 files changed, 215 insertions(+), 6 deletions(-) create mode 100644 chain/wallet/multi.go diff --git a/chain/wallet/ledger/ledger.go b/chain/wallet/ledger/ledger.go index 94a828603..231b3faae 100644 --- a/chain/wallet/ledger/ledger.go +++ b/chain/wallet/ledger/ledger.go @@ -17,13 +17,14 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/node/modules/dtypes" ) type LedgerWallet struct { ds datastore.Datastore } -func NewWallet(ds datastore.Datastore) *LedgerWallet { +func NewWallet(ds dtypes.MetadataDS) *LedgerWallet { return &LedgerWallet{ds} } @@ -127,7 +128,7 @@ func (lw LedgerWallet) WalletImport(ctx context.Context, kinfo *types.KeyInfo) ( } func (lw LedgerWallet) WalletList(ctx context.Context) ([]address.Address, error) { - res, err := lw.ds.Query(query.Query{Prefix: "ledgerkey/"}) + res, err := lw.ds.Query(query.Query{Prefix: "/ledgerkey/"}) if err != nil { return nil, err } @@ -153,6 +154,14 @@ func (lw LedgerWallet) WalletNew(ctx context.Context, t crypto.SigType) (address return address.Undef, fmt.Errorf("cannot create new address on ledger") } -func keyForAddr(addr address.Address) datastore.Key { - return datastore.NewKey("ledgerkey/" + addr.String()) +func (lw *LedgerWallet) Get() api.WalletAPI { + if lw == nil { + return nil + } + + return lw +} + +func keyForAddr(addr address.Address) datastore.Key { + return datastore.NewKey("/ledgerkey/" + addr.String()) } diff --git a/chain/wallet/multi.go b/chain/wallet/multi.go new file mode 100644 index 000000000..bff8d7003 --- /dev/null +++ b/chain/wallet/multi.go @@ -0,0 +1,160 @@ +package wallet + +import ( + "context" + + "go.uber.org/fx" + "golang.org/x/xerrors" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/crypto" + + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/types" + ledgerwallet "github.com/filecoin-project/lotus/chain/wallet/ledger" + "github.com/filecoin-project/lotus/chain/wallet/remotewallet" +) + +type MultiWallet struct { + fx.In // "constructed" with fx.In instead of normal constructor + + Local *LocalWallet `optional:"true"` + Remote *remotewallet.RemoteWallet `optional:"true"` + Ledger *ledgerwallet.LedgerWallet `optional:"true"` +} + +type getif interface { + api.WalletAPI + + // workaround for the fact that iface(*struct(nil)) != nil + Get() api.WalletAPI +} + +func firstNonNil(wallets ...getif) api.WalletAPI { + for _, w := range wallets { + if w.Get() != nil { + return w + } + } + + return nil +} + +func nonNil(wallets ...getif) []api.WalletAPI { + var out []api.WalletAPI + for _, w := range wallets { + if w.Get() == nil { + continue + } + + out = append(out, w) + } + + return out +} + +func (m MultiWallet) find(ctx context.Context, address address.Address, wallets ...getif) (api.WalletAPI, error) { + ws := nonNil(wallets...) + + for _, w := range ws { + have, err := w.WalletHas(ctx, address) + if err != nil { + return nil, err + } + + if have { + return w, nil + } + } + + return nil, nil +} + +func (m MultiWallet) WalletNew(ctx context.Context, sigType crypto.SigType) (address.Address, error) { + w := firstNonNil(m.Remote, m.Local) + if w == nil { + return address.Undef, xerrors.Errorf("no wallet backends configured") + } + + return w.WalletNew(ctx, sigType) +} + +func (m MultiWallet) WalletHas(ctx context.Context, address address.Address) (bool, error) { + w, err := m.find(ctx, address, m.Remote, m.Ledger, m.Local) + return w != nil, err +} + +func (m MultiWallet) WalletList(ctx context.Context) ([]address.Address, error) { + var out []address.Address + seen := map[address.Address]struct{}{} + + ws := nonNil(m.Remote, m.Ledger, m.Local) + for _, w := range ws { + l, err := w.WalletList(ctx) + if err != nil { + return nil, err + } + + for _, a := range l { + if _, ok := seen[a]; ok { + continue + } + seen[a] = struct{}{} + + out = append(out, a) + } + } + + return out, nil +} + +func (m MultiWallet) WalletSign(ctx context.Context, signer address.Address, toSign []byte, meta api.MsgMeta) (*crypto.Signature, error) { + w, err := m.find(ctx, signer, m.Remote, m.Ledger, m.Local) + if err != nil { + return nil, err + } + if w == nil { + return nil, xerrors.Errorf("key not found") + } + + return w.WalletSign(ctx, signer, toSign, meta) +} + +func (m MultiWallet) WalletExport(ctx context.Context, address address.Address) (*types.KeyInfo, error) { + w, err := m.find(ctx, address, m.Remote, m.Local) + if err != nil { + return nil, err + } + if w == nil { + return nil, xerrors.Errorf("key not found") + } + + return w.WalletExport(ctx, address) +} + +func (m MultiWallet) WalletImport(ctx context.Context, info *types.KeyInfo) (address.Address, error) { + w := firstNonNil(m.Remote, m.Ledger, m.Local) + if w == nil { + return address.Undef, xerrors.Errorf("no wallet backends configured") + } + + return w.WalletImport(ctx, info) +} + +func (m MultiWallet) WalletDelete(ctx context.Context, address address.Address) error { + for { + w, err := m.find(ctx, address, m.Remote, m.Ledger, m.Local) + if err != nil { + return err + } + if w == nil { + return nil + } + + if err := w.WalletDelete(ctx, address); err != nil { + return err + } + } +} + +var _ api.WalletAPI = MultiWallet{} diff --git a/chain/wallet/remotewallet/remote.go b/chain/wallet/remotewallet/remote.go index c7192f496..aa4427132 100644 --- a/chain/wallet/remotewallet/remote.go +++ b/chain/wallet/remotewallet/remote.go @@ -40,3 +40,11 @@ func SetupRemoteWallet(info string) func(mctx helpers.MetricsCtx, lc fx.Lifecycl return &RemoteWallet{wapi}, nil } } + +func (w *RemoteWallet) Get() api.WalletAPI { + if w == nil { + return nil + } + + return w +} diff --git a/chain/wallet/wallet.go b/chain/wallet/wallet.go index 57e63625b..66529d889 100644 --- a/chain/wallet/wallet.go +++ b/chain/wallet/wallet.go @@ -300,6 +300,14 @@ func (w *LocalWallet) WalletDelete(ctx context.Context, addr address.Address) er return nil } +func (w *LocalWallet) Get() api.WalletAPI { + if w == nil { + return nil + } + + return w +} + var _ api.WalletAPI = &LocalWallet{} func swapMainnetForTestnetPrefix(addr string) (string, error) { @@ -312,3 +320,16 @@ func swapMainnetForTestnetPrefix(addr string) (string, error) { aChars[0] = prefixRunes[0] return string(aChars), nil } + +type nilDefault struct{} + +func (n nilDefault) GetDefault() (address.Address, error) { + return address.Undef, nil +} + +func (n nilDefault) SetDefault(a address.Address) error { + return xerrors.Errorf("not supported; local wallet disabled") +} + +var NilDefault nilDefault +var _ Default = NilDefault diff --git a/node/builder.go b/node/builder.go index b91172386..f96505eec 100644 --- a/node/builder.go +++ b/node/builder.go @@ -44,6 +44,7 @@ import ( "github.com/filecoin-project/lotus/chain/metrics" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/types" + ledgerwallet "github.com/filecoin-project/lotus/chain/wallet/ledger" "github.com/filecoin-project/lotus/chain/wallet/remotewallet" sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" @@ -251,8 +252,8 @@ func Online() Option { Override(new(*stmgr.StateManager), stmgr.NewStateManagerWithUpgradeSchedule), Override(new(stmgr.StateManagerAPI), From(new(*stmgr.StateManager))), Override(new(*wallet.LocalWallet), wallet.NewWallet), - Override(new(api.WalletAPI), From(new(*wallet.LocalWallet))), Override(new(wallet.Default), From(new(*wallet.LocalWallet))), + Override(new(api.WalletAPI), From(new(wallet.MultiWallet))), Override(new(*messagesigner.MessageSigner), messagesigner.NewMessageSigner), Override(new(dtypes.ChainGCLocker), blockstore.NewGCLocker), @@ -459,8 +460,16 @@ func ConfigFullNode(c interface{}) Option { If(cfg.Metrics.HeadNotifs, Override(HeadMetricsKey, metrics.SendHeadNotifs(cfg.Metrics.Nickname)), ), + If(cfg.Wallet.RemoteBackend != "", - Override(new(api.WalletAPI), remotewallet.SetupRemoteWallet(cfg.Wallet.RemoteBackend)), + Override(new(*remotewallet.RemoteWallet), remotewallet.SetupRemoteWallet(cfg.Wallet.RemoteBackend)), + ), + If(cfg.Wallet.EnableLedger, + Override(new(*ledgerwallet.LedgerWallet), ledgerwallet.NewWallet), + ), + If(cfg.Wallet.DisableLocal, + Unset(new(*wallet.LocalWallet)), + Override(new(wallet.Default), wallet.NilDefault), ), ) } diff --git a/node/config/def.go b/node/config/def.go index 63340cfd5..7eb7e19f0 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -110,6 +110,8 @@ type Client struct { type Wallet struct { RemoteBackend string + EnableLedger bool + DisableLocal bool } func defCommon() Common { From 2b21fdef3348dcc5799a9ecc21c04cfdd40e9cc1 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Sun, 11 Oct 2020 20:12:01 +0200 Subject: [PATCH 064/313] Refactor from crypto.SigType to types.KeyType Signed-off-by: Jakub Sztandera --- api/api_full.go | 4 +- api/api_wallet.go | 2 +- api/apistruct/struct.go | 8 ++-- api/docgen/docgen.go | 1 + api/test/paych.go | 3 +- chain/gen/gen.go | 4 +- chain/messagepool/messagepool_test.go | 25 ++++++------ chain/messagepool/repub_test.go | 6 +-- chain/messagepool/selection_test.go | 43 +++++++++++---------- chain/messagesigner/messagesigner_test.go | 9 ++--- chain/types/keystore.go | 46 ++++++++++++++++++++++- chain/vectors/gen/main.go | 5 +-- chain/wallet/key.go | 30 ++++++++------- chain/wallet/ledger/ledger.go | 2 +- chain/wallet/multi.go | 11 ++++-- chain/wallet/wallet.go | 4 +- cli/paych_test.go | 3 +- cli/wallet.go | 7 ++-- cmd/chain-noise/main.go | 4 +- cmd/lotus-gateway/endtoend_test.go | 5 +-- cmd/lotus-keygen/main.go | 8 ++-- cmd/lotus-seed/seed/seed.go | 3 +- cmd/lotus-shed/keyinfo.go | 20 +++++----- cmd/lotus-shed/ledger.go | 3 +- cmd/lotus-storage-miner/init.go | 3 +- cmd/lotus-wallet/logged.go | 9 +---- cmd/lotus-wallet/main.go | 19 ++++++---- documentation/en/api-methods.md | 8 ++-- node/modules/lp2p/libp2p.go | 4 +- scripts/dev/api.bash | 4 +- storage/mockstorage/preseal.go | 3 +- 31 files changed, 173 insertions(+), 133 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index a2fe94ee9..f42c8d03f 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -229,7 +229,9 @@ type FullNode interface { // MethodGroup: Wallet // WalletNew creates a new address in the wallet with the given sigType. - WalletNew(context.Context, crypto.SigType) (address.Address, error) + // Available key types: bls, secp256k1, secp256k1-ledger + // Support for numerical types: 1 - secp256k1, 2 - BLS is deprecated + WalletNew(context.Context, types.KeyType) (address.Address, error) // WalletHas indicates whether the given address is in the wallet. WalletHas(context.Context, address.Address) (bool, error) // WalletList lists all the addresses in the wallet. diff --git a/api/api_wallet.go b/api/api_wallet.go index 1213ffc1d..88ad8f43a 100644 --- a/api/api_wallet.go +++ b/api/api_wallet.go @@ -35,7 +35,7 @@ type MsgMeta struct { } type WalletAPI interface { - WalletNew(context.Context, crypto.SigType) (address.Address, error) + WalletNew(context.Context, types.KeyType) (address.Address, error) WalletHas(context.Context, address.Address) (bool, error) WalletList(context.Context) ([]address.Address, error) diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 22d50e726..cef335939 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -133,7 +133,7 @@ type FullNodeStruct struct { MinerGetBaseInfo func(context.Context, address.Address, abi.ChainEpoch, types.TipSetKey) (*api.MiningBaseInfo, error) `perm:"read"` MinerCreateBlock func(context.Context, *api.BlockTemplate) (*types.BlockMsg, error) `perm:"write"` - WalletNew func(context.Context, crypto.SigType) (address.Address, error) `perm:"write"` + WalletNew func(context.Context, types.KeyType) (address.Address, error) `perm:"write"` WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"` WalletList func(context.Context) ([]address.Address, error) `perm:"write"` WalletBalance func(context.Context, address.Address) (types.BigInt, error) `perm:"read"` @@ -384,7 +384,7 @@ type GatewayStruct struct { type WalletStruct struct { Internal struct { - WalletNew func(context.Context, crypto.SigType) (address.Address, error) `perm:"write"` + WalletNew func(context.Context, types.KeyType) (address.Address, error) `perm:"write"` WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"` WalletList func(context.Context) ([]address.Address, error) `perm:"write"` WalletSign func(context.Context, address.Address, []byte, api.MsgMeta) (*crypto.Signature, error) `perm:"sign"` @@ -631,7 +631,7 @@ func (c *FullNodeStruct) ChainGetTipSetByHeight(ctx context.Context, h abi.Chain return c.Internal.ChainGetTipSetByHeight(ctx, h, tsk) } -func (c *FullNodeStruct) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) { +func (c *FullNodeStruct) WalletNew(ctx context.Context, typ types.KeyType) (address.Address, error) { return c.Internal.WalletNew(ctx, typ) } @@ -1465,7 +1465,7 @@ func (g GatewayStruct) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence return g.Internal.StateWaitMsg(ctx, msg, confidence) } -func (c *WalletStruct) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) { +func (c *WalletStruct) WalletNew(ctx context.Context, typ types.KeyType) (address.Address, error) { return c.Internal.WalletNew(ctx, typ) } diff --git a/api/docgen/docgen.go b/api/docgen/docgen.go index ced536cc3..dc6004121 100644 --- a/api/docgen/docgen.go +++ b/api/docgen/docgen.go @@ -87,6 +87,7 @@ func init() { addExample(abi.RegisteredPoStProof_StackedDrgWindow32GiBV1) addExample(abi.ChainEpoch(10101)) addExample(crypto.SigTypeBLS) + addExample(types.KTBLS) addExample(int64(9)) addExample(12.3) addExample(123) diff --git a/api/test/paych.go b/api/test/paych.go index a8ccebdde..43401554d 100644 --- a/api/test/paych.go +++ b/api/test/paych.go @@ -26,7 +26,6 @@ import ( "github.com/filecoin-project/lotus/chain/events" "github.com/filecoin-project/lotus/chain/events/state" "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/lotus/chain/wallet" ) func TestPaymentChannels(t *testing.T, b APIBuilder, blocktime time.Duration) { @@ -58,7 +57,7 @@ func TestPaymentChannels(t *testing.T, b APIBuilder, blocktime time.Duration) { bm.MineBlocks() // send some funds to register the receiver - receiverAddr, err := paymentReceiver.WalletNew(ctx, wallet.ActSigType("secp256k1")) + receiverAddr, err := paymentReceiver.WalletNew(ctx, types.KTSecp256k1) if err != nil { t.Fatal(err) } diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 9133f14b4..288c84219 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -155,14 +155,14 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) { return nil, xerrors.Errorf("creating memrepo wallet failed: %w", err) } - banker, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + banker, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { return nil, xerrors.Errorf("failed to generate banker key: %w", err) } receievers := make([]address.Address, msgsPerBlock) for r := range receievers { - receievers[r], err = w.WalletNew(context.Background(), crypto.SigTypeBLS) + receievers[r], err = w.WalletNew(context.Background(), types.KTBLS) if err != nil { return nil, xerrors.Errorf("failed to generate receiver key: %w", err) } diff --git a/chain/messagepool/messagepool_test.go b/chain/messagepool/messagepool_test.go index 063e0bbab..8f6613cad 100644 --- a/chain/messagepool/messagepool_test.go +++ b/chain/messagepool/messagepool_test.go @@ -8,7 +8,6 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/lotus/chain/messagepool/gasguess" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types/mock" @@ -232,7 +231,7 @@ func TestMessagePool(t *testing.T) { a := tma.nextBlock() - sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS) + sender, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -273,7 +272,7 @@ func TestMessagePoolMessagesInEachBlock(t *testing.T) { a := tma.nextBlock() - sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS) + sender, err := w.WalletNew(context.Background(), types.KTBLS) if err != nil { t.Fatal(err) } @@ -323,7 +322,7 @@ func TestRevertMessages(t *testing.T) { a := tma.nextBlock() b := tma.nextBlock() - sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS) + sender, err := w.WalletNew(context.Background(), types.KTBLS) if err != nil { t.Fatal(err) } @@ -386,7 +385,7 @@ func TestPruningSimple(t *testing.T) { a := tma.nextBlock() tma.applyBlock(t, a) - sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS) + sender, err := w.WalletNew(context.Background(), types.KTBLS) if err != nil { t.Fatal(err) } @@ -433,7 +432,7 @@ func TestLoadLocal(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -443,7 +442,7 @@ func TestLoadLocal(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -505,7 +504,7 @@ func TestClearAll(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -515,7 +514,7 @@ func TestClearAll(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -559,7 +558,7 @@ func TestClearNonLocal(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -569,7 +568,7 @@ func TestClearNonLocal(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -620,7 +619,7 @@ func TestUpdates(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -630,7 +629,7 @@ func TestUpdates(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } diff --git a/chain/messagepool/repub_test.go b/chain/messagepool/repub_test.go index 3e1252eec..9cadf24c7 100644 --- a/chain/messagepool/repub_test.go +++ b/chain/messagepool/repub_test.go @@ -5,8 +5,8 @@ import ( "testing" "time" - "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/lotus/chain/messagepool/gasguess" + "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/specs-actors/actors/builtin" "github.com/ipfs/go-datastore" @@ -33,7 +33,7 @@ func TestRepubMessages(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -43,7 +43,7 @@ func TestRepubMessages(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } diff --git a/chain/messagepool/selection_test.go b/chain/messagepool/selection_test.go index 9e4fe39e5..37c2f2dc0 100644 --- a/chain/messagepool/selection_test.go +++ b/chain/messagepool/selection_test.go @@ -18,7 +18,6 @@ import ( logging "github.com/ipfs/go-log" "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/messagepool/gasguess" "github.com/filecoin-project/lotus/chain/types" @@ -77,7 +76,7 @@ func TestMessageChains(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -87,7 +86,7 @@ func TestMessageChains(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -315,7 +314,7 @@ func TestMessageChainSkipping(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -325,7 +324,7 @@ func TestMessageChainSkipping(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -391,7 +390,7 @@ func TestBasicMessageSelection(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -401,7 +400,7 @@ func TestBasicMessageSelection(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -535,7 +534,7 @@ func TestMessageSelectionTrimming(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -545,7 +544,7 @@ func TestMessageSelectionTrimming(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -598,7 +597,7 @@ func TestPriorityMessageSelection(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -608,7 +607,7 @@ func TestPriorityMessageSelection(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -677,7 +676,7 @@ func TestPriorityMessageSelection2(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -687,7 +686,7 @@ func TestPriorityMessageSelection2(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -746,7 +745,7 @@ func TestPriorityMessageSelection3(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -756,7 +755,7 @@ func TestPriorityMessageSelection3(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -843,7 +842,7 @@ func TestOptimalMessageSelection1(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -853,7 +852,7 @@ func TestOptimalMessageSelection1(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -910,7 +909,7 @@ func TestOptimalMessageSelection2(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -920,7 +919,7 @@ func TestOptimalMessageSelection2(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -994,7 +993,7 @@ func TestOptimalMessageSelection3(t *testing.T) { t.Fatal(err) } - a, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -1074,7 +1073,7 @@ func testCompetitiveMessageSelection(t *testing.T, rng *rand.Rand, getPremium fu t.Fatal(err) } - a, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -1344,7 +1343,7 @@ readLoop: t.Fatal(err) } - a, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } diff --git a/chain/messagesigner/messagesigner_test.go b/chain/messagesigner/messagesigner_test.go index 0dafce9a1..5eebd36da 100644 --- a/chain/messagesigner/messagesigner_test.go +++ b/chain/messagesigner/messagesigner_test.go @@ -9,7 +9,6 @@ import ( "github.com/filecoin-project/lotus/chain/wallet" - "github.com/filecoin-project/go-state-types/crypto" "github.com/stretchr/testify/require" ds_sync "github.com/ipfs/go-datastore/sync" @@ -47,13 +46,13 @@ func TestMessageSignerSignMessage(t *testing.T) { ctx := context.Background() w, _ := wallet.NewWallet(wallet.NewMemKeyStore()) - from1, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1) + from1, err := w.WalletNew(ctx, types.KTSecp256k1) require.NoError(t, err) - from2, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1) + from2, err := w.WalletNew(ctx, types.KTSecp256k1) require.NoError(t, err) - to1, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1) + to1, err := w.WalletNew(ctx, types.KTSecp256k1) require.NoError(t, err) - to2, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1) + to2, err := w.WalletNew(ctx, types.KTSecp256k1) require.NoError(t, err) type msgSpec struct { diff --git a/chain/types/keystore.go b/chain/types/keystore.go index 76eb5f296..107c1fbe3 100644 --- a/chain/types/keystore.go +++ b/chain/types/keystore.go @@ -1,7 +1,10 @@ package types import ( + "encoding/json" "fmt" + + "github.com/filecoin-project/go-state-types/crypto" ) var ( @@ -9,9 +12,50 @@ var ( ErrKeyExists = fmt.Errorf("key already exists") ) +// KeyType defines a type of a key +type KeyType string + +func (kt *KeyType) UnmarshalJSON(bb []byte) error { + { + // first option, try unmarshaling as string + var s string + err := json.Unmarshal(bb, &s) + if err == nil { + *kt = KeyType(s) + return nil + } + } + + { + var b byte + err := json.Unmarshal(bb, &b) + if err != nil { + return fmt.Errorf("could not unmarshal KeyType either as string nor integer: %w", err) + } + bst := crypto.SigType(b) + + switch bst { + case crypto.SigTypeBLS: + *kt = KTBLS + case crypto.SigTypeSecp256k1: + *kt = KTSecp256k1 + default: + return fmt.Errorf("unknown sigtype: %d", bst) + } + log.Warnf("deprecation: integer style 'KeyType' is deprecated, switch to string style") + return nil + } +} + +const ( + KTBLS KeyType = "bls" + KTSecp256k1 KeyType = "secp256k1" + KTSecp256k1Ledger KeyType = "secp256k1-ledger" +) + // KeyInfo is used for storing keys in KeyStore type KeyInfo struct { - Type string + Type KeyType PrivateKey []byte } diff --git a/chain/vectors/gen/main.go b/chain/vectors/gen/main.go index 096548e04..757227d0d 100644 --- a/chain/vectors/gen/main.go +++ b/chain/vectors/gen/main.go @@ -11,7 +11,6 @@ import ( "golang.org/x/xerrors" "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/types" @@ -62,7 +61,7 @@ func MakeMessageSigningVectors() []vectors.MessageSigningVector { panic(err) } - blsk, err := w.WalletNew(context.Background(), crypto.SigTypeBLS) + blsk, err := w.WalletNew(context.Background(), types.KTBLS) if err != nil { panic(err) } @@ -86,7 +85,7 @@ func MakeMessageSigningVectors() []vectors.MessageSigningVector { Signature: &bmsg.Signature, } - secpk, err := w.WalletNew(context.Background(), crypto.SigTypeBLS) + secpk, err := w.WalletNew(context.Background(), types.KTBLS) if err != nil { panic(err) } diff --git a/chain/wallet/key.go b/chain/wallet/key.go index 4b746a17a..ac9fc436f 100644 --- a/chain/wallet/key.go +++ b/chain/wallet/key.go @@ -10,13 +10,17 @@ import ( "github.com/filecoin-project/lotus/lib/sigs" ) -func GenerateKey(typ crypto.SigType) (*Key, error) { - pk, err := sigs.Generate(typ) +func GenerateKey(typ types.KeyType) (*Key, error) { + ctyp := ActSigType(typ) + if ctyp == crypto.SigTypeUnknown { + return nil, xerrors.Errorf("unknown key type: %s", typ) + } + pk, err := sigs.Generate(ctyp) if err != nil { return nil, err } ki := types.KeyInfo{ - Type: kstoreSigType(typ), + Type: typ, PrivateKey: pk, } return NewKey(ki) @@ -41,41 +45,41 @@ func NewKey(keyinfo types.KeyInfo) (*Key, error) { } switch k.Type { - case KTSecp256k1: + case types.KTSecp256k1: k.Address, err = address.NewSecp256k1Address(k.PublicKey) if err != nil { return nil, xerrors.Errorf("converting Secp256k1 to address: %w", err) } - case KTBLS: + case types.KTBLS: k.Address, err = address.NewBLSAddress(k.PublicKey) if err != nil { return nil, xerrors.Errorf("converting BLS to address: %w", err) } default: - return nil, xerrors.Errorf("unknown key type") + return nil, xerrors.Errorf("unknown key type: %s", k.Type) } return k, nil } -func kstoreSigType(typ crypto.SigType) string { +func kstoreSigType(typ crypto.SigType) types.KeyType { switch typ { case crypto.SigTypeBLS: - return KTBLS + return types.KTBLS case crypto.SigTypeSecp256k1: - return KTSecp256k1 + return types.KTSecp256k1 default: return "" } } -func ActSigType(typ string) crypto.SigType { +func ActSigType(typ types.KeyType) crypto.SigType { switch typ { - case KTBLS: + case types.KTBLS: return crypto.SigTypeBLS - case KTSecp256k1: + case types.KTSecp256k1: return crypto.SigTypeSecp256k1 default: - return 0 + return crypto.SigTypeUnknown } } diff --git a/chain/wallet/ledger/ledger.go b/chain/wallet/ledger/ledger.go index 231b3faae..b6b5683cd 100644 --- a/chain/wallet/ledger/ledger.go +++ b/chain/wallet/ledger/ledger.go @@ -150,7 +150,7 @@ func (lw LedgerWallet) WalletList(ctx context.Context) ([]address.Address, error return out, nil } -func (lw LedgerWallet) WalletNew(ctx context.Context, t crypto.SigType) (address.Address, error) { +func (lw LedgerWallet) WalletNew(ctx context.Context, t types.KeyType) (address.Address, error) { return address.Undef, fmt.Errorf("cannot create new address on ledger") } diff --git a/chain/wallet/multi.go b/chain/wallet/multi.go index bff8d7003..6eac03367 100644 --- a/chain/wallet/multi.go +++ b/chain/wallet/multi.go @@ -18,7 +18,7 @@ import ( type MultiWallet struct { fx.In // "constructed" with fx.In instead of normal constructor - Local *LocalWallet `optional:"true"` + Local *LocalWallet `optional:"true"` Remote *remotewallet.RemoteWallet `optional:"true"` Ledger *ledgerwallet.LedgerWallet `optional:"true"` } @@ -70,7 +70,7 @@ func (m MultiWallet) find(ctx context.Context, address address.Address, wallets return nil, nil } -func (m MultiWallet) WalletNew(ctx context.Context, sigType crypto.SigType) (address.Address, error) { +func (m MultiWallet) WalletNew(ctx context.Context, sigType types.KeyType) (address.Address, error) { w := firstNonNil(m.Remote, m.Local) if w == nil { return address.Undef, xerrors.Errorf("no wallet backends configured") @@ -133,7 +133,12 @@ func (m MultiWallet) WalletExport(ctx context.Context, address address.Address) } func (m MultiWallet) WalletImport(ctx context.Context, info *types.KeyInfo) (address.Address, error) { - w := firstNonNil(m.Remote, m.Ledger, m.Local) + var local getif = m.Local + if info.Type == types.KTSecp256k1Ledger { + local = m.Ledger + } + + w := firstNonNil(m.Remote, local) if w == nil { return address.Undef, xerrors.Errorf("no wallet backends configured") } diff --git a/chain/wallet/wallet.go b/chain/wallet/wallet.go index 66529d889..925547ea8 100644 --- a/chain/wallet/wallet.go +++ b/chain/wallet/wallet.go @@ -26,8 +26,6 @@ const ( KNamePrefix = "wallet-" KTrashPrefix = "trash-" KDefault = "default" - KTBLS = "bls" - KTSecp256k1 = "secp256k1" ) type LocalWallet struct { @@ -236,7 +234,7 @@ func (w *LocalWallet) SetDefault(a address.Address) error { return nil } -func (w *LocalWallet) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) { +func (w *LocalWallet) WalletNew(ctx context.Context, typ types.KeyType) (address.Address, error) { w.lk.Lock() defer w.lk.Unlock() diff --git a/cli/paych_test.go b/cli/paych_test.go index 862ca2e74..b94ba27e7 100644 --- a/cli/paych_test.go +++ b/cli/paych_test.go @@ -29,7 +29,6 @@ import ( "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/events" "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/lotus/chain/wallet" builder "github.com/filecoin-project/lotus/node/test" ) @@ -415,7 +414,7 @@ func startTwoNodesOneMiner(ctx context.Context, t *testing.T, blocktime time.Dur bm.MineBlocks() // Send some funds to register the receiver - receiverAddr, err := paymentReceiver.WalletNew(ctx, wallet.ActSigType("secp256k1")) + receiverAddr, err := paymentReceiver.WalletNew(ctx, types.KTSecp256k1) if err != nil { t.Fatal(err) } diff --git a/cli/wallet.go b/cli/wallet.go index aa5b9bed3..3d6abc357 100644 --- a/cli/wallet.go +++ b/cli/wallet.go @@ -17,7 +17,6 @@ import ( "github.com/filecoin-project/go-state-types/crypto" types "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/lotus/lib/tablewriter" ) @@ -55,7 +54,7 @@ var walletNew = &cli.Command{ t = "secp256k1" } - nk, err := api.WalletNew(ctx, wallet.ActSigType(t)) + nk, err := api.WalletNew(ctx, types.KeyType(t)) if err != nil { return err } @@ -329,9 +328,9 @@ var walletImport = &cli.Command{ ki.PrivateKey = gk.PrivateKey switch gk.SigType { case 1: - ki.Type = wallet.KTSecp256k1 + ki.Type = types.KTSecp256k1 case 2: - ki.Type = wallet.KTBLS + ki.Type = types.KTBLS default: return fmt.Errorf("unrecognized key type: %d", gk.SigType) } diff --git a/cmd/chain-noise/main.go b/cmd/chain-noise/main.go index 7b9824016..81586e1b2 100644 --- a/cmd/chain-noise/main.go +++ b/cmd/chain-noise/main.go @@ -7,8 +7,6 @@ import ( "os" "time" - "github.com/filecoin-project/go-state-types/crypto" - "github.com/filecoin-project/go-address" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" @@ -61,7 +59,7 @@ var runCmd = &cli.Command{ func sendSmallFundsTxs(ctx context.Context, api api.FullNode, from address.Address, rate int) error { var sendSet []address.Address for i := 0; i < 20; i++ { - naddr, err := api.WalletNew(ctx, crypto.SigTypeSecp256k1) + naddr, err := api.WalletNew(ctx, types.KTSecp256k1) if err != nil { return err } diff --git a/cmd/lotus-gateway/endtoend_test.go b/cmd/lotus-gateway/endtoend_test.go index 206034968..eebf56a9f 100644 --- a/cmd/lotus-gateway/endtoend_test.go +++ b/cmd/lotus-gateway/endtoend_test.go @@ -22,7 +22,6 @@ import ( "github.com/filecoin-project/lotus/api/test" "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/lotus/node" builder "github.com/filecoin-project/lotus/node/test" ) @@ -53,7 +52,7 @@ func TestEndToEnd(t *testing.T) { fmt.Println(balance) // Create a wallet on the lite node - liteWalletAddr, err := lite.WalletNew(ctx, wallet.ActSigType("secp256k1")) + liteWalletAddr, err := lite.WalletNew(ctx, types.KTSecp256k1) require.NoError(t, err) // Send some funds from the full node to the lite node @@ -77,7 +76,7 @@ func TestEndToEnd(t *testing.T) { // Create some wallets on the lite node to use for testing multisig var walletAddrs []address.Address for i := 0; i < 4; i++ { - addr, err := lite.WalletNew(ctx, wallet.ActSigType("secp256k1")) + addr, err := lite.WalletNew(ctx, types.KTSecp256k1) require.NoError(t, err) walletAddrs = append(walletAddrs, addr) diff --git a/cmd/lotus-keygen/main.go b/cmd/lotus-keygen/main.go index 4b971cf48..d296cb5da 100644 --- a/cmd/lotus-keygen/main.go +++ b/cmd/lotus-keygen/main.go @@ -5,7 +5,7 @@ import ( "fmt" "os" - "github.com/filecoin-project/go-state-types/crypto" + "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/wallet" _ "github.com/filecoin-project/lotus/lib/sigs/bls" _ "github.com/filecoin-project/lotus/lib/sigs/secp" @@ -30,12 +30,12 @@ func main() { return err } - var kt crypto.SigType + var kt types.KeyType switch cctx.String("type") { case "bls": - kt = crypto.SigTypeBLS + kt = types.KTBLS case "secp256k1": - kt = crypto.SigTypeSecp256k1 + kt = types.KTSecp256k1 default: return fmt.Errorf("unrecognized key type: %q", cctx.String("type")) } diff --git a/cmd/lotus-seed/seed/seed.go b/cmd/lotus-seed/seed/seed.go index 5e911991d..cd0c4e7ab 100644 --- a/cmd/lotus-seed/seed/seed.go +++ b/cmd/lotus-seed/seed/seed.go @@ -21,7 +21,6 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" - "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/lotus/extern/sector-storage/zerocomm" "github.com/filecoin-project/specs-actors/actors/builtin/market" @@ -93,7 +92,7 @@ func PreSeal(maddr address.Address, spt abi.RegisteredSealProof, offset abi.Sect return nil, nil, err } } else { - minerAddr, err = wallet.GenerateKey(crypto.SigTypeBLS) + minerAddr, err = wallet.GenerateKey(types.KTBLS) if err != nil { return nil, nil, err } diff --git a/cmd/lotus-shed/keyinfo.go b/cmd/lotus-shed/keyinfo.go index fdd1fcb49..4dcd10cbf 100644 --- a/cmd/lotus-shed/keyinfo.go +++ b/cmd/lotus-shed/keyinfo.go @@ -32,10 +32,10 @@ import ( _ "github.com/filecoin-project/lotus/lib/sigs/secp" ) -var validTypes = []string{wallet.KTBLS, wallet.KTSecp256k1, lp2p.KTLibp2pHost} +var validTypes = []types.KeyType{types.KTBLS, types.KTSecp256k1, lp2p.KTLibp2pHost} type keyInfoOutput struct { - Type string + Type types.KeyType Address string PublicKey string } @@ -86,7 +86,7 @@ var keyinfoVerifyCmd = &cli.Command{ return xerrors.Errorf("decoding key: '%s': %w", fileName, err) } - if string(name) != keyInfo.Type { + if types.KeyType(name) != keyInfo.Type { return fmt.Errorf("%s of type %s is incorrect", fileName, keyInfo.Type) } case modules.KTJwtHmacSecret: @@ -98,7 +98,7 @@ var keyinfoVerifyCmd = &cli.Command{ if string(name) != modules.JWTSecretName { return fmt.Errorf("%s of type %s is incorrect", fileName, keyInfo.Type) } - case wallet.KTSecp256k1, wallet.KTBLS: + case types.KTSecp256k1, types.KTBLS: keystore := wallet.NewMemKeyStore() w, err := wallet.NewWallet(keystore) if err != nil { @@ -214,7 +214,7 @@ var keyinfoImportCmd = &cli.Command{ fmt.Printf("%s\n", peerid.String()) break - case wallet.KTSecp256k1, wallet.KTBLS: + case types.KTSecp256k1, types.KTBLS: w, err := wallet.NewWallet(keystore) if err != nil { return err @@ -317,7 +317,7 @@ var keyinfoInfoCmd = &cli.Command{ kio.PublicKey = base64.StdEncoding.EncodeToString(pkBytes) break - case wallet.KTSecp256k1, wallet.KTBLS: + case types.KTSecp256k1, types.KTBLS: kio.Type = keyInfo.Type key, err := wallet.NewKey(keyInfo) @@ -366,7 +366,7 @@ var keyinfoNewCmd = &cli.Command{ return fmt.Errorf("please specify a type to generate") } - keyType := cctx.Args().First() + keyType := types.KeyType(cctx.Args().First()) flagOutput := cctx.String("output") if i := SliceIndex(len(validTypes), func(i int) bool { @@ -404,8 +404,8 @@ var keyinfoNewCmd = &cli.Command{ keyInfo = ki break - case wallet.KTSecp256k1, wallet.KTBLS: - key, err := wallet.GenerateKey(wallet.ActSigType(keyType)) + case types.KTSecp256k1, types.KTBLS: + key, err := wallet.GenerateKey(keyType) if err != nil { return err } @@ -418,7 +418,7 @@ var keyinfoNewCmd = &cli.Command{ filename := flagOutput filename = strings.ReplaceAll(filename, "", keyAddr) - filename = strings.ReplaceAll(filename, "", keyType) + filename = strings.ReplaceAll(filename, "", string(keyType)) file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { diff --git a/cmd/lotus-shed/ledger.go b/cmd/lotus-shed/ledger.go index f8267ce12..f64916534 100644 --- a/cmd/lotus-shed/ledger.go +++ b/cmd/lotus-shed/ledger.go @@ -13,7 +13,6 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/lotus/chain/wallet" ledgerwallet "github.com/filecoin-project/lotus/chain/wallet/ledger" lcli "github.com/filecoin-project/lotus/cli" ) @@ -191,7 +190,7 @@ var ledgerKeyInfoCmd = &cli.Command{ } var ki types.KeyInfo - ki.Type = wallet.KTSecp256k1 + ki.Type = types.KTSecp256k1Ledger ki.PrivateKey = b out, err := json.Marshal(ki) diff --git a/cmd/lotus-storage-miner/init.go b/cmd/lotus-storage-miner/init.go index 0f830023f..ccea707af 100644 --- a/cmd/lotus-storage-miner/init.go +++ b/cmd/lotus-storage-miner/init.go @@ -27,7 +27,6 @@ import ( cborutil "github.com/filecoin-project/go-cbor-util" paramfetch "github.com/filecoin-project/go-paramfetch" "github.com/filecoin-project/go-state-types/abi" - crypto2 "github.com/filecoin-project/go-state-types/crypto" sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" "github.com/filecoin-project/lotus/extern/sector-storage/stores" @@ -624,7 +623,7 @@ func createStorageMiner(ctx context.Context, api lapi.FullNode, peerid peer.ID, if cctx.String("worker") != "" { worker, err = address.NewFromString(cctx.String("worker")) } else if cctx.Bool("create-worker-key") { // TODO: Do we need to force this if owner is Secpk? - worker, err = api.WalletNew(ctx, crypto2.SigTypeBLS) + worker, err = api.WalletNew(ctx, types.KTBLS) } // TODO: Transfer some initial funds to worker if err != nil { diff --git a/cmd/lotus-wallet/logged.go b/cmd/lotus-wallet/logged.go index 3bcb3f867..272a8d10b 100644 --- a/cmd/lotus-wallet/logged.go +++ b/cmd/lotus-wallet/logged.go @@ -19,13 +19,8 @@ type LoggedWallet struct { under api.WalletAPI } -func (c *LoggedWallet) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) { - n, err := typ.Name() - if err != nil { - return address.Address{}, err - } - - log.Infow("WalletNew", "type", n) +func (c *LoggedWallet) WalletNew(ctx context.Context, typ types.KeyType) (address.Address, error) { + log.Infow("WalletNew", "type", typ) return c.under.WalletNew(ctx, typ) } diff --git a/cmd/lotus-wallet/main.go b/cmd/lotus-wallet/main.go index ffaddc7e3..3285b13e7 100644 --- a/cmd/lotus-wallet/main.go +++ b/cmd/lotus-wallet/main.go @@ -101,19 +101,22 @@ var runCmd = &cli.Command{ return err } - var w api.WalletAPI - if !cctx.Bool("ledger") { - w, err = wallet.NewWallet(ks) - if err != nil { - return err - } - } else { + lw, err := wallet.NewWallet(ks) + if err != nil { + return err + } + + var w api.WalletAPI = lw + if cctx.Bool("ledger") { ds, err := lr.Datastore("/metadata") if err != nil { return err } - w = ledgerwallet.NewWallet(ds) + w = wallet.MultiWallet{ + Local: lw, + Ledger: ledgerwallet.NewWallet(ds), + } } address := cctx.String("listen") diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index ec8071b57..6d201b435 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -4710,7 +4710,7 @@ Inputs: Response: ```json { - "Type": "string value", + "Type": "bls", "PrivateKey": "Ynl0ZSBhcnJheQ==" } ``` @@ -4740,7 +4740,7 @@ Inputs: ```json [ { - "Type": "string value", + "Type": "bls", "PrivateKey": "Ynl0ZSBhcnJheQ==" } ] @@ -4760,6 +4760,8 @@ Response: `null` ### WalletNew WalletNew creates a new address in the wallet with the given sigType. +Available key types: bls, secp256k1, secp256k1-ledger +Support for numerical types: 1 - secp256k1, 2 - BLS is deprecated Perms: write @@ -4767,7 +4769,7 @@ Perms: write Inputs: ```json [ - 2 + "bls" ] ``` diff --git a/node/modules/lp2p/libp2p.go b/node/modules/lp2p/libp2p.go index 5a1666cb6..51749c4d6 100644 --- a/node/modules/lp2p/libp2p.go +++ b/node/modules/lp2p/libp2p.go @@ -20,8 +20,8 @@ import ( var log = logging.Logger("p2pnode") const ( - KLibp2pHost = "libp2p-host" - KTLibp2pHost = KLibp2pHost + KLibp2pHost = "libp2p-host" + KTLibp2pHost types.KeyType = KLibp2pHost ) type Libp2pOpts struct { diff --git a/scripts/dev/api.bash b/scripts/dev/api.bash index 5539e4fef..ac9eb4e66 100644 --- a/scripts/dev/api.bash +++ b/scripts/dev/api.bash @@ -1,11 +1,11 @@ #!/bin/bash # vim: set expandtab ts=2 sw=2: -token=$(lotus auth create-token --perm admin) +_lotus_token=$(./lotus auth create-token --perm admin) runAPI() { curl -X POST \ -H "Content-Type: application/json" \ --data '{"jsonrpc":"2.0","id":2,"method":"Filecoin.'"$1"'","params":'"${2:-null}"'}' \ - 'http://127.0.0.1:1234/rpc/v0?token='"$token" + 'http://127.0.0.1:1234/rpc/v0?token='"$_lotus_token" } diff --git a/storage/mockstorage/preseal.go b/storage/mockstorage/preseal.go index 8ca789ba6..090aacc3c 100644 --- a/storage/mockstorage/preseal.go +++ b/storage/mockstorage/preseal.go @@ -7,7 +7,6 @@ import ( commcid "github.com/filecoin-project/go-fil-commcid" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" - "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/lotus/extern/sector-storage/mock" market0 "github.com/filecoin-project/specs-actors/actors/builtin/market" @@ -20,7 +19,7 @@ import ( ) func PreSeal(ssize abi.SectorSize, maddr address.Address, sectors int) (*genesis.Miner, *types.KeyInfo, error) { - k, err := wallet.GenerateKey(crypto.SigTypeBLS) + k, err := wallet.GenerateKey(types.KTBLS) if err != nil { return nil, nil, err } From d6c8276c7a3e76e32484aaae745a0ccb2e6fef53 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Mon, 12 Oct 2020 00:48:23 +0200 Subject: [PATCH 065/313] Add support for WalletNew to ledger Signed-off-by: Jakub Sztandera --- chain/wallet/key.go | 15 +------ chain/wallet/ledger/ledger.go | 76 +++++++++++++++++++++++++++++++++-- 2 files changed, 74 insertions(+), 17 deletions(-) diff --git a/chain/wallet/key.go b/chain/wallet/key.go index ac9fc436f..1b191cc4b 100644 --- a/chain/wallet/key.go +++ b/chain/wallet/key.go @@ -13,7 +13,7 @@ import ( func GenerateKey(typ types.KeyType) (*Key, error) { ctyp := ActSigType(typ) if ctyp == crypto.SigTypeUnknown { - return nil, xerrors.Errorf("unknown key type: %s", typ) + return nil, xerrors.Errorf("unknown sig type: %s", typ) } pk, err := sigs.Generate(ctyp) if err != nil { @@ -56,23 +56,12 @@ func NewKey(keyinfo types.KeyInfo) (*Key, error) { return nil, xerrors.Errorf("converting BLS to address: %w", err) } default: - return nil, xerrors.Errorf("unknown key type: %s", k.Type) + return nil, xerrors.Errorf("unsupported key type: %s", k.Type) } return k, nil } -func kstoreSigType(typ crypto.SigType) types.KeyType { - switch typ { - case crypto.SigTypeBLS: - return types.KTBLS - case crypto.SigTypeSecp256k1: - return types.KTSecp256k1 - default: - return "" - } -} - func ActSigType(typ types.KeyType) crypto.SigType { switch typ { case types.KTBLS: diff --git a/chain/wallet/ledger/ledger.go b/chain/wallet/ledger/ledger.go index b6b5683cd..9a0d13419 100644 --- a/chain/wallet/ledger/ledger.go +++ b/chain/wallet/ledger/ledger.go @@ -115,12 +115,22 @@ func (lw LedgerWallet) WalletImport(ctx context.Context, kinfo *types.KeyInfo) ( if err := json.Unmarshal(kinfo.PrivateKey, &ki); err != nil { return address.Undef, err } + return lw.importKey(ki) +} +func (lw LedgerWallet) importKey(ki LedgerKeyInfo) (address.Address, error) { if ki.Address == address.Undef { return address.Undef, fmt.Errorf("no address given in imported key info") } + if len(ki.Path) != filHdPathLen { + return address.Undef, fmt.Errorf("bad hd path len: %d, expected: %d", len(ki.Path), filHdPathLen) + } + bb, err := json.Marshal(ki) + if err != nil { + return address.Undef, xerrors.Errorf("marshaling key info: %w", err) + } - if err := lw.ds.Put(keyForAddr(ki.Address), kinfo.PrivateKey); err != nil { + if err := lw.ds.Put(keyForAddr(ki.Address), bb); err != nil { return address.Undef, err } @@ -128,10 +138,11 @@ func (lw LedgerWallet) WalletImport(ctx context.Context, kinfo *types.KeyInfo) ( } func (lw LedgerWallet) WalletList(ctx context.Context) ([]address.Address, error) { - res, err := lw.ds.Query(query.Query{Prefix: "/ledgerkey/"}) + res, err := lw.ds.Query(query.Query{Prefix: dsLedgerPrefix}) if err != nil { return nil, err } + defer res.Close() var out []address.Address for { @@ -150,8 +161,63 @@ func (lw LedgerWallet) WalletList(ctx context.Context) ([]address.Address, error return out, nil } +const hdHard = 0x80000000 + +var filHDBasePath = []uint32{hdHard | 44, hdHard | 461, hdHard, 0} +var filHdPathLen = 5 + func (lw LedgerWallet) WalletNew(ctx context.Context, t types.KeyType) (address.Address, error) { - return address.Undef, fmt.Errorf("cannot create new address on ledger") + if t != types.KTSecp256k1Ledger { + return address.Undef, fmt.Errorf("unsupported key type: '%s', only '%s' supported", + t, types.KTSecp256k1Ledger) + } + + res, err := lw.ds.Query(query.Query{Prefix: dsLedgerPrefix}) + if err != nil { + return address.Undef, err + } + defer res.Close() + + var maxi int64 = -1 + for { + res, ok := res.NextSync() + if !ok { + break + } + + var ki LedgerKeyInfo + if err := json.Unmarshal(res.Value, &ki); err != nil { + return address.Undef, err + } + if i := ki.Path[filHdPathLen-1]; maxi == -1 || maxi < int64(i) { + maxi = int64(i) + } + } + if maxi == -1 { + maxi = 0 + } + + fl, err := ledgerfil.FindLedgerFilecoinApp() + if err != nil { + return address.Undef, xerrors.Errorf("finding ledger: %w", err) + } + + path := append(append([]uint32(nil), filHDBasePath...), uint32(maxi)) + _, _, addr, err := fl.GetAddressPubKeySECP256K1(path) + if err != nil { + return address.Undef, xerrors.Errorf("getting public key from ledger: %w", err) + } + + a, err := address.NewFromString(addr) + if err != nil { + return address.Undef, fmt.Errorf("parsing address: %w", err) + } + + var lki LedgerKeyInfo + lki.Address = a + lki.Path = path + + return lw.importKey(lki) } func (lw *LedgerWallet) Get() api.WalletAPI { @@ -162,6 +228,8 @@ func (lw *LedgerWallet) Get() api.WalletAPI { return lw } +var dsLedgerPrefix = "/ledgerkey/" + func keyForAddr(addr address.Address) datastore.Key { - return datastore.NewKey("/ledgerkey/" + addr.String()) + return datastore.NewKey(dsLedgerPrefix + addr.String()) } From 7b4a5fc7ca0cd0fd5fd6068c93005adbec3167db Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Mon, 12 Oct 2020 00:50:29 +0200 Subject: [PATCH 066/313] Fixup off by one Signed-off-by: Jakub Sztandera --- chain/wallet/ledger/ledger.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/chain/wallet/ledger/ledger.go b/chain/wallet/ledger/ledger.go index 9a0d13419..14c75b356 100644 --- a/chain/wallet/ledger/ledger.go +++ b/chain/wallet/ledger/ledger.go @@ -193,16 +193,13 @@ func (lw LedgerWallet) WalletNew(ctx context.Context, t types.KeyType) (address. maxi = int64(i) } } - if maxi == -1 { - maxi = 0 - } fl, err := ledgerfil.FindLedgerFilecoinApp() if err != nil { return address.Undef, xerrors.Errorf("finding ledger: %w", err) } - path := append(append([]uint32(nil), filHDBasePath...), uint32(maxi)) + path := append(append([]uint32(nil), filHDBasePath...), uint32(maxi+1)) _, _, addr, err := fl.GetAddressPubKeySECP256K1(path) if err != nil { return address.Undef, xerrors.Errorf("getting public key from ledger: %w", err) From bae3b7d5940d758cdee0ff9f1daa0f03f6f8b76c Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Sun, 11 Oct 2020 18:55:50 -0400 Subject: [PATCH 067/313] add a shed util to determine % of power that has won a block --- chain/actors/builtin/power/power.go | 8 ++ cmd/lotus-shed/sync.go | 120 ++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) diff --git a/chain/actors/builtin/power/power.go b/chain/actors/builtin/power/power.go index e683cfd96..8faad718e 100644 --- a/chain/actors/builtin/power/power.go +++ b/chain/actors/builtin/power/power.go @@ -2,6 +2,7 @@ package power import ( "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/big" "github.com/ipfs/go-cid" "golang.org/x/xerrors" @@ -60,3 +61,10 @@ type Claim struct { // Sum of quality adjusted power for a miner's sectors. QualityAdjPower abi.StoragePower } + +func AddClaims(a Claim, b Claim) Claim { + return Claim{ + RawBytePower: big.Add(a.RawBytePower, b.RawBytePower), + QualityAdjPower: big.Add(a.QualityAdjPower, b.QualityAdjPower), + } +} diff --git a/cmd/lotus-shed/sync.go b/cmd/lotus-shed/sync.go index bfe7cc8b7..65d2b6d6f 100644 --- a/cmd/lotus-shed/sync.go +++ b/cmd/lotus-shed/sync.go @@ -2,6 +2,15 @@ package main import ( "fmt" + "strconv" + + "github.com/filecoin-project/go-state-types/big" + + "github.com/filecoin-project/lotus/chain/actors/builtin/power" + + "github.com/filecoin-project/go-address" + + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" @@ -16,6 +25,7 @@ var syncCmd = &cli.Command{ Flags: []cli.Flag{}, Subcommands: []*cli.Command{ syncValidateCmd, + syncScrapePowerCmd, }, } @@ -62,3 +72,113 @@ var syncValidateCmd = &cli.Command{ return nil }, } + +var syncScrapePowerCmd = &cli.Command{ + Name: "scrape-power", + Usage: "given a height and a tipset, reports what percentage of mining power had a winning ticket between the tipset and height", + ArgsUsage: "[height tipsetkey]", + Action: func(cctx *cli.Context) error { + if cctx.Args().Len() < 1 { + fmt.Println("usage: [blockCid1 blockCid2...]") + fmt.Println("Any CIDs passed after the height will be used as the tipset key") + fmt.Println("If no block CIDs are provided, chain head will be used") + return nil + } + + api, closer, err := lcli.GetFullNodeAPI(cctx) + if err != nil { + return err + } + + defer closer() + ctx := lcli.ReqContext(cctx) + + if cctx.Args().Len() < 1 { + fmt.Println("usage: ...") + fmt.Println("At least one block cid must be provided") + return nil + } + + h, err := strconv.ParseInt(cctx.Args().Get(0), 10, 0) + if err != nil { + return err + } + + height := abi.ChainEpoch(h) + + var ts *types.TipSet + var startTsk types.TipSetKey + if cctx.NArg() > 1 { + var tscids []cid.Cid + args := cctx.Args().Slice() + + for _, s := range args[1:] { + c, err := cid.Decode(s) + if err != nil { + return fmt.Errorf("block cid was invalid: %s", err) + } + tscids = append(tscids, c) + } + + startTsk = types.NewTipSetKey(tscids...) + ts, err = api.ChainGetTipSet(ctx, startTsk) + if err != nil { + return err + } + } else { + ts, err = api.ChainHead(ctx) + if err != nil { + return err + } + + startTsk = ts.Key() + } + + if ts.Height() < height { + return fmt.Errorf("start tipset's height < stop height: %d < %d", ts.Height(), height) + } + + miners := make(map[address.Address]struct{}) + for ts.Height() >= height { + for _, blk := range ts.Blocks() { + _, found := miners[blk.Miner] + if !found { + // do the thing + miners[blk.Miner] = struct{}{} + } + } + + ts, err = api.ChainGetTipSet(ctx, ts.Parents()) + if err != nil { + return err + } + } + + totalWonPower := power.Claim{ + RawBytePower: big.Zero(), + QualityAdjPower: big.Zero(), + } + for miner := range miners { + mp, err := api.StateMinerPower(ctx, miner, startTsk) + if err != nil { + return err + } + + totalWonPower = power.AddClaims(totalWonPower, mp.MinerPower) + } + + totalPower, err := api.StateMinerPower(ctx, address.Undef, startTsk) + if err != nil { + return err + } + + qpercI := types.BigDiv(types.BigMul(totalWonPower.QualityAdjPower, types.NewInt(1000000)), totalPower.TotalPower.QualityAdjPower) + + fmt.Println("Number of winning miners: ", len(miners)) + fmt.Println("QAdjPower of winning miners: ", totalWonPower.QualityAdjPower) + fmt.Println("QAdjPower of all miners: ", totalPower.TotalPower.QualityAdjPower) + fmt.Println("Percentage of winning QAdjPower: ", float64(qpercI.Int64())/10000) + + return nil + }, +} From fda8b932bab6899e28089b72ef18ea366408fbf0 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Mon, 12 Oct 2020 01:27:15 +0200 Subject: [PATCH 068/313] Ask for confirmation when creating a key Signed-off-by: Jakub Sztandera --- chain/wallet/ledger/ledger.go | 9 +++++++++ chain/wallet/multi.go | 15 ++++++++++----- go.mod | 3 ++- go.sum | 9 +++++++++ 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/chain/wallet/ledger/ledger.go b/chain/wallet/ledger/ledger.go index 14c75b356..34307d192 100644 --- a/chain/wallet/ledger/ledger.go +++ b/chain/wallet/ledger/ledger.go @@ -9,6 +9,7 @@ import ( "github.com/ipfs/go-cid" "github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore/query" + logging "github.com/ipfs/go-log" ledgerfil "github.com/whyrusleeping/ledger-filecoin-go" "golang.org/x/xerrors" @@ -20,6 +21,8 @@ import ( "github.com/filecoin-project/lotus/node/modules/dtypes" ) +var log = logging.Logger("wallet-ledger") + type LedgerWallet struct { ds datastore.Datastore } @@ -205,6 +208,12 @@ func (lw LedgerWallet) WalletNew(ctx context.Context, t types.KeyType) (address. return address.Undef, xerrors.Errorf("getting public key from ledger: %w", err) } + log.Warnf("creating key: %s, accept the key in ledger device", addr) + _, _, addr, err = fl.ShowAddressPubKeySECP256K1(path) + if err != nil { + return address.Undef, xerrors.Errorf("verifying public key with ledger: %w", err) + } + a, err := address.NewFromString(addr) if err != nil { return address.Undef, fmt.Errorf("parsing address: %w", err) diff --git a/chain/wallet/multi.go b/chain/wallet/multi.go index 6eac03367..532ad217b 100644 --- a/chain/wallet/multi.go +++ b/chain/wallet/multi.go @@ -70,13 +70,18 @@ func (m MultiWallet) find(ctx context.Context, address address.Address, wallets return nil, nil } -func (m MultiWallet) WalletNew(ctx context.Context, sigType types.KeyType) (address.Address, error) { - w := firstNonNil(m.Remote, m.Local) - if w == nil { - return address.Undef, xerrors.Errorf("no wallet backends configured") +func (m MultiWallet) WalletNew(ctx context.Context, keyType types.KeyType) (address.Address, error) { + var local getif = m.Local + if keyType == types.KTSecp256k1Ledger { + local = m.Ledger } - return w.WalletNew(ctx, sigType) + w := firstNonNil(m.Remote, local) + if w == nil { + return address.Undef, xerrors.Errorf("no wallet backends supporting key type: %s", keyType) + } + + return w.WalletNew(ctx, keyType) } func (m MultiWallet) WalletHas(ctx context.Context, address address.Address) (bool, error) { diff --git a/go.mod b/go.mod index d6a4768b7..922e4b6b5 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/drand/kyber v1.1.2 github.com/dustin/go-humanize v1.0.0 github.com/elastic/go-sysinfo v1.3.0 - github.com/fatih/color v1.8.0 + github.com/fatih/color v1.9.0 github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200716204036-cddc56607e1d github.com/filecoin-project/go-address v0.0.4 github.com/filecoin-project/go-amt-ipld/v2 v2.1.1-0.20201006184820-924ee87a1349 // indirect @@ -104,6 +104,7 @@ require ( github.com/libp2p/go-libp2p-tls v0.1.3 github.com/libp2p/go-libp2p-yamux v0.2.8 github.com/libp2p/go-maddr-filter v0.1.0 + github.com/mattn/go-colorable v0.1.6 // indirect github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 github.com/mitchellh/go-homedir v1.1.0 github.com/multiformats/go-base32 v0.0.3 diff --git a/go.sum b/go.sum index fe7aacbf9..6dfc9aac6 100644 --- a/go.sum +++ b/go.sum @@ -221,6 +221,8 @@ github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:Jp github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.8.0 h1:5bzFgL+oy7JITMTxUPJ00n7VxmYd/PdMp5mHFX40/RY= github.com/fatih/color v1.8.0/go.mod h1:3l45GVGkyrnYNl9HoIjnp2NnNWvh6hLAqD8yTfGjnw8= +github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fd/go-nat v1.0.0/go.mod h1:BTBu/CKvMmOMUPkKVef1pngt2WFH/lg7E6yQnulfp6E= github.com/filecoin-project/go-address v0.0.3 h1:eVfbdjEbpbzIrbiSa+PiGUY+oDK9HnUn+M1R/ggoHf8= github.com/filecoin-project/go-address v0.0.3/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= @@ -1045,11 +1047,16 @@ github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcncea github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= @@ -1665,11 +1672,13 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191025021431-6c3a3bfe00ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191025090151-53bf42e6b339/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= From df7ee610cd426bbd20bdf6ccdeae4b9b4e89e3fe Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Mon, 12 Oct 2020 01:29:19 +0200 Subject: [PATCH 069/313] Re-enable repub Signed-off-by: Jakub Sztandera --- chain/messagepool/messagepool.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index 2a4704c3b..d3c638b22 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -1249,9 +1249,6 @@ func (mp *MessagePool) Updates(ctx context.Context) (<-chan api.MpoolUpdate, err } func (mp *MessagePool) loadLocal() error { - return nil - // TODO: this causes super slow startup... - res, err := mp.localMsgs.Query(query.Query{}) if err != nil { return xerrors.Errorf("query local messages: %w", err) From b4215e5f46003284599f4736eb6f7003f9785ae5 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Sun, 11 Oct 2020 19:49:57 -0400 Subject: [PATCH 070/313] Add a CLI tool for miner's to repay debt --- chain/actors/builtin/miner/miner.go | 14 ++++ cmd/lotus-storage-miner/actor.go | 105 ++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+) diff --git a/chain/actors/builtin/miner/miner.go b/chain/actors/builtin/miner/miner.go index 8649d4351..281068827 100644 --- a/chain/actors/builtin/miner/miner.go +++ b/chain/actors/builtin/miner/miner.go @@ -148,6 +148,20 @@ type MinerInfo struct { ConsensusFaultElapsed abi.ChainEpoch } +func (mi MinerInfo) IsController(addr address.Address) bool { + if addr == mi.Owner || addr == mi.Worker { + return true + } + + for _, ca := range mi.ControlAddresses { + if addr == ca { + return true + } + } + + return false +} + type SectorExpiration struct { OnTime abi.ChainEpoch diff --git a/cmd/lotus-storage-miner/actor.go b/cmd/lotus-storage-miner/actor.go index fa320289e..35e2a268e 100644 --- a/cmd/lotus-storage-miner/actor.go +++ b/cmd/lotus-storage-miner/actor.go @@ -5,6 +5,11 @@ import ( "os" "strings" + "github.com/filecoin-project/lotus/api/apibstore" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin/miner" + cbor "github.com/ipfs/go-ipld-cbor" + "github.com/filecoin-project/lotus/build" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" @@ -34,6 +39,7 @@ var actorCmd = &cli.Command{ Subcommands: []*cli.Command{ actorSetAddrsCmd, actorWithdrawCmd, + actorRepayDebtCmd, actorSetPeeridCmd, actorSetOwnerCmd, actorControl, @@ -254,6 +260,105 @@ var actorWithdrawCmd = &cli.Command{ }, } +var actorRepayDebtCmd = &cli.Command{ + Name: "repay-debt", + Usage: "pay down a miner's debt", + ArgsUsage: "[amount (FIL)]", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "from", + Usage: "optionally specify the account to send funds from", + }, + }, + Action: func(cctx *cli.Context) error { + nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx) + if err != nil { + return err + } + defer closer() + + api, acloser, err := lcli.GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer acloser() + + ctx := lcli.ReqContext(cctx) + + maddr, err := nodeApi.ActorAddress(ctx) + if err != nil { + return err + } + + mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK) + if err != nil { + return err + } + + var amount abi.TokenAmount + if cctx.Args().Present() { + f, err := types.ParseFIL(cctx.Args().First()) + if err != nil { + return xerrors.Errorf("parsing 'amount' argument: %w", err) + } + + amount = abi.TokenAmount(f) + } else { + mact, err := api.StateGetActor(ctx, maddr, types.EmptyTSK) + if err != nil { + return err + } + + store := adt.WrapStore(ctx, cbor.NewCborStore(apibstore.NewAPIBlockstore(api))) + + mst, err := miner.Load(store, mact) + if err != nil { + return err + } + + amount, err = mst.FeeDebt() + if err != nil { + return err + } + + } + + fromAddr := mi.Worker + if from := cctx.String("from"); from != "" { + addr, err := address.NewFromString(from) + if err != nil { + return err + } + + fromAddr = addr + } + + fromId, err := api.StateLookupID(ctx, fromAddr, types.EmptyTSK) + if err != nil { + return err + } + + if !mi.IsController(fromId) { + return xerrors.Errorf("sender isn't a controller of miner: %s", fromId) + } + + smsg, err := api.MpoolPushMessage(ctx, &types.Message{ + To: maddr, + From: fromId, + Value: amount, + Method: builtin2.MethodsMiner.RepayDebt, + Params: nil, + }, nil) + if err != nil { + return err + } + + fmt.Printf("Sent repay debt message %s\n", smsg.Cid()) + + return nil + }, +} + var actorControl = &cli.Command{ Name: "control", Usage: "Manage control addresses", From ae366972a9e8170d616d8c1f36a819dd27d78c3f Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Mon, 12 Oct 2020 05:11:04 +0200 Subject: [PATCH 071/313] Chain is love Signed-off-by: Jakub Sztandera --- cli/chain.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cli/chain.go b/cli/chain.go index 763752f23..bc0d7b508 100644 --- a/cli/chain.go +++ b/cli/chain.go @@ -521,8 +521,9 @@ var chainInspectUsage = &cli.Command{ } var chainListCmd = &cli.Command{ - Name: "list", - Usage: "View a segment of the chain", + Name: "list", + Aliases: []string{"love"}, + Usage: "View a segment of the chain", Flags: []cli.Flag{ &cli.Uint64Flag{Name: "height"}, &cli.IntFlag{Name: "count", Value: 30}, From c296e1bbcac98225f1d5ef7b34e9790c3dbed31e Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Sun, 11 Oct 2020 20:31:20 -0700 Subject: [PATCH 072/313] use actor abstraction in metrics command --- chain/actors/builtin/power/power.go | 1 + chain/actors/builtin/power/v0.go | 19 +++++++++++++++++ chain/actors/builtin/power/v2.go | 19 +++++++++++++++++ tools/stats/metrics.go | 33 ++++------------------------- 4 files changed, 43 insertions(+), 29 deletions(-) diff --git a/chain/actors/builtin/power/power.go b/chain/actors/builtin/power/power.go index e683cfd96..bafb14de0 100644 --- a/chain/actors/builtin/power/power.go +++ b/chain/actors/builtin/power/power.go @@ -51,6 +51,7 @@ type State interface { MinerPower(address.Address) (Claim, bool, error) MinerNominalPowerMeetsConsensusMinimum(address.Address) (bool, error) ListAllMiners() ([]address.Address, error) + ForEachClaim(func(miner address.Address, claim Claim) error) error } type Claim struct { diff --git a/chain/actors/builtin/power/v0.go b/chain/actors/builtin/power/v0.go index e2a9cf382..3f9a65777 100644 --- a/chain/actors/builtin/power/v0.go +++ b/chain/actors/builtin/power/v0.go @@ -96,3 +96,22 @@ func (s *state0) ListAllMiners() ([]address.Address, error) { return miners, nil } + +func (s *state0) ForEachClaim(cb func(miner address.Address, claim Claim) error) error { + claims, err := adt0.AsMap(s.store, s.Claims) + if err != nil { + return err + } + + var claim power0.Claim + return claims.ForEach(&claim, func(k string) error { + a, err := address.NewFromBytes([]byte(k)) + if err != nil { + return err + } + return cb(a, Claim{ + RawBytePower: claim.RawBytePower, + QualityAdjPower: claim.QualityAdjPower, + }) + }) +} diff --git a/chain/actors/builtin/power/v2.go b/chain/actors/builtin/power/v2.go index 6346a09b6..0c15f0669 100644 --- a/chain/actors/builtin/power/v2.go +++ b/chain/actors/builtin/power/v2.go @@ -96,3 +96,22 @@ func (s *state2) ListAllMiners() ([]address.Address, error) { return miners, nil } + +func (s *state2) ForEachClaim(cb func(miner address.Address, claim Claim) error) error { + claims, err := adt2.AsMap(s.store, s.Claims) + if err != nil { + return err + } + + var claim power2.Claim + return claims.ForEach(&claim, func(k string) error { + a, err := address.NewFromBytes([]byte(k)) + if err != nil { + return err + } + return cb(a, Claim{ + RawBytePower: claim.RawBytePower, + QualityAdjPower: claim.QualityAdjPower, + }) + }) +} diff --git a/tools/stats/metrics.go b/tools/stats/metrics.go index 8dc79ea44..795203c40 100644 --- a/tools/stats/metrics.go +++ b/tools/stats/metrics.go @@ -13,12 +13,10 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/actors/builtin/power" "github.com/filecoin-project/lotus/chain/actors/builtin/reward" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/specs-actors/actors/builtin" - "github.com/filecoin-project/specs-actors/actors/builtin/power" - "github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/ipfs/go-cid" "github.com/multiformats/go-multihash" @@ -272,35 +270,17 @@ func RecordTipsetStatePoints(ctx context.Context, api api.FullNode, pl *PointLis p = NewPoint("chain.power", totalPower.TotalPower.QualityAdjPower.Int64()) pl.AddPoint(p) - powerActor, err := api.StateGetActor(ctx, builtin.StoragePowerActorAddr, tipset.Key()) + powerActor, err := api.StateGetActor(ctx, power.Address, tipset.Key()) if err != nil { return err } - powerRaw, err := api.ChainReadObj(ctx, powerActor.Head) + powerActorState, err := power.Load(&ApiIpldStore{ctx, api}, powerActor) if err != nil { return err } - var powerActorState power.State - - if err := powerActorState.UnmarshalCBOR(bytes.NewReader(powerRaw)); err != nil { - return fmt.Errorf("failed to unmarshal power actor state: %w", err) - } - - s := &ApiIpldStore{ctx, api} - mp, err := adt.AsMap(s, powerActorState.Claims) - if err != nil { - return err - } - - var claim power.Claim - err = mp.ForEach(&claim, func(key string) error { - addr, err := address.NewFromBytes([]byte(key)) - if err != nil { - return err - } - + return powerActorState.ForEachClaim(func(addr address.Address, claim power.Claim) error { if claim.QualityAdjPower.Int64() == 0 { return nil } @@ -311,11 +291,6 @@ func RecordTipsetStatePoints(ctx context.Context, api api.FullNode, pl *PointLis return nil }) - if err != nil { - return err - } - - return nil } type msgTag struct { From a2e0832a12f220678ac73bf96542c747814b02bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 12 Oct 2020 06:17:00 +0200 Subject: [PATCH 073/313] Fix lint --- chain/wallet/ledger/ledger.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chain/wallet/ledger/ledger.go b/chain/wallet/ledger/ledger.go index 34307d192..c1757fd0a 100644 --- a/chain/wallet/ledger/ledger.go +++ b/chain/wallet/ledger/ledger.go @@ -145,7 +145,7 @@ func (lw LedgerWallet) WalletList(ctx context.Context) ([]address.Address, error if err != nil { return nil, err } - defer res.Close() + defer res.Close() // nolint:errcheck var out []address.Address for { @@ -179,7 +179,7 @@ func (lw LedgerWallet) WalletNew(ctx context.Context, t types.KeyType) (address. if err != nil { return address.Undef, err } - defer res.Close() + defer res.Close() // nolint:errcheck var maxi int64 = -1 for { From 4ac2bee81ce92676e966959299a4cd1a18b3a6ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 12 Oct 2020 06:34:45 +0200 Subject: [PATCH 074/313] Update oni --- extern/oni | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/oni b/extern/oni index dbee44e4f..10ed9ef57 160000 --- a/extern/oni +++ b/extern/oni @@ -1 +1 @@ -Subproject commit dbee44e4f940a502971f17116ccbba61ceaf2674 +Subproject commit 10ed9ef576836186de3b8513c03cdc3fb18c44ed From 92177b573812cd19e56f5873921b7ed8ec685906 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Sun, 11 Oct 2020 22:31:46 -0700 Subject: [PATCH 075/313] implement tape upgrade Upgrade to specs-actors v2.1 and network version 5. This fixes the bug where prove commits were not accepted. --- build/params_2k.go | 3 ++- build/params_shared_vals.go | 2 +- build/params_testground.go | 5 +++-- build/params_testnet.go | 2 ++ chain/actors/version.go | 2 +- chain/stmgr/forks.go | 5 ++++- documentation/en/api-methods.md | 2 +- go.mod | 4 ++-- go.sum | 6 ++++-- 9 files changed, 20 insertions(+), 11 deletions(-) diff --git a/build/params_2k.go b/build/params_2k.go index c6538dc08..b09b60fae 100644 --- a/build/params_2k.go +++ b/build/params_2k.go @@ -17,9 +17,10 @@ const BreezeGasTampingDuration = 0 const UpgradeSmokeHeight = -1 const UpgradeIgnitionHeight = -2 const UpgradeRefuelHeight = -3 +const UpgradeTapeHeight = -4 var UpgradeActorsV2Height = abi.ChainEpoch(10) -var UpgradeLiftoffHeight = abi.ChainEpoch(-4) +var UpgradeLiftoffHeight = abi.ChainEpoch(-5) var DrandSchedule = map[abi.ChainEpoch]DrandEnum{ 0: DrandMainnet, diff --git a/build/params_shared_vals.go b/build/params_shared_vals.go index 722590575..ede40c0e3 100644 --- a/build/params_shared_vals.go +++ b/build/params_shared_vals.go @@ -25,7 +25,7 @@ const UnixfsLinksPerLevel = 1024 // Consensus / Network const AllowableClockDriftSecs = uint64(1) -const NewestNetworkVersion = network.Version4 +const NewestNetworkVersion = network.Version5 const ActorUpgradeNetworkVersion = network.Version4 // Epochs diff --git a/build/params_testground.go b/build/params_testground.go index 6109cbc04..7ef034234 100644 --- a/build/params_testground.go +++ b/build/params_testground.go @@ -83,14 +83,15 @@ var ( UpgradeSmokeHeight abi.ChainEpoch = -1 UpgradeIgnitionHeight abi.ChainEpoch = -2 UpgradeRefuelHeight abi.ChainEpoch = -3 + UpgradeTapeHeight abi.ChainEpoch = -4 UpgradeActorsV2Height abi.ChainEpoch = 10 - UpgradeLiftoffHeight abi.ChainEpoch = -4 + UpgradeLiftoffHeight abi.ChainEpoch = -5 DrandSchedule = map[abi.ChainEpoch]DrandEnum{ 0: DrandMainnet, } - NewestNetworkVersion = network.Version4 + NewestNetworkVersion = network.Version5 ActorUpgradeNetworkVersion = network.Version4 Devnet = true diff --git a/build/params_testnet.go b/build/params_testnet.go index fe70deaef..54f50ac6e 100644 --- a/build/params_testnet.go +++ b/build/params_testnet.go @@ -30,6 +30,8 @@ const UpgradeRefuelHeight = 130800 var UpgradeActorsV2Height = abi.ChainEpoch(138720) +const UpgradeTapeHeight = 140760 + // This signals our tentative epoch for mainnet launch. Can make it later, but not earlier. // Miners, clients, developers, custodians all need time to prepare. // We still have upgrades and state changes to do, but can happen after signaling timing here. diff --git a/chain/actors/version.go b/chain/actors/version.go index 17af8b08b..2efd903bb 100644 --- a/chain/actors/version.go +++ b/chain/actors/version.go @@ -18,7 +18,7 @@ func VersionForNetwork(version network.Version) Version { switch version { case network.Version0, network.Version1, network.Version2, network.Version3: return Version0 - case network.Version4: + case network.Version4, network.Version5: return Version2 default: panic(fmt.Sprintf("unsupported network version %d", version)) diff --git a/chain/stmgr/forks.go b/chain/stmgr/forks.go index fba92ee3f..6ebe8a5b9 100644 --- a/chain/stmgr/forks.go +++ b/chain/stmgr/forks.go @@ -79,9 +79,12 @@ func DefaultUpgradeSchedule() UpgradeSchedule { Network: network.Version4, Expensive: true, Migration: UpgradeActorsV2, + }, { + Height: build.UpgradeTapeHeight, + Network: network.Version5, }, { Height: build.UpgradeLiftoffHeight, - Network: network.Version4, + Network: network.Version5, Migration: UpgradeLiftoff, }} diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index ec8071b57..76dce56db 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -3975,7 +3975,7 @@ Inputs: ] ``` -Response: `4` +Response: `5` ### StateReadState StateReadState returns the indicated actor's state. diff --git a/go.mod b/go.mod index eb79a496c..ef43a5274 100644 --- a/go.mod +++ b/go.mod @@ -34,12 +34,12 @@ require ( github.com/filecoin-project/go-multistore v0.0.3 github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20 github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261 - github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab + github.com/filecoin-project/go-state-types v0.0.0-20201003010437-c33112184a2b github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe github.com/filecoin-project/go-statestore v0.1.0 github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b github.com/filecoin-project/specs-actors v0.9.12 - github.com/filecoin-project/specs-actors/v2 v2.0.3 + github.com/filecoin-project/specs-actors/v2 v2.1.0 github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796 github.com/filecoin-project/test-vectors/schema v0.0.4 github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1 diff --git a/go.sum b/go.sum index e13359f6c..a9ac12ff7 100644 --- a/go.sum +++ b/go.sum @@ -265,6 +265,8 @@ github.com/filecoin-project/go-state-types v0.0.0-20200904021452-1883f36ca2f4/go github.com/filecoin-project/go-state-types v0.0.0-20200905071437-95828685f9df/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I= github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab h1:cEDC5Ei8UuT99hPWhCjA72SM9AuRtnpvdSTIYbnzN8I= github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= +github.com/filecoin-project/go-state-types v0.0.0-20201003010437-c33112184a2b h1:bMUfG6Sy6YSMbsjQAO1Q2vEZldbSdsbRy/FX3OlTck0= +github.com/filecoin-project/go-state-types v0.0.0-20201003010437-c33112184a2b/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-statemachine v0.0.0-20200714194326-a77c3ae20989/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe h1:dF8u+LEWeIcTcfUcCf3WFVlc81Fr2JKg8zPzIbBDKDw= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= @@ -276,8 +278,8 @@ github.com/filecoin-project/specs-actors v0.9.4/go.mod h1:BStZQzx5x7TmCkLv0Bpa07 github.com/filecoin-project/specs-actors v0.9.7/go.mod h1:wM2z+kwqYgXn5Z7scV1YHLyd1Q1cy0R8HfTIWQ0BFGU= github.com/filecoin-project/specs-actors v0.9.12 h1:iIvk58tuMtmloFNHhAOQHG+4Gci6Lui0n7DYQGi3cJk= github.com/filecoin-project/specs-actors v0.9.12/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= -github.com/filecoin-project/specs-actors/v2 v2.0.3 h1:Niy6xncgi8bI8aBCt1McdZfATBfG4Uxytt8KW4s3bAc= -github.com/filecoin-project/specs-actors/v2 v2.0.3/go.mod h1:v2NZVYinNIKA9acEMBm5wWXxqv5+frFEbekBFemYghY= +github.com/filecoin-project/specs-actors/v2 v2.1.0 h1:ocEuGz8DG2cUWw32c/tvF8D6xT+dGVWJTr5yDevU00g= +github.com/filecoin-project/specs-actors/v2 v2.1.0/go.mod h1:E7fAX4CZkDVQvDNRCxfq+hc3nx56KcCKyuZf0hlQJ20= github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796 h1:dJsTPWpG2pcTeojO2pyn0c6l+x/3MZYCBgo/9d11JEk= github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g= github.com/filecoin-project/test-vectors/schema v0.0.4 h1:QTRd0gb/NP4ZOTM7Dib5U3xE1/ToGDKnYLfxkC3t/m8= From 160f209f6a857eb4b16a8d96b48b0c0d1a0ac404 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Mon, 12 Oct 2020 02:08:38 -0400 Subject: [PATCH 076/313] Lotus version 0.10.0 --- CHANGELOG.md | 19 +++++++++++++++++++ build/version.go | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d397762a6..16d8d15b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Lotus changelog +# 0.10.0 / 2020-10-12 + +This is a consensus-breaking hotfix that addresses an issue in specs-actors v2.0.3 that made it impossible to pledge new 32GiB sectors. The change in Lotus is to update to actors v2.1.0, behind the new network version 5. + +## Changes + +- make pledge test pass with the race detector (https://github.com/filecoin-project/lotus/pull/4291) +- fix a race in tipset cache usage (https://github.com/filecoin-project/lotus/pull/4282) +- add an api for removing multisig signers (https://github.com/filecoin-project/lotus/pull/4274) +- cli: Don't output errors to stdout (https://github.com/filecoin-project/lotus/pull/4298) +- Fix panic in wallet export when key is not found (https://github.com/filecoin-project/lotus/pull/4299) +- Dump the block validation cache whenever we perform an import (https://github.com/filecoin-project/lotus/pull/4287) +- Fix two races (https://github.com/filecoin-project/lotus/pull/4301) +- sync unmark-bad --all (https://github.com/filecoin-project/lotus/pull/4296) +- decode parameters for multisig transactions in inspect (https://github.com/filecoin-project/lotus/pull/4312) +- Chain is love (https://github.com/filecoin-project/lotus/pull/4321) +- lotus-stats: optmize getting miner power (https://github.com/filecoin-project/lotus/pull/4315) +- implement tape upgrade (https://github.com/filecoin-project/lotus/pull/4322) + # 0.9.1 / 2020-10-10 This release fixes an issue which may cause the actors v2 migration to compute the state incorrectly when more than one migration is running in parallel. diff --git a/build/version.go b/build/version.go index 5baed1fb7..baeafdfe7 100644 --- a/build/version.go +++ b/build/version.go @@ -29,7 +29,7 @@ func buildType() string { } // BuildVersion is the local build version, set by build system -const BuildVersion = "0.9.1" +const BuildVersion = "0.10.0" func UserVersion() string { return BuildVersion + buildType() + CurrentCommit From dc4e73c73724115f6fff6c17df608860c03de510 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Sun, 11 Oct 2020 23:31:23 -0700 Subject: [PATCH 077/313] Test the tape upgrade --- api/test/tape.go | 114 +++++++++++++++++++++++++++++ api/test/test.go | 4 +- extern/sector-storage/mock/mock.go | 9 ++- node/node_test.go | 10 +++ 4 files changed, 132 insertions(+), 5 deletions(-) create mode 100644 api/test/tape.go diff --git a/api/test/tape.go b/api/test/tape.go new file mode 100644 index 000000000..466bdd829 --- /dev/null +++ b/api/test/tape.go @@ -0,0 +1,114 @@ +package test + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/network" + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/stmgr" + sealing "github.com/filecoin-project/lotus/extern/storage-sealing" + "github.com/filecoin-project/lotus/node" + "github.com/filecoin-project/lotus/node/impl" + "github.com/stretchr/testify/require" +) + +func TestTapeFix(t *testing.T, b APIBuilder, blocktime time.Duration) { + t.Run("before", func(t *testing.T) { testTapeFix(t, b, blocktime, false) }) + t.Run("after", func(t *testing.T) { testTapeFix(t, b, blocktime, true) }) +} +func testTapeFix(t *testing.T, b APIBuilder, blocktime time.Duration, after bool) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + upgradeSchedule := stmgr.UpgradeSchedule{{ + Network: build.ActorUpgradeNetworkVersion, + Height: 1, + Migration: stmgr.UpgradeActorsV2, + }} + if after { + upgradeSchedule = append(upgradeSchedule, stmgr.Upgrade{ + Network: network.Version5, + Height: 2, + }) + } + + n, sn := b(t, []FullNodeOpts{{Opts: func(_ []TestNode) node.Option { + return node.Override(new(stmgr.UpgradeSchedule), upgradeSchedule) + }}}, OneMiner) + + client := n[0].FullNode.(*impl.FullNodeAPI) + miner := sn[0] + + addrinfo, err := client.NetAddrsListen(ctx) + if err != nil { + t.Fatal(err) + } + + if err := miner.NetConnect(ctx, addrinfo); err != nil { + t.Fatal(err) + } + build.Clock.Sleep(time.Second) + + done := make(chan struct{}) + go func() { + defer close(done) + for ctx.Err() == nil { + build.Clock.Sleep(blocktime) + if err := sn[0].MineOne(ctx, MineNext); err != nil { + if ctx.Err() != nil { + // context was canceled, ignore the error. + return + } + t.Error(err) + } + } + }() + defer func() { + cancel() + <-done + }() + + err = miner.PledgeSector(ctx) + require.NoError(t, err) + + // Wait till done. + var sectorNo abi.SectorNumber + for { + s, err := miner.SectorsList(ctx) // Note - the test builder doesn't import genesis sectors into FSM + require.NoError(t, err) + fmt.Printf("Sectors: %d\n", len(s)) + if len(s) == 1 { + sectorNo = s[0] + break + } + + build.Clock.Sleep(100 * time.Millisecond) + } + + fmt.Printf("All sectors is fsm\n") + + // If before, we expect the precommit to fail + successState := api.SectorState(sealing.CommitFailed) + failureState := api.SectorState(sealing.Proving) + if after { + // otherwise, it should succeed. + successState, failureState = failureState, successState + } + + for { + st, err := miner.SectorsStatus(ctx, sectorNo, false) + require.NoError(t, err) + if st.State == successState { + break + } + require.NotEqual(t, failureState, st.State) + build.Clock.Sleep(100 * time.Millisecond) + fmt.Println("WaitSeal") + } + +} diff --git a/api/test/test.go b/api/test/test.go index 35b397740..947f2bef4 100644 --- a/api/test/test.go +++ b/api/test/test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/network" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/miner" @@ -96,7 +97,8 @@ var FullNodeWithUpgradeAt = func(upgradeHeight abi.ChainEpoch) FullNodeOpts { return FullNodeOpts{ Opts: func(nodes []TestNode) node.Option { return node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{ - Network: build.ActorUpgradeNetworkVersion, + // Skip directly to tape height so precommits work. + Network: network.Version5, Height: upgradeHeight, Migration: stmgr.UpgradeActorsV2, }}) diff --git a/extern/sector-storage/mock/mock.go b/extern/sector-storage/mock/mock.go index 64207e66d..001c7159c 100644 --- a/extern/sector-storage/mock/mock.go +++ b/extern/sector-storage/mock/mock.go @@ -230,8 +230,8 @@ func (mgr *SectorMgr) SealCommit1(ctx context.Context, sid abi.SectorID, ticket } func (mgr *SectorMgr) SealCommit2(ctx context.Context, sid abi.SectorID, phase1Out storage.Commit1Out) (proof storage.Proof, err error) { - var out [32]byte - for i := range out { + var out [1920]byte + for i := range out[:len(phase1Out)] { out[i] = phase1Out[i] ^ byte(sid.Number&0xff) } @@ -407,11 +407,12 @@ func (mgr *SectorMgr) CheckProvable(ctx context.Context, spt abi.RegisteredSealP } func (m mockVerif) VerifySeal(svi proof.SealVerifyInfo) (bool, error) { - if len(svi.Proof) != 32 { // Real ones are longer, but this should be fine + if len(svi.Proof) != 1920 { return false, nil } - for i, b := range svi.Proof { + // only the first 32 bytes, the rest are 0. + for i, b := range svi.Proof[:32] { if b != svi.UnsealedCID.Bytes()[i]+svi.SealedCID.Bytes()[31-i]-svi.InteractiveRandomness[i]*svi.Randomness[i] { return false, nil } diff --git a/node/node_test.go b/node/node_test.go index 001b99c04..e553e83b2 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -117,6 +117,16 @@ func TestPledgeSectors(t *testing.T) { }) } +func TestTapeFix(t *testing.T) { + logging.SetLogLevel("miner", "ERROR") + logging.SetLogLevel("chainstore", "ERROR") + logging.SetLogLevel("chain", "ERROR") + logging.SetLogLevel("sub", "ERROR") + logging.SetLogLevel("storageminer", "ERROR") + + test.TestTapeFix(t, builder.MockSbBuilder, 2*time.Millisecond) +} + func TestWindowedPost(t *testing.T) { if os.Getenv("LOTUS_TEST_WINDOW_POST") != "1" { t.Skip("this takes a few minutes, set LOTUS_TEST_WINDOW_POST=1 to run") From c0961fb63d7311d7c41f4c40340e0de013382703 Mon Sep 17 00:00:00 2001 From: Dan Shao Date: Mon, 12 Oct 2020 15:07:56 +0800 Subject: [PATCH 078/313] Improve the UX for `lotus-miner sealing workers`: add total number of cores --- cmd/lotus-storage-miner/sealing.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/lotus-storage-miner/sealing.go b/cmd/lotus-storage-miner/sealing.go index 5cc5c419a..507e842c3 100644 --- a/cmd/lotus-storage-miner/sealing.go +++ b/cmd/lotus-storage-miner/sealing.go @@ -80,7 +80,8 @@ var sealingWorkersCmd = &cli.Command{ cpuBars := int(stat.CpuUse * barCols / stat.Info.Resources.CPUs) cpuBar := strings.Repeat("|", cpuBars) + strings.Repeat(" ", int(barCols)-cpuBars) - fmt.Printf("\tCPU: [%s] %d core(s) in use\n", color.GreenString(cpuBar), stat.CpuUse) + fmt.Printf("\tCPU: [%s] %d/%d core(s) in use\n", + color.GreenString(cpuBar), stat.CpuUse, stat.Info.Resources.CPUs) ramBarsRes := int(stat.Info.Resources.MemReserved * barCols / stat.Info.Resources.MemPhysical) ramBarsUsed := int(stat.MemUsedMin * barCols / stat.Info.Resources.MemPhysical) From 8b648cf77cba845ae1bf0f0c46a906b51ffd1ec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 12 Oct 2020 09:21:42 +0200 Subject: [PATCH 079/313] ledger: Close device in WalletNew --- chain/wallet/ledger/ledger.go | 1 + 1 file changed, 1 insertion(+) diff --git a/chain/wallet/ledger/ledger.go b/chain/wallet/ledger/ledger.go index c1757fd0a..07f92e7ff 100644 --- a/chain/wallet/ledger/ledger.go +++ b/chain/wallet/ledger/ledger.go @@ -201,6 +201,7 @@ func (lw LedgerWallet) WalletNew(ctx context.Context, t types.KeyType) (address. if err != nil { return address.Undef, xerrors.Errorf("finding ledger: %w", err) } + defer fl.Close() // nolint:errcheck path := append(append([]uint32(nil), filHDBasePath...), uint32(maxi+1)) _, _, addr, err := fl.GetAddressPubKeySECP256K1(path) From b7726c4ca83d632f15bc311d53281a5ad2a9929d Mon Sep 17 00:00:00 2001 From: zgfzgf <1901989065@qq.com> Date: Mon, 12 Oct 2020 16:44:39 +0800 Subject: [PATCH 080/313] optimize walkSnapshot recurseLinks --- chain/store/store.go | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/chain/store/store.go b/chain/store/store.go index c6fc0cbef..067629dc0 100644 --- a/chain/store/store.go +++ b/chain/store/store.go @@ -1312,11 +1312,13 @@ func (cs *ChainStore) WalkSnapshot(ctx context.Context, ts *types.TipSet, inclRe var cids []cid.Cid if !skipOldMsgs || b.Height > ts.Height()-inclRecentRoots { - mcids, err := recurseLinks(cs.bs, walked, b.Messages, []cid.Cid{b.Messages}) - if err != nil { - return xerrors.Errorf("recursing messages failed: %w", err) + if walked.Visit(b.Messages) { + mcids, err := recurseLinks(cs.bs, walked, b.Messages, []cid.Cid{b.Messages}) + if err != nil { + return xerrors.Errorf("recursing messages failed: %w", err) + } + cids = mcids } - cids = mcids } if b.Height > 0 { @@ -1331,12 +1333,14 @@ func (cs *ChainStore) WalkSnapshot(ctx context.Context, ts *types.TipSet, inclRe out := cids if b.Height == 0 || b.Height > ts.Height()-inclRecentRoots { - cids, err := recurseLinks(cs.bs, walked, b.ParentStateRoot, []cid.Cid{b.ParentStateRoot}) - if err != nil { - return xerrors.Errorf("recursing genesis state failed: %w", err) - } + if walked.Visit(b.ParentStateRoot) { + cids, err := recurseLinks(cs.bs, walked, b.ParentStateRoot, []cid.Cid{b.ParentStateRoot}) + if err != nil { + return xerrors.Errorf("recursing genesis state failed: %w", err) + } - out = append(out, cids...) + out = append(out, cids...) + } } for _, c := range out { From 8001ed30308f3e81bd695e8f329a45b162f4b46d Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Thu, 1 Oct 2020 11:02:57 +0200 Subject: [PATCH 081/313] Drand: add cloudflare. Use HTTP for PL nodes. Adding Cloudflare ensures additional redundancy. Switching to HTTP for PL nodes reduces latency and cost. Randomness is verified after being received. --- build/drand.go | 11 +---------- chain/beacon/drand/drand_test.go | 2 +- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/build/drand.go b/build/drand.go index 73299249a..3b976ac92 100644 --- a/build/drand.go +++ b/build/drand.go @@ -35,6 +35,7 @@ var DrandConfigs = map[DrandEnum]dtypes.DrandConfig{ "https://api.drand.sh", "https://api2.drand.sh", "https://api3.drand.sh", + "https://drand.cloudflare.com", }, Relays: []string{ "/dnsaddr/api.drand.sh/", @@ -68,16 +69,6 @@ var DrandConfigs = map[DrandEnum]dtypes.DrandConfig{ ChainInfoJSON: `{"public_key":"8cda589f88914aa728fd183f383980b35789ce81b274e5daee1f338b77d02566ef4d3fb0098af1f844f10f9c803c1827","period":25,"genesis_time":1595348225,"hash":"e73b7dc3c4f6a236378220c0dd6aa110eb16eed26c11259606e07ee122838d4f","groupHash":"567d4785122a5a3e75a9bc9911d7ea807dd85ff76b78dc4ff06b075712898607"}`, }, DrandIncentinet: { - Servers: []string{ - "https://pl-eu.incentinet.drand.sh", - "https://pl-us.incentinet.drand.sh", - "https://pl-sin.incentinet.drand.sh", - }, - Relays: []string{ - "/dnsaddr/pl-eu.incentinet.drand.sh/", - "/dnsaddr/pl-us.incentinet.drand.sh/", - "/dnsaddr/pl-sin.incentinet.drand.sh/", - }, ChainInfoJSON: `{"public_key":"8cad0c72c606ab27d36ee06de1d5b2db1faf92e447025ca37575ab3a8aac2eaae83192f846fc9e158bc738423753d000","period":30,"genesis_time":1595873820,"hash":"80c8b872c714f4c00fdd3daa465d5514049f457f01f85a4caf68cdcd394ba039","groupHash":"d9406aaed487f7af71851b4399448e311f2328923d454e971536c05398ce2d9b"}`, }, } diff --git a/chain/beacon/drand/drand_test.go b/chain/beacon/drand/drand_test.go index 0cb9c2ba8..d66ee7b54 100644 --- a/chain/beacon/drand/drand_test.go +++ b/chain/beacon/drand/drand_test.go @@ -12,7 +12,7 @@ import ( ) func TestPrintGroupInfo(t *testing.T) { - server := build.DrandConfigs[build.DrandIncentinet].Servers[0] + server := build.DrandConfigs[build.DrandDevnet].Servers[0] c, err := hclient.New(server, nil, nil) assert.NoError(t, err) cg := c.(interface { From 79c5d2c6d2524a064af1a715fd56bb10af000bb5 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 12 Oct 2020 11:04:46 -0700 Subject: [PATCH 082/313] Rename params_testnet to params_mainnet --- build/{params_testnet.go => params_mainnet.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename build/{params_testnet.go => params_mainnet.go} (100%) diff --git a/build/params_testnet.go b/build/params_mainnet.go similarity index 100% rename from build/params_testnet.go rename to build/params_mainnet.go From 6c0812062881bb26681bf84633af9e454d7824c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 12 Oct 2020 20:46:34 +0200 Subject: [PATCH 083/313] types: Add CID fields to messages in json marshalers --- chain/types/message.go | 15 ++++++++ chain/types/message_test.go | 66 ++++++++++++++++++++++++++++++++++++ chain/types/signedmessage.go | 15 ++++++++ 3 files changed, 96 insertions(+) diff --git a/chain/types/message.go b/chain/types/message.go index 4fead44bc..cbc7c1dad 100644 --- a/chain/types/message.go +++ b/chain/types/message.go @@ -2,6 +2,7 @@ package types import ( "bytes" + "encoding/json" "fmt" "github.com/filecoin-project/go-state-types/abi" @@ -106,6 +107,20 @@ func (m *Message) Cid() cid.Cid { return b.Cid() } +type mCid struct { + *RawMessage + CID cid.Cid +} + +type RawMessage Message + +func (m *Message) MarshalJSON() ([]byte, error) { + return json.Marshal(&mCid{ + RawMessage: (*RawMessage)(m), + CID: m.Cid(), + }) +} + func (m *Message) RequiredFunds() BigInt { return BigMul(m.GasFeeCap, NewInt(uint64(m.GasLimit))) } diff --git a/chain/types/message_test.go b/chain/types/message_test.go index f57385a09..dab8e0939 100644 --- a/chain/types/message_test.go +++ b/chain/types/message_test.go @@ -1,11 +1,14 @@ package types import ( + "encoding/json" + "fmt" "testing" "github.com/stretchr/testify/require" "github.com/filecoin-project/go-state-types/big" + "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/specs-actors/actors/builtin" ) @@ -70,3 +73,66 @@ func TestEqualCall(t *testing.T) { require.True(t, m1.EqualCall(m3)) require.False(t, m1.EqualCall(m4)) } + +func TestMessageJson(t *testing.T) { + m := &Message{ + To: builtin.StoragePowerActorAddr, + From: builtin.SystemActorAddr, + Nonce: 34, + Value: big.Zero(), + + GasLimit: 123, + GasFeeCap: big.NewInt(234), + GasPremium: big.NewInt(234), + + Method: 6, + Params: []byte("hai"), + } + + b, err := json.Marshal(m) + require.NoError(t, err) + + exp := []byte("{\"Version\":0,\"To\":\"f04\",\"From\":\"f00\",\"Nonce\":34,\"Value\":\"0\",\"GasLimit\":123,\"GasFeeCap\":\"234\",\"GasPremium\":\"234\",\"Method\":6,\"Params\":\"aGFp\",\"CID\":{\"/\":\"bafy2bzaced5rdpz57e64sc7mdwjn3blicglhpialnrph2dlbufhf6iha63dmc\"}}") + fmt.Println(string(b)) + + require.Equal(t, exp, b) + + var um Message + require.NoError(t, json.Unmarshal(b, &um)) + + require.EqualValues(t, *m, um) +} + +func TestSignedMessageJson(t *testing.T) { + m := Message{ + To: builtin.StoragePowerActorAddr, + From: builtin.SystemActorAddr, + Nonce: 34, + Value: big.Zero(), + + GasLimit: 123, + GasFeeCap: big.NewInt(234), + GasPremium: big.NewInt(234), + + Method: 6, + Params: []byte("hai"), + } + + sm := &SignedMessage{ + Message: m, + Signature: crypto.Signature{}, + } + + b, err := json.Marshal(sm) + require.NoError(t, err) + + exp := []byte("{\"Message\":{\"Version\":0,\"To\":\"f04\",\"From\":\"f00\",\"Nonce\":34,\"Value\":\"0\",\"GasLimit\":123,\"GasFeeCap\":\"234\",\"GasPremium\":\"234\",\"Method\":6,\"Params\":\"aGFp\",\"CID\":{\"/\":\"bafy2bzaced5rdpz57e64sc7mdwjn3blicglhpialnrph2dlbufhf6iha63dmc\"}},\"Signature\":{\"Type\":0,\"Data\":null},\"CID\":{\"/\":\"bafy2bzacea5ainifngxj3rygaw2hppnyz2cw72x5pysqty2x6dxmjs5qg2uus\"}}") + fmt.Println(string(b)) + + require.Equal(t, exp, b) + + var um SignedMessage + require.NoError(t, json.Unmarshal(b, &um)) + + require.EqualValues(t, *sm, um) +} diff --git a/chain/types/signedmessage.go b/chain/types/signedmessage.go index 17d2f5d94..7532bea35 100644 --- a/chain/types/signedmessage.go +++ b/chain/types/signedmessage.go @@ -2,6 +2,7 @@ package types import ( "bytes" + "encoding/json" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/crypto" @@ -62,6 +63,20 @@ func (sm *SignedMessage) Serialize() ([]byte, error) { return buf.Bytes(), nil } +type smCid struct { + *RawSignedMessage + CID cid.Cid +} + +type RawSignedMessage SignedMessage + +func (sm *SignedMessage) MarshalJSON() ([]byte, error) { + return json.Marshal(&smCid{ + RawSignedMessage: (*RawSignedMessage)(sm), + CID: sm.Cid(), + }) +} + func (sm *SignedMessage) ChainLength() int { ser, err := sm.Serialize() if err != nil { From 61661fb1f06986d9fbfe25f31dfb15ea6743c9d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 12 Oct 2020 20:47:09 +0200 Subject: [PATCH 084/313] docsgen --- documentation/en/api-methods.md | 105 ++++++++++++++++++++++++++------ 1 file changed, 87 insertions(+), 18 deletions(-) diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index 50a6a160d..97d10b064 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -462,7 +462,10 @@ Response: "GasFeeCap": "0", "GasPremium": "0", "Method": 1, - "Params": "Ynl0ZSBhcnJheQ==" + "Params": "Ynl0ZSBhcnJheQ==", + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" + } } ``` @@ -1333,7 +1336,10 @@ Inputs: "GasFeeCap": "0", "GasPremium": "0", "Method": 1, - "Params": "Ynl0ZSBhcnJheQ==" + "Params": "Ynl0ZSBhcnJheQ==", + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" + } }, 9, [ @@ -1369,7 +1375,10 @@ Inputs: "GasFeeCap": "0", "GasPremium": "0", "Method": 1, - "Params": "Ynl0ZSBhcnJheQ==" + "Params": "Ynl0ZSBhcnJheQ==", + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" + } }, [ { @@ -1429,7 +1438,10 @@ Inputs: "GasFeeCap": "0", "GasPremium": "0", "Method": 1, - "Params": "Ynl0ZSBhcnJheQ==" + "Params": "Ynl0ZSBhcnJheQ==", + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" + } }, { "MaxFee": "0" @@ -1457,7 +1469,10 @@ Response: "GasFeeCap": "0", "GasPremium": "0", "Method": 1, - "Params": "Ynl0ZSBhcnJheQ==" + "Params": "Ynl0ZSBhcnJheQ==", + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" + } } ``` @@ -1741,11 +1756,17 @@ Inputs: "GasFeeCap": "0", "GasPremium": "0", "Method": 1, - "Params": "Ynl0ZSBhcnJheQ==" + "Params": "Ynl0ZSBhcnJheQ==", + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" + } }, "Signature": { "Type": 2, "Data": "Ynl0ZSBhcnJheQ==" + }, + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" } } ] @@ -1782,7 +1803,10 @@ Inputs: "GasFeeCap": "0", "GasPremium": "0", "Method": 1, - "Params": "Ynl0ZSBhcnJheQ==" + "Params": "Ynl0ZSBhcnJheQ==", + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" + } }, { "MaxFee": "0" @@ -1803,11 +1827,17 @@ Response: "GasFeeCap": "0", "GasPremium": "0", "Method": 1, - "Params": "Ynl0ZSBhcnJheQ==" + "Params": "Ynl0ZSBhcnJheQ==", + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" + } }, "Signature": { "Type": 2, "Data": "Ynl0ZSBhcnJheQ==" + }, + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" } } ``` @@ -1832,11 +1862,17 @@ Inputs: "GasFeeCap": "0", "GasPremium": "0", "Method": 1, - "Params": "Ynl0ZSBhcnJheQ==" + "Params": "Ynl0ZSBhcnJheQ==", + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" + } }, "Signature": { "Type": 2, "Data": "Ynl0ZSBhcnJheQ==" + }, + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" } } ] @@ -1916,11 +1952,17 @@ Response: "GasFeeCap": "0", "GasPremium": "0", "Method": 1, - "Params": "Ynl0ZSBhcnJheQ==" + "Params": "Ynl0ZSBhcnJheQ==", + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" + } }, "Signature": { "Type": 2, "Data": "Ynl0ZSBhcnJheQ==" + }, + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" } } } @@ -2997,7 +3039,10 @@ Inputs: "GasFeeCap": "0", "GasPremium": "0", "Method": 1, - "Params": "Ynl0ZSBhcnJheQ==" + "Params": "Ynl0ZSBhcnJheQ==", + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" + } }, [ { @@ -3023,7 +3068,10 @@ Response: "GasFeeCap": "0", "GasPremium": "0", "Method": 1, - "Params": "Ynl0ZSBhcnJheQ==" + "Params": "Ynl0ZSBhcnJheQ==", + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" + } }, "MsgRct": { "ExitCode": 0, @@ -3041,7 +3089,10 @@ Response: "GasFeeCap": "0", "GasPremium": "0", "Method": 1, - "Params": "Ynl0ZSBhcnJheQ==" + "Params": "Ynl0ZSBhcnJheQ==", + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" + } }, "MsgRct": { "ExitCode": 0, @@ -3296,7 +3347,10 @@ Inputs: "GasFeeCap": "0", "GasPremium": "0", "Method": 1, - "Params": "Ynl0ZSBhcnJheQ==" + "Params": "Ynl0ZSBhcnJheQ==", + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" + } }, [ { @@ -4042,7 +4096,10 @@ Response: "GasFeeCap": "0", "GasPremium": "0", "Method": 1, - "Params": "Ynl0ZSBhcnJheQ==" + "Params": "Ynl0ZSBhcnJheQ==", + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" + } }, "MsgRct": { "ExitCode": 0, @@ -4060,7 +4117,10 @@ Response: "GasFeeCap": "0", "GasPremium": "0", "Method": 1, - "Params": "Ynl0ZSBhcnJheQ==" + "Params": "Ynl0ZSBhcnJheQ==", + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" + } }, "MsgRct": { "ExitCode": 0, @@ -4832,7 +4892,10 @@ Inputs: "GasFeeCap": "0", "GasPremium": "0", "Method": 1, - "Params": "Ynl0ZSBhcnJheQ==" + "Params": "Ynl0ZSBhcnJheQ==", + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" + } } ] ``` @@ -4850,11 +4913,17 @@ Response: "GasFeeCap": "0", "GasPremium": "0", "Method": 1, - "Params": "Ynl0ZSBhcnJheQ==" + "Params": "Ynl0ZSBhcnJheQ==", + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" + } }, "Signature": { "Type": 2, "Data": "Ynl0ZSBhcnJheQ==" + }, + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" } } ``` From 96e1dfd8d7f5778b5d534f3b29bac2c8a50f0118 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Sun, 11 Oct 2020 18:17:28 -0400 Subject: [PATCH 085/313] Add an endpoint for precise circulating supply --- api/api_full.go | 8 ++- api/apistruct/struct.go | 9 ++- chain/actors/builtin/builtin.go | 9 ++- chain/actors/builtin/miner/miner.go | 5 ++ chain/actors/builtin/miner/v0.go | 12 +++- chain/actors/builtin/miner/v2.go | 12 +++- chain/stmgr/call.go | 4 +- chain/stmgr/forks.go | 26 +++---- chain/stmgr/stmgr.go | 103 ++++++++++++++++++++++++++-- chain/stmgr/utils.go | 2 +- cli/state.go | 37 +++++++--- cmd/lotus-chainwatch/syncer/sync.go | 2 +- cmd/lotus-shed/balances.go | 2 +- cmd/tvx/extract.go | 2 +- documentation/en/api-methods.md | 47 ++++++++++--- node/impl/full/state.go | 21 ++++-- 16 files changed, 236 insertions(+), 65 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index f42c8d03f..b7cdf9524 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -416,8 +416,12 @@ type FullNode interface { // can issue. It takes the deal size and verified status as parameters. StateDealProviderCollateralBounds(context.Context, abi.PaddedPieceSize, bool, types.TipSetKey) (DealCollateralBounds, error) - // StateCirculatingSupply returns the circulating supply of Filecoin at the given tipset - StateCirculatingSupply(context.Context, types.TipSetKey) (CirculatingSupply, error) + // StateCirculatingSupply returns the exact circulating supply of Filecoin at the given tipset. + // This is not used anywhere in the protocol itself, and is only for external consumption. + StateCirculatingSupply(context.Context, types.TipSetKey) (abi.TokenAmount, error) + // StateVMCirculatingSupply returns an approximation of the circulating supply of Filecoin at the given tipset. + // This is the value reported by the runtime interface to actors code. + StateVMCirculatingSupply(context.Context, types.TipSetKey) (CirculatingSupply, error) // StateNetworkVersion returns the network version at the given tipset StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error) diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index cef335939..a938653ce 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -210,7 +210,8 @@ type FullNodeStruct struct { StateVerifiedClientStatus func(context.Context, address.Address, types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` StateVerifiedRegistryRootKey func(ctx context.Context, tsk types.TipSetKey) (address.Address, error) `perm:"read"` StateDealProviderCollateralBounds func(context.Context, abi.PaddedPieceSize, bool, types.TipSetKey) (api.DealCollateralBounds, error) `perm:"read"` - StateCirculatingSupply func(context.Context, types.TipSetKey) (api.CirculatingSupply, error) `perm:"read"` + StateCirculatingSupply func(context.Context, types.TipSetKey) (abi.TokenAmount, error) `perm:"read"` + StateVMCirculatingSupply func(context.Context, types.TipSetKey) (api.CirculatingSupply, error) `perm:"read"` StateNetworkVersion func(context.Context, types.TipSetKey) (stnetwork.Version, error) `perm:"read"` MsigGetAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"` @@ -963,10 +964,14 @@ func (c *FullNodeStruct) StateDealProviderCollateralBounds(ctx context.Context, return c.Internal.StateDealProviderCollateralBounds(ctx, size, verified, tsk) } -func (c *FullNodeStruct) StateCirculatingSupply(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) { +func (c *FullNodeStruct) StateCirculatingSupply(ctx context.Context, tsk types.TipSetKey) (abi.TokenAmount, error) { return c.Internal.StateCirculatingSupply(ctx, tsk) } +func (c *FullNodeStruct) StateVMCirculatingSupply(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) { + return c.Internal.StateVMCirculatingSupply(ctx, tsk) +} + func (c *FullNodeStruct) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (stnetwork.Version, error) { return c.Internal.StateNetworkVersion(ctx, tsk) } diff --git a/chain/actors/builtin/builtin.go b/chain/actors/builtin/builtin.go index cb24a2c33..350b3a9a6 100644 --- a/chain/actors/builtin/builtin.go +++ b/chain/actors/builtin/builtin.go @@ -2,25 +2,28 @@ package builtin import ( "github.com/filecoin-project/go-address" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + smoothing2 "github.com/filecoin-project/specs-actors/v2/actors/util/smoothing" "github.com/ipfs/go-cid" "golang.org/x/xerrors" + builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" + "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/cbor" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/types" - builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" proof0 "github.com/filecoin-project/specs-actors/actors/runtime/proof" smoothing0 "github.com/filecoin-project/specs-actors/actors/util/smoothing" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" - smoothing2 "github.com/filecoin-project/specs-actors/v2/actors/util/smoothing" ) var SystemActorAddr = builtin0.SystemActorAddr var BurntFundsActorAddr = builtin0.BurntFundsActorAddr +var CronActorAddr = builtin0.CronActorAddr +var SaftAddress = makeAddress("t0122") var ReserveAddress = makeAddress("t090") var RootVerifierAddress = makeAddress("t080") diff --git a/chain/actors/builtin/miner/miner.go b/chain/actors/builtin/miner/miner.go index 281068827..3cca39326 100644 --- a/chain/actors/builtin/miner/miner.go +++ b/chain/actors/builtin/miner/miner.go @@ -1,6 +1,7 @@ package miner import ( + "github.com/filecoin-project/go-state-types/big" "github.com/ipfs/go-cid" "github.com/libp2p/go-libp2p-core/peer" cbg "github.com/whyrusleeping/cbor-gen" @@ -196,3 +197,7 @@ type LockedFunds struct { InitialPledgeRequirement abi.TokenAmount PreCommitDeposits abi.TokenAmount } + +func (lf LockedFunds) TotalLockedFunds() abi.TokenAmount { + return big.Add(lf.VestingFunds, big.Add(lf.InitialPledgeRequirement, lf.PreCommitDeposits)) +} diff --git a/chain/actors/builtin/miner/v0.go b/chain/actors/builtin/miner/v0.go index 7e71c7611..14718d002 100644 --- a/chain/actors/builtin/miner/v0.go +++ b/chain/actors/builtin/miner/v0.go @@ -47,8 +47,16 @@ type partition0 struct { store adt.Store } -func (s *state0) AvailableBalance(bal abi.TokenAmount) (abi.TokenAmount, error) { - return s.GetAvailableBalance(bal), nil +func (s *state0) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmount, err error) { + defer func() { + if r := recover(); r != nil { + err = xerrors.Errorf("failed to get available balance: %w", r) + available = abi.NewTokenAmount(0) + } + }() + // this panics if the miner doesnt have enough funds to cover their locked pledge + available = s.GetAvailableBalance(bal) + return available, err } func (s *state0) VestedFunds(epoch abi.ChainEpoch) (abi.TokenAmount, error) { diff --git a/chain/actors/builtin/miner/v2.go b/chain/actors/builtin/miner/v2.go index eed82257f..9e599f891 100644 --- a/chain/actors/builtin/miner/v2.go +++ b/chain/actors/builtin/miner/v2.go @@ -45,8 +45,16 @@ type partition2 struct { store adt.Store } -func (s *state2) AvailableBalance(bal abi.TokenAmount) (abi.TokenAmount, error) { - return s.GetAvailableBalance(bal) +func (s *state2) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmount, err error) { + defer func() { + if r := recover(); r != nil { + err = xerrors.Errorf("failed to get available balance: %w", r) + available = abi.NewTokenAmount(0) + } + }() + // this panics if the miner doesnt have enough funds to cover their locked pledge + available, err = s.GetAvailableBalance(bal) + return available, err } func (s *state2) VestedFunds(epoch abi.ChainEpoch) (abi.TokenAmount, error) { diff --git a/chain/stmgr/call.go b/chain/stmgr/call.go index df3bfa357..8d0f6f6c1 100644 --- a/chain/stmgr/call.go +++ b/chain/stmgr/call.go @@ -61,7 +61,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types. Rand: store.NewChainRand(sm.cs, ts.Cids()), Bstore: sm.cs.Blockstore(), Syscalls: sm.cs.VMSys(), - CircSupplyCalc: sm.GetCirculatingSupply, + CircSupplyCalc: sm.GetVMCirculatingSupply, NtwkVersion: sm.GetNtwkVersion, BaseFee: types.NewInt(0), } @@ -174,7 +174,7 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri Rand: r, Bstore: sm.cs.Blockstore(), Syscalls: sm.cs.VMSys(), - CircSupplyCalc: sm.GetCirculatingSupply, + CircSupplyCalc: sm.GetVMCirculatingSupply, NtwkVersion: sm.GetNtwkVersion, BaseFee: ts.Blocks()[0].ParentBaseFee, } diff --git a/chain/stmgr/forks.go b/chain/stmgr/forks.go index 6ebe8a5b9..7f2b57546 100644 --- a/chain/stmgr/forks.go +++ b/chain/stmgr/forks.go @@ -265,11 +265,6 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal return cid.Undef, xerrors.Errorf("loading state tree failed: %w", err) } - ReserveAddress, err := address.NewFromString("t090") - if err != nil { - return cid.Undef, xerrors.Errorf("failed to parse reserve address: %w", err) - } - tree, err := sm.StateTree(root) if err != nil { return cid.Undef, xerrors.Errorf("getting state tree: %w", err) @@ -295,7 +290,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal if !sysAcc { transfers = append(transfers, transfer{ From: addr, - To: ReserveAddress, + To: builtin.ReserveAddress, Amt: act.Balance, }) } @@ -319,7 +314,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal transfers = append(transfers, transfer{ From: addr, - To: ReserveAddress, + To: builtin.ReserveAddress, Amt: available, }) } @@ -370,7 +365,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal nbalance := big.Min(prevBalance, AccountCap) if nbalance.Sign() != 0 { transfersBack = append(transfersBack, transfer{ - From: ReserveAddress, + From: builtin.ReserveAddress, To: addr, Amt: nbalance, }) @@ -397,7 +392,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal mfunds := minerFundsAlloc(power, totalPower) transfersBack = append(transfersBack, transfer{ - From: ReserveAddress, + From: builtin.ReserveAddress, To: minfo.Worker, Amt: mfunds, }) @@ -417,7 +412,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal if lbsectors.Length() > 0 { transfersBack = append(transfersBack, transfer{ - From: ReserveAddress, + From: builtin.ReserveAddress, To: minfo.Worker, Amt: BaseMinerBalance, }) @@ -444,7 +439,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal if err != nil { return cid.Undef, xerrors.Errorf("failed to load burnt funds actor: %w", err) } - if err := doTransfer(cb, tree, builtin0.BurntFundsActorAddr, ReserveAddress, burntAct.Balance); err != nil { + if err := doTransfer(cb, tree, builtin0.BurntFundsActorAddr, builtin.ReserveAddress, burntAct.Balance); err != nil { return cid.Undef, xerrors.Errorf("failed to unburn funds: %w", err) } @@ -460,7 +455,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal } difference := types.BigSub(DesiredReimbursementBalance, reimb.Balance) - if err := doTransfer(cb, tree, ReserveAddress, reimbAddr, difference); err != nil { + if err := doTransfer(cb, tree, builtin.ReserveAddress, reimbAddr, difference); err != nil { return cid.Undef, xerrors.Errorf("failed to top up reimbursement account: %w", err) } @@ -545,12 +540,7 @@ func UpgradeRefuel(ctx context.Context, sm *StateManager, cb ExecCallback, root return cid.Undef, xerrors.Errorf("getting state tree: %w", err) } - addr, err := address.NewFromString("t0122") - if err != nil { - return cid.Undef, xerrors.Errorf("getting address: %w", err) - } - - err = resetMultisigVesting(ctx, store, tree, addr, 0, 0, big.Zero()) + err = resetMultisigVesting(ctx, store, tree, builtin.SaftAddress, 0, 0, big.Zero()) if err != nil { return cid.Undef, xerrors.Errorf("tweaking msig vesting: %w", err) } diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index d6b6f4360..b470cfe83 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -7,6 +7,11 @@ import ( "sync" "github.com/filecoin-project/lotus/chain/actors/builtin" + "github.com/filecoin-project/lotus/chain/actors/builtin/verifreg" + + _init "github.com/filecoin-project/lotus/chain/actors/builtin/init" + + "github.com/filecoin-project/lotus/chain/actors/builtin/miner" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig" @@ -229,7 +234,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp Rand: r, Bstore: sm.cs.Blockstore(), Syscalls: sm.cs.VMSys(), - CircSupplyCalc: sm.GetCirculatingSupply, + CircSupplyCalc: sm.GetVMCirculatingSupply, NtwkVersion: sm.GetNtwkVersion, BaseFee: baseFee, } @@ -1294,7 +1299,16 @@ func GetFilBurnt(ctx context.Context, st *state.StateTree) (abi.TokenAmount, err return burnt.Balance, nil } -func (sm *StateManager) GetCirculatingSupplyDetailed(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (api.CirculatingSupply, error) { +func (sm *StateManager) GetVMCirculatingSupply(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (abi.TokenAmount, error) { + cs, err := sm.GetVMCirculatingSupplyDetailed(ctx, height, st) + if err != nil { + return types.EmptyInt, err + } + + return cs.FilCirculating, err +} + +func (sm *StateManager) GetVMCirculatingSupplyDetailed(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (api.CirculatingSupply, error) { sm.genesisMsigLk.Lock() defer sm.genesisMsigLk.Unlock() if sm.preIgnitionGenInfos == nil { @@ -1357,12 +1371,91 @@ func (sm *StateManager) GetCirculatingSupplyDetailed(ctx context.Context, height } func (sm *StateManager) GetCirculatingSupply(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (abi.TokenAmount, error) { - csi, err := sm.GetCirculatingSupplyDetailed(ctx, height, st) + circ := big.Zero() + unCirc := big.Zero() + err := st.ForEach(func(a address.Address, actor *types.Actor) error { + switch { + case actor.Balance.IsZero(): + // Do nothing for zero-balance actors + break + case a == _init.Address || + a == reward.Address || + a == verifreg.Address || + // The power actor itself should never receive funds + a == power.Address || + a == builtin.SystemActorAddr || + a == builtin.CronActorAddr || + a == builtin.BurntFundsActorAddr || + a == builtin.SaftAddress || + a == builtin.ReserveAddress: + + unCirc = big.Add(unCirc, actor.Balance) + + case a == market.Address: + mst, err := market.Load(sm.cs.Store(ctx), actor) + if err != nil { + return err + } + + lb, err := mst.TotalLocked() + if err != nil { + return err + } + + circ = big.Add(circ, big.Sub(actor.Balance, lb)) + unCirc = big.Add(unCirc, lb) + + case builtin.IsAccountActor(actor.Code) || builtin.IsPaymentChannelActor(actor.Code): + circ = big.Add(circ, actor.Balance) + + case builtin.IsStorageMinerActor(actor.Code): + mst, err := miner.Load(sm.cs.Store(ctx), actor) + if err != nil { + return err + } + + ab, err := mst.AvailableBalance(actor.Balance) + + if err == nil { + circ = big.Add(circ, ab) + unCirc = big.Add(unCirc, big.Sub(actor.Balance, ab)) + } else { + // Assume any error is because the miner state is "broken" (lower actor balance than locked funds) + // In this case, the actor's entire balance is considered "uncirculating" + unCirc = big.Add(unCirc, actor.Balance) + } + + case builtin.IsMultisigActor(actor.Code): + mst, err := multisig.Load(sm.cs.Store(ctx), actor) + if err != nil { + return err + } + + lb, err := mst.LockedBalance(height) + if err != nil { + return err + } + + ab := big.Sub(actor.Balance, lb) + circ = big.Add(circ, big.Max(ab, big.Zero())) + unCirc = big.Add(unCirc, big.Min(actor.Balance, lb)) + default: + return xerrors.Errorf("unexpected actor: %s", a) + } + + return nil + }) + if err != nil { - return big.Zero(), err + return types.EmptyInt, err } - return csi.FilCirculating, nil + total := big.Add(circ, unCirc) + if !total.Equals(types.TotalFilecoinInt) { + return types.EmptyInt, xerrors.Errorf("total filecoin didn't add to expected amount: %s != %s", total, types.TotalFilecoinInt) + } + + return circ, nil } func (sm *StateManager) GetNtwkVersion(ctx context.Context, height abi.ChainEpoch) network.Version { diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index c0f0c4d2f..cbc78ca5b 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -383,7 +383,7 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch, Rand: r, Bstore: sm.cs.Blockstore(), Syscalls: sm.cs.VMSys(), - CircSupplyCalc: sm.GetCirculatingSupply, + CircSupplyCalc: sm.GetVMCirculatingSupply, NtwkVersion: sm.GetNtwkVersion, BaseFee: ts.Blocks()[0].ParentBaseFee, } diff --git a/cli/state.go b/cli/state.go index 453cde77f..5acdf940f 100644 --- a/cli/state.go +++ b/cli/state.go @@ -1688,7 +1688,14 @@ func parseParamsForMethod(act cid.Cid, method uint64, args []string) ([]byte, er var stateCircSupplyCmd = &cli.Command{ Name: "circulating-supply", - Usage: "Get the current circulating supply of filecoin", + Usage: "Get the exact current circulating supply of Filecoin", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "vm-supply", + Usage: "calculates the approximation of the circulating supply used internally by the VM (instead of the exact amount)", + Value: false, + }, + }, Action: func(cctx *cli.Context) error { api, closer, err := GetFullNodeAPI(cctx) if err != nil { @@ -1703,16 +1710,26 @@ var stateCircSupplyCmd = &cli.Command{ return err } - circ, err := api.StateCirculatingSupply(ctx, ts.Key()) - if err != nil { - return err - } + if cctx.IsSet("vm-supply") { + circ, err := api.StateVMCirculatingSupply(ctx, ts.Key()) + if err != nil { + return err + } - fmt.Println("Circulating supply: ", types.FIL(circ.FilCirculating)) - fmt.Println("Mined: ", types.FIL(circ.FilMined)) - fmt.Println("Vested: ", types.FIL(circ.FilVested)) - fmt.Println("Burnt: ", types.FIL(circ.FilBurnt)) - fmt.Println("Locked: ", types.FIL(circ.FilLocked)) + fmt.Println("Circulating supply: ", types.FIL(circ.FilCirculating)) + fmt.Println("Mined: ", types.FIL(circ.FilMined)) + fmt.Println("Vested: ", types.FIL(circ.FilVested)) + fmt.Println("Burnt: ", types.FIL(circ.FilBurnt)) + fmt.Println("Locked: ", types.FIL(circ.FilLocked)) + } else { + circ, err := api.StateCirculatingSupply(ctx, ts.Key()) + if err != nil { + return err + } + + fmt.Println("Exact circulating supply: ", types.FIL(circ)) + return nil + } return nil }, diff --git a/cmd/lotus-chainwatch/syncer/sync.go b/cmd/lotus-chainwatch/syncer/sync.go index 609b71088..d0931a978 100644 --- a/cmd/lotus-chainwatch/syncer/sync.go +++ b/cmd/lotus-chainwatch/syncer/sync.go @@ -316,7 +316,7 @@ limit 1 } func (s *Syncer) storeCirculatingSupply(ctx context.Context, tipset *types.TipSet) error { - supply, err := s.node.StateCirculatingSupply(ctx, tipset.Key()) + supply, err := s.node.StateVMCirculatingSupply(ctx, tipset.Key()) if err != nil { return err } diff --git a/cmd/lotus-shed/balances.go b/cmd/lotus-shed/balances.go index c2099bb2d..dfdaf9fa9 100644 --- a/cmd/lotus-shed/balances.go +++ b/cmd/lotus-shed/balances.go @@ -372,7 +372,7 @@ var chainPledgeCmd = &cli.Command{ pledgeCollateral = c } - circ, err := sm.GetCirculatingSupplyDetailed(ctx, abi.ChainEpoch(epoch), state) + circ, err := sm.GetVMCirculatingSupplyDetailed(ctx, abi.ChainEpoch(epoch), state) if err != nil { return err } diff --git a/cmd/tvx/extract.go b/cmd/tvx/extract.go index b0ed574df..cc4494d0f 100644 --- a/cmd/tvx/extract.go +++ b/cmd/tvx/extract.go @@ -135,7 +135,7 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error { } // get the circulating supply before the message was executed. - circSupplyDetail, err := fapi.StateCirculatingSupply(ctx, incTs.Key()) + circSupplyDetail, err := fapi.StateVMCirculatingSupply(ctx, incTs.Key()) if err != nil { return fmt.Errorf("failed while fetching circulating supply: %w", err) } diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index 50a6a160d..f5dfcf815 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -165,6 +165,7 @@ * [StateSectorGetInfo](#StateSectorGetInfo) * [StateSectorPartition](#StateSectorPartition) * [StateSectorPreCommitInfo](#StateSectorPreCommitInfo) + * [StateVMCirculatingSupply](#StateVMCirculatingSupply) * [StateVerifiedClientStatus](#StateVerifiedClientStatus) * [StateVerifiedRegistryRootKey](#StateVerifiedRegistryRootKey) * [StateVerifierStatus](#StateVerifierStatus) @@ -3094,7 +3095,8 @@ Response: ``` ### StateCirculatingSupply -StateCirculatingSupply returns the circulating supply of Filecoin at the given tipset +StateCirculatingSupply returns the exact circulating supply of Filecoin at the given tipset. +This is not used anywhere in the protocol itself, and is only for external consumption. Perms: read @@ -3113,16 +3115,7 @@ Inputs: ] ``` -Response: -```json -{ - "FilVested": "0", - "FilMined": "0", - "FilBurnt": "0", - "FilLocked": "0", - "FilCirculating": "0" -} -``` +Response: `"0"` ### StateCompute StateCompute is a flexible command that applies the given messages on the given tipset. @@ -4265,6 +4258,38 @@ Response: } ``` +### StateVMCirculatingSupply +StateVMCirculatingSupply returns an approximation of the circulating supply of Filecoin at the given tipset. +This is the value reported by the runtime interface to actors code. + + +Perms: read + +Inputs: +```json +[ + [ + { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + { + "/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve" + } + ] +] +``` + +Response: +```json +{ + "FilVested": "0", + "FilMined": "0", + "FilBurnt": "0", + "FilLocked": "0", + "FilCirculating": "0" +} +``` + ### StateVerifiedClientStatus StateVerifiedClientStatus returns the data cap for the given address. Returns nil if there is no entry in the data cap table for the diff --git a/node/impl/full/state.go b/node/impl/full/state.go index db91433aa..62636e4fa 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -1049,7 +1049,7 @@ func (a *StateAPI) StateMinerInitialPledgeCollateral(ctx context.Context, maddr return types.EmptyInt, xerrors.Errorf("loading reward actor state: %w", err) } - circSupply, err := a.StateCirculatingSupply(ctx, ts.Key()) + circSupply, err := a.StateVMCirculatingSupply(ctx, ts.Key()) if err != nil { return big.Zero(), xerrors.Errorf("getting circulating supply: %w", err) } @@ -1203,7 +1203,7 @@ func (a *StateAPI) StateDealProviderCollateralBounds(ctx context.Context, size a return api.DealCollateralBounds{}, xerrors.Errorf("failed to load reward actor state: %w", err) } - circ, err := a.StateCirculatingSupply(ctx, ts.Key()) + circ, err := a.StateVMCirculatingSupply(ctx, ts.Key()) if err != nil { return api.DealCollateralBounds{}, xerrors.Errorf("getting total circulating supply: %w", err) } @@ -1231,7 +1231,20 @@ func (a *StateAPI) StateDealProviderCollateralBounds(ctx context.Context, size a }, nil } -func (a *StateAPI) StateCirculatingSupply(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) { +func (a *StateAPI) StateCirculatingSupply(ctx context.Context, tsk types.TipSetKey) (abi.TokenAmount, error) { + ts, err := a.Chain.GetTipSetFromKey(tsk) + if err != nil { + return types.EmptyInt, xerrors.Errorf("loading tipset %s: %w", tsk, err) + } + + sTree, err := a.stateForTs(ctx, ts) + if err != nil { + return types.EmptyInt, err + } + return a.StateManager.GetCirculatingSupply(ctx, ts.Height(), sTree) +} + +func (a *StateAPI) StateVMCirculatingSupply(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) { ts, err := a.Chain.GetTipSetFromKey(tsk) if err != nil { return api.CirculatingSupply{}, xerrors.Errorf("loading tipset %s: %w", tsk, err) @@ -1241,7 +1254,7 @@ func (a *StateAPI) StateCirculatingSupply(ctx context.Context, tsk types.TipSetK if err != nil { return api.CirculatingSupply{}, err } - return a.StateManager.GetCirculatingSupplyDetailed(ctx, ts.Height(), sTree) + return a.StateManager.GetVMCirculatingSupplyDetailed(ctx, ts.Height(), sTree) } func (a *StateAPI) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (network.Version, error) { From 83624a8858d1983a28e0cd523c5ec353a5bbdaee Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Mon, 12 Oct 2020 16:41:27 -0400 Subject: [PATCH 086/313] Rename StateVMCirculatingSupply to StateVMCirculatingSupplyInternal --- api/api_full.go | 4 ++-- api/apistruct/struct.go | 6 +++--- cli/state.go | 2 +- cmd/lotus-chainwatch/syncer/sync.go | 2 +- cmd/tvx/extract.go | 2 +- documentation/en/api-methods.md | 6 +++--- node/impl/full/state.go | 6 +++--- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index b7cdf9524..657e945ca 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -419,9 +419,9 @@ type FullNode interface { // StateCirculatingSupply returns the exact circulating supply of Filecoin at the given tipset. // This is not used anywhere in the protocol itself, and is only for external consumption. StateCirculatingSupply(context.Context, types.TipSetKey) (abi.TokenAmount, error) - // StateVMCirculatingSupply returns an approximation of the circulating supply of Filecoin at the given tipset. + // StateVMCirculatingSupplyInternal returns an approximation of the circulating supply of Filecoin at the given tipset. // This is the value reported by the runtime interface to actors code. - StateVMCirculatingSupply(context.Context, types.TipSetKey) (CirculatingSupply, error) + StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (CirculatingSupply, error) // StateNetworkVersion returns the network version at the given tipset StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error) diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index a938653ce..7896d566e 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -211,7 +211,7 @@ type FullNodeStruct struct { StateVerifiedRegistryRootKey func(ctx context.Context, tsk types.TipSetKey) (address.Address, error) `perm:"read"` StateDealProviderCollateralBounds func(context.Context, abi.PaddedPieceSize, bool, types.TipSetKey) (api.DealCollateralBounds, error) `perm:"read"` StateCirculatingSupply func(context.Context, types.TipSetKey) (abi.TokenAmount, error) `perm:"read"` - StateVMCirculatingSupply func(context.Context, types.TipSetKey) (api.CirculatingSupply, error) `perm:"read"` + StateVMCirculatingSupplyInternal func(context.Context, types.TipSetKey) (api.CirculatingSupply, error) `perm:"read"` StateNetworkVersion func(context.Context, types.TipSetKey) (stnetwork.Version, error) `perm:"read"` MsigGetAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"` @@ -968,8 +968,8 @@ func (c *FullNodeStruct) StateCirculatingSupply(ctx context.Context, tsk types.T return c.Internal.StateCirculatingSupply(ctx, tsk) } -func (c *FullNodeStruct) StateVMCirculatingSupply(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) { - return c.Internal.StateVMCirculatingSupply(ctx, tsk) +func (c *FullNodeStruct) StateVMCirculatingSupplyInternal(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) { + return c.Internal.StateVMCirculatingSupplyInternal(ctx, tsk) } func (c *FullNodeStruct) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (stnetwork.Version, error) { diff --git a/cli/state.go b/cli/state.go index 5acdf940f..1e7e24ddb 100644 --- a/cli/state.go +++ b/cli/state.go @@ -1711,7 +1711,7 @@ var stateCircSupplyCmd = &cli.Command{ } if cctx.IsSet("vm-supply") { - circ, err := api.StateVMCirculatingSupply(ctx, ts.Key()) + circ, err := api.StateVMCirculatingSupplyInternal(ctx, ts.Key()) if err != nil { return err } diff --git a/cmd/lotus-chainwatch/syncer/sync.go b/cmd/lotus-chainwatch/syncer/sync.go index d0931a978..37af9cce0 100644 --- a/cmd/lotus-chainwatch/syncer/sync.go +++ b/cmd/lotus-chainwatch/syncer/sync.go @@ -316,7 +316,7 @@ limit 1 } func (s *Syncer) storeCirculatingSupply(ctx context.Context, tipset *types.TipSet) error { - supply, err := s.node.StateVMCirculatingSupply(ctx, tipset.Key()) + supply, err := s.node.StateVMCirculatingSupplyInternal(ctx, tipset.Key()) if err != nil { return err } diff --git a/cmd/tvx/extract.go b/cmd/tvx/extract.go index cc4494d0f..4bb391af6 100644 --- a/cmd/tvx/extract.go +++ b/cmd/tvx/extract.go @@ -135,7 +135,7 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error { } // get the circulating supply before the message was executed. - circSupplyDetail, err := fapi.StateVMCirculatingSupply(ctx, incTs.Key()) + circSupplyDetail, err := fapi.StateVMCirculatingSupplyInternal(ctx, incTs.Key()) if err != nil { return fmt.Errorf("failed while fetching circulating supply: %w", err) } diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index f5dfcf815..cbec60c10 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -165,7 +165,7 @@ * [StateSectorGetInfo](#StateSectorGetInfo) * [StateSectorPartition](#StateSectorPartition) * [StateSectorPreCommitInfo](#StateSectorPreCommitInfo) - * [StateVMCirculatingSupply](#StateVMCirculatingSupply) + * [StateVMCirculatingSupplyInternal](#StateVMCirculatingSupplyInternal) * [StateVerifiedClientStatus](#StateVerifiedClientStatus) * [StateVerifiedRegistryRootKey](#StateVerifiedRegistryRootKey) * [StateVerifierStatus](#StateVerifierStatus) @@ -4258,8 +4258,8 @@ Response: } ``` -### StateVMCirculatingSupply -StateVMCirculatingSupply returns an approximation of the circulating supply of Filecoin at the given tipset. +### StateVMCirculatingSupplyInternal +StateVMCirculatingSupplyInternal returns an approximation of the circulating supply of Filecoin at the given tipset. This is the value reported by the runtime interface to actors code. diff --git a/node/impl/full/state.go b/node/impl/full/state.go index 62636e4fa..1c39b59da 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -1049,7 +1049,7 @@ func (a *StateAPI) StateMinerInitialPledgeCollateral(ctx context.Context, maddr return types.EmptyInt, xerrors.Errorf("loading reward actor state: %w", err) } - circSupply, err := a.StateVMCirculatingSupply(ctx, ts.Key()) + circSupply, err := a.StateVMCirculatingSupplyInternal(ctx, ts.Key()) if err != nil { return big.Zero(), xerrors.Errorf("getting circulating supply: %w", err) } @@ -1203,7 +1203,7 @@ func (a *StateAPI) StateDealProviderCollateralBounds(ctx context.Context, size a return api.DealCollateralBounds{}, xerrors.Errorf("failed to load reward actor state: %w", err) } - circ, err := a.StateVMCirculatingSupply(ctx, ts.Key()) + circ, err := a.StateVMCirculatingSupplyInternal(ctx, ts.Key()) if err != nil { return api.DealCollateralBounds{}, xerrors.Errorf("getting total circulating supply: %w", err) } @@ -1244,7 +1244,7 @@ func (a *StateAPI) StateCirculatingSupply(ctx context.Context, tsk types.TipSetK return a.StateManager.GetCirculatingSupply(ctx, ts.Height(), sTree) } -func (a *StateAPI) StateVMCirculatingSupply(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) { +func (a *StateAPI) StateVMCirculatingSupplyInternal(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) { ts, err := a.Chain.GetTipSetFromKey(tsk) if err != nil { return api.CirculatingSupply{}, xerrors.Errorf("loading tipset %s: %w", tsk, err) From 49155ace62ab22ea13202ce60c755ad266d04581 Mon Sep 17 00:00:00 2001 From: Ingar Shu Date: Mon, 12 Oct 2020 13:45:37 -0700 Subject: [PATCH 087/313] Use seal-duration in calculating the earliest StartEpoch that we will consider (#4337) --- node/modules/storageminer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 9011c4821..4dbce4cdb 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -473,7 +473,7 @@ func BasicDealFilter(user dtypes.DealFilter) func(onlineOk dtypes.ConsiderOnline // Reject if it's more than 7 days in the future // TODO: read from cfg - maxStartEpoch := ht + abi.ChainEpoch(7*builtin.EpochsInDay) + maxStartEpoch := earliest + abi.ChainEpoch(7*builtin.EpochsInDay) if deal.Proposal.StartEpoch > maxStartEpoch { return false, fmt.Sprintf("deal start epoch is too far in the future: %s > %s", deal.Proposal.StartEpoch, maxStartEpoch), nil } From be74a137365bc250b592718aa2a7436e1c25eae0 Mon Sep 17 00:00:00 2001 From: Travis Person Date: Mon, 12 Oct 2020 21:41:48 +0000 Subject: [PATCH 088/313] lotus-pcr: ignore all other market messages --- cmd/lotus-pcr/main.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/lotus-pcr/main.go b/cmd/lotus-pcr/main.go index 5491e4af2..f88a0a9dc 100644 --- a/cmd/lotus-pcr/main.go +++ b/cmd/lotus-pcr/main.go @@ -884,6 +884,8 @@ func (r *refunder) processTipsetStorageMarketActor(ctx context.Context, tipset * } refundValue = types.BigMul(types.NewInt(uint64(recp.GasUsed)), tipset.Blocks()[0].ParentBaseFee) + default: + return false, messageMethod, types.NewInt(0), nil } return true, messageMethod, refundValue, nil From 9b4cac961229ca4a9396a10862c9a80470c67466 Mon Sep 17 00:00:00 2001 From: Lucas Molas Date: Mon, 12 Oct 2020 21:14:16 -0300 Subject: [PATCH 089/313] fix(sync state): set state height to actual tipset height --- chain/sync.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chain/sync.go b/chain/sync.go index 9040e3f05..dd83bf319 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -1478,7 +1478,7 @@ func (syncer *Syncer) syncFork(ctx context.Context, incoming *types.TipSet, know func (syncer *Syncer) syncMessagesAndCheckState(ctx context.Context, headers []*types.TipSet) error { ss := extractSyncState(ctx) - ss.SetHeight(0) + ss.SetHeight(headers[len(headers)-1].Height()) return syncer.iterFullTipsets(ctx, headers, func(ctx context.Context, fts *store.FullTipSet) error { log.Debugw("validating tipset", "height", fts.TipSet().Height(), "size", len(fts.TipSet().Cids())) From 07d0b6762812881fc85295aa5a1b45b14cf063ac Mon Sep 17 00:00:00 2001 From: zgfzgf <1901989065@qq.com> Date: Tue, 13 Oct 2020 10:46:41 +0800 Subject: [PATCH 090/313] optimize code use ts.Cids --- chain/stmgr/stmgr.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index b470cfe83..b381b2d59 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -435,12 +435,7 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, ts *types.TipSet parentEpoch = parent.Height } - cids := make([]cid.Cid, len(blks)) - for i, v := range blks { - cids[i] = v.Cid() - } - - r := store.NewChainRand(sm.cs, cids) + r := store.NewChainRand(sm.cs, ts.Cids()) blkmsgs, err := sm.cs.BlockMsgsForTipset(ts) if err != nil { From 4edebcec2b9e5c13b69743d812db604bd05398da Mon Sep 17 00:00:00 2001 From: hannahhoward Date: Tue, 13 Oct 2020 03:37:00 -0700 Subject: [PATCH 091/313] feat(markets): update markets 0.9.0 and add data transfer restart command --- api/api_full.go | 3 ++ api/apistruct/struct.go | 6 ++++ cli/client.go | 62 +++++++++++++++++++++++++++++++++ documentation/en/api-methods.md | 18 ++++++++++ go.mod | 6 ++-- go.sum | 16 ++++----- node/impl/client/client.go | 10 +++++- node/modules/client.go | 1 + node/modules/storageminer.go | 1 + 9 files changed, 110 insertions(+), 13 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index 657e945ca..5b1316730 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -5,6 +5,7 @@ import ( "fmt" "time" + datatransfer "github.com/filecoin-project/go-data-transfer" "github.com/filecoin-project/go-state-types/network" "github.com/ipfs/go-cid" @@ -298,6 +299,8 @@ type FullNode interface { // ClientListTransfers returns the status of all ongoing transfers of data ClientListDataTransfers(ctx context.Context) ([]DataTransferChannel, error) ClientDataTransferUpdates(ctx context.Context) (<-chan DataTransferChannel, error) + // ClientRestartDataTransfer attempts to restart a data transfer with the given transfer ID and other peer + ClientRestartDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error // ClientRetrieveTryRestartInsufficientFunds attempts to restart stalled retrievals on a given payment channel // which are stuck due to insufficient funds ClientRetrieveTryRestartInsufficientFunds(ctx context.Context, paymentChannel address.Address) error diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 7896d566e..7723e0b1f 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -15,6 +15,7 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-bitfield" + datatransfer "github.com/filecoin-project/go-data-transfer" "github.com/filecoin-project/go-fil-markets/piecestore" "github.com/filecoin-project/go-fil-markets/retrievalmarket" "github.com/filecoin-project/go-fil-markets/storagemarket" @@ -165,6 +166,7 @@ type FullNodeStruct struct { ClientDealSize func(ctx context.Context, root cid.Cid) (api.DataSize, error) `perm:"read"` ClientListDataTransfers func(ctx context.Context) ([]api.DataTransferChannel, error) `perm:"write"` ClientDataTransferUpdates func(ctx context.Context) (<-chan api.DataTransferChannel, error) `perm:"write"` + ClientRestartDataTransfer func(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error `perm:"write"` ClientRetrieveTryRestartInsufficientFunds func(ctx context.Context, paymentChannel address.Address) error `perm:"write"` StateNetworkName func(context.Context) (dtypes.NetworkName, error) `perm:"read"` @@ -552,6 +554,10 @@ func (c *FullNodeStruct) ClientDataTransferUpdates(ctx context.Context) (<-chan return c.Internal.ClientDataTransferUpdates(ctx) } +func (c *FullNodeStruct) ClientRestartDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error { + return c.Internal.ClientRestartDataTransfer(ctx, transferID, otherPeer, isInitiator) +} + func (c *FullNodeStruct) ClientRetrieveTryRestartInsufficientFunds(ctx context.Context, paymentChannel address.Address) error { return c.Internal.ClientRetrieveTryRestartInsufficientFunds(ctx, paymentChannel) } diff --git a/cli/client.go b/cli/client.go index 34d151ace..7035fb64b 100644 --- a/cli/client.go +++ b/cli/client.go @@ -3,6 +3,7 @@ package cli import ( "context" "encoding/json" + "errors" "fmt" "io" "os" @@ -82,6 +83,7 @@ var clientCmd = &cli.Command{ WithCategory("util", clientCarGenCmd), WithCategory("util", clientInfoCmd), WithCategory("util", clientListTransfers), + WithCategory("util", clientRestartTransfer), }, } @@ -1326,6 +1328,66 @@ var clientInfoCmd = &cli.Command{ }, } +var clientRestartTransfer = &cli.Command{ + Name: "restart-transfer", + Usage: "Force restart a stalled data transfer", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "peerid", + Usage: "narrow to transfer with specific peer", + }, + &cli.BoolFlag{ + Name: "initiator", + Usage: "specify only transfers where peer is/is not initiator", + Value: true, + }, + }, + Action: func(cctx *cli.Context) error { + if !cctx.Args().Present() { + return cli.ShowCommandHelp(cctx, cctx.Command.Name) + } + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + transferUint, err := strconv.ParseUint(cctx.Args().First(), 10, 64) + if err != nil { + return fmt.Errorf("Error reading transfer ID: %w", err) + } + transferID := datatransfer.TransferID(transferUint) + initiator := cctx.Bool("initiator") + var other peer.ID + if pidstr := cctx.String("peerid"); pidstr != "" { + p, err := peer.Decode(pidstr) + if err != nil { + return err + } + other = p + } else { + channels, err := api.ClientListDataTransfers(ctx) + if err != nil { + return err + } + found := false + for _, channel := range channels { + if channel.IsInitiator == initiator && channel.TransferID == transferID { + other = channel.OtherPeer + found = true + break + } + } + if !found { + return errors.New("unable to find matching data transfer") + } + } + + return api.ClientRestartDataTransfer(ctx, transferID, other, initiator) + }, +} + var clientListTransfers = &cli.Command{ Name: "list-transfers", Usage: "List ongoing data transfers for deals", diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index cbec60c10..c5d612fbe 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -46,6 +46,7 @@ * [ClientMinerQueryOffer](#ClientMinerQueryOffer) * [ClientQueryAsk](#ClientQueryAsk) * [ClientRemoveImport](#ClientRemoveImport) + * [ClientRestartDataTransfer](#ClientRestartDataTransfer) * [ClientRetrieve](#ClientRetrieve) * [ClientRetrieveTryRestartInsufficientFunds](#ClientRetrieveTryRestartInsufficientFunds) * [ClientRetrieveWithEvents](#ClientRetrieveWithEvents) @@ -1161,6 +1162,23 @@ Inputs: Response: `{}` +### ClientRestartDataTransfer +ClientRestartDataTransfer attempts to restart a data transfer with the given transfer ID and other peer + + +Perms: write + +Inputs: +```json +[ + 3, + "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf", + true +] +``` + +Response: `{}` + ### ClientRetrieve ClientRetrieve initiates the retrieval of a file, as specified in the order. diff --git a/go.mod b/go.mod index adff07d32..75926117a 100644 --- a/go.mod +++ b/go.mod @@ -27,9 +27,9 @@ require ( github.com/filecoin-project/go-bitfield v0.2.1 github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 - github.com/filecoin-project/go-data-transfer v0.6.7 + github.com/filecoin-project/go-data-transfer v0.6.8-0.20201013092017-eee8d1cde5d5 github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f - github.com/filecoin-project/go-fil-markets v0.7.1 + github.com/filecoin-project/go-fil-markets v0.7.2-0.20201013095312-bbda6c6fd17a github.com/filecoin-project/go-jsonrpc v0.1.2-0.20201008195726-68c6a2704e49 github.com/filecoin-project/go-multistore v0.0.3 github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20 @@ -66,7 +66,7 @@ require ( github.com/ipfs/go-ds-pebble v0.0.2-0.20200921225637-ce220f8ac459 github.com/ipfs/go-filestore v1.0.0 github.com/ipfs/go-fs-lock v0.0.6 - github.com/ipfs/go-graphsync v0.2.1 + github.com/ipfs/go-graphsync v0.2.1-0.20201013053840-5d8ea8076a2c github.com/ipfs/go-ipfs-blockstore v1.0.1 github.com/ipfs/go-ipfs-chunker v0.0.5 github.com/ipfs/go-ipfs-ds-help v1.0.0 diff --git a/go.sum b/go.sum index 576690c10..50e85dfd5 100644 --- a/go.sum +++ b/go.sum @@ -240,14 +240,14 @@ github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 h1:a github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2/go.mod h1:pqTiPHobNkOVM5thSRsHYjyQfq7O5QSCMhvuu9JoDlg= github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 h1:2pMXdBnCiXjfCYx/hLqFxccPoqsSveQFxVLvNxy9bus= github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= -github.com/filecoin-project/go-data-transfer v0.6.7 h1:Kacr5qz2YWtd3sensU6aXFtES7joeapVDeXApeUD35I= -github.com/filecoin-project/go-data-transfer v0.6.7/go.mod h1:C++k1U6+jMQODOaen5OPDo9XQbth9Yq3ie94vNjBJbk= +github.com/filecoin-project/go-data-transfer v0.6.8-0.20201013092017-eee8d1cde5d5 h1:kgmVHDP+rqcPqytpC215MzRRXrW9FqTfn0VFWhB2oog= +github.com/filecoin-project/go-data-transfer v0.6.8-0.20201013092017-eee8d1cde5d5/go.mod h1:1zaap881YZLMeIxhvLM0zA9qfUkh3bjOLSRaOoO9WRM= github.com/filecoin-project/go-ds-versioning v0.1.0 h1:y/X6UksYTsK8TLCI7rttCKEvl8btmWxyFMEeeWGUxIQ= github.com/filecoin-project/go-ds-versioning v0.1.0/go.mod h1:mp16rb4i2QPmxBnmanUx8i/XANp+PFCCJWiAb+VW4/s= github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f h1:GxJzR3oRIMTPtpZ0b7QF8FKPK6/iPAc7trhlL5k/g+s= github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= -github.com/filecoin-project/go-fil-markets v0.7.1 h1:e0NlpSnaeGyDUhCOzevjcxkSA54kt9BzlXpLRgduUFI= -github.com/filecoin-project/go-fil-markets v0.7.1/go.mod h1:5Pt4DXQqUoUrp9QzlSdlYTpItXxwAtqKrxRWQ6hAOqk= +github.com/filecoin-project/go-fil-markets v0.7.2-0.20201013095312-bbda6c6fd17a h1:jC3yO5R0+jGnVAHVqIHXb3BqCN/crslxTALz4I5gw1o= +github.com/filecoin-project/go-fil-markets v0.7.2-0.20201013095312-bbda6c6fd17a/go.mod h1:HqbtLIwJ4Lonp0BWq4ajmdXZ2UTh2+YK3wZSXXAE8yA= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= @@ -264,12 +264,10 @@ github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261 h github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261/go.mod h1:fZzmf4tftbwf9S37XRifoJlz7nCjRdIrMGLR07dKLCc= github.com/filecoin-project/go-state-types v0.0.0-20200903145444-247639ffa6ad/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I= github.com/filecoin-project/go-state-types v0.0.0-20200904021452-1883f36ca2f4/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I= -github.com/filecoin-project/go-state-types v0.0.0-20200905071437-95828685f9df/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I= github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab h1:cEDC5Ei8UuT99hPWhCjA72SM9AuRtnpvdSTIYbnzN8I= github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.0.0-20201003010437-c33112184a2b h1:bMUfG6Sy6YSMbsjQAO1Q2vEZldbSdsbRy/FX3OlTck0= github.com/filecoin-project/go-state-types v0.0.0-20201003010437-c33112184a2b/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= -github.com/filecoin-project/go-statemachine v0.0.0-20200714194326-a77c3ae20989/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe h1:dF8u+LEWeIcTcfUcCf3WFVlc81Fr2JKg8zPzIbBDKDw= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= github.com/filecoin-project/go-statestore v0.1.0 h1:t56reH59843TwXHkMcwyuayStBIiWBRilQjQ+5IiwdQ= @@ -277,9 +275,9 @@ github.com/filecoin-project/go-statestore v0.1.0/go.mod h1:LFc9hD+fRxPqiHiaqUEZO github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b h1:fkRZSPrYpk42PV3/lIXiL0LHetxde7vyYYvSsttQtfg= github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b/go.mod h1:Q0GQOBtKf1oE10eSXSlhN45kDBdGvEcVOqMiffqX+N8= github.com/filecoin-project/specs-actors v0.9.4/go.mod h1:BStZQzx5x7TmCkLv0Bpa07U6cPKol6fd3w9KjMPZ6Z4= -github.com/filecoin-project/specs-actors v0.9.7/go.mod h1:wM2z+kwqYgXn5Z7scV1YHLyd1Q1cy0R8HfTIWQ0BFGU= github.com/filecoin-project/specs-actors v0.9.12 h1:iIvk58tuMtmloFNHhAOQHG+4Gci6Lui0n7DYQGi3cJk= github.com/filecoin-project/specs-actors v0.9.12/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= +github.com/filecoin-project/specs-actors/v2 v2.0.1/go.mod h1:v2NZVYinNIKA9acEMBm5wWXxqv5+frFEbekBFemYghY= github.com/filecoin-project/specs-actors/v2 v2.1.0 h1:ocEuGz8DG2cUWw32c/tvF8D6xT+dGVWJTr5yDevU00g= github.com/filecoin-project/specs-actors/v2 v2.1.0/go.mod h1:E7fAX4CZkDVQvDNRCxfq+hc3nx56KcCKyuZf0hlQJ20= github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796 h1:dJsTPWpG2pcTeojO2pyn0c6l+x/3MZYCBgo/9d11JEk= @@ -540,8 +538,8 @@ github.com/ipfs/go-filestore v1.0.0/go.mod h1:/XOCuNtIe2f1YPbiXdYvD0BKLA0JR1MgPi github.com/ipfs/go-fs-lock v0.0.6 h1:sn3TWwNVQqSeNjlWy6zQ1uUGAZrV3hPOyEA6y1/N2a0= github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28L7zESmM= github.com/ipfs/go-graphsync v0.1.0/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CEGevngQbmE= -github.com/ipfs/go-graphsync v0.2.1 h1:MdehhqBSuTI2LARfKLkpYnt0mUrqHs/mtuDnESXHBfU= -github.com/ipfs/go-graphsync v0.2.1/go.mod h1:gEBvJUNelzMkaRPJTpg/jaKN4AQW/7wDWu0K92D8o10= +github.com/ipfs/go-graphsync v0.2.1-0.20201013053840-5d8ea8076a2c h1:De/AZGvRa3WMyw5zdMMhcvRcho46BVo+C0NRud+T4io= +github.com/ipfs/go-graphsync v0.2.1-0.20201013053840-5d8ea8076a2c/go.mod h1:gEBvJUNelzMkaRPJTpg/jaKN4AQW/7wDWu0K92D8o10= github.com/ipfs/go-hamt-ipld v0.1.1 h1:0IQdvwnAAUKmDE+PMJa5y1QiwOPHpI9+eAbQEEEYthk= github.com/ipfs/go-hamt-ipld v0.1.1/go.mod h1:1EZCr2v0jlCnhpa+aZ0JZYp8Tt2w16+JJOAVz17YcDk= github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= diff --git a/node/impl/client/client.go b/node/impl/client/client.go index fe83fda7b..f04d310ce 100644 --- a/node/impl/client/client.go +++ b/node/impl/client/client.go @@ -8,7 +8,6 @@ import ( "github.com/filecoin-project/go-state-types/dline" - datatransfer "github.com/filecoin-project/go-data-transfer" "github.com/filecoin-project/go-state-types/big" "golang.org/x/xerrors" @@ -33,6 +32,7 @@ import ( "go.uber.org/fx" "github.com/filecoin-project/go-address" + datatransfer "github.com/filecoin-project/go-data-transfer" "github.com/filecoin-project/go-fil-markets/discovery" "github.com/filecoin-project/go-fil-markets/pieceio" "github.com/filecoin-project/go-fil-markets/retrievalmarket" @@ -850,6 +850,14 @@ func (a *API) ClientDataTransferUpdates(ctx context.Context) (<-chan api.DataTra return channels, nil } +func (a *API) ClientRestartDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error { + selfPeer := a.Host.ID() + if isInitiator { + return a.DataTransfer.RestartDataTransferChannel(ctx, datatransfer.ChannelID{Initiator: selfPeer, Responder: otherPeer, ID: transferID}) + } + return a.DataTransfer.RestartDataTransferChannel(ctx, datatransfer.ChannelID{Initiator: otherPeer, Responder: selfPeer, ID: transferID}) +} + func newDealInfo(v storagemarket.ClientDeal) api.DealInfo { return api.DealInfo{ ProposalCid: v.ProposalCid, diff --git a/node/modules/client.go b/node/modules/client.go index d012e4539..eab309445 100644 --- a/node/modules/client.go +++ b/node/modules/client.go @@ -91,6 +91,7 @@ func NewClientGraphsyncDataTransfer(lc fx.Lifecycle, h host.Host, gs dtypes.Grap return nil, err } + dt.OnReady(marketevents.ReadyLogger("provider data transfer")) lc.Append(fx.Hook{ OnStart: func(ctx context.Context) error { return dt.Start(ctx) diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 4dbce4cdb..613203a60 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -267,6 +267,7 @@ func NewProviderDAGServiceDataTransfer(lc fx.Lifecycle, h host.Host, gs dtypes.S return nil, err } + dt.OnReady(marketevents.ReadyLogger("provider data transfer")) lc.Append(fx.Hook{ OnStart: func(ctx context.Context) error { return dt.Start(ctx) From 1eb2d0ae5059604be9d878cab370e71eeba288ea Mon Sep 17 00:00:00 2001 From: zgfzgf <1901989065@qq.com> Date: Tue, 13 Oct 2020 22:34:07 +0800 Subject: [PATCH 092/313] optimize map use struct{} --- chain/stmgr/stmgr.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index b470cfe83..e3bd5f89d 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -313,7 +313,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp } var receipts []cbg.CBORMarshaler - processedMsgs := map[cid.Cid]bool{} + processedMsgs := make(map[cid.Cid]struct{}) for _, b := range bms { penalty := types.NewInt(0) gasReward := big.Zero() @@ -337,7 +337,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp return cid.Undef, cid.Undef, err } } - processedMsgs[m.Cid()] = true + processedMsgs[m.Cid()] = struct{}{} } params, err := actors.SerializeParams(&reward.AwardBlockRewardParams{ From 87cd8c672571ec22ae36b9eef1a42557e8546436 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Tue, 13 Oct 2020 17:48:54 +0200 Subject: [PATCH 093/313] Fix off by one tipset in searchBackForMsg This way we will return the tipset the message was executed in Signed-off-by: Jakub Sztandera --- chain/stmgr/stmgr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index b470cfe83..0cb17fcf3 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -738,7 +738,7 @@ func (sm *StateManager) searchBackForMsg(ctx context.Context, from *types.TipSet } if r != nil { - return pts, r, foundMsg, nil + return cur, r, foundMsg, nil } } From 8987defb9d8ba19ecc9bc6cb675bb3740cbb6923 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Tue, 13 Oct 2020 19:20:11 +0200 Subject: [PATCH 094/313] Fix BLS message ChainLength add more detail to ValidForBlockInclusion Signed-off-by: Jakub Sztandera --- chain/types/message.go | 2 +- chain/types/signedmessage.go | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/chain/types/message.go b/chain/types/message.go index cbc7c1dad..c53ecc7c1 100644 --- a/chain/types/message.go +++ b/chain/types/message.go @@ -195,7 +195,7 @@ func (m *Message) ValidForBlockInclusion(minGas int64) error { // since prices might vary with time, this is technically semantic validation if m.GasLimit < minGas { - return xerrors.New("'GasLimit' field cannot be less than the cost of storing a message on chain") + return xerrors.Errorf("'GasLimit' field cannot be less than the cost of storing a message on chain %d < %d", m.GasLimit, minGas) } return nil diff --git a/chain/types/signedmessage.go b/chain/types/signedmessage.go index 7532bea35..c539ac240 100644 --- a/chain/types/signedmessage.go +++ b/chain/types/signedmessage.go @@ -78,7 +78,14 @@ func (sm *SignedMessage) MarshalJSON() ([]byte, error) { } func (sm *SignedMessage) ChainLength() int { - ser, err := sm.Serialize() + var ser []byte + var err error + if sm.Signature.Type == crypto.SigTypeBLS { + // BLS chain message length doesn't include signature + ser, err = sm.Message.Serialize() + } else { + ser, err = sm.Serialize() + } if err != nil { panic(err) } From ce548c8f95aa7f3459ec58b8df27902579b6ef4e Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Tue, 13 Oct 2020 18:25:49 +0200 Subject: [PATCH 095/313] Add test Signed-off-by: Jakub Sztandera --- api/test/test.go | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/api/test/test.go b/api/test/test.go index 947f2bef4..4074ce4a6 100644 --- a/api/test/test.go +++ b/api/test/test.go @@ -3,8 +3,10 @@ package test import ( "context" "testing" + "time" "github.com/filecoin-project/lotus/chain/stmgr" + "github.com/filecoin-project/lotus/chain/types" "github.com/multiformats/go-multiaddr" @@ -12,6 +14,7 @@ import ( "github.com/stretchr/testify/require" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/network" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" @@ -75,6 +78,7 @@ func TestApis(t *testing.T, b APIBuilder) { t.Run("testConnectTwo", ts.testConnectTwo) t.Run("testMining", ts.testMining) t.Run("testMiningReal", ts.testMiningReal) + t.Run("testSearchMsg", ts.testSearchMsg) } func DefaultFullOpts(nFull int) []FullNodeOpts { @@ -120,6 +124,49 @@ func (ts *testSuite) testVersion(t *testing.T) { require.Equal(t, v.Version, build.BuildVersion) } +func (ts *testSuite) testSearchMsg(t *testing.T) { + apis, miners := ts.makeNodes(t, OneFull, OneMiner) + + api := apis[0] + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + senderAddr, err := api.WalletDefaultAddress(ctx) + if err != nil { + t.Fatal(err) + } + + msg := &types.Message{ + From: senderAddr, + To: senderAddr, + Value: big.Zero(), + } + bm := NewBlockMiner(ctx, t, miners[0], 100*time.Millisecond) + bm.MineBlocks() + defer bm.Stop() + + sm, err := api.MpoolPushMessage(ctx, msg, nil) + if err != nil { + t.Fatal(err) + } + res, err := api.StateWaitMsg(ctx, sm.Cid(), 1) + if err != nil { + t.Fatal(err) + } + if res.Receipt.ExitCode != 0 { + t.Fatal("did not successfully send message") + } + + searchRes, err := api.StateSearchMsg(ctx, sm.Cid()) + if err != nil { + t.Fatal(err) + } + + if searchRes.TipSet != res.TipSet { + t.Fatalf("search ts: %s, different from wait ts: %s", searchRes.TipSet, res.TipSet) + } + +} + func (ts *testSuite) testID(t *testing.T) { ctx := context.Background() apis, _ := ts.makeNodes(t, OneFull, OneMiner) From b74a3229f8d9d5d4b009d287d5a8df501f00b8ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 13 Oct 2020 21:35:29 +0200 Subject: [PATCH 096/313] fsm: process expired-ticket sectors --- api/api_full.go | 2 ++ api/apistruct/struct.go | 5 +++++ extern/storage-sealing/fsm.go | 8 ++++++-- extern/storage-sealing/fsm_events.go | 5 +++++ extern/storage-sealing/sealing.go | 1 + extern/storage-sealing/states_failed.go | 2 +- extern/storage-sealing/states_sealing.go | 15 +++++++++++++++ node/impl/full/state.go | 19 +++++++++++++++++++ storage/adapter_storage_miner.go | 9 +++++++++ storage/miner.go | 1 + 10 files changed, 64 insertions(+), 3 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index 657e945ca..957529eaa 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -355,6 +355,8 @@ type FullNode interface { StateMinerInitialPledgeCollateral(context.Context, address.Address, miner.SectorPreCommitInfo, types.TipSetKey) (types.BigInt, error) // StateMinerAvailableBalance returns the portion of a miner's balance that can be withdrawn or spent StateMinerAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) + // StateMinerSectorAllocated checks if a sector is allocated + StateMinerSectorAllocated(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (bool, error) // StateSectorPreCommitInfo returns the PreCommit info for the specified miner's sector StateSectorPreCommitInfo(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) // StateSectorGetInfo returns the on-chain info for the specified miner's sector. Returns null in case the sector info isn't found diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 61863044e..edf119114 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -181,6 +181,7 @@ type FullNodeStruct struct { StateMinerPreCommitDepositForPower func(context.Context, address.Address, miner.SectorPreCommitInfo, types.TipSetKey) (types.BigInt, error) `perm:"read"` StateMinerInitialPledgeCollateral func(context.Context, address.Address, miner.SectorPreCommitInfo, types.TipSetKey) (types.BigInt, error) `perm:"read"` StateMinerAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"` + StateMinerSectorAllocated func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (bool, error) `perm:"read"` StateSectorPreCommitInfo func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) `perm:"read"` StateSectorGetInfo func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorOnChainInfo, error) `perm:"read"` StateSectorExpiration func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorExpiration, error) `perm:"read"` @@ -863,6 +864,10 @@ func (c *FullNodeStruct) StateMinerAvailableBalance(ctx context.Context, maddr a return c.Internal.StateMinerAvailableBalance(ctx, maddr, tsk) } +func (c *FullNodeStruct) StateMinerSectorAllocated(ctx context.Context, maddr address.Address, s abi.SectorNumber, tsk types.TipSetKey) (bool, error) { + return c.Internal.StateMinerSectorAllocated(ctx, maddr, s, tsk) +} + func (c *FullNodeStruct) StateSectorPreCommitInfo(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) { return c.Internal.StateSectorPreCommitInfo(ctx, maddr, n, tsk) } diff --git a/extern/storage-sealing/fsm.go b/extern/storage-sealing/fsm.go index a936e14b8..3a5931c8b 100644 --- a/extern/storage-sealing/fsm.go +++ b/extern/storage-sealing/fsm.go @@ -45,8 +45,11 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto on(SectorAddPiece{}, WaitDeals), on(SectorStartPacking{}, Packing), ), - Packing: planOne(on(SectorPacked{}, GetTicket)), - GetTicket: planOne(on(SectorTicket{}, PreCommit1)), + Packing: planOne(on(SectorPacked{}, GetTicket)), + GetTicket: planOne( + on(SectorTicket{}, PreCommit1), + on(SectorCommitFailed{}, CommitFailed), + ), PreCommit1: planOne( on(SectorPreCommit1{}, PreCommit2), on(SectorSealPreCommit1Failed{}, SealPreCommit1Failed), @@ -124,6 +127,7 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto on(SectorRetryCommitWait{}, CommitWait), on(SectorDealsExpired{}, DealsExpired), on(SectorInvalidDealIDs{}, RecoverDealIDs), + on(SectorTicketExpired{}, Removing), ), FinalizeFailed: planOne( on(SectorRetryFinalize{}, FinalizeSector), diff --git a/extern/storage-sealing/fsm_events.go b/extern/storage-sealing/fsm_events.go index aec2beb0a..59f5e77e6 100644 --- a/extern/storage-sealing/fsm_events.go +++ b/extern/storage-sealing/fsm_events.go @@ -206,6 +206,11 @@ type SectorDealsExpired struct{ error } func (evt SectorDealsExpired) FormatError(xerrors.Printer) (next error) { return evt.error } func (evt SectorDealsExpired) apply(*SectorInfo) {} +type SectorTicketExpired struct{ error } + +func (evt SectorTicketExpired) FormatError(xerrors.Printer) (next error) { return evt.error } +func (evt SectorTicketExpired) apply(*SectorInfo) {} + type SectorCommitted struct { Proof []byte } diff --git a/extern/storage-sealing/sealing.go b/extern/storage-sealing/sealing.go index 1ba53661a..d9953eee0 100644 --- a/extern/storage-sealing/sealing.go +++ b/extern/storage-sealing/sealing.go @@ -53,6 +53,7 @@ type SealingAPI interface { StateMinerWorkerAddress(ctx context.Context, maddr address.Address, tok TipSetToken) (address.Address, error) StateMinerPreCommitDepositForPower(context.Context, address.Address, miner.SectorPreCommitInfo, TipSetToken) (big.Int, error) StateMinerInitialPledgeCollateral(context.Context, address.Address, miner.SectorPreCommitInfo, TipSetToken) (big.Int, error) + StateMinerSectorAllocated(context.Context, address.Address, abi.SectorNumber, TipSetToken) (bool, error) StateMarketStorageDeal(context.Context, abi.DealID, TipSetToken) (market.DealProposal, error) StateNetworkVersion(ctx context.Context, tok TipSetToken) (network.Version, error) SendMsg(ctx context.Context, from, to address.Address, method abi.MethodNum, value, maxFee abi.TokenAmount, params []byte) (cid.Cid, error) diff --git a/extern/storage-sealing/states_failed.go b/extern/storage-sealing/states_failed.go index d22830253..b583701ae 100644 --- a/extern/storage-sealing/states_failed.go +++ b/extern/storage-sealing/states_failed.go @@ -170,7 +170,7 @@ func (m *Sealing) handleCommitFailed(ctx statemachine.Context, sector SectorInfo case *ErrExpiredTicket: return ctx.Send(SectorSealPreCommit1Failed{xerrors.Errorf("ticket expired error: %w", err)}) case *ErrBadTicket: - return ctx.Send(SectorSealPreCommit1Failed{xerrors.Errorf("bad ticket: %w", err)}) + return ctx.Send(SectorTicketExpired{xerrors.Errorf("expired ticket: %w", err)}) case *ErrInvalidDeals: log.Warnf("invalid deals in sector %d: %v", sector.SectorNumber, err) return ctx.Send(SectorInvalidDealIDs{Return: RetCommitFailed}) diff --git a/extern/storage-sealing/states_sealing.go b/extern/storage-sealing/states_sealing.go index 7915660fa..415335f68 100644 --- a/extern/storage-sealing/states_sealing.go +++ b/extern/storage-sealing/states_sealing.go @@ -87,6 +87,21 @@ func (m *Sealing) getTicket(ctx statemachine.Context, sector SectorInfo) (abi.Se func (m *Sealing) handleGetTicket(ctx statemachine.Context, sector SectorInfo) error { ticketValue, ticketEpoch, err := m.getTicket(ctx, sector) if err != nil { + allocated, aerr := m.api.StateMinerSectorAllocated(ctx.Context(), m.maddr, sector.SectorNumber, nil) + if aerr == nil { + log.Errorf("error checking if sector is allocated: %+v", err) + } + + if allocated { + if sector.CommitMessage != nil { + // Some recovery paths with unfortunate timing lead here + return ctx.Send(SectorCommitFailed{xerrors.Errorf("sector %s is committed but got into the GetTicket state", sector.SectorNumber)}) + } + + log.Errorf("Sector %s precommitted but expired", sector.SectorNumber) + return ctx.Send(SectorRemove{}) + } + return ctx.Send(SectorSealPreCommit1Failed{xerrors.Errorf("getting ticket failed: %w", err)}) } diff --git a/node/impl/full/state.go b/node/impl/full/state.go index 1c39b59da..2cdbf00e4 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -1096,6 +1096,25 @@ func (a *StateAPI) StateMinerAvailableBalance(ctx context.Context, maddr address return types.BigAdd(abal, vested), nil } +func (a *StateAPI) StateMinerSectorAllocated(ctx context.Context, maddr address.Address, s abi.SectorNumber, tsk types.TipSetKey) (bool, error) { + ts, err := a.Chain.GetTipSetFromKey(tsk) + if err != nil { + return false, xerrors.Errorf("loading tipset %s: %w", tsk, err) + } + + act, err := a.StateManager.LoadActor(ctx, maddr, ts) + if err != nil { + return false, xerrors.Errorf("failed to load miner actor: %w", err) + } + + mas, err := miner.Load(a.StateManager.ChainStore().Store(ctx), act) + if err != nil { + return false, xerrors.Errorf("failed to load miner actor state: %w", err) + } + + return mas.IsAllocated(s) +} + // StateVerifiedClientStatus returns the data cap for the given address. // Returns zero if there is no entry in the data cap table for the // address. diff --git a/storage/adapter_storage_miner.go b/storage/adapter_storage_miner.go index 380fb4471..8d74a897a 100644 --- a/storage/adapter_storage_miner.go +++ b/storage/adapter_storage_miner.go @@ -94,6 +94,15 @@ func (s SealingAPIAdapter) StateMinerDeadlines(ctx context.Context, maddr addres return s.delegate.StateMinerDeadlines(ctx, maddr, tsk) } +func (s SealingAPIAdapter) StateMinerSectorAllocated(ctx context.Context, maddr address.Address, sid abi.SectorNumber, tok sealing.TipSetToken) (bool, error) { + tsk, err := types.TipSetKeyFromBytes(tok) + if err != nil { + return false, xerrors.Errorf("failed to unmarshal TipSetToken to TipSetKey: %w", err) + } + + return s.delegate.StateMinerSectorAllocated(ctx, maddr, sid, tsk) +} + func (s SealingAPIAdapter) StateWaitMsg(ctx context.Context, mcid cid.Cid) (sealing.MsgLookup, error) { wmsg, err := s.delegate.StateWaitMsg(ctx, mcid, build.MessageConfidence) if err != nil { diff --git a/storage/miner.go b/storage/miner.go index 74a048c8e..b8985c1a5 100644 --- a/storage/miner.go +++ b/storage/miner.go @@ -83,6 +83,7 @@ type storageMinerApi interface { StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*dline.Info, error) StateMinerPreCommitDepositForPower(context.Context, address.Address, miner.SectorPreCommitInfo, types.TipSetKey) (types.BigInt, error) StateMinerInitialPledgeCollateral(context.Context, address.Address, miner.SectorPreCommitInfo, types.TipSetKey) (types.BigInt, error) + StateMinerSectorAllocated(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (bool, error) StateSearchMsg(context.Context, cid.Cid) (*api.MsgLookup, error) StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64) (*api.MsgLookup, error) // TODO: removeme eventually StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) From 98c1aa7988750b172bce86ce13554bc218af33ad Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Tue, 13 Oct 2020 13:31:20 -0700 Subject: [PATCH 097/313] add WalletVerify to lotus-gateway --- cmd/lotus-gateway/api.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cmd/lotus-gateway/api.go b/cmd/lotus-gateway/api.go index d5fac0a06..1e680daac 100644 --- a/cmd/lotus-gateway/api.go +++ b/cmd/lotus-gateway/api.go @@ -7,9 +7,13 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/lib/sigs" + _ "github.com/filecoin-project/lotus/lib/sigs/bls" + _ "github.com/filecoin-project/lotus/lib/sigs/secp" "github.com/filecoin-project/lotus/node/impl/full" "github.com/ipfs/go-cid" ) @@ -172,6 +176,10 @@ func (a *GatewayAPI) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence u return a.api.StateWaitMsgLimited(ctx, msg, confidence, stateWaitLookbackLimit) } +func (a *GatewayAPI) WalletVerify(ctx context.Context, k address.Address, msg []byte, sig *crypto.Signature) (bool, error) { + return sigs.Verify(sig, k, msg) == nil, nil +} + var _ api.GatewayAPI = (*GatewayAPI)(nil) var _ full.ChainModuleAPI = (*GatewayAPI)(nil) var _ full.GasModuleAPI = (*GatewayAPI)(nil) From 3d80c3806473c02984d51de61de903615f61a876 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Tue, 13 Oct 2020 14:23:08 -0700 Subject: [PATCH 098/313] support stateReadState in gateway --- cmd/lotus-gateway/api.go | 5 +++++ cmd/lotus-gateway/api_test.go | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/cmd/lotus-gateway/api.go b/cmd/lotus-gateway/api.go index 1e680daac..381dd931b 100644 --- a/cmd/lotus-gateway/api.go +++ b/cmd/lotus-gateway/api.go @@ -41,6 +41,7 @@ type gatewayDepsAPI interface { StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) StateWaitMsgLimited(ctx context.Context, msg cid.Cid, confidence uint64, h abi.ChainEpoch) (*api.MsgLookup, error) + StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error) } type GatewayAPI struct { @@ -180,6 +181,10 @@ func (a *GatewayAPI) WalletVerify(ctx context.Context, k address.Address, msg [] return sigs.Verify(sig, k, msg) == nil, nil } +func (a *GatewayAPI) StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error) { + return a.api.StateReadState(ctx, actor, tsk) +} + var _ api.GatewayAPI = (*GatewayAPI)(nil) var _ full.ChainModuleAPI = (*GatewayAPI)(nil) var _ full.GasModuleAPI = (*GatewayAPI)(nil) diff --git a/cmd/lotus-gateway/api_test.go b/cmd/lotus-gateway/api_test.go index f34f887f5..6719c57c5 100644 --- a/cmd/lotus-gateway/api_test.go +++ b/cmd/lotus-gateway/api_test.go @@ -189,3 +189,7 @@ func (m *mockGatewayDepsAPI) StateLookupID(ctx context.Context, addr address.Add func (m *mockGatewayDepsAPI) StateWaitMsgLimited(ctx context.Context, msg cid.Cid, confidence uint64, h abi.ChainEpoch) (*api.MsgLookup, error) { panic("implement me") } + +func (m *mockGatewayDepsAPI) StateReadState(ctx context.Context, act address.Address, ts types.TipSetKey) (*api.ActorState, error) { + panic("implement me") +} From b61281ba4bea27b334343e2a1ebc65663e736146 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 13 Oct 2020 15:06:47 -0700 Subject: [PATCH 099/313] fix a panic on startup when we fail to load the tipset There may be a deeper issue here, but we need to handle this more gracefully somehow. See #4358. --- chain/messagepool/messagepool.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index d3c638b22..83b1a7f29 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -670,6 +670,10 @@ func (mp *MessagePool) addLoaded(m *types.SignedMessage) error { curTs := mp.curTs + if curTs == nil { + return xerrors.Errorf("current tipset not loaded") + } + snonce, err := mp.getStateNonce(m.Message.From, curTs) if err != nil { return xerrors.Errorf("failed to look up actor state nonce: %s: %w", err, ErrSoftValidationFailure) From 51aca86e98ccb23d1069a542e176bf1fe7ce26d6 Mon Sep 17 00:00:00 2001 From: zgfzgf <1901989065@qq.com> Date: Wed, 14 Oct 2020 08:44:42 +0800 Subject: [PATCH 100/313] optimize mining code --- chain/gen/mining.go | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/chain/gen/mining.go b/chain/gen/mining.go index 45a089452..f6d697ec0 100644 --- a/chain/gen/mining.go +++ b/chain/gen/mining.go @@ -6,15 +6,12 @@ import ( "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/specs-actors/actors/util/adt" cid "github.com/ipfs/go-cid" - cbor "github.com/ipfs/go-ipld-cbor" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/lib/sigs/bls" ) @@ -114,23 +111,12 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w api.WalletA } next.ParentBaseFee = baseFee - cst := cbor.NewCborStore(sm.ChainStore().Blockstore()) - tree, err := state.LoadStateTree(cst, st) - if err != nil { - return nil, xerrors.Errorf("failed to load state tree: %w", err) - } - - waddr, err := vm.ResolveToKeyAddr(tree, cst, worker) - if err != nil { - return nil, xerrors.Errorf("failed to resolve miner address to key address: %w", err) - } - nosigbytes, err := next.SigningBytes() if err != nil { return nil, xerrors.Errorf("failed to get signing bytes for block: %w", err) } - sig, err := w.WalletSign(ctx, waddr, nosigbytes, api.MsgMeta{ + sig, err := w.WalletSign(ctx, worker, nosigbytes, api.MsgMeta{ Type: api.MTBlock, }) if err != nil { From 24267008212f8330bf67ba8d064d2784ae557e4a Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Mon, 12 Oct 2020 21:50:11 -0400 Subject: [PATCH 101/313] Don't transfer zero FIL during rebalancing fork --- chain/stmgr/forks.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/chain/stmgr/forks.go b/chain/stmgr/forks.go index 7f2b57546..36b0da83c 100644 --- a/chain/stmgr/forks.go +++ b/chain/stmgr/forks.go @@ -312,11 +312,13 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal available = st.GetAvailableBalance(act.Balance) } - transfers = append(transfers, transfer{ - From: addr, - To: builtin.ReserveAddress, - Amt: available, - }) + if !available.IsZero() { + transfers = append(transfers, transfer{ + From: addr, + To: builtin.ReserveAddress, + Amt: available, + }) + } } return nil }) From 7dbc8965bea3c17e22c643b34e4d91fc3091a38a Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Tue, 13 Oct 2020 01:05:28 -0400 Subject: [PATCH 102/313] Apply nonces to implicit messages --- chain/stmgr/stmgr.go | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index 0cb17fcf3..113304de1 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -247,17 +247,12 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp return cid.Undef, cid.Undef, xerrors.Errorf("making vm: %w", err) } - runCron := func() error { - // TODO: this nonce-getting is a tiny bit ugly - ca, err := vmi.StateTree().GetActor(builtin0.SystemActorAddr) - if err != nil { - return err - } + runCron := func(epoch abi.ChainEpoch) error { cronMsg := &types.Message{ To: builtin0.CronActorAddr, From: builtin0.SystemActorAddr, - Nonce: ca.Nonce, + Nonce: uint64(epoch), Value: types.NewInt(0), GasFeeCap: types.NewInt(0), GasPremium: types.NewInt(0), @@ -284,7 +279,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp for i := parentEpoch; i < epoch; i++ { if i > parentEpoch { // run cron for null rounds if any - if err := runCron(); err != nil { + if err := runCron(i); err != nil { return cid.Undef, cid.Undef, err } @@ -350,15 +345,10 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp return cid.Undef, cid.Undef, xerrors.Errorf("failed to serialize award params: %w", err) } - sysAct, actErr := vmi.StateTree().GetActor(builtin0.SystemActorAddr) - if actErr != nil { - return cid.Undef, cid.Undef, xerrors.Errorf("failed to get system actor: %w", actErr) - } - rwMsg := &types.Message{ From: builtin0.SystemActorAddr, To: reward.Address, - Nonce: sysAct.Nonce, + Nonce: uint64(epoch), Value: types.NewInt(0), GasFeeCap: types.NewInt(0), GasPremium: types.NewInt(0), @@ -381,7 +371,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp } } - if err := runCron(); err != nil { + if err := runCron(epoch); err != nil { return cid.Cid{}, cid.Cid{}, err } From 58662b79b38be538d76ec06c7ab06dcaef854ac7 Mon Sep 17 00:00:00 2001 From: hannahhoward Date: Tue, 13 Oct 2020 19:50:13 -0700 Subject: [PATCH 103/313] fix(deps): use tagged go-fil-markets 0.9.0 --- go.mod | 6 +++--- go.sum | 12 ++++++------ node/modules/client.go | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index 75926117a..0118baa88 100644 --- a/go.mod +++ b/go.mod @@ -27,9 +27,9 @@ require ( github.com/filecoin-project/go-bitfield v0.2.1 github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 - github.com/filecoin-project/go-data-transfer v0.6.8-0.20201013092017-eee8d1cde5d5 + github.com/filecoin-project/go-data-transfer v0.9.0 github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f - github.com/filecoin-project/go-fil-markets v0.7.2-0.20201013095312-bbda6c6fd17a + github.com/filecoin-project/go-fil-markets v0.9.0 github.com/filecoin-project/go-jsonrpc v0.1.2-0.20201008195726-68c6a2704e49 github.com/filecoin-project/go-multistore v0.0.3 github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20 @@ -66,7 +66,7 @@ require ( github.com/ipfs/go-ds-pebble v0.0.2-0.20200921225637-ce220f8ac459 github.com/ipfs/go-filestore v1.0.0 github.com/ipfs/go-fs-lock v0.0.6 - github.com/ipfs/go-graphsync v0.2.1-0.20201013053840-5d8ea8076a2c + github.com/ipfs/go-graphsync v0.3.0 github.com/ipfs/go-ipfs-blockstore v1.0.1 github.com/ipfs/go-ipfs-chunker v0.0.5 github.com/ipfs/go-ipfs-ds-help v1.0.0 diff --git a/go.sum b/go.sum index 50e85dfd5..2b0859bfd 100644 --- a/go.sum +++ b/go.sum @@ -240,14 +240,14 @@ github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 h1:a github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2/go.mod h1:pqTiPHobNkOVM5thSRsHYjyQfq7O5QSCMhvuu9JoDlg= github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 h1:2pMXdBnCiXjfCYx/hLqFxccPoqsSveQFxVLvNxy9bus= github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= -github.com/filecoin-project/go-data-transfer v0.6.8-0.20201013092017-eee8d1cde5d5 h1:kgmVHDP+rqcPqytpC215MzRRXrW9FqTfn0VFWhB2oog= -github.com/filecoin-project/go-data-transfer v0.6.8-0.20201013092017-eee8d1cde5d5/go.mod h1:1zaap881YZLMeIxhvLM0zA9qfUkh3bjOLSRaOoO9WRM= +github.com/filecoin-project/go-data-transfer v0.9.0 h1:nTT8j7Hu3TM0wRWrGy83/ctawG7sleJGdFWtIsUsKgY= +github.com/filecoin-project/go-data-transfer v0.9.0/go.mod h1:i2CqUy7TMQGKukj9BgqIxiP8nDHDXU2VLd771KVaCaQ= github.com/filecoin-project/go-ds-versioning v0.1.0 h1:y/X6UksYTsK8TLCI7rttCKEvl8btmWxyFMEeeWGUxIQ= github.com/filecoin-project/go-ds-versioning v0.1.0/go.mod h1:mp16rb4i2QPmxBnmanUx8i/XANp+PFCCJWiAb+VW4/s= github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f h1:GxJzR3oRIMTPtpZ0b7QF8FKPK6/iPAc7trhlL5k/g+s= github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= -github.com/filecoin-project/go-fil-markets v0.7.2-0.20201013095312-bbda6c6fd17a h1:jC3yO5R0+jGnVAHVqIHXb3BqCN/crslxTALz4I5gw1o= -github.com/filecoin-project/go-fil-markets v0.7.2-0.20201013095312-bbda6c6fd17a/go.mod h1:HqbtLIwJ4Lonp0BWq4ajmdXZ2UTh2+YK3wZSXXAE8yA= +github.com/filecoin-project/go-fil-markets v0.9.0 h1:RVdMKeOdRtpHawB14+uvJhvq243/UfZ4g3yFa/6qekk= +github.com/filecoin-project/go-fil-markets v0.9.0/go.mod h1:h+bJ/IUnYjnW5HMKyt9JQSnhslqetkpuzwwugc3K8vM= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= @@ -538,8 +538,8 @@ github.com/ipfs/go-filestore v1.0.0/go.mod h1:/XOCuNtIe2f1YPbiXdYvD0BKLA0JR1MgPi github.com/ipfs/go-fs-lock v0.0.6 h1:sn3TWwNVQqSeNjlWy6zQ1uUGAZrV3hPOyEA6y1/N2a0= github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28L7zESmM= github.com/ipfs/go-graphsync v0.1.0/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CEGevngQbmE= -github.com/ipfs/go-graphsync v0.2.1-0.20201013053840-5d8ea8076a2c h1:De/AZGvRa3WMyw5zdMMhcvRcho46BVo+C0NRud+T4io= -github.com/ipfs/go-graphsync v0.2.1-0.20201013053840-5d8ea8076a2c/go.mod h1:gEBvJUNelzMkaRPJTpg/jaKN4AQW/7wDWu0K92D8o10= +github.com/ipfs/go-graphsync v0.3.0 h1:I6Y20kSuCWkUvPoUWo4V3am704/9QjgDVVkf0zIV8+8= +github.com/ipfs/go-graphsync v0.3.0/go.mod h1:gEBvJUNelzMkaRPJTpg/jaKN4AQW/7wDWu0K92D8o10= github.com/ipfs/go-hamt-ipld v0.1.1 h1:0IQdvwnAAUKmDE+PMJa5y1QiwOPHpI9+eAbQEEEYthk= github.com/ipfs/go-hamt-ipld v0.1.1/go.mod h1:1EZCr2v0jlCnhpa+aZ0JZYp8Tt2w16+JJOAVz17YcDk= github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= diff --git a/node/modules/client.go b/node/modules/client.go index eab309445..f1380bc97 100644 --- a/node/modules/client.go +++ b/node/modules/client.go @@ -91,7 +91,7 @@ func NewClientGraphsyncDataTransfer(lc fx.Lifecycle, h host.Host, gs dtypes.Grap return nil, err } - dt.OnReady(marketevents.ReadyLogger("provider data transfer")) + dt.OnReady(marketevents.ReadyLogger("client data transfer")) lc.Append(fx.Hook{ OnStart: func(ctx context.Context) error { return dt.Start(ctx) From 458ea277fcb4cb9f0e52453da4b50399632040e6 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Tue, 13 Oct 2020 01:20:49 -0400 Subject: [PATCH 104/313] Aggregate irregular state transitions into a single EexcutionTrace --- chain/stmgr/forks.go | 118 +++++++++++++++++++++++++++++++++---------- 1 file changed, 92 insertions(+), 26 deletions(-) diff --git a/chain/stmgr/forks.go b/chain/stmgr/forks.go index 36b0da83c..156c68783 100644 --- a/chain/stmgr/forks.go +++ b/chain/stmgr/forks.go @@ -168,7 +168,7 @@ func (sm *StateManager) hasExpensiveFork(ctx context.Context, height abi.ChainEp return ok } -func doTransfer(cb ExecCallback, tree types.StateTree, from, to address.Address, amt abi.TokenAmount) error { +func doTransfer(tree types.StateTree, from, to address.Address, amt abi.TokenAmount, cb func(trace types.ExecutionTrace)) error { fromAct, err := tree.GetActor(from) if err != nil { return xerrors.Errorf("failed to get 'from' actor for transfer: %w", err) @@ -201,7 +201,6 @@ func doTransfer(cb ExecCallback, tree types.StateTree, from, to address.Address, From: from, To: to, Value: amt, - Nonce: math.MaxUint64, } fakeRct := &types.MessageReceipt{ ExitCode: 0, @@ -209,22 +208,14 @@ func doTransfer(cb ExecCallback, tree types.StateTree, from, to address.Address, GasUsed: 0, } - if err := cb(fakeMsg.Cid(), fakeMsg, &vm.ApplyRet{ - MessageReceipt: *fakeRct, - ActorErr: nil, - ExecutionTrace: types.ExecutionTrace{ - Msg: fakeMsg, - MsgRct: fakeRct, - Error: "", - Duration: 0, - GasCharges: nil, - Subcalls: nil, - }, - Duration: 0, - GasCosts: vm.ZeroGasOutputs(), - }); err != nil { - return xerrors.Errorf("recording transfer: %w", err) - } + cb(types.ExecutionTrace{ + Msg: fakeMsg, + MsgRct: fakeRct, + Error: "", + Duration: 0, + GasCharges: nil, + Subcalls: nil, + }) } return nil @@ -277,6 +268,10 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal } var transfers []transfer + subcalls := make([]types.ExecutionTrace, 0) + transferCb := func(trace types.ExecutionTrace) { + subcalls = append(subcalls, trace) + } // Take all excess funds away, put them into the reserve account err = tree.ForEach(func(addr address.Address, act *types.Actor) error { @@ -328,7 +323,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal // Execute transfers from previous step for _, t := range transfers { - if err := doTransfer(cb, tree, t.From, t.To, t.Amt); err != nil { + if err := doTransfer(tree, t.From, t.To, t.Amt, transferCb); err != nil { return cid.Undef, xerrors.Errorf("transfer %s %s->%s failed: %w", t.Amt, t.From, t.To, err) } } @@ -431,7 +426,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal } for _, t := range transfersBack { - if err := doTransfer(cb, tree, t.From, t.To, t.Amt); err != nil { + if err := doTransfer(tree, t.From, t.To, t.Amt, transferCb); err != nil { return cid.Undef, xerrors.Errorf("transfer %s %s->%s failed: %w", t.Amt, t.From, t.To, err) } } @@ -441,7 +436,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal if err != nil { return cid.Undef, xerrors.Errorf("failed to load burnt funds actor: %w", err) } - if err := doTransfer(cb, tree, builtin0.BurntFundsActorAddr, builtin.ReserveAddress, burntAct.Balance); err != nil { + if err := doTransfer(tree, builtin0.BurntFundsActorAddr, builtin.ReserveAddress, burntAct.Balance, transferCb); err != nil { return cid.Undef, xerrors.Errorf("failed to unburn funds: %w", err) } @@ -457,7 +452,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal } difference := types.BigSub(DesiredReimbursementBalance, reimb.Balance) - if err := doTransfer(cb, tree, builtin.ReserveAddress, reimbAddr, difference); err != nil { + if err := doTransfer(tree, builtin.ReserveAddress, reimbAddr, difference, transferCb); err != nil { return cid.Undef, xerrors.Errorf("failed to top up reimbursement account: %w", err) } @@ -476,6 +471,39 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal return cid.Undef, xerrors.Errorf("resultant state tree account balance was not correct: %s", total) } + if cb != nil { + // record the transfer in execution traces + + fakeMsg := &types.Message{ + From: builtin.SystemActorAddr, + To: builtin.SystemActorAddr, + Value: big.Zero(), + Nonce: uint64(epoch), + } + fakeRct := &types.MessageReceipt{ + ExitCode: 0, + Return: nil, + GasUsed: 0, + } + + if err := cb(fakeMsg.Cid(), fakeMsg, &vm.ApplyRet{ + MessageReceipt: *fakeRct, + ActorErr: nil, + ExecutionTrace: types.ExecutionTrace{ + Msg: fakeMsg, + MsgRct: fakeRct, + Error: "", + Duration: 0, + GasCharges: nil, + Subcalls: subcalls, + }, + Duration: 0, + GasCosts: vm.ZeroGasOutputs(), + }); err != nil { + return cid.Undef, xerrors.Errorf("recording transfers: %w", err) + } + } + return tree.Flush(ctx) } @@ -516,12 +544,12 @@ func UpgradeIgnition(ctx context.Context, sm *StateManager, cb ExecCallback, roo return cid.Undef, xerrors.Errorf("resetting genesis msig start epochs: %w", err) } - err = splitGenesisMultisig(ctx, cb, split1, store, tree, 50) + err = splitGenesisMultisig(ctx, cb, split1, store, tree, 50, epoch) if err != nil { return cid.Undef, xerrors.Errorf("splitting first msig: %w", err) } - err = splitGenesisMultisig(ctx, cb, split2, store, tree, 50) + err = splitGenesisMultisig(ctx, cb, split2, store, tree, 50, epoch) if err != nil { return cid.Undef, xerrors.Errorf("splitting second msig: %w", err) } @@ -647,7 +675,7 @@ func setNetworkName(ctx context.Context, store adt.Store, tree *state.StateTree, return nil } -func splitGenesisMultisig(ctx context.Context, cb ExecCallback, addr address.Address, store adt0.Store, tree *state.StateTree, portions uint64) error { +func splitGenesisMultisig(ctx context.Context, cb ExecCallback, addr address.Address, store adt0.Store, tree *state.StateTree, portions uint64, epoch abi.ChainEpoch) error { if portions < 1 { return xerrors.Errorf("cannot split into 0 portions") } @@ -716,6 +744,11 @@ func splitGenesisMultisig(ctx context.Context, cb ExecCallback, addr address.Add } i := uint64(0) + subcalls := make([]types.ExecutionTrace, 0, portions) + transferCb := func(trace types.ExecutionTrace) { + subcalls = append(subcalls, trace) + } + for i < portions { keyAddr, err := makeKeyAddr(addr, i) if err != nil { @@ -732,13 +765,46 @@ func splitGenesisMultisig(ctx context.Context, cb ExecCallback, addr address.Add return xerrors.Errorf("setting new msig actor state: %w", err) } - if err := doTransfer(cb, tree, addr, idAddr, newIbal); err != nil { + if err := doTransfer(tree, addr, idAddr, newIbal, transferCb); err != nil { return xerrors.Errorf("transferring split msig balance: %w", err) } i++ } + if cb != nil { + // record the transfer in execution traces + + fakeMsg := &types.Message{ + From: builtin.SystemActorAddr, + To: addr, + Value: big.Zero(), + Nonce: uint64(epoch), + } + fakeRct := &types.MessageReceipt{ + ExitCode: 0, + Return: nil, + GasUsed: 0, + } + + if err := cb(fakeMsg.Cid(), fakeMsg, &vm.ApplyRet{ + MessageReceipt: *fakeRct, + ActorErr: nil, + ExecutionTrace: types.ExecutionTrace{ + Msg: fakeMsg, + MsgRct: fakeRct, + Error: "", + Duration: 0, + GasCharges: nil, + Subcalls: subcalls, + }, + Duration: 0, + GasCosts: vm.ZeroGasOutputs(), + }); err != nil { + return xerrors.Errorf("recording transfers: %w", err) + } + } + return nil } From ce541102289ee8db4017c84c9fb88250e9ce4fbe Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Tue, 13 Oct 2020 23:45:47 -0400 Subject: [PATCH 105/313] Add message CID to InvocResult --- api/api_full.go | 1 + chain/stmgr/call.go | 2 ++ chain/stmgr/stmgr.go | 1 + documentation/en/api-methods.md | 6 ++++++ node/impl/full/state.go | 1 + 5 files changed, 11 insertions(+) diff --git a/api/api_full.go b/api/api_full.go index 657e945ca..22a7380ac 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -734,6 +734,7 @@ type RetrievalOrder struct { } type InvocResult struct { + MsgCid cid.Cid Msg *types.Message MsgRct *types.MessageReceipt ExecutionTrace types.ExecutionTrace diff --git a/chain/stmgr/call.go b/chain/stmgr/call.go index 8d0f6f6c1..86035140b 100644 --- a/chain/stmgr/call.go +++ b/chain/stmgr/call.go @@ -113,6 +113,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types. } return &api.InvocResult{ + MsgCid: msg.Cid(), Msg: msg, MsgRct: &ret.MessageReceipt, ExecutionTrace: ret.ExecutionTrace, @@ -228,6 +229,7 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri } return &api.InvocResult{ + MsgCid: msg.Cid(), Msg: msg, MsgRct: &ret.MessageReceipt, ExecutionTrace: ret.ExecutionTrace, diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index 0cb17fcf3..e5accc0c9 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -200,6 +200,7 @@ func (sm *StateManager) TipSetState(ctx context.Context, ts *types.TipSet) (st c func traceFunc(trace *[]*api.InvocResult) func(mcid cid.Cid, msg *types.Message, ret *vm.ApplyRet) error { return func(mcid cid.Cid, msg *types.Message, ret *vm.ApplyRet) error { ir := &api.InvocResult{ + MsgCid: mcid, Msg: msg, MsgRct: &ret.MessageReceipt, ExecutionTrace: ret.ExecutionTrace, diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index eefc53ab7..2ed000c59 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -3059,6 +3059,9 @@ Inputs: Response: ```json { + "MsgCid": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, "Msg": { "Version": 42, "To": "f01234", @@ -4079,6 +4082,9 @@ Inputs: Response: ```json { + "MsgCid": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, "Msg": { "Version": 42, "To": "f01234", diff --git a/node/impl/full/state.go b/node/impl/full/state.go index 1c39b59da..08ac62f2e 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -362,6 +362,7 @@ func (a *StateAPI) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid. } return &api.InvocResult{ + MsgCid: mc, Msg: m, MsgRct: &r.MessageReceipt, ExecutionTrace: r.ExecutionTrace, From 2e7cd024df10d9c0ea9840dd17f4ec6b4c980698 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Wed, 14 Oct 2020 02:10:26 -0400 Subject: [PATCH 106/313] Lotus version 0.10.1 --- CHANGELOG.md | 23 +++++++++++++++++++++++ build/version.go | 4 ++-- documentation/en/api-methods.md | 2 +- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16d8d15b8..7c94e387c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,28 @@ # Lotus changelog +# 0.10.1 / 2020-10-14 + +This is an optional release of Lotus that updates markets to 0.9.0, which adds the ability to restart data transfers. This release also introduces Ledger support, and various UX improvements. + +## Changes + +- Test the tape upgrade (https://github.com/filecoin-project/lotus/pull/4328) +- Adding in Ledger support (https://github.com/filecoin-project/lotus/pull/4290) +- Improve the UX for lotus-miner sealing workers (https://github.com/filecoin-project/lotus/pull/4329) +- Add a CLI tool for miner's to repay debt (https://github.com/filecoin-project/lotus/pull/4319) +- Rename params_testnet to params_mainnet (https://github.com/filecoin-project/lotus/pull/4336) +- Use seal-duration in calculating the earliest StartEpoch (https://github.com/filecoin-project/lotus/pull/4337) +- Reject deals that are > 7 days in the future in the BasicDealFilter (https://github.com/filecoin-project/lotus/pull/4173) +- Add an API endpoint to calculate the exact circulating supply (https://github.com/filecoin-project/lotus/pull/4148) +- lotus-pcr: ignore all other market messages (https://github.com/filecoin-project/lotus/pull/4341) +- Add message CID to InvocResult (https://github.com/filecoin-project/lotus/pull/4382) +- types: Add CID fields to messages in json marshalers (https://github.com/filecoin-project/lotus/pull/4338) +- fix(sync state): set state height to actual tipset height (https://github.com/filecoin-project/lotus/pull/4347) +- Fix off by one tipset in searchBackForMsg (https://github.com/filecoin-project/lotus/pull/4367) +- fix a panic on startup when we fail to load the tipset (https://github.com/filecoin-project/lotus/pull/4376) +- Avoid having the same message CID show up in execution traces (https://github.com/filecoin-project/lotus/pull/4350) +- feat(markets): update markets 0.9.0 and add data transfer restart (https://github.com/filecoin-project/lotus/pull/4363) + # 0.10.0 / 2020-10-12 This is a consensus-breaking hotfix that addresses an issue in specs-actors v2.0.3 that made it impossible to pledge new 32GiB sectors. The change in Lotus is to update to actors v2.1.0, behind the new network version 5. diff --git a/build/version.go b/build/version.go index baeafdfe7..39f9d48ff 100644 --- a/build/version.go +++ b/build/version.go @@ -29,7 +29,7 @@ func buildType() string { } // BuildVersion is the local build version, set by build system -const BuildVersion = "0.10.0" +const BuildVersion = "0.10.1" func UserVersion() string { return BuildVersion + buildType() + CurrentCommit @@ -83,7 +83,7 @@ func VersionForType(nodeType NodeType) (Version, error) { // semver versions of the rpc api exposed var ( - FullAPIVersion = newVer(0, 16, 0) + FullAPIVersion = newVer(0, 17, 0) MinerAPIVersion = newVer(0, 15, 0) WorkerAPIVersion = newVer(0, 15, 0) ) diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index 1c8a3a24f..a905ef2e3 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -228,7 +228,7 @@ Response: ```json { "Version": "string value", - "APIVersion": 4096, + "APIVersion": 4352, "BlockDelay": 42 } ``` From 30dd5d9644d88c157b0f025607df84a50e7ad388 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Wed, 14 Oct 2020 11:17:44 +0530 Subject: [PATCH 107/313] use updated stored ask api --- node/modules/storageminer.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 613203a60..adacf5405 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -393,13 +393,13 @@ func NewStorageAsk(ctx helpers.MetricsCtx, fapi lapi.FullNode, ds dtypes.Metadat if err != nil { return nil, err } - storedAsk, err := storedask.NewStoredAsk(namespace.Wrap(providerDs, datastore.NewKey("/storage-ask")), datastore.NewKey("latest"), spn, address.Address(minerAddress)) + storedAsk, err := storedask.NewStoredAsk(namespace.Wrap(providerDs, datastore.NewKey("/storage-ask")), datastore.NewKey("latest"), spn, address.Address(minerAddress), + storagemarket.MaxPieceSize(abi.PaddedPieceSize(mi.SectorSize))) if err != nil { return nil, err } - // Hacky way to set max piece size to the sector size a := storedAsk.GetAsk().Ask - err = storedAsk.SetAsk(a.Price, a.VerifiedPrice, a.Expiry-a.Timestamp, storagemarket.MaxPieceSize(abi.PaddedPieceSize(mi.SectorSize))) + err = storedAsk.SetAsk(a.Price, a.VerifiedPrice, a.Expiry-a.Timestamp) if err != nil { return storedAsk, err } From c6ed6a0d65bbf294c1d634161b2ea4288630bddf Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Wed, 14 Oct 2020 14:53:11 +0200 Subject: [PATCH 108/313] Add support for /https, /http, /wss API multiaddresses. Lotus API endpoint are by default expressed as multiaddresses (i.e. lotus auth api-info) which end in /http, although they can be provided as standard URLs too. There is an inconsistency here because despite the "http" part, Lotus will use "ws" protocol. This lets lotus default to "ws" but honor whatever the user puts in the multiaddress (i.e. /dns4/my.lotus.node/tcp/443/https) would work now using https, where before it uses "ws". --- cli/util/apiinfo.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/cli/util/apiinfo.go b/cli/util/apiinfo.go index 1f9a83769..dec4c2e19 100644 --- a/cli/util/apiinfo.go +++ b/cli/util/apiinfo.go @@ -44,7 +44,22 @@ func (a APIInfo) DialArgs() (string, error) { return "", err } - return "ws://" + addr + "/rpc/v0", nil + protocol := "ws" + + // If the user specifies the multiaddress as + // /something/tcp/1234/http or/something/tcp/1234/https + // or /something/tcp/1234/wss then honor that. + for _, p := range []int{ + multiaddr.P_HTTP, + multiaddr.P_HTTPS, + multiaddr.P_WSS, + } { + if _, err := ma.ValueForProtocol(p); err == nil { + protocol = multiaddr.ProtocolWithCode(p).Name + break + } + } + return protocol + "://" + addr + "/rpc/v0", nil } _, err = url.Parse(a.Addr) From 00a50831460c41727cb9d1bc67a1ef4f78b949a0 Mon Sep 17 00:00:00 2001 From: David Dias Date: Wed, 14 Oct 2020 15:11:30 +0200 Subject: [PATCH 109/313] Update SECURITY.md --- SECURITY.md | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index ecb600deb..592206bc5 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,9 +2,7 @@ ## Reporting a Vulnerability -For *critical* bugs, please send an email to security@filecoin.org. - -The bug reporting process differs between bugs that are critical and may crash the network, and others that are unlikely to cause problems if malicious parties know about it. For non-critical bugs, please simply file a GitHub [issue](https://github.com/filecoin-project/lotus/issues/new?template=bug_report.md). +For *critical* bugs, please consult our Security Policy and Responsible Disclosure Program information at https://github.com/filecoin-project/community/blob/master/SECURITY.md Please try to provide a clear description of any bugs reported, along with how to reproduce the bug if possible. More detailed bug reports (especially those with a PoC included) will help us move forward much faster. Additionally, please avoid reporting bugs that already have open issues. Take a moment to search the issue list of the related GitHub repositories before writing up a new report. @@ -20,10 +18,6 @@ Here are some examples of bugs we would consider 'critical': This is not an exhaustive list, but should provide some idea of what we consider 'critical'. -## Supported Versions +## Reporting a non security bug -* TODO: This should be defined and set up by Mainnet launch. - -| Version | Supported | -| ------- | ------------------ | -| Testnet | :white_check_mark: | +For non-critical bugs, please simply file a GitHub [issue](https://github.com/filecoin-project/lotus/issues/new?template=bug_report.md). From 45cd510da11807351ef87cc47c4169581eb2779b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Tue, 13 Oct 2020 23:00:01 +0100 Subject: [PATCH 110/313] conformance: support multiple protocol versions. This PR introduces support for running multiple variants of a vector, each of which targets a unique protocol version. tvx tooling has been adapted to produce and parse the new version of the schema. --- cmd/tvx/codenames.go | 40 ++++++++++++++++++++++++++++++++++++++ cmd/tvx/codenames_test.go | 28 ++++++++++++++++++++++++++ cmd/tvx/exec.go | 30 +++++++++++++++------------- cmd/tvx/extract.go | 14 ++++++++++++- conformance/corpus_test.go | 22 ++++++++++++++------- conformance/driver.go | 5 ++--- conformance/runner.go | 26 +++++++++++++------------ go.mod | 2 +- go.sum | 4 ++-- 9 files changed, 132 insertions(+), 39 deletions(-) create mode 100644 cmd/tvx/codenames.go create mode 100644 cmd/tvx/codenames_test.go diff --git a/cmd/tvx/codenames.go b/cmd/tvx/codenames.go new file mode 100644 index 000000000..1cb1b32fb --- /dev/null +++ b/cmd/tvx/codenames.go @@ -0,0 +1,40 @@ +package main + +import ( + "github.com/filecoin-project/go-state-types/abi" + + "github.com/filecoin-project/lotus/build" +) + +// ProtocolCodenames is a table that summarises the protocol codenames that +// will be set on extracted vectors, depending on the original execution height. +// +// Implementers rely on these names to filter the vectors they can run through +// their implementations, based on their support level +var ProtocolCodenames = []struct { + firstEpoch abi.ChainEpoch + name string +}{ + {0, "genesis"}, + // TODO there is some off-by-one trickery in GetNtwkVersion. Not sure if the + // protocol version really kicks in at the designated height, or at the + // following epoch. + {build.UpgradeBreezeHeight + 1, "breeze"}, + {build.UpgradeSmokeHeight + 1, "smoke"}, + {build.UpgradeIgnitionHeight + 1, "ignition"}, + {build.UpgradeRefuelHeight + 1, "refuel"}, + {build.UpgradeActorsV2Height + 1, "actorsv2"}, + {build.UpgradeTapeHeight + 1, "tape"}, + {build.UpgradeLiftoffHeight + 1, "liftoff"}, +} + +// GetProtocolCodename gets the protocol codename associated with a height. +func GetProtocolCodename(height abi.ChainEpoch) string { + for i, v := range ProtocolCodenames { + if height < v.firstEpoch { + // found the cutoff, return previous. + return ProtocolCodenames[i-1].name + } + } + return ProtocolCodenames[len(ProtocolCodenames)-1].name +} diff --git a/cmd/tvx/codenames_test.go b/cmd/tvx/codenames_test.go new file mode 100644 index 000000000..0b1de9fc2 --- /dev/null +++ b/cmd/tvx/codenames_test.go @@ -0,0 +1,28 @@ +package main + +import ( + "math" + "testing" + + "github.com/filecoin-project/go-state-types/abi" + + "github.com/filecoin-project/lotus/build" +) + +func TestProtocolCodenames(t *testing.T) { + if height := abi.ChainEpoch(100); GetProtocolCodename(height) != "genesis" { + t.Fatal("expected genesis codename") + } + + if height := abi.ChainEpoch(build.UpgradeBreezeHeight + 1); GetProtocolCodename(height) != "breeze" { + t.Fatal("expected breeze codename") + } + + if height := abi.ChainEpoch(build.UpgradeActorsV2Height + 1); GetProtocolCodename(height) != "actorsv2" { + t.Fatal("expected actorsv2 codename") + } + + if height := abi.ChainEpoch(math.MaxInt64); GetProtocolCodename(height) != ProtocolCodenames[len(ProtocolCodenames)-1].name { + t.Fatal("expected last codename") + } +} diff --git a/cmd/tvx/exec.go b/cmd/tvx/exec.go index 9ec6f9e2b..de7d2a398 100644 --- a/cmd/tvx/exec.go +++ b/cmd/tvx/exec.go @@ -72,20 +72,24 @@ func runExecLotus(_ *cli.Context) error { func executeTestVector(tv schema.TestVector) error { log.Println("executing test vector:", tv.Meta.ID) - r := new(conformance.LogReporter) - switch class := tv.Class; class { - case "message": - conformance.ExecuteMessageVector(r, &tv) - case "tipset": - conformance.ExecuteTipsetVector(r, &tv) - default: - return fmt.Errorf("test vector class %s not supported", class) - } - if r.Failed() { - log.Println(color.HiRedString("❌ test vector failed")) - } else { - log.Println(color.GreenString("✅ test vector succeeded")) + for _, v := range tv.Pre.Variants { + r := new(conformance.LogReporter) + + switch class := tv.Class; class { + case "message": + conformance.ExecuteMessageVector(r, &tv, &v) + case "tipset": + conformance.ExecuteTipsetVector(r, &tv, &v) + default: + return fmt.Errorf("test vector class %s not supported", class) + } + + if r.Failed() { + log.Println(color.HiRedString("❌ test vector failed for variant %s", v.ID)) + } else { + log.Println(color.GreenString("✅ test vector succeeded for variant %s", v.ID)) + } } return nil diff --git a/cmd/tvx/extract.go b/cmd/tvx/extract.go index 4bb391af6..4a8dd162c 100644 --- a/cmd/tvx/extract.go +++ b/cmd/tvx/extract.go @@ -347,6 +347,13 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error { return err } + nv, err := fapi.StateNetworkVersion(ctx, execTs.Key()) + if err != nil { + return err + } + + codename := GetProtocolCodename(execTs.Height()) + // Write out the test vector. vector := schema.TestVector{ Class: schema.ClassMessage, @@ -363,10 +370,15 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error { {Source: fmt.Sprintf("execution_tipset:%s", execTs.Key().String())}, {Source: "github.com/filecoin-project/lotus", Version: version.String()}}, }, + Selector: schema.Selector{ + schema.SelectorMinProtocolVersion: codename, + }, Randomness: recordingRand.Recorded(), CAR: out.Bytes(), Pre: &schema.Preconditions{ - Epoch: int64(execTs.Height()), + Variants: []schema.Variant{ + {ID: codename, Epoch: int64(execTs.Height()), NetworkVersion: uint(nv)}, + }, CircSupply: circSupply.Int, BaseFee: basefee.Int, StateTree: &schema.StateTree{ diff --git a/conformance/corpus_test.go b/conformance/corpus_test.go index 3d447570d..a09f9a8d3 100644 --- a/conformance/corpus_test.go +++ b/conformance/corpus_test.go @@ -11,6 +11,11 @@ import ( "github.com/filecoin-project/test-vectors/schema" ) +var invokees = map[schema.Class]func(Reporter, *schema.TestVector, *schema.Variant){ + schema.ClassMessage: ExecuteMessageVector, + schema.ClassTipset: ExecuteTipsetVector, +} + const ( // EnvSkipConformance, if 1, skips the conformance test suite. EnvSkipConformance = "SKIP_CONFORMANCE" @@ -120,13 +125,16 @@ func TestConformance(t *testing.T) { } // dispatch the execution depending on the vector class. - switch vector.Class { - case "message": - ExecuteMessageVector(t, &vector) - case "tipset": - ExecuteTipsetVector(t, &vector) - default: - t.Fatalf("test vector class not supported: %s", vector.Class) + invokee, ok := invokees[vector.Class] + if !ok { + t.Fatalf("unsupported test vector class: %s", vector.Class) + } + + for _, variant := range vector.Pre.Variants { + variant := variant + t.Run(variant.ID, func(t *testing.T) { + invokee(t, &vector, &variant) + }) } }) } diff --git a/conformance/driver.go b/conformance/driver.go index f49022b9c..fbb7dda6d 100644 --- a/conformance/driver.go +++ b/conformance/driver.go @@ -82,7 +82,7 @@ type ExecuteTipsetResult struct { // This method returns the the receipts root, the poststate root, and the VM // message results. The latter _include_ implicit messages, such as cron ticks // and reward withdrawal per miner. -func (d *Driver) ExecuteTipset(bs blockstore.Blockstore, ds ds.Batching, preroot cid.Cid, parentEpoch abi.ChainEpoch, tipset *schema.Tipset) (*ExecuteTipsetResult, error) { +func (d *Driver) ExecuteTipset(bs blockstore.Blockstore, ds ds.Batching, preroot cid.Cid, parentEpoch abi.ChainEpoch, tipset *schema.Tipset, execEpoch abi.ChainEpoch) (*ExecuteTipsetResult, error) { var ( syscalls = vm.Syscalls(ffiwrapper.ProofVerifier) vmRand = NewFixedRand() @@ -121,11 +121,10 @@ func (d *Driver) ExecuteTipset(bs blockstore.Blockstore, ds ds.Batching, preroot messages []*types.Message results []*vm.ApplyRet - epoch = abi.ChainEpoch(tipset.Epoch) basefee = abi.NewTokenAmount(tipset.BaseFee.Int64()) ) - postcid, receiptsroot, err := sm.ApplyBlocks(context.Background(), parentEpoch, preroot, blocks, epoch, vmRand, func(_ cid.Cid, msg *types.Message, ret *vm.ApplyRet) error { + postcid, receiptsroot, err := sm.ApplyBlocks(context.Background(), parentEpoch, preroot, blocks, execEpoch, vmRand, func(_ cid.Cid, msg *types.Message, ret *vm.ApplyRet) error { messages = append(messages, msg) results = append(results, ret) return nil diff --git a/conformance/runner.go b/conformance/runner.go index d489ac288..6f9d73305 100644 --- a/conformance/runner.go +++ b/conformance/runner.go @@ -30,11 +30,11 @@ import ( ) // ExecuteMessageVector executes a message-class test vector. -func ExecuteMessageVector(r Reporter, vector *schema.TestVector) { +func ExecuteMessageVector(r Reporter, vector *schema.TestVector, variant *schema.Variant) { var ( - ctx = context.Background() - epoch = vector.Pre.Epoch - root = vector.Pre.StateTree.RootCID + ctx = context.Background() + baseEpoch = variant.Epoch + root = vector.Pre.StateTree.RootCID ) // Load the CAR into a new temporary Blockstore. @@ -53,16 +53,16 @@ func ExecuteMessageVector(r Reporter, vector *schema.TestVector) { r.Fatalf("failed to deserialize message: %s", err) } - // add an epoch if one's set. - if m.Epoch != nil { - epoch = *m.Epoch + // add the epoch offset if one is set. + if m.EpochOffset != nil { + baseEpoch += *m.EpochOffset } // Execute the message. var ret *vm.ApplyRet ret, root, err = driver.ExecuteMessage(bs, ExecuteMessageParams{ Preroot: root, - Epoch: abi.ChainEpoch(epoch), + Epoch: abi.ChainEpoch(baseEpoch), Message: msg, BaseFee: BaseFeeOrDefault(vector.Pre.BaseFee), CircSupply: CircSupplyOrDefault(vector.Pre.CircSupply), @@ -86,10 +86,10 @@ func ExecuteMessageVector(r Reporter, vector *schema.TestVector) { } // ExecuteTipsetVector executes a tipset-class test vector. -func ExecuteTipsetVector(r Reporter, vector *schema.TestVector) { +func ExecuteTipsetVector(r Reporter, vector *schema.TestVector, variant *schema.Variant) { var ( ctx = context.Background() - prevEpoch = vector.Pre.Epoch + baseEpoch = abi.ChainEpoch(variant.Epoch) root = vector.Pre.StateTree.RootCID tmpds = ds.NewMapDatastore() ) @@ -105,9 +105,11 @@ func ExecuteTipsetVector(r Reporter, vector *schema.TestVector) { // Apply every tipset. var receiptsIdx int + var prevEpoch = baseEpoch for i, ts := range vector.ApplyTipsets { ts := ts // capture - ret, err := driver.ExecuteTipset(bs, tmpds, root, abi.ChainEpoch(prevEpoch), &ts) + execEpoch := baseEpoch + abi.ChainEpoch(ts.EpochOffset) + ret, err := driver.ExecuteTipset(bs, tmpds, root, prevEpoch, &ts, execEpoch) if err != nil { r.Fatalf("failed to apply tipset %d message: %s", i, err) } @@ -122,7 +124,7 @@ func ExecuteTipsetVector(r Reporter, vector *schema.TestVector) { r.Errorf("post receipts root doesn't match; expected: %s, was: %s", expected, actual) } - prevEpoch = ts.Epoch + prevEpoch = execEpoch root = ret.PostStateRoot } diff --git a/go.mod b/go.mod index 0118baa88..1516cba81 100644 --- a/go.mod +++ b/go.mod @@ -41,7 +41,7 @@ require ( github.com/filecoin-project/specs-actors v0.9.12 github.com/filecoin-project/specs-actors/v2 v2.1.0 github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796 - github.com/filecoin-project/test-vectors/schema v0.0.4 + github.com/filecoin-project/test-vectors/schema v0.0.5-0.20201014133607-1352e6bb4e71 github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1 github.com/go-kit/kit v0.10.0 github.com/go-ole/go-ole v1.2.4 // indirect diff --git a/go.sum b/go.sum index 2b0859bfd..47301c784 100644 --- a/go.sum +++ b/go.sum @@ -282,8 +282,8 @@ github.com/filecoin-project/specs-actors/v2 v2.1.0 h1:ocEuGz8DG2cUWw32c/tvF8D6xT github.com/filecoin-project/specs-actors/v2 v2.1.0/go.mod h1:E7fAX4CZkDVQvDNRCxfq+hc3nx56KcCKyuZf0hlQJ20= github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796 h1:dJsTPWpG2pcTeojO2pyn0c6l+x/3MZYCBgo/9d11JEk= github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g= -github.com/filecoin-project/test-vectors/schema v0.0.4 h1:QTRd0gb/NP4ZOTM7Dib5U3xE1/ToGDKnYLfxkC3t/m8= -github.com/filecoin-project/test-vectors/schema v0.0.4/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E= +github.com/filecoin-project/test-vectors/schema v0.0.5-0.20201014133607-1352e6bb4e71 h1:qnleaW7X8Gi2e3QtqPMFdqVn/DUaNI5tCnq7wNVMnio= +github.com/filecoin-project/test-vectors/schema v0.0.5-0.20201014133607-1352e6bb4e71/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6 h1:u/UEqS66A5ckRmS4yNpjmVH56sVtS/RfclBAYocb4as= github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6/go.mod h1:1i71OnUq3iUe1ma7Lr6yG6/rjvM3emb6yoL7xLFzcVQ= From 12f36c5bda4c8c49b42bbaf19d0964bccf448987 Mon Sep 17 00:00:00 2001 From: Whyrusleeping Date: Wed, 14 Oct 2020 09:22:25 -0500 Subject: [PATCH 111/313] Update cmd/lotus-gateway/api.go Co-authored-by: dirkmc --- cmd/lotus-gateway/api.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/lotus-gateway/api.go b/cmd/lotus-gateway/api.go index 381dd931b..8f1d69c18 100644 --- a/cmd/lotus-gateway/api.go +++ b/cmd/lotus-gateway/api.go @@ -182,6 +182,9 @@ func (a *GatewayAPI) WalletVerify(ctx context.Context, k address.Address, msg [] } func (a *GatewayAPI) StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error) { + if err := a.checkTipsetKey(ctx, tsk); err != nil { + return nil, err + } return a.api.StateReadState(ctx, actor, tsk) } From ab4f051b837646cd2fe7efeef98513604e2abf82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 14 Oct 2020 18:09:31 +0200 Subject: [PATCH 112/313] sync wait --watch --- cli/sync.go | 12 +++++++++--- cmd/lotus-storage-miner/init.go | 2 +- cmd/lotus-storage-miner/init_restore.go | 2 +- cmd/lotus-storage-miner/run.go | 2 +- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/cli/sync.go b/cli/sync.go index ea066cbda..c3f25eb1d 100644 --- a/cli/sync.go +++ b/cli/sync.go @@ -84,6 +84,12 @@ var syncStatusCmd = &cli.Command{ var syncWaitCmd = &cli.Command{ Name: "wait", Usage: "Wait for sync to be complete", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "watch", + Usage: "don't exit after node is synced", + }, + }, Action: func(cctx *cli.Context) error { napi, closer, err := GetFullNodeAPI(cctx) if err != nil { @@ -92,7 +98,7 @@ var syncWaitCmd = &cli.Command{ defer closer() ctx := ReqContext(cctx) - return SyncWait(ctx, napi) + return SyncWait(ctx, napi, cctx.Bool("watch")) }, } @@ -234,7 +240,7 @@ var syncCheckpointCmd = &cli.Command{ }, } -func SyncWait(ctx context.Context, napi api.FullNode) error { +func SyncWait(ctx context.Context, napi api.FullNode, watch bool) error { tick := time.Second / 4 lastLines := 0 @@ -311,7 +317,7 @@ func SyncWait(ctx context.Context, napi api.FullNode) error { _ = target // todo: maybe print? (creates a bunch of line wrapping issues with most tipsets) - if time.Now().Unix()-int64(head.MinTimestamp()) < int64(build.BlockDelaySecs) { + if !watch && time.Now().Unix()-int64(head.MinTimestamp()) < int64(build.BlockDelaySecs) { fmt.Println("\nDone!") return nil } diff --git a/cmd/lotus-storage-miner/init.go b/cmd/lotus-storage-miner/init.go index ccea707af..326a39e5e 100644 --- a/cmd/lotus-storage-miner/init.go +++ b/cmd/lotus-storage-miner/init.go @@ -155,7 +155,7 @@ var initCmd = &cli.Command{ log.Info("Checking full node sync status") if !cctx.Bool("genesis-miner") && !cctx.Bool("nosync") { - if err := lcli.SyncWait(ctx, api); err != nil { + if err := lcli.SyncWait(ctx, api, false); err != nil { return xerrors.Errorf("sync wait: %w", err) } } diff --git a/cmd/lotus-storage-miner/init_restore.go b/cmd/lotus-storage-miner/init_restore.go index bdbb99fe0..83a9ad87c 100644 --- a/cmd/lotus-storage-miner/init_restore.go +++ b/cmd/lotus-storage-miner/init_restore.go @@ -72,7 +72,7 @@ var initRestoreCmd = &cli.Command{ } if !cctx.Bool("nosync") { - if err := lcli.SyncWait(ctx, api); err != nil { + if err := lcli.SyncWait(ctx, api, false); err != nil { return xerrors.Errorf("sync wait: %w", err) } } diff --git a/cmd/lotus-storage-miner/run.go b/cmd/lotus-storage-miner/run.go index 98a9cfaba..c043bd903 100644 --- a/cmd/lotus-storage-miner/run.go +++ b/cmd/lotus-storage-miner/run.go @@ -84,7 +84,7 @@ var runCmd = &cli.Command{ log.Info("Checking full node sync status") if !cctx.Bool("nosync") { - if err := lcli.SyncWait(ctx, nodeApi); err != nil { + if err := lcli.SyncWait(ctx, nodeApi, false); err != nil { return xerrors.Errorf("sync wait: %w", err) } } From b060569fe92cb374ef79c22df2dab40e93c43477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 14 Oct 2020 19:55:36 +0200 Subject: [PATCH 113/313] Revert "Add support for /https, /http, /wss API multiaddresses." --- cli/util/apiinfo.go | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/cli/util/apiinfo.go b/cli/util/apiinfo.go index dec4c2e19..1f9a83769 100644 --- a/cli/util/apiinfo.go +++ b/cli/util/apiinfo.go @@ -44,22 +44,7 @@ func (a APIInfo) DialArgs() (string, error) { return "", err } - protocol := "ws" - - // If the user specifies the multiaddress as - // /something/tcp/1234/http or/something/tcp/1234/https - // or /something/tcp/1234/wss then honor that. - for _, p := range []int{ - multiaddr.P_HTTP, - multiaddr.P_HTTPS, - multiaddr.P_WSS, - } { - if _, err := ma.ValueForProtocol(p); err == nil { - protocol = multiaddr.ProtocolWithCode(p).Name - break - } - } - return protocol + "://" + addr + "/rpc/v0", nil + return "ws://" + addr + "/rpc/v0", nil } _, err = url.Parse(a.Addr) From 8df58064e3da1a19cc9ae1e869443143b1636be6 Mon Sep 17 00:00:00 2001 From: hannahhoward Date: Wed, 14 Oct 2020 13:20:18 -0700 Subject: [PATCH 114/313] feat(markets): update to 0.9.1 bugfix release --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0118baa88..c3935be19 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 github.com/filecoin-project/go-data-transfer v0.9.0 github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f - github.com/filecoin-project/go-fil-markets v0.9.0 + github.com/filecoin-project/go-fil-markets v0.9.1 github.com/filecoin-project/go-jsonrpc v0.1.2-0.20201008195726-68c6a2704e49 github.com/filecoin-project/go-multistore v0.0.3 github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20 diff --git a/go.sum b/go.sum index 2b0859bfd..feff6abbd 100644 --- a/go.sum +++ b/go.sum @@ -246,8 +246,8 @@ github.com/filecoin-project/go-ds-versioning v0.1.0 h1:y/X6UksYTsK8TLCI7rttCKEvl github.com/filecoin-project/go-ds-versioning v0.1.0/go.mod h1:mp16rb4i2QPmxBnmanUx8i/XANp+PFCCJWiAb+VW4/s= github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f h1:GxJzR3oRIMTPtpZ0b7QF8FKPK6/iPAc7trhlL5k/g+s= github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= -github.com/filecoin-project/go-fil-markets v0.9.0 h1:RVdMKeOdRtpHawB14+uvJhvq243/UfZ4g3yFa/6qekk= -github.com/filecoin-project/go-fil-markets v0.9.0/go.mod h1:h+bJ/IUnYjnW5HMKyt9JQSnhslqetkpuzwwugc3K8vM= +github.com/filecoin-project/go-fil-markets v0.9.1 h1:MgO+UkpreD6x8DV2Zkw2xlBogixfpw9/wf4+nBii7bU= +github.com/filecoin-project/go-fil-markets v0.9.1/go.mod h1:h+bJ/IUnYjnW5HMKyt9JQSnhslqetkpuzwwugc3K8vM= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= From 470a565c349cd150675b01607ea08cd995b407ee Mon Sep 17 00:00:00 2001 From: frrist Date: Wed, 14 Oct 2020 14:27:35 -0700 Subject: [PATCH 115/313] fix: return true when deadlines changed --- chain/actors/builtin/miner/v0.go | 2 +- chain/actors/builtin/miner/v2.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/chain/actors/builtin/miner/v0.go b/chain/actors/builtin/miner/v0.go index 14718d002..1b1c817b6 100644 --- a/chain/actors/builtin/miner/v0.go +++ b/chain/actors/builtin/miner/v0.go @@ -274,7 +274,7 @@ func (s *state0) DeadlinesChanged(other State) (bool, error) { return true, nil } - return s.State.Deadlines.Equals(other0.Deadlines), nil + return !s.State.Deadlines.Equals(other0.Deadlines), nil } func (s *state0) Info() (MinerInfo, error) { diff --git a/chain/actors/builtin/miner/v2.go b/chain/actors/builtin/miner/v2.go index 9e599f891..7217f6b58 100644 --- a/chain/actors/builtin/miner/v2.go +++ b/chain/actors/builtin/miner/v2.go @@ -273,7 +273,7 @@ func (s *state2) DeadlinesChanged(other State) (bool, error) { return true, nil } - return s.State.Deadlines.Equals(other2.Deadlines), nil + return !s.State.Deadlines.Equals(other2.Deadlines), nil } func (s *state2) Info() (MinerInfo, error) { From ea1349205b69c548b35b774830c592ba8bdd6997 Mon Sep 17 00:00:00 2001 From: frrist Date: Wed, 14 Oct 2020 14:37:33 -0700 Subject: [PATCH 116/313] fix: return true when partitions changed --- chain/actors/builtin/miner/v0.go | 2 +- chain/actors/builtin/miner/v2.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/chain/actors/builtin/miner/v0.go b/chain/actors/builtin/miner/v0.go index 1b1c817b6..c79f4a2f7 100644 --- a/chain/actors/builtin/miner/v0.go +++ b/chain/actors/builtin/miner/v0.go @@ -370,7 +370,7 @@ func (d *deadline0) PartitionsChanged(other Deadline) (bool, error) { return true, nil } - return d.Deadline.Partitions.Equals(other0.Deadline.Partitions), nil + return !d.Deadline.Partitions.Equals(other0.Deadline.Partitions), nil } func (d *deadline0) PostSubmissions() (bitfield.BitField, error) { diff --git a/chain/actors/builtin/miner/v2.go b/chain/actors/builtin/miner/v2.go index 7217f6b58..c686fa483 100644 --- a/chain/actors/builtin/miner/v2.go +++ b/chain/actors/builtin/miner/v2.go @@ -369,7 +369,7 @@ func (d *deadline2) PartitionsChanged(other Deadline) (bool, error) { return true, nil } - return d.Deadline.Partitions.Equals(other2.Deadline.Partitions), nil + return !d.Deadline.Partitions.Equals(other2.Deadline.Partitions), nil } func (d *deadline2) PostSubmissions() (bitfield.BitField, error) { From bbc6de94fc5ce48aa18928827ff6485f96c7f27d Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 14 Oct 2020 12:23:11 -0700 Subject: [PATCH 117/313] write messages to a temp blockstore when validating --- chain/sync.go | 86 ++++++++++++++++++++++++++++----------------------- 1 file changed, 47 insertions(+), 39 deletions(-) diff --git a/chain/sync.go b/chain/sync.go index dd83bf319..97915d8df 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -323,25 +323,35 @@ func (syncer *Syncer) ValidateMsgMeta(fblk *types.FullBlock) error { return xerrors.Errorf("block %s has too many messages (%d)", fblk.Header.Cid(), msgc) } - // Collect the CIDs of both types of messages separately: BLS and Secpk. - var bcids, scids []cid.Cid - for _, m := range fblk.BlsMessages { - bcids = append(bcids, m.Cid()) - } - - for _, m := range fblk.SecpkMessages { - scids = append(scids, m.Cid()) - } - // TODO: IMPORTANT(GARBAGE). These message puts and the msgmeta // computation need to go into the 'temporary' side of the blockstore when // we implement that - blockstore := syncer.store.Blockstore() - bs := cbor.NewCborStore(blockstore) + // We use a temporary bstore here to avoid writing intermediate pieces + // into the blockstore. + blockstore := bstore.NewTemporary() + cst := cbor.NewCborStore(blockstore) + + var bcids, scids []cid.Cid + + for _, m := range fblk.BlsMessages { + c, err := store.PutMessage(blockstore, m) + if err != nil { + return xerrors.Errorf("putting bls message to blockstore after msgmeta computation: %w", err) + } + bcids = append(bcids, c) + } + + for _, m := range fblk.SecpkMessages { + c, err := store.PutMessage(blockstore, m) + if err != nil { + return xerrors.Errorf("putting bls message to blockstore after msgmeta computation: %w", err) + } + scids = append(scids, c) + } // Compute the root CID of the combined message trie. - smroot, err := computeMsgMeta(bs, bcids, scids) + smroot, err := computeMsgMeta(cst, bcids, scids) if err != nil { return xerrors.Errorf("validating msgmeta, compute failed: %w", err) } @@ -351,21 +361,8 @@ func (syncer *Syncer) ValidateMsgMeta(fblk *types.FullBlock) error { return xerrors.Errorf("messages in full block did not match msgmeta root in header (%s != %s)", fblk.Header.Messages, smroot) } - for _, m := range fblk.BlsMessages { - _, err := store.PutMessage(blockstore, m) - if err != nil { - return xerrors.Errorf("putting bls message to blockstore after msgmeta computation: %w", err) - } - } - - for _, m := range fblk.SecpkMessages { - _, err := store.PutMessage(blockstore, m) - if err != nil { - return xerrors.Errorf("putting bls message to blockstore after msgmeta computation: %w", err) - } - } - - return nil + // Finally, flush. + return vm.Copy(context.TODO(), blockstore, syncer.store.Blockstore(), smroot) } func (syncer *Syncer) LocalPeer() peer.ID { @@ -1064,8 +1061,7 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock return err } - cst := cbor.NewCborStore(syncer.store.Blockstore()) - st, err := state.LoadStateTree(cst, stateroot) + st, err := state.LoadStateTree(syncer.store.Store(ctx), stateroot) if err != nil { return xerrors.Errorf("failed to load base state tree: %w", err) } @@ -1111,21 +1107,28 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock return nil } - store := adt0.WrapStore(ctx, cst) + // Validate message arrays in a temporary blockstore. + tmpbs := bstore.NewTemporary() + tmpstore := adt0.WrapStore(ctx, cbor.NewCborStore(tmpbs)) - bmArr := adt0.MakeEmptyArray(store) + bmArr := adt0.MakeEmptyArray(tmpstore) for i, m := range b.BlsMessages { if err := checkMsg(m); err != nil { return xerrors.Errorf("block had invalid bls message at index %d: %w", i, err) } - c := cbg.CborCid(m.Cid()) - if err := bmArr.Set(uint64(i), &c); err != nil { + c, err := store.PutMessage(tmpbs, m) + if err != nil { + return xerrors.Errorf("failed to store message %s: %w", m.Cid(), err) + } + + k := cbg.CborCid(c) + if err := bmArr.Set(uint64(i), &k); err != nil { return xerrors.Errorf("failed to put bls message at index %d: %w", i, err) } } - smArr := adt0.MakeEmptyArray(store) + smArr := adt0.MakeEmptyArray(tmpstore) for i, m := range b.SecpkMessages { if err := checkMsg(m); err != nil { return xerrors.Errorf("block had invalid secpk message at index %d: %w", i, err) @@ -1142,8 +1145,12 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock return xerrors.Errorf("secpk message %s has invalid signature: %w", m.Cid(), err) } - c := cbg.CborCid(m.Cid()) - if err := smArr.Set(uint64(i), &c); err != nil { + c, err := store.PutMessage(tmpbs, m) + if err != nil { + return xerrors.Errorf("failed to store message %s: %w", m.Cid(), err) + } + k := cbg.CborCid(c) + if err := smArr.Set(uint64(i), &k); err != nil { return xerrors.Errorf("failed to put secpk message at index %d: %w", i, err) } } @@ -1158,7 +1165,7 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock return err } - mrcid, err := cst.Put(ctx, &types.MsgMeta{ + mrcid, err := tmpstore.Put(ctx, &types.MsgMeta{ BlsMessages: bmroot, SecpkMessages: smroot, }) @@ -1170,7 +1177,8 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock return fmt.Errorf("messages didnt match message root in header") } - return nil + // Finally, flush. + return vm.Copy(ctx, tmpbs, syncer.store.Blockstore(), mrcid) } func (syncer *Syncer) verifyBlsAggregate(ctx context.Context, sig *crypto.Signature, msgs []cid.Cid, pubks [][]byte) error { From e2fbbdcb15d30c79e02810a5bca1d8a5467e5c4b Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 14 Oct 2020 12:23:30 -0700 Subject: [PATCH 118/313] reject messages with invalid CIDs These can't possibly be valid messages, so we should just drop the block. --- chain/sub/incoming.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/chain/sub/incoming.go b/chain/sub/incoming.go index 68ee5e20c..99ca2fc65 100644 --- a/chain/sub/incoming.go +++ b/chain/sub/incoming.go @@ -37,6 +37,7 @@ import ( "github.com/filecoin-project/lotus/lib/bufbstore" "github.com/filecoin-project/lotus/lib/sigs" "github.com/filecoin-project/lotus/metrics" + "github.com/filecoin-project/lotus/node/impl/client" ) var log = logging.Logger("sub") @@ -44,6 +45,13 @@ var log = logging.Logger("sub") var ErrSoftFailure = errors.New("soft validation failure") var ErrInsufficientPower = errors.New("incoming block's miner does not have minimum power") +var msgCidPrefix = cid.Prefix{ + Version: 1, + Codec: cid.DagCBOR, + MhType: client.DefaultHashFunction, + MhLength: 32, +} + func HandleIncomingBlocks(ctx context.Context, bsub *pubsub.Subscription, s *chain.Syncer, bs bserv.BlockService, cmgr connmgr.ConnManager) { // Timeout after (block time + propagation delay). This is useless at // this point. @@ -168,6 +176,9 @@ func fetchCids( cidIndex := make(map[cid.Cid]int) for i, c := range cids { + if c.Prefix() != msgCidPrefix { + return fmt.Errorf("invalid msg CID: %s", c) + } cidIndex[c] = i } if len(cids) != len(cidIndex) { From 4b38809c0b4cab14fef028c24502c096937c1c7b Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 12 Oct 2020 15:52:38 -0700 Subject: [PATCH 119/313] in-memory blockstore Instead of using an in-memory datastore and dealing with the overhead of computing datastore keys, creating new blocks, etc, use an in-memory blockstore. --- lib/blockstore/blockstore.go | 9 ++-- lib/blockstore/memstore.go | 80 ++++++++++++++++++++++++++++++++++++ lib/blockstore/syncstore.go | 68 ++++++++++++++++++++++++++++++ lib/bufbstore/buf_bstore.go | 4 +- 4 files changed, 155 insertions(+), 6 deletions(-) create mode 100644 lib/blockstore/memstore.go create mode 100644 lib/blockstore/syncstore.go diff --git a/lib/blockstore/blockstore.go b/lib/blockstore/blockstore.go index 9e74f4373..f274cd708 100644 --- a/lib/blockstore/blockstore.go +++ b/lib/blockstore/blockstore.go @@ -18,19 +18,18 @@ import ( "context" ds "github.com/ipfs/go-datastore" - dssync "github.com/ipfs/go-datastore/sync" blockstore "github.com/ipfs/go-ipfs-blockstore" ) // NewTemporary returns a temporary blockstore. -func NewTemporary() blockstore.Blockstore { - return NewBlockstore(ds.NewMapDatastore()) +func NewTemporary() MemStore { + return make(MemStore) } // NewTemporarySync returns a thread-safe temporary blockstore. -func NewTemporarySync() blockstore.Blockstore { - return NewBlockstore(dssync.MutexWrap(ds.NewMapDatastore())) +func NewTemporarySync() *SyncStore { + return &SyncStore{bs: make(MemStore)} } // WrapIDStore wraps the underlying blockstore in an "identity" blockstore. diff --git a/lib/blockstore/memstore.go b/lib/blockstore/memstore.go new file mode 100644 index 000000000..9745d6f03 --- /dev/null +++ b/lib/blockstore/memstore.go @@ -0,0 +1,80 @@ +package blockstore + +import ( + "context" + + blocks "github.com/ipfs/go-block-format" + "github.com/ipfs/go-cid" + blockstore "github.com/ipfs/go-ipfs-blockstore" +) + +type MemStore map[cid.Cid]blocks.Block + +func (m MemStore) DeleteBlock(k cid.Cid) error { + delete(m, k) + return nil +} +func (m MemStore) Has(k cid.Cid) (bool, error) { + _, ok := m[k] + return ok, nil +} +func (m MemStore) Get(k cid.Cid) (blocks.Block, error) { + b, ok := m[k] + if !ok { + return nil, blockstore.ErrNotFound + } + return b, nil +} + +// GetSize returns the CIDs mapped BlockSize +func (m MemStore) GetSize(k cid.Cid) (int, error) { + b, ok := m[k] + if !ok { + return 0, blockstore.ErrNotFound + } + return len(b.RawData()), nil +} + +// Put puts a given block to the underlying datastore +func (m MemStore) Put(b blocks.Block) error { + // Convert to a basic block for safety, but try to reuse the existing + // block if it's already a basic block. + k := b.Cid() + if _, ok := b.(*blocks.BasicBlock); !ok { + // If we already have the block, abort. + if _, ok := m[k]; ok { + return nil + } + // the error is only for debugging. + b, _ = blocks.NewBlockWithCid(b.RawData(), b.Cid()) + } + m[b.Cid()] = b + return nil +} + +// PutMany puts a slice of blocks at the same time using batching +// capabilities of the underlying datastore whenever possible. +func (m MemStore) PutMany(bs []blocks.Block) error { + for _, b := range bs { + _ = m.Put(b) // can't fail + } + return nil +} + +// AllKeysChan returns a channel from which +// the CIDs in the Blockstore can be read. It should respect +// the given context, closing the channel if it becomes Done. +func (m MemStore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) { + ch := make(chan cid.Cid, len(m)) + for k := range m { + ch <- k + } + close(ch) + return ch, nil +} + +// HashOnRead specifies if every read block should be +// rehashed to make sure it matches its CID. +func (m MemStore) HashOnRead(enabled bool) { + // no-op +} diff --git a/lib/blockstore/syncstore.go b/lib/blockstore/syncstore.go new file mode 100644 index 000000000..be9f6b5c4 --- /dev/null +++ b/lib/blockstore/syncstore.go @@ -0,0 +1,68 @@ +package blockstore + +import ( + "context" + "sync" + + blocks "github.com/ipfs/go-block-format" + "github.com/ipfs/go-cid" +) + +type SyncStore struct { + mu sync.RWMutex + bs MemStore // specifically use a memStore to save indirection overhead. +} + +func (m *SyncStore) DeleteBlock(k cid.Cid) error { + m.mu.Lock() + defer m.mu.Unlock() + return m.bs.DeleteBlock(k) +} +func (m *SyncStore) Has(k cid.Cid) (bool, error) { + m.mu.RLock() + defer m.mu.RUnlock() + return m.bs.Has(k) +} +func (m *SyncStore) Get(k cid.Cid) (blocks.Block, error) { + m.mu.RLock() + defer m.mu.RUnlock() + return m.bs.Get(k) +} + +// GetSize returns the CIDs mapped BlockSize +func (m *SyncStore) GetSize(k cid.Cid) (int, error) { + m.mu.RLock() + defer m.mu.RUnlock() + return m.bs.GetSize(k) +} + +// Put puts a given block to the underlying datastore +func (m *SyncStore) Put(b blocks.Block) error { + m.mu.Lock() + defer m.mu.Unlock() + return m.bs.Put(b) +} + +// PutMany puts a slice of blocks at the same time using batching +// capabilities of the underlying datastore whenever possible. +func (m *SyncStore) PutMany(bs []blocks.Block) error { + m.mu.Lock() + defer m.mu.Unlock() + return m.bs.PutMany(bs) +} + +// AllKeysChan returns a channel from which +// the CIDs in the Blockstore can be read. It should respect +// the given context, closing the channel if it becomes Done. +func (m *SyncStore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) { + m.mu.RLock() + defer m.mu.RUnlock() + // this blockstore implementation doesn't do any async work. + return m.bs.AllKeysChan(ctx) +} + +// HashOnRead specifies if every read block should be +// rehashed to make sure it matches its CID. +func (m *SyncStore) HashOnRead(enabled bool) { + // noop +} diff --git a/lib/bufbstore/buf_bstore.go b/lib/bufbstore/buf_bstore.go index a766c2b52..4ea746444 100644 --- a/lib/bufbstore/buf_bstore.go +++ b/lib/bufbstore/buf_bstore.go @@ -19,10 +19,12 @@ type BufferedBS struct { } func NewBufferedBstore(base bstore.Blockstore) *BufferedBS { - buf := bstore.NewTemporary() + var buf bstore.Blockstore if os.Getenv("LOTUS_DISABLE_VM_BUF") == "iknowitsabadidea" { log.Warn("VM BLOCKSTORE BUFFERING IS DISABLED") buf = base + } else { + buf = bstore.NewTemporary() } return &BufferedBS{ From 15fe998c68b3980cc064feabfe770eded2e77fde Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 14 Oct 2020 14:02:19 -0700 Subject: [PATCH 120/313] add an timed-cache blockstore This blockstore lets us write to a temporary scratch location where blocks older than the specified cache time are automatically cleared. --- lib/timedbs/timedbs.go | 156 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 lib/timedbs/timedbs.go diff --git a/lib/timedbs/timedbs.go b/lib/timedbs/timedbs.go new file mode 100644 index 000000000..bb03a59e9 --- /dev/null +++ b/lib/timedbs/timedbs.go @@ -0,0 +1,156 @@ +package timedbs + +import ( + "context" + "fmt" + "sync" + "time" + + blocks "github.com/ipfs/go-block-format" + "github.com/ipfs/go-cid" + "go.uber.org/multierr" + + "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/lib/blockstore" +) + +// TimedCacheBS is a blockstore that keeps blocks for at least the specified +// caching interval before discarding them. Garbage collection must be started +// and stopped by calling Start/Stop. +// +// Under the covers, it's implemented with an active and an inactive blockstore +// that are rotated every cache time interval. This means all blocks will be +// stored at most 2x the cache interval. +type TimedCacheBS struct { + mu sync.RWMutex + active, inactive blockstore.MemStore + + interval time.Duration + closeCh chan struct{} +} + +func NewTimedCacheBS(cacheTime time.Duration) *TimedCacheBS { + return &TimedCacheBS{ + active: blockstore.NewTemporary(), + inactive: blockstore.NewTemporary(), + interval: cacheTime, + } +} + +func (t *TimedCacheBS) Start(ctx context.Context) error { + t.mu.Lock() + defer t.mu.Unlock() + if t.closeCh != nil { + return fmt.Errorf("already started") + } + t.closeCh = make(chan struct{}) + go func() { + ticker := build.Clock.Ticker(t.interval) + defer ticker.Stop() + for { + select { + case <-ticker.C: + t.rotate() + case <-t.closeCh: + return + } + } + }() + return nil +} + +func (t *TimedCacheBS) Stop(ctx context.Context) error { + t.mu.Lock() + defer t.mu.Unlock() + if t.closeCh == nil { + return fmt.Errorf("not started started") + } + select { + case <-t.closeCh: + // already closed + default: + close(t.closeCh) + } + return nil +} + +func (t *TimedCacheBS) rotate() { + newBs := blockstore.NewTemporary() + + t.mu.Lock() + t.inactive, t.active = t.active, newBs + t.mu.Unlock() +} + +func (t *TimedCacheBS) Put(b blocks.Block) error { + // Don't check the inactive set here. We want to keep this block for at + // least one interval. + t.mu.Lock() + defer t.mu.Unlock() + return t.active.Put(b) +} + +func (t *TimedCacheBS) PutMany(bs []blocks.Block) error { + t.mu.Lock() + defer t.mu.Unlock() + return t.active.PutMany(bs) +} + +func (t *TimedCacheBS) Get(k cid.Cid) (blocks.Block, error) { + t.mu.RLock() + defer t.mu.RUnlock() + b, err := t.active.Get(k) + if err == blockstore.ErrNotFound { + b, err = t.inactive.Get(k) + } + return b, err +} + +func (t *TimedCacheBS) GetSize(k cid.Cid) (int, error) { + t.mu.RLock() + defer t.mu.RUnlock() + size, err := t.active.GetSize(k) + if err == blockstore.ErrNotFound { + size, err = t.inactive.GetSize(k) + } + return size, err +} + +func (t *TimedCacheBS) Has(k cid.Cid) (bool, error) { + t.mu.RLock() + defer t.mu.RUnlock() + if has, err := t.active.Has(k); err != nil { + return false, err + } else if has { + return true, nil + } + return t.inactive.Has(k) +} + +func (t *TimedCacheBS) HashOnRead(_ bool) { + // no-op +} + +func (t *TimedCacheBS) DeleteBlock(k cid.Cid) error { + t.mu.Lock() + defer t.mu.Unlock() + return multierr.Combine(t.active.DeleteBlock(k), t.inactive.DeleteBlock(k)) +} + +func (t *TimedCacheBS) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) { + t.mu.RLock() + defer t.mu.RUnlock() + + ch := make(chan cid.Cid, len(t.active)+len(t.inactive)) + for c := range t.active { + ch <- c + } + for c := range t.inactive { + if _, ok := t.active[c]; ok { + continue + } + ch <- c + } + close(ch) + return ch, nil +} From ddade32bd37654f343e13ba4ad0983d03f1f05e9 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 14 Oct 2020 13:49:43 -0700 Subject: [PATCH 121/313] write bitswap blocks into a temporary, in-memory block cache If they end up validating, we'll write them back to the underlying blockstore. Otherwise, there's no reason to keep them. --- node/modules/chain.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/node/modules/chain.go b/node/modules/chain.go index f563b4cdd..ce3e9f749 100644 --- a/node/modules/chain.go +++ b/node/modules/chain.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "os" + "time" "github.com/ipfs/go-bitswap" "github.com/ipfs/go-bitswap/network" @@ -30,6 +31,8 @@ import ( "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/lib/blockstore" + "github.com/filecoin-project/lotus/lib/bufbstore" + "github.com/filecoin-project/lotus/lib/timedbs" "github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/helpers" "github.com/filecoin-project/lotus/node/repo" @@ -41,8 +44,15 @@ func ChainBitswap(mctx helpers.MetricsCtx, lc fx.Lifecycle, host host.Host, rt r bitswapNetwork := network.NewFromIpfsHost(host, rt, network.Prefix("/chain")) bitswapOptions := []bitswap.Option{bitswap.ProvideEnabled(false)} + // Write all incoming bitswap blocks into a temporary blockstore for two + // block times. If they validate, they'll be persisted later. + cache := timedbs.NewTimedCacheBS(2 * time.Duration(build.BlockDelaySecs) * time.Second) + lc.Append(fx.Hook{OnStop: cache.Stop, OnStart: cache.Start}) + + bitswapBs := bufbstore.NewTieredBstore(bs, cache) + // Use just exch.Close(), closing the context is not needed - exch := bitswap.New(mctx, bitswapNetwork, bs, bitswapOptions...) + exch := bitswap.New(mctx, bitswapNetwork, bitswapBs, bitswapOptions...) lc.Append(fx.Hook{ OnStop: func(ctx context.Context) error { return exch.Close() From 28823fb8e9f7f276e915f0935e424c404287e957 Mon Sep 17 00:00:00 2001 From: frrist Date: Wed, 14 Oct 2020 14:50:59 -0700 Subject: [PATCH 122/313] fix: bad indirection of deadline diffing --- chain/actors/builtin/miner/diff_deadlines.go | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/chain/actors/builtin/miner/diff_deadlines.go b/chain/actors/builtin/miner/diff_deadlines.go index e1e839960..7d686ece5 100644 --- a/chain/actors/builtin/miner/diff_deadlines.go +++ b/chain/actors/builtin/miner/diff_deadlines.go @@ -7,9 +7,9 @@ import ( "github.com/filecoin-project/go-state-types/exitcode" ) -type DeadlinesDiff map[uint64]*DeadlineDiff +type DeadlinesDiff map[uint64]DeadlineDiff -func DiffDeadlines(pre, cur State) (*DeadlinesDiff, error) { +func DiffDeadlines(pre, cur State) (DeadlinesDiff, error) { changed, err := pre.DeadlinesChanged(cur) if err != nil { return nil, err @@ -18,11 +18,7 @@ func DiffDeadlines(pre, cur State) (*DeadlinesDiff, error) { return nil, nil } - numDl, err := pre.NumDeadlines() - if err != nil { - return nil, err - } - dlDiff := make(DeadlinesDiff, numDl) + dlDiff := make(DeadlinesDiff) if err := pre.ForEachDeadline(func(idx uint64, preDl Deadline) error { curDl, err := cur.LoadDeadline(idx) if err != nil { @@ -39,12 +35,12 @@ func DiffDeadlines(pre, cur State) (*DeadlinesDiff, error) { }); err != nil { return nil, err } - return &dlDiff, nil + return dlDiff, nil } type DeadlineDiff map[uint64]*PartitionDiff -func DiffDeadline(pre, cur Deadline) (*DeadlineDiff, error) { +func DiffDeadline(pre, cur Deadline) (DeadlineDiff, error) { changed, err := pre.PartitionsChanged(cur) if err != nil { return nil, err @@ -104,7 +100,7 @@ func DiffDeadline(pre, cur Deadline) (*DeadlineDiff, error) { return nil, err } - return &partDiff, nil + return partDiff, nil } type PartitionDiff struct { From 811f1304e673c2208a8902c761da9d3548473d3d Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 14 Oct 2020 16:17:55 -0700 Subject: [PATCH 123/313] test timed cache blockstore --- lib/timedbs/timedbs_test.go | 78 +++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 lib/timedbs/timedbs_test.go diff --git a/lib/timedbs/timedbs_test.go b/lib/timedbs/timedbs_test.go new file mode 100644 index 000000000..75f298a1d --- /dev/null +++ b/lib/timedbs/timedbs_test.go @@ -0,0 +1,78 @@ +package timedbs_test + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/require" + + blocks "github.com/ipfs/go-block-format" + "github.com/ipfs/go-cid" + + "github.com/filecoin-project/lotus/lib/timedbs" +) + +func TestTimedBSSimple(t *testing.T) { + tc := timedbs.NewTimedCacheBS(3 * time.Millisecond) + _ = tc.Start(context.Background()) + defer func() { + _ = tc.Stop(context.Background()) + }() + + b1 := blocks.NewBlock([]byte("foo")) + require.NoError(t, tc.Put(b1)) + + b2 := blocks.NewBlock([]byte("bar")) + require.NoError(t, tc.Put(b2)) + + b3 := blocks.NewBlock([]byte("baz")) + + b1out, err := tc.Get(b1.Cid()) + require.NoError(t, err) + require.Equal(t, b1.RawData(), b1out.RawData()) + + has, err := tc.Has(b1.Cid()) + require.NoError(t, err) + require.True(t, has) + + time.Sleep(4 * time.Millisecond) + + // We should still have everything. + has, err = tc.Has(b1.Cid()) + require.NoError(t, err) + require.True(t, has) + + has, err = tc.Has(b2.Cid()) + require.NoError(t, err) + require.True(t, has) + + // extend b2, add b3. + require.NoError(t, tc.Put(b2)) + require.NoError(t, tc.Put(b3)) + + // all keys once. + allKeys, err := tc.AllKeysChan(context.Background()) + var ks []cid.Cid + for k := range allKeys { + ks = append(ks, k) + } + require.NoError(t, err) + require.ElementsMatch(t, ks, []cid.Cid{b1.Cid(), b2.Cid(), b3.Cid()}) + + time.Sleep(4 * time.Millisecond) + + // should still have b2, and b3, but not b1 + + has, err = tc.Has(b1.Cid()) + require.NoError(t, err) + require.False(t, has) + + has, err = tc.Has(b2.Cid()) + require.NoError(t, err) + require.True(t, has) + + has, err = tc.Has(b3.Cid()) + require.NoError(t, err) + require.True(t, has) +} From 86e30729bf142a2c8db12b9b26ee63c83de279c6 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 14 Oct 2020 16:51:26 -0700 Subject: [PATCH 124/313] give the TimeCacheBS tests a bit more time Otherwise, they flake once in a while. --- lib/timedbs/timedbs_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/timedbs/timedbs_test.go b/lib/timedbs/timedbs_test.go index 75f298a1d..2126b9287 100644 --- a/lib/timedbs/timedbs_test.go +++ b/lib/timedbs/timedbs_test.go @@ -14,7 +14,7 @@ import ( ) func TestTimedBSSimple(t *testing.T) { - tc := timedbs.NewTimedCacheBS(3 * time.Millisecond) + tc := timedbs.NewTimedCacheBS(10 * time.Millisecond) _ = tc.Start(context.Background()) defer func() { _ = tc.Stop(context.Background()) @@ -36,7 +36,7 @@ func TestTimedBSSimple(t *testing.T) { require.NoError(t, err) require.True(t, has) - time.Sleep(4 * time.Millisecond) + time.Sleep(15 * time.Millisecond) // We should still have everything. has, err = tc.Has(b1.Cid()) @@ -60,7 +60,7 @@ func TestTimedBSSimple(t *testing.T) { require.NoError(t, err) require.ElementsMatch(t, ks, []cid.Cid{b1.Cid(), b2.Cid(), b3.Cid()}) - time.Sleep(4 * time.Millisecond) + time.Sleep(10 * time.Millisecond) // should still have b2, and b3, but not b1 From 698b49b7ef5dfcce4a6eb277b8d38ad9c094887c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 15 Oct 2020 02:46:47 +0200 Subject: [PATCH 125/313] Improve gas defaults --- chain/messagepool/messagepool.go | 4 +++- chain/types/fil.go | 9 +++++++++ node/config/def.go | 10 +++++----- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index 83b1a7f29..88e721ef4 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -59,6 +59,8 @@ var MaxUntrustedActorPendingMessages = 10 var MaxNonceGap = uint64(4) +var DefaultMaxFee = abi.TokenAmount(types.MustParseFIL("0.007")) + var ( ErrMessageTooBig = errors.New("message too big") @@ -183,7 +185,7 @@ func ComputeMinRBF(curPrem abi.TokenAmount) abi.TokenAmount { func CapGasFee(msg *types.Message, maxFee abi.TokenAmount) { if maxFee.Equals(big.Zero()) { - maxFee = types.NewInt(build.FilecoinPrecision / 10) + maxFee = DefaultMaxFee } gl := types.NewInt(uint64(msg.GasLimit)) diff --git a/chain/types/fil.go b/chain/types/fil.go index 7eac8ce93..0ea77660c 100644 --- a/chain/types/fil.go +++ b/chain/types/fil.go @@ -81,5 +81,14 @@ func ParseFIL(s string) (FIL, error) { return FIL{r.Num()}, nil } +func MustParseFIL(s string) FIL { + n, err := ParseFIL(s) + if err != nil { + panic(err) + } + + return n +} + var _ encoding.TextMarshaler = (*FIL)(nil) var _ encoding.TextUnmarshaler = (*FIL)(nil) diff --git a/node/config/def.go b/node/config/def.go index 7eb7e19f0..f1bb1edef 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -182,11 +182,11 @@ func DefaultStorageMiner() *StorageMiner { }, Fees: MinerFeeConfig{ - MaxPreCommitGasFee: types.FIL(types.BigDiv(types.FromFil(1), types.NewInt(20))), // 0.05 - MaxCommitGasFee: types.FIL(types.BigDiv(types.FromFil(1), types.NewInt(20))), - MaxWindowPoStGasFee: types.FIL(types.FromFil(50)), - MaxPublishDealsFee: types.FIL(types.BigDiv(types.FromFil(1), types.NewInt(33))), // 0.03ish - MaxMarketBalanceAddFee: types.FIL(types.BigDiv(types.FromFil(1), types.NewInt(100))), // 0.01 + MaxPreCommitGasFee: types.MustParseFIL("0.025"), + MaxCommitGasFee: types.MustParseFIL("0.05"), + MaxWindowPoStGasFee: types.MustParseFIL("5"), + MaxPublishDealsFee: types.MustParseFIL("0.05"), + MaxMarketBalanceAddFee: types.MustParseFIL("0.007"), }, } cfg.Common.API.ListenAddress = "/ip4/127.0.0.1/tcp/2345/http" From df6f4a572cc0d45e5695a1135c72e3963fecc23c Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Wed, 7 Oct 2020 21:00:24 +0200 Subject: [PATCH 126/313] Change default gas premium to for 6 block inclusion Signed-off-by: Jakub Sztandera --- node/impl/full/gas.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/impl/full/gas.go b/node/impl/full/gas.go index 0cb1eb084..2e5063ccb 100644 --- a/node/impl/full/gas.go +++ b/node/impl/full/gas.go @@ -277,7 +277,7 @@ func (m *GasModule) GasEstimateMessageGas(ctx context.Context, msg *types.Messag } if msg.GasPremium == types.EmptyInt || types.BigCmp(msg.GasPremium, types.NewInt(0)) == 0 { - gasPremium, err := m.GasEstimateGasPremium(ctx, 2, msg.From, msg.GasLimit, types.TipSetKey{}) + gasPremium, err := m.GasEstimateGasPremium(ctx, 10, msg.From, msg.GasLimit, types.TipSetKey{}) if err != nil { return nil, xerrors.Errorf("estimating gas price: %w", err) } From 251374eca723959cf836e2f5cc48d585b742fe6b Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Wed, 14 Oct 2020 21:01:20 -0400 Subject: [PATCH 127/313] Lotus version 0.10.2 --- CHANGELOG.md | 18 ++++++++++++++++++ build/version.go | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c94e387c..701f221b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ # Lotus changelog +# 0.10.2 / 2020-10-14 + +This is an optional release of Lotus that updates markets to 0.9.1, which fixes an issue affecting deals that were mid-transfer when the node was upgraded to 0.9.0. This release also includes some tweaks to default gas values and minor performance improvements. + +## Changes + +- Use updated stored ask API (https://github.com/filecoin-project/lotus/pull/4384) +- tvx: trace puts to blockstore for inclusion in CAR. (https://github.com/filecoin-project/lotus/pull/4278) +- Add propose remove (https://github.com/filecoin-project/lotus/pull/4311) +- Update to 0.9.1 bugfix release (https://github.com/filecoin-project/lotus/pull/4402) +- Update drand endpoints (https://github.com/filecoin-project/lotus/pull/4125) +- fix: return true when deadlines changed (https://github.com/filecoin-project/lotus/pull/4403) +- sync wait --watch (https://github.com/filecoin-project/lotus/pull/4396) +- reduce garbage in blockstore (https://github.com/filecoin-project/lotus/pull/4406) +- give the TimeCacheBS tests a bit more time (https://github.com/filecoin-project/lotus/pull/4407) +- Improve gas defaults (https://github.com/filecoin-project/lotus/pull/4408) +- Change default gas premium to for 10 block inclusion (https://github.com/filecoin-project/lotus/pull/4222) + # 0.10.1 / 2020-10-14 This is an optional release of Lotus that updates markets to 0.9.0, which adds the ability to restart data transfers. This release also introduces Ledger support, and various UX improvements. diff --git a/build/version.go b/build/version.go index 39f9d48ff..df1fe28de 100644 --- a/build/version.go +++ b/build/version.go @@ -29,7 +29,7 @@ func buildType() string { } // BuildVersion is the local build version, set by build system -const BuildVersion = "0.10.1" +const BuildVersion = "0.10.2" func UserVersion() string { return BuildVersion + buildType() + CurrentCommit From a40fc98e5635545cb70f4fd675971fdb1df5de11 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 14 Oct 2020 17:22:39 -0700 Subject: [PATCH 128/313] fix code coverage ignore It looks like we need to use globs. --- .codecov.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.codecov.yml b/.codecov.yml index 1551f2276..a53081be7 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -1,5 +1,9 @@ comment: off ignore: - - "cbor_gen.go" + - "**/cbor_gen.go" + - "api/test/**/*" + - "api/test/*" + - "gen/**/*" + - "gen/*" github_checks: annotations: false From 3fb5334959eab2a2f8aaf5493dcef2b6ad581f1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 15 Oct 2020 03:36:55 +0200 Subject: [PATCH 129/313] mpool: Don't block node startup loading messages --- chain/messagepool/messagepool.go | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index 88e721ef4..cc26be0b5 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -370,11 +370,23 @@ func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName, j journ return err }) - if err := mp.loadLocal(); err != nil { - log.Errorf("loading local messages: %+v", err) - } + mp.curTsLk.Lock() + mp.lk.Lock() - go mp.runLoop() + go func() { + err := mp.loadLocal() + + mp.lk.Unlock() + mp.curTsLk.Unlock() + + if err != nil { + log.Errorf("loading local messages: %+v", err) + } + + log.Info("mpool ready") + + mp.runLoop() + }() return mp, nil } @@ -667,9 +679,6 @@ func (mp *MessagePool) addLoaded(m *types.SignedMessage) error { return err } - mp.curTsLk.Lock() - defer mp.curTsLk.Unlock() - curTs := mp.curTs if curTs == nil { @@ -685,9 +694,6 @@ func (mp *MessagePool) addLoaded(m *types.SignedMessage) error { return xerrors.Errorf("minimum expected nonce is %d: %w", snonce, ErrNonceTooLow) } - mp.lk.Lock() - defer mp.lk.Unlock() - _, err = mp.verifyMsgBeforeAdd(m, curTs, true) if err != nil { return err From b29e3b5242704d4a8a82f07abcc195016417a1b3 Mon Sep 17 00:00:00 2001 From: hannahhoward Date: Wed, 14 Oct 2020 21:28:36 -0700 Subject: [PATCH 130/313] feat(markets): use build.BlockDelaySecs for start buffer instead of constant from spec-actors which uses hardcoded start epoch, use one that factors in possibility of different block time --- node/modules/storageminer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index adacf5405..cd5517a1c 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -474,7 +474,7 @@ func BasicDealFilter(user dtypes.DealFilter) func(onlineOk dtypes.ConsiderOnline // Reject if it's more than 7 days in the future // TODO: read from cfg - maxStartEpoch := earliest + abi.ChainEpoch(7*builtin.EpochsInDay) + maxStartEpoch := earliest + abi.ChainEpoch(7*builtin.SecondsInDay/build.BlockDelaySecs) if deal.Proposal.StartEpoch > maxStartEpoch { return false, fmt.Sprintf("deal start epoch is too far in the future: %s > %s", deal.Proposal.StartEpoch, maxStartEpoch), nil } From 6d771d29c7c5420d13f00de4785e689a97166ee8 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Wed, 14 Oct 2020 10:56:51 -0700 Subject: [PATCH 131/313] improve the UX of multisig approves --- cli/multisig.go | 132 ++++++++++++++++++++++++++++-------------------- 1 file changed, 76 insertions(+), 56 deletions(-) diff --git a/cli/multisig.go b/cli/multisig.go index 831b1bbe4..19a80e66f 100644 --- a/cli/multisig.go +++ b/cli/multisig.go @@ -24,6 +24,7 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-address" + cid "github.com/ipfs/go-cid" cbor "github.com/ipfs/go-ipld-cbor" "github.com/urfave/cli/v2" "golang.org/x/xerrors" @@ -41,6 +42,13 @@ import ( var multisigCmd = &cli.Command{ Name: "msig", Usage: "Interact with a multisig wallet", + Flags: []cli.Flag{ + &cli.IntFlag{ + Name: "confirmations", + Usage: "number of block confirmations to wait for", + Value: int(build.MessageConfidence), + }, + }, Subcommands: []*cli.Command{ msigCreateCmd, msigInspectCmd, @@ -146,7 +154,7 @@ var msigCreateCmd = &cli.Command{ } // wait for it to get mined into a block - wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence) + wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence"))) if err != nil { return err } @@ -410,7 +418,7 @@ var msigProposeCmd = &cli.Command{ fmt.Println("send proposal in message: ", msgCid) - wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence) + wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence"))) if err != nil { return err } @@ -446,14 +454,18 @@ var msigApproveCmd = &cli.Command{ }, }, Action: func(cctx *cli.Context) error { - if cctx.Args().Len() < 5 { - return ShowHelp(cctx, fmt.Errorf("must pass multisig address, message ID, proposer address, destination, and value")) + if cctx.Args().Len() < 2 { + return ShowHelp(cctx, fmt.Errorf("must pass at least multisig address and message ID")) } if cctx.Args().Len() > 5 && cctx.Args().Len() != 7 { return ShowHelp(cctx, fmt.Errorf("usage: msig approve [ ]")) } + if cctx.Args().Len() > 2 && cctx.Args().Len() != 5 { + return ShowHelp(cctx, fmt.Errorf("usage: msig approve ")) + } + api, closer, err := GetFullNodeAPI(cctx) if err != nil { return err @@ -471,44 +483,6 @@ var msigApproveCmd = &cli.Command{ return err } - proposer, err := address.NewFromString(cctx.Args().Get(2)) - if err != nil { - return err - } - - if proposer.Protocol() != address.ID { - proposer, err = api.StateLookupID(ctx, proposer, types.EmptyTSK) - if err != nil { - return err - } - } - - dest, err := address.NewFromString(cctx.Args().Get(3)) - if err != nil { - return err - } - - value, err := types.ParseFIL(cctx.Args().Get(4)) - if err != nil { - return err - } - - var method uint64 - var params []byte - if cctx.Args().Len() == 7 { - m, err := strconv.ParseUint(cctx.Args().Get(5), 10, 64) - if err != nil { - return err - } - method = m - - p, err := hex.DecodeString(cctx.Args().Get(6)) - if err != nil { - return err - } - params = p - } - var from address.Address if cctx.IsSet("from") { f, err := address.NewFromString(cctx.String("from")) @@ -524,14 +498,60 @@ var msigApproveCmd = &cli.Command{ from = defaddr } - msgCid, err := api.MsigApproveTxnHash(ctx, msig, txid, proposer, dest, types.BigInt(value), from, method, params) - if err != nil { - return err + var msgCid cid.Cid + if cctx.Args().Len() == 2 { + msgCid, err = api.MsigApprove(ctx, msig, txid, from) + if err != nil { + return err + } + } else { + proposer, err := address.NewFromString(cctx.Args().Get(2)) + if err != nil { + return err + } + + if proposer.Protocol() != address.ID { + proposer, err = api.StateLookupID(ctx, proposer, types.EmptyTSK) + if err != nil { + return err + } + } + + dest, err := address.NewFromString(cctx.Args().Get(3)) + if err != nil { + return err + } + + value, err := types.ParseFIL(cctx.Args().Get(4)) + if err != nil { + return err + } + + var method uint64 + var params []byte + if cctx.Args().Len() == 7 { + m, err := strconv.ParseUint(cctx.Args().Get(5), 10, 64) + if err != nil { + return err + } + method = m + + p, err := hex.DecodeString(cctx.Args().Get(6)) + if err != nil { + return err + } + params = p + } + + msgCid, err = api.MsigApproveTxnHash(ctx, msig, txid, proposer, dest, types.BigInt(value), from, method, params) + if err != nil { + return err + } } fmt.Println("sent approval in message: ", msgCid) - wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence) + wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence"))) if err != nil { return err } @@ -602,7 +622,7 @@ var msigRemoveProposeCmd = &cli.Command{ fmt.Println("sent remove proposal in message: ", msgCid) - wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence) + wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence"))) if err != nil { return err } @@ -680,7 +700,7 @@ var msigAddProposeCmd = &cli.Command{ fmt.Println("sent add proposal in message: ", msgCid) - wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence) + wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence"))) if err != nil { return err } @@ -762,7 +782,7 @@ var msigAddApproveCmd = &cli.Command{ fmt.Println("sent add approval in message: ", msgCid) - wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence) + wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence"))) if err != nil { return err } @@ -839,7 +859,7 @@ var msigAddCancelCmd = &cli.Command{ fmt.Println("sent add cancellation in message: ", msgCid) - wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence) + wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence"))) if err != nil { return err } @@ -911,7 +931,7 @@ var msigSwapProposeCmd = &cli.Command{ fmt.Println("sent swap proposal in message: ", msgCid) - wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence) + wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence"))) if err != nil { return err } @@ -993,7 +1013,7 @@ var msigSwapApproveCmd = &cli.Command{ fmt.Println("sent swap approval in message: ", msgCid) - wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence) + wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence"))) if err != nil { return err } @@ -1070,7 +1090,7 @@ var msigSwapCancelCmd = &cli.Command{ fmt.Println("sent swap cancellation in message: ", msgCid) - wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence) + wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence"))) if err != nil { return err } @@ -1157,7 +1177,7 @@ var msigLockProposeCmd = &cli.Command{ fmt.Println("sent lock proposal in message: ", msgCid) - wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence) + wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence"))) if err != nil { return err } @@ -1254,7 +1274,7 @@ var msigLockApproveCmd = &cli.Command{ fmt.Println("sent lock approval in message: ", msgCid) - wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence) + wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence"))) if err != nil { return err } @@ -1346,7 +1366,7 @@ var msigLockCancelCmd = &cli.Command{ fmt.Println("sent lock cancellation in message: ", msgCid) - wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence) + wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence"))) if err != nil { return err } From 3bd2e2f7771b068f7d32e37e2813c38f58149d41 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Wed, 14 Oct 2020 22:55:23 -0700 Subject: [PATCH 132/313] fix typo --- cli/multisig.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/multisig.go b/cli/multisig.go index 19a80e66f..d606d2acb 100644 --- a/cli/multisig.go +++ b/cli/multisig.go @@ -44,7 +44,7 @@ var multisigCmd = &cli.Command{ Usage: "Interact with a multisig wallet", Flags: []cli.Flag{ &cli.IntFlag{ - Name: "confirmations", + Name: "confidence", Usage: "number of block confirmations to wait for", Value: int(build.MessageConfidence), }, From fdb115e3692493d5e74f7224aee7a0781d540838 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Wed, 14 Oct 2020 23:10:00 -0700 Subject: [PATCH 133/313] add command to propose changing multisig threshold --- cli/multisig.go | 76 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/cli/multisig.go b/cli/multisig.go index d606d2acb..73589086a 100644 --- a/cli/multisig.go +++ b/cli/multisig.go @@ -65,6 +65,7 @@ var multisigCmd = &cli.Command{ msigLockApproveCmd, msigLockCancelCmd, msigVestedCmd, + msigProposeThresholdCmd, }, } @@ -1440,3 +1441,78 @@ var msigVestedCmd = &cli.Command{ return nil }, } + +var msigProposeThresholdCmd = &cli.Command{ + Name: "propose-threshold", + Usage: "Propose setting a different signing threshold on the account", + ArgsUsage: "", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "from", + Usage: "account to send the proposal from", + }, + }, + Action: func(cctx *cli.Context) error { + if cctx.Args().Len() != 2 { + return ShowHelp(cctx, fmt.Errorf("must pass multisig address and new threshold value")) + } + + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + msig, err := address.NewFromString(cctx.Args().Get(0)) + if err != nil { + return err + } + + newM, err := strconv.ParseUint(cctx.Args().Get(2), 10, 64) + if err != nil { + return err + } + + var from address.Address + if cctx.IsSet("from") { + f, err := address.NewFromString(cctx.String("from")) + if err != nil { + return err + } + from = f + } else { + defaddr, err := api.WalletDefaultAddress(ctx) + if err != nil { + return err + } + from = defaddr + } + + params, actErr := actors.SerializeParams(&msig0.ChangeNumApprovalsThresholdParams{ + NewThreshold: newM, + }) + + if actErr != nil { + return actErr + } + + msgCid, err := api.MsigPropose(ctx, msig, msig, types.NewInt(0), from, uint64(builtin2.MethodsMultisig.ChangeNumApprovalsThreshold), params) + if err != nil { + return fmt.Errorf("failed to propose change of threshold: %w", err) + } + + fmt.Println("sent change threshold proposal in message: ", msgCid) + + wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence"))) + if err != nil { + return err + } + + if wait.Receipt.ExitCode != 0 { + return fmt.Errorf("change threshold proposal returned exit %d", wait.Receipt.ExitCode) + } + + return nil + }, +} From ccc780f35ac27eb7136efed3b55851e3076ed68b Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Wed, 14 Oct 2020 23:16:31 -0700 Subject: [PATCH 134/313] fix wrong index --- cli/multisig.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/multisig.go b/cli/multisig.go index 73589086a..e352ed64b 100644 --- a/cli/multisig.go +++ b/cli/multisig.go @@ -1469,7 +1469,7 @@ var msigProposeThresholdCmd = &cli.Command{ return err } - newM, err := strconv.ParseUint(cctx.Args().Get(2), 10, 64) + newM, err := strconv.ParseUint(cctx.Args().Get(1), 10, 64) if err != nil { return err } From 925606ff26c3e3856caf2c3a725da46faf7b9905 Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Thu, 15 Oct 2020 12:02:12 +0200 Subject: [PATCH 135/313] Chore: update drand to v1.2.0 --- go.mod | 6 +++--- go.sum | 23 +++++++++++++++++------ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index c3935be19..e36f821d3 100644 --- a/go.mod +++ b/go.mod @@ -16,8 +16,8 @@ require ( github.com/detailyang/go-fallocate v0.0.0-20180908115635-432fa640bd2e github.com/dgraph-io/badger/v2 v2.2007.2 github.com/docker/go-units v0.4.0 - github.com/drand/drand v1.1.2-0.20200905144319-79c957281b32 - github.com/drand/kyber v1.1.2 + github.com/drand/drand v1.2.0 + github.com/drand/kyber v1.1.4 github.com/dustin/go-humanize v1.0.0 github.com/elastic/go-sysinfo v1.3.0 github.com/fatih/color v1.9.0 @@ -131,7 +131,7 @@ require ( go.uber.org/multierr v1.5.0 go.uber.org/zap v1.15.0 golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 - golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 + golang.org/x/sys v0.0.0-20200926100807-9d91bd62050c golang.org/x/time v0.0.0-20191024005414-555d28b269f0 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 gopkg.in/cheggaaa/pb.v1 v1.0.28 diff --git a/go.sum b/go.sum index feff6abbd..6737eff06 100644 --- a/go.sum +++ b/go.sum @@ -91,6 +91,7 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= +github.com/briandowns/spinner v1.11.1 h1:OixPqDEcX3juo5AjQZAnFPbeUA0jvkp2qzB5gOZJ/L0= github.com/briandowns/spinner v1.11.1/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= @@ -191,14 +192,15 @@ github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/drand/bls12-381 v0.3.2 h1:RImU8Wckmx8XQx1tp1q04OV73J9Tj6mmpQLYDP7V1XE= github.com/drand/bls12-381 v0.3.2/go.mod h1:dtcLgPtYT38L3NO6mPDYH0nbpc5tjPassDqiniuAt4Y= -github.com/drand/drand v1.1.2-0.20200905144319-79c957281b32 h1:sU+51aQRaDxg0KnjQg19KuYRIxDBEUHffBAICSnBys8= -github.com/drand/drand v1.1.2-0.20200905144319-79c957281b32/go.mod h1:0sQEVg+ngs1jaDPVIiEgY0lbENWJPaUlWxGHEaSmKVM= +github.com/drand/drand v1.2.0 h1:EWeIxKFxUR9A+9xZ2oV09sqlxxWhDhgBbgCaCVwnvok= +github.com/drand/drand v1.2.0/go.mod h1:j0P7RGmVaY7E/OuO2yQOcQj7OgeZCuhgu2gdv0JAm+g= github.com/drand/kyber v1.0.1-0.20200110225416-8de27ed8c0e2/go.mod h1:UpXoA0Upd1N9l4TvRPHr1qAUBBERj6JQ/mnKI3BPEmw= github.com/drand/kyber v1.0.2/go.mod h1:x6KOpK7avKj0GJ4emhXFP5n7M7W7ChAPmnQh/OL6vRw= -github.com/drand/kyber v1.1.2 h1:faemqlaFyLrbBSjZGRzzu5SG/do+uTYpHlnrJIHbAhQ= -github.com/drand/kyber v1.1.2/go.mod h1:x6KOpK7avKj0GJ4emhXFP5n7M7W7ChAPmnQh/OL6vRw= -github.com/drand/kyber-bls12381 v0.1.0 h1:/P4C65VnyEwxzR5ZYYVMNzY1If+aYBrdUU5ukwh7LQw= -github.com/drand/kyber-bls12381 v0.1.0/go.mod h1:N1emiHpm+jj7kMlxEbu3MUyOiooTgNySln564cgD9mk= +github.com/drand/kyber v1.1.4 h1:YvKM03QWGvLrdTnYmxxP5iURAX+Gdb6qRDUOgg8i60Q= +github.com/drand/kyber v1.1.4/go.mod h1:9+IgTq7kadePhZg7eRwSD7+bA+bmvqRK+8DtmoV5a3U= +github.com/drand/kyber-bls12381 v0.2.0/go.mod h1:zQip/bHdeEB6HFZSU3v+d3cQE0GaBVQw9aR2E7AdoeI= +github.com/drand/kyber-bls12381 v0.2.1 h1:/d5/YAdaCmHpYjF1NZevOEcKGaq6LBbyvkCTIdGqDjs= +github.com/drand/kyber-bls12381 v0.2.1/go.mod h1:JwWn4nHO9Mp4F5qCie5sVIPQZ0X6cw8XAeMRvc/GXBE= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -705,6 +707,9 @@ github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dv github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= github.com/kilic/bls12-381 v0.0.0-20200607163746-32e1441c8a9f h1:qET3Wx0v8tMtoTOQnsJXVvqvCopSf48qobR6tcJuDHo= github.com/kilic/bls12-381 v0.0.0-20200607163746-32e1441c8a9f/go.mod h1:XXfR6YFCRSrkEXbNlIyDsgXVNJWVUV30m/ebkVy9n6s= +github.com/kilic/bls12-381 v0.0.0-20200731194930-64c428e1bff5/go.mod h1:XXfR6YFCRSrkEXbNlIyDsgXVNJWVUV30m/ebkVy9n6s= +github.com/kilic/bls12-381 v0.0.0-20200820230200-6b2c19996391 h1:51kHw7l/dUDdOdW06AlUGT5jnpj6nqQSILebcsikSjA= +github.com/kilic/bls12-381 v0.0.0-20200820230200-6b2c19996391/go.mod h1:XXfR6YFCRSrkEXbNlIyDsgXVNJWVUV30m/ebkVy9n6s= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -1537,6 +1542,9 @@ golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM= +golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1691,6 +1699,9 @@ golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 h1:OjiUf46hAmXblsZdnoSXsEUSKU8r1UEzcL5RVZ4gO9Y= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200812155832-6a926be9bd1d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200926100807-9d91bd62050c h1:38q6VNPWR010vN82/SB121GujZNIfAUb4YttE2rhGuc= +golang.org/x/sys v0.0.0-20200926100807-9d91bd62050c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 9c99171cb830b811daf23be21bf64394c700bf63 Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Thu, 15 Oct 2020 12:15:21 +0200 Subject: [PATCH 136/313] fix: ensure msig inspect cli works with lotus-lite --- api/api_gateway.go | 2 + api/apistruct/struct.go | 10 +++ cli/multisig.go | 25 +++--- cli/multisig_test.go | 55 +++++++++++++ cli/paych_test.go | 1 + cli/test/mockcli.go | 124 +++++++++++++++++++++++++++++ cli/test/multisig.go | 77 ++++++++++++++++++ cmd/lotus-gateway/api.go | 25 +++++- cmd/lotus-gateway/api_test.go | 8 ++ cmd/lotus-gateway/endtoend_test.go | 52 +++++++++--- cmd/lotus-gateway/main.go | 2 +- node/impl/full/chain.go | 10 ++- 12 files changed, 361 insertions(+), 30 deletions(-) create mode 100644 cli/multisig_test.go create mode 100644 cli/test/mockcli.go create mode 100644 cli/test/multisig.go diff --git a/api/api_gateway.go b/api/api_gateway.go index 95d28887d..c99ff8408 100644 --- a/api/api_gateway.go +++ b/api/api_gateway.go @@ -10,9 +10,11 @@ import ( ) type GatewayAPI interface { + ChainHasObj(context.Context, cid.Cid) (bool, error) ChainHead(ctx context.Context) (*types.TipSet, error) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) + ChainReadObj(context.Context, cid.Cid) ([]byte, error) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 7723e0b1f..3854e1dd6 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -371,9 +371,11 @@ type WorkerStruct struct { type GatewayStruct struct { Internal struct { // TODO: does the gateway need perms? + ChainHasObj func(context.Context, cid.Cid) (bool, error) ChainGetTipSet func(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) ChainGetTipSetByHeight func(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) ChainHead func(ctx context.Context) (*types.TipSet, error) + ChainReadObj func(context.Context, cid.Cid) ([]byte, error) GasEstimateMessageGas func(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) MpoolPush func(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) MsigGetAvailableBalance func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) @@ -1432,6 +1434,10 @@ func (w *WorkerStruct) Closing(ctx context.Context) (<-chan struct{}, error) { return w.Internal.Closing(ctx) } +func (g GatewayStruct) ChainHasObj(ctx context.Context, c cid.Cid) (bool, error) { + return g.Internal.ChainHasObj(ctx, c) +} + func (g GatewayStruct) ChainHead(ctx context.Context) (*types.TipSet, error) { return g.Internal.ChainHead(ctx) } @@ -1444,6 +1450,10 @@ func (g GatewayStruct) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEp return g.Internal.ChainGetTipSetByHeight(ctx, h, tsk) } +func (g GatewayStruct) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) { + return g.Internal.ChainReadObj(ctx, c) +} + func (g GatewayStruct) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) { return g.Internal.GasEstimateMessageGas(ctx, msg, spec, tsk) } diff --git a/cli/multisig.go b/cli/multisig.go index 831b1bbe4..97a77a75b 100644 --- a/cli/multisig.go +++ b/cli/multisig.go @@ -5,7 +5,6 @@ import ( "encoding/hex" "encoding/json" "fmt" - "os" "reflect" "sort" "strconv" @@ -153,7 +152,7 @@ var msigCreateCmd = &cli.Command{ // check it executed successfully if wait.Receipt.ExitCode != 0 { - fmt.Println("actor creation failed!") + fmt.Fprintln(cctx.App.Writer, "actor creation failed!") return err } @@ -163,7 +162,7 @@ var msigCreateCmd = &cli.Command{ if err := execreturn.UnmarshalCBOR(bytes.NewReader(wait.Receipt.Return)); err != nil { return err } - fmt.Println("Created new multisig: ", execreturn.IDAddress, execreturn.RobustAddress) + fmt.Fprintln(cctx.App.Writer, "Created new multisig: ", execreturn.IDAddress, execreturn.RobustAddress) // TODO: maybe register this somewhere return nil @@ -227,25 +226,25 @@ var msigInspectCmd = &cli.Command{ return err } - fmt.Printf("Balance: %s\n", types.FIL(act.Balance)) - fmt.Printf("Spendable: %s\n", types.FIL(types.BigSub(act.Balance, locked))) + fmt.Fprintf(cctx.App.Writer, "Balance: %s\n", types.FIL(act.Balance)) + fmt.Fprintf(cctx.App.Writer, "Spendable: %s\n", types.FIL(types.BigSub(act.Balance, locked))) if cctx.Bool("vesting") { ib, err := mstate.InitialBalance() if err != nil { return err } - fmt.Printf("InitialBalance: %s\n", types.FIL(ib)) + fmt.Fprintf(cctx.App.Writer, "InitialBalance: %s\n", types.FIL(ib)) se, err := mstate.StartEpoch() if err != nil { return err } - fmt.Printf("StartEpoch: %d\n", se) + fmt.Fprintf(cctx.App.Writer, "StartEpoch: %d\n", se) ud, err := mstate.UnlockDuration() if err != nil { return err } - fmt.Printf("UnlockDuration: %d\n", ud) + fmt.Fprintf(cctx.App.Writer, "UnlockDuration: %d\n", ud) } signers, err := mstate.Signers() @@ -256,10 +255,10 @@ var msigInspectCmd = &cli.Command{ if err != nil { return err } - fmt.Printf("Threshold: %d / %d\n", threshold, len(signers)) - fmt.Println("Signers:") + fmt.Fprintf(cctx.App.Writer, "Threshold: %d / %d\n", threshold, len(signers)) + fmt.Fprintln(cctx.App.Writer, "Signers:") for _, s := range signers { - fmt.Printf("\t%s\n", s) + fmt.Fprintf(cctx.App.Writer, "\t%s\n", s) } pending := make(map[int64]multisig.Transaction) @@ -271,7 +270,7 @@ var msigInspectCmd = &cli.Command{ } decParams := cctx.Bool("decode-params") - fmt.Println("Transactions: ", len(pending)) + fmt.Fprintln(cctx.App.Writer, "Transactions: ", len(pending)) if len(pending) > 0 { var txids []int64 for txid := range pending { @@ -281,7 +280,7 @@ var msigInspectCmd = &cli.Command{ return txids[i] < txids[j] }) - w := tabwriter.NewWriter(os.Stdout, 8, 4, 2, ' ', 0) + w := tabwriter.NewWriter(cctx.App.Writer, 8, 4, 2, ' ', 0) fmt.Fprintf(w, "ID\tState\tApprovals\tTo\tValue\tMethod\tParams\n") for _, txid := range txids { tx := pending[txid] diff --git a/cli/multisig_test.go b/cli/multisig_test.go new file mode 100644 index 000000000..09cdbe056 --- /dev/null +++ b/cli/multisig_test.go @@ -0,0 +1,55 @@ +package cli + +import ( + "context" + "os" + "testing" + "time" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/lotus/api/test" + clitest "github.com/filecoin-project/lotus/cli/test" + builder "github.com/filecoin-project/lotus/node/test" +) + +// TestMultisig does a basic test to exercise the multisig CLI +// commands +func TestMultisig(t *testing.T) { + _ = os.Setenv("BELLMAN_NO_GPU", "1") + + blocktime := 5 * time.Millisecond + ctx := context.Background() + nodes, _ := startNodes(ctx, t, blocktime) + clientNode := nodes[0] + clitest.RunMultisigTest(t, Commands, clientNode) +} + +func startNodes(ctx context.Context, t *testing.T, blocktime time.Duration) ([]test.TestNode, []address.Address) { + n, sn := builder.RPCMockSbBuilder(t, test.OneFull, test.OneMiner) + + full := n[0] + miner := sn[0] + + // Get everyone connected + addrs, err := full.NetAddrsListen(ctx) + if err != nil { + t.Fatal(err) + } + + if err := miner.NetConnect(ctx, addrs); err != nil { + t.Fatal(err) + } + + // Start mining blocks + bm := test.NewBlockMiner(ctx, t, miner, blocktime) + bm.MineBlocks() + + // Get the creator's address + creatorAddr, err := full.WalletDefaultAddress(ctx) + if err != nil { + t.Fatal(err) + } + + // Create mock CLI + return n, []address.Address{creatorAddr} +} diff --git a/cli/paych_test.go b/cli/paych_test.go index b94ba27e7..77a6e61eb 100644 --- a/cli/paych_test.go +++ b/cli/paych_test.go @@ -437,6 +437,7 @@ type mockCLI struct { out *bytes.Buffer } +// TODO: refactor to use the methods in cli/test/mockcli.go func newMockCLI(t *testing.T) *mockCLI { // Create a CLI App with an --api-url flag so that we can specify which node // the command should be executed against diff --git a/cli/test/mockcli.go b/cli/test/mockcli.go new file mode 100644 index 000000000..f5d5cfcba --- /dev/null +++ b/cli/test/mockcli.go @@ -0,0 +1,124 @@ +package test + +import ( + "bytes" + "flag" + "strings" + "testing" + + "github.com/multiformats/go-multiaddr" + "github.com/stretchr/testify/require" + lcli "github.com/urfave/cli/v2" +) + +type mockCLI struct { + t *testing.T + cmds []*lcli.Command + cctx *lcli.Context + out *bytes.Buffer +} + +func newMockCLI(t *testing.T, cmds []*lcli.Command) *mockCLI { + // Create a CLI App with an --api-url flag so that we can specify which node + // the command should be executed against + app := &lcli.App{ + Flags: []lcli.Flag{ + &lcli.StringFlag{ + Name: "api-url", + Hidden: true, + }, + }, + Commands: cmds, + } + + var out bytes.Buffer + app.Writer = &out + app.Setup() + + cctx := lcli.NewContext(app, &flag.FlagSet{}, nil) + return &mockCLI{t: t, cmds: cmds, cctx: cctx, out: &out} +} + +func (c *mockCLI) client(addr multiaddr.Multiaddr) *mockCLIClient { + return &mockCLIClient{t: c.t, cmds: c.cmds, addr: addr, cctx: c.cctx, out: c.out} +} + +// mockCLIClient runs commands against a particular node +type mockCLIClient struct { + t *testing.T + cmds []*lcli.Command + addr multiaddr.Multiaddr + cctx *lcli.Context + out *bytes.Buffer +} + +func (c *mockCLIClient) run(cmd []string, params []string, args []string) string { + // Add parameter --api-url= + apiFlag := "--api-url=" + c.addr.String() + params = append([]string{apiFlag}, params...) + + err := c.cctx.App.Run(append(append(cmd, params...), args...)) + require.NoError(c.t, err) + + // Get the output + str := strings.TrimSpace(c.out.String()) + c.out.Reset() + return str +} + +func (c *mockCLIClient) runCmd(input []string) string { + cmd := c.cmdByNameSub(input[0], input[1]) + out, err := c.runCmdRaw(cmd, input[2:]) + require.NoError(c.t, err) + + return out +} + +func (c *mockCLIClient) cmdByNameSub(name string, sub string) *lcli.Command { + for _, c := range c.cmds { + if c.Name == name { + for _, s := range c.Subcommands { + if s.Name == sub { + return s + } + } + } + } + return nil +} + +func (c *mockCLIClient) runCmdRaw(cmd *lcli.Command, input []string) (string, error) { + // prepend --api-url= + apiFlag := "--api-url=" + c.addr.String() + input = append([]string{apiFlag}, input...) + + fs := c.flagSet(cmd) + err := fs.Parse(input) + require.NoError(c.t, err) + + err = cmd.Action(lcli.NewContext(c.cctx.App, fs, c.cctx)) + + // Get the output + str := strings.TrimSpace(c.out.String()) + c.out.Reset() + return str, err +} + +func (c *mockCLIClient) flagSet(cmd *lcli.Command) *flag.FlagSet { + // Apply app level flags (so we can process --api-url flag) + fs := &flag.FlagSet{} + for _, f := range c.cctx.App.Flags { + err := f.Apply(fs) + if err != nil { + c.t.Fatal(err) + } + } + // Apply command level flags + for _, f := range cmd.Flags { + err := f.Apply(fs) + if err != nil { + c.t.Fatal(err) + } + } + return fs +} diff --git a/cli/test/multisig.go b/cli/test/multisig.go new file mode 100644 index 000000000..96025aa8c --- /dev/null +++ b/cli/test/multisig.go @@ -0,0 +1,77 @@ +package test + +import ( + "context" + "fmt" + "regexp" + "strings" + "testing" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/lotus/api/test" + "github.com/filecoin-project/lotus/chain/types" + logging "github.com/ipfs/go-log/v2" + "github.com/stretchr/testify/require" + lcli "github.com/urfave/cli/v2" +) + +func QuietMiningLogs() { + logging.SetLogLevel("miner", "ERROR") + logging.SetLogLevel("chainstore", "ERROR") + logging.SetLogLevel("chain", "ERROR") + logging.SetLogLevel("sub", "ERROR") + logging.SetLogLevel("storageminer", "ERROR") +} + +func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) { + ctx := context.Background() + + // Create mock CLI + mockCLI := newMockCLI(t, cmds) + clientCLI := mockCLI.client(clientNode.ListenAddr) + + // Create some wallets on the node to use for testing multisig + var walletAddrs []address.Address + for i := 0; i < 4; i++ { + addr, err := clientNode.WalletNew(ctx, types.KTSecp256k1) + require.NoError(t, err) + + walletAddrs = append(walletAddrs, addr) + + test.SendFunds(ctx, t, clientNode, addr, types.NewInt(1e15)) + } + + // Create an msig with three of the addresses and threshold of two sigs + // msig create --required=2 --duration=50 --value=1000attofil + amtAtto := types.NewInt(1000) + threshold := 2 + paramDuration := "--duration=50" + paramRequired := fmt.Sprintf("--required=%d", threshold) + paramValue := fmt.Sprintf("--value=%dattofil", amtAtto) + cmd := []string{ + "msig", "create", + paramRequired, + paramDuration, + paramValue, + walletAddrs[0].String(), + walletAddrs[1].String(), + walletAddrs[2].String(), + } + out := clientCLI.runCmd(cmd) + fmt.Println(out) + + // Extract msig robust address from output + expCreateOutPrefix := "Created new multisig:" + require.Regexp(t, regexp.MustCompile(expCreateOutPrefix), out) + parts := strings.Split(strings.TrimSpace(strings.Replace(out, expCreateOutPrefix, "", -1)), " ") + require.Len(t, parts, 2) + msigRobustAddr := parts[1] + fmt.Println("msig robust address:", msigRobustAddr) + + // msig inspect + cmd = []string{"msig", "inspect", msigRobustAddr} + out = clientCLI.runCmd(cmd) + fmt.Println(out) + + require.Regexp(t, regexp.MustCompile("Balance: 0.000000000000001 FIL"), out) +} diff --git a/cmd/lotus-gateway/api.go b/cmd/lotus-gateway/api.go index d5fac0a06..6d47ff214 100644 --- a/cmd/lotus-gateway/api.go +++ b/cmd/lotus-gateway/api.go @@ -26,9 +26,11 @@ var ( // gatewayDepsAPI defines the API methods that the GatewayAPI depends on // (to make it easy to mock for tests) type gatewayDepsAPI interface { + ChainHasObj(context.Context, cid.Cid) (bool, error) ChainHead(ctx context.Context) (*types.TipSet, error) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) + ChainReadObj(context.Context, cid.Cid) ([]byte, error) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) MpoolPushUntrusted(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) @@ -40,7 +42,18 @@ type gatewayDepsAPI interface { } type GatewayAPI struct { - api gatewayDepsAPI + api gatewayDepsAPI + lookbackCap time.Duration +} + +// NewGatewayAPI creates a new GatewayAPI with the default lookback cap +func NewGatewayAPI(api gatewayDepsAPI) *GatewayAPI { + return newGatewayAPI(api, LookbackCap) +} + +// used by the tests +func newGatewayAPI(api gatewayDepsAPI, lookbackCap time.Duration) *GatewayAPI { + return &GatewayAPI{api: api, lookbackCap: lookbackCap} } func (a *GatewayAPI) checkTipsetKey(ctx context.Context, tsk types.TipSetKey) error { @@ -76,13 +89,17 @@ func (a *GatewayAPI) checkTipsetHeight(ts *types.TipSet, h abi.ChainEpoch) error } func (a *GatewayAPI) checkTimestamp(at time.Time) error { - if time.Since(at) > LookbackCap { + if time.Since(at) > a.lookbackCap { return ErrLookbackTooLong } return nil } +func (a *GatewayAPI) ChainHasObj(ctx context.Context, c cid.Cid) (bool, error) { + return a.api.ChainHasObj(ctx, c) +} + func (a *GatewayAPI) ChainHead(ctx context.Context) (*types.TipSet, error) { // TODO: cache and invalidate cache when timestamp is up (or have internal ChainNotify) @@ -112,6 +129,10 @@ func (a *GatewayAPI) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoc return a.api.ChainGetTipSetByHeight(ctx, h, tsk) } +func (a *GatewayAPI) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) { + return a.api.ChainReadObj(ctx, c) +} + func (a *GatewayAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) { if err := a.checkTipsetKey(ctx, tsk); err != nil { return nil, err diff --git a/cmd/lotus-gateway/api_test.go b/cmd/lotus-gateway/api_test.go index f34f887f5..4946e2a26 100644 --- a/cmd/lotus-gateway/api_test.go +++ b/cmd/lotus-gateway/api_test.go @@ -109,6 +109,10 @@ type mockGatewayDepsAPI struct { tipsets []*types.TipSet } +func (m *mockGatewayDepsAPI) ChainHasObj(context.Context, cid.Cid) (bool, error) { + panic("implement me") +} + func (m *mockGatewayDepsAPI) ChainHead(ctx context.Context) (*types.TipSet, error) { m.lk.RLock() defer m.lk.RUnlock() @@ -158,6 +162,10 @@ func (m *mockGatewayDepsAPI) ChainGetTipSetByHeight(ctx context.Context, h abi.C return m.tipsets[h], nil } +func (m *mockGatewayDepsAPI) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) { + panic("implement me") +} + func (m *mockGatewayDepsAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) { panic("implement me") } diff --git a/cmd/lotus-gateway/endtoend_test.go b/cmd/lotus-gateway/endtoend_test.go index eebf56a9f..379c96053 100644 --- a/cmd/lotus-gateway/endtoend_test.go +++ b/cmd/lotus-gateway/endtoend_test.go @@ -4,10 +4,14 @@ import ( "bytes" "context" "fmt" + "math" "os" "testing" "time" + "github.com/filecoin-project/lotus/cli" + clitest "github.com/filecoin-project/lotus/cli/test" + init0 "github.com/filecoin-project/specs-actors/actors/builtin/init" "github.com/filecoin-project/specs-actors/actors/builtin/multisig" @@ -26,20 +30,22 @@ import ( builder "github.com/filecoin-project/lotus/node/test" ) +const maxLookbackCap = time.Duration(math.MaxInt64) + func init() { policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1) policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048)) policy.SetMinVerifiedDealSize(abi.NewStoragePower(256)) } -// TestEndToEnd tests that API calls can be made on a lite node that is -// connected through a gateway to a full API node -func TestEndToEnd(t *testing.T) { +// TestEndToEndWalletMsig tests that wallet and msig API calls can be made +// on a lite node that is connected through a gateway to a full API node +func TestEndToEndWalletMsig(t *testing.T) { _ = os.Setenv("BELLMAN_NO_GPU", "1") blocktime := 5 * time.Millisecond ctx := context.Background() - full, lite, closer := startNodes(ctx, t, blocktime) + full, lite, closer := startNodes(ctx, t, blocktime, maxLookbackCap) defer closer() // The full node starts with a wallet @@ -56,11 +62,11 @@ func TestEndToEnd(t *testing.T) { require.NoError(t, err) // Send some funds from the full node to the lite node - err = sendFunds(ctx, t, full, fullWalletAddr, liteWalletAddr, types.NewInt(1e18)) + err = sendFunds(ctx, full, fullWalletAddr, liteWalletAddr, types.NewInt(1e18)) require.NoError(t, err) // Send some funds from the lite node back to the full node - err = sendFunds(ctx, t, lite, liteWalletAddr, fullWalletAddr, types.NewInt(100)) + err = sendFunds(ctx, lite, liteWalletAddr, fullWalletAddr, types.NewInt(100)) require.NoError(t, err) // Sign some data with the lite node wallet address @@ -81,7 +87,7 @@ func TestEndToEnd(t *testing.T) { walletAddrs = append(walletAddrs, addr) - err = sendFunds(ctx, t, lite, liteWalletAddr, addr, types.NewInt(1e15)) + err = sendFunds(ctx, lite, liteWalletAddr, addr, types.NewInt(1e15)) require.NoError(t, err) } @@ -135,7 +141,33 @@ func TestEndToEnd(t *testing.T) { require.True(t, approveReturn.Applied) } -func sendFunds(ctx context.Context, t *testing.T, fromNode test.TestNode, fromAddr address.Address, toAddr address.Address, amt types.BigInt) error { +// TestEndToEndMsigCLI tests that msig CLI calls can be made +// on a lite node that is connected through a gateway to a full API node +func TestEndToEndMsigCLI(t *testing.T) { + _ = os.Setenv("BELLMAN_NO_GPU", "1") + clitest.QuietMiningLogs() + + blocktime := 5 * time.Millisecond + ctx := context.Background() + full, lite, closer := startNodes(ctx, t, blocktime, maxLookbackCap) + defer closer() + + // The full node starts with a wallet + fullWalletAddr, err := full.WalletDefaultAddress(ctx) + require.NoError(t, err) + + // Create a wallet on the lite node + liteWalletAddr, err := lite.WalletNew(ctx, types.KTSecp256k1) + require.NoError(t, err) + + // Send some funds from the full node to the lite node + err = sendFunds(ctx, full, fullWalletAddr, liteWalletAddr, types.NewInt(1e18)) + require.NoError(t, err) + + clitest.RunMultisigTest(t, cli.Commands, lite) +} + +func sendFunds(ctx context.Context, fromNode test.TestNode, fromAddr address.Address, toAddr address.Address, amt types.BigInt) error { msg := &types.Message{ From: fromAddr, To: toAddr, @@ -158,7 +190,7 @@ func sendFunds(ctx context.Context, t *testing.T, fromNode test.TestNode, fromAd return nil } -func startNodes(ctx context.Context, t *testing.T, blocktime time.Duration) (test.TestNode, test.TestNode, jsonrpc.ClientCloser) { +func startNodes(ctx context.Context, t *testing.T, blocktime time.Duration, lookbackCap time.Duration) (test.TestNode, test.TestNode, jsonrpc.ClientCloser) { var closer jsonrpc.ClientCloser // Create one miner and two full nodes. @@ -175,7 +207,7 @@ func startNodes(ctx context.Context, t *testing.T, blocktime time.Duration) (tes fullNode := nodes[0] // Create a gateway server in front of the full node - _, addr, err := builder.CreateRPCServer(&GatewayAPI{api: fullNode}) + _, addr, err := builder.CreateRPCServer(newGatewayAPI(fullNode, lookbackCap)) require.NoError(t, err) // Create a gateway client API that connects to the gateway server diff --git a/cmd/lotus-gateway/main.go b/cmd/lotus-gateway/main.go index c19599084..34e068ffd 100644 --- a/cmd/lotus-gateway/main.go +++ b/cmd/lotus-gateway/main.go @@ -76,7 +76,7 @@ var runCmd = &cli.Command{ log.Info("Setting up API endpoint at " + address) rpcServer := jsonrpc.NewServer() - rpcServer.Register("Filecoin", &GatewayAPI{api: api}) + rpcServer.Register("Filecoin", NewGatewayAPI(api)) mux.Handle("/rpc/v0", rpcServer) mux.PathPrefix("/").Handler(http.DefaultServeMux) diff --git a/node/impl/full/chain.go b/node/impl/full/chain.go index 5b4f41114..095b51ed8 100644 --- a/node/impl/full/chain.go +++ b/node/impl/full/chain.go @@ -40,9 +40,11 @@ import ( var log = logging.Logger("fullnode") type ChainModuleAPI interface { + ChainHasObj(context.Context, cid.Cid) (bool, error) ChainHead(context.Context) (*types.TipSet, error) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) + ChainReadObj(context.Context, cid.Cid) ([]byte, error) } // ChainModule provides a default implementation of ChainModuleAPI. @@ -206,8 +208,8 @@ func (m *ChainModule) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpo return m.Chain.GetTipsetByHeight(ctx, h, ts, true) } -func (a *ChainAPI) ChainReadObj(ctx context.Context, obj cid.Cid) ([]byte, error) { - blk, err := a.Chain.Blockstore().Get(obj) +func (m *ChainModule) ChainReadObj(ctx context.Context, obj cid.Cid) ([]byte, error) { + blk, err := m.Chain.Blockstore().Get(obj) if err != nil { return nil, xerrors.Errorf("blockstore get: %w", err) } @@ -219,8 +221,8 @@ func (a *ChainAPI) ChainDeleteObj(ctx context.Context, obj cid.Cid) error { return a.Chain.Blockstore().DeleteBlock(obj) } -func (a *ChainAPI) ChainHasObj(ctx context.Context, obj cid.Cid) (bool, error) { - return a.Chain.Blockstore().Has(obj) +func (m *ChainModule) ChainHasObj(ctx context.Context, obj cid.Cid) (bool, error) { + return m.Chain.Blockstore().Has(obj) } func (a *ChainAPI) ChainStatObj(ctx context.Context, obj cid.Cid, base cid.Cid) (api.ObjStat, error) { From f74852bd73ab9beed57500f879d5e07b0abf3dcf Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Thu, 15 Oct 2020 12:45:02 +0200 Subject: [PATCH 137/313] test: add more msig cli tests --- cli/multisig.go | 2 +- cli/test/multisig.go | 37 +++++++++++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/cli/multisig.go b/cli/multisig.go index 97a77a75b..90b074421 100644 --- a/cli/multisig.go +++ b/cli/multisig.go @@ -677,7 +677,7 @@ var msigAddProposeCmd = &cli.Command{ return err } - fmt.Println("sent add proposal in message: ", msgCid) + fmt.Fprintln(cctx.App.Writer, "sent add proposal in message: ", msgCid) wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence) if err != nil { diff --git a/cli/test/multisig.go b/cli/test/multisig.go index 96025aa8c..e77879346 100644 --- a/cli/test/multisig.go +++ b/cli/test/multisig.go @@ -68,10 +68,43 @@ func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNod msigRobustAddr := parts[1] fmt.Println("msig robust address:", msigRobustAddr) - // msig inspect - cmd = []string{"msig", "inspect", msigRobustAddr} + // Propose to add a new address to the msig + // msig add-propose --from= + paramFrom := fmt.Sprintf("--from=%s", walletAddrs[0]) + cmd = []string{ + "msig", "add-propose", + paramFrom, + msigRobustAddr, + walletAddrs[3].String(), + } out = clientCLI.runCmd(cmd) fmt.Println(out) + // msig inspect + cmd = []string{"msig", "inspect", "--vesting", "--decode-params", msigRobustAddr} + out = clientCLI.runCmd(cmd) + fmt.Println(out) + + // Expect correct balance require.Regexp(t, regexp.MustCompile("Balance: 0.000000000000001 FIL"), out) + // Expect 1 transaction + require.Regexp(t, regexp.MustCompile(`Transactions:\s*1`), out) + // Expect transaction to be "AddSigner" + require.Regexp(t, regexp.MustCompile(`AddSigner`), out) + + // Approve adding the new address + // msig add-approve --from= 0 false + txnID := "0" + paramFrom = fmt.Sprintf("--from=%s", walletAddrs[1]) + cmd = []string{ + "msig", "add-approve", + paramFrom, + msigRobustAddr, + walletAddrs[0].String(), + txnID, + walletAddrs[3].String(), + "false", + } + out = clientCLI.runCmd(cmd) + fmt.Println(out) } From f5d48b0e86a3771a9aa36232c21e749aca188491 Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Thu, 15 Oct 2020 12:47:24 +0200 Subject: [PATCH 138/313] fix: lotus-gateway api tests --- cmd/lotus-gateway/api_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/lotus-gateway/api_test.go b/cmd/lotus-gateway/api_test.go index 4946e2a26..5b8261974 100644 --- a/cmd/lotus-gateway/api_test.go +++ b/cmd/lotus-gateway/api_test.go @@ -88,7 +88,7 @@ func TestGatewayAPIChainGetTipSetByHeight(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { mock := &mockGatewayDepsAPI{} - a := &GatewayAPI{api: mock} + a := NewGatewayAPI(mock) // Create tipsets from genesis up to tskh and return the highest ts := mock.createTipSets(tt.args.tskh, tt.args.genesisTS) From 4e659e30c54e58af2a59be858aa5f3d14cafb6df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Thu, 15 Oct 2020 12:14:16 +0100 Subject: [PATCH 139/313] fix lint errors. --- cmd/tvx/codenames_test.go | 2 +- cmd/tvx/exec.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/tvx/codenames_test.go b/cmd/tvx/codenames_test.go index 0b1de9fc2..00d107707 100644 --- a/cmd/tvx/codenames_test.go +++ b/cmd/tvx/codenames_test.go @@ -18,7 +18,7 @@ func TestProtocolCodenames(t *testing.T) { t.Fatal("expected breeze codename") } - if height := abi.ChainEpoch(build.UpgradeActorsV2Height + 1); GetProtocolCodename(height) != "actorsv2" { + if height := build.UpgradeActorsV2Height + 1; GetProtocolCodename(height) != "actorsv2" { t.Fatal("expected actorsv2 codename") } diff --git a/cmd/tvx/exec.go b/cmd/tvx/exec.go index de7d2a398..89ad23913 100644 --- a/cmd/tvx/exec.go +++ b/cmd/tvx/exec.go @@ -76,7 +76,7 @@ func executeTestVector(tv schema.TestVector) error { for _, v := range tv.Pre.Variants { r := new(conformance.LogReporter) - switch class := tv.Class; class { + switch class, v := tv.Class, v; class { case "message": conformance.ExecuteMessageVector(r, &tv, &v) case "tipset": From 7e6ede7563fc859b909fa5f54660bb5e5127a4e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Thu, 15 Oct 2020 12:49:23 +0100 Subject: [PATCH 140/313] update schema; test-vectors submodule. --- extern/test-vectors | 2 +- go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/extern/test-vectors b/extern/test-vectors index a8f968ade..d9a75a787 160000 --- a/extern/test-vectors +++ b/extern/test-vectors @@ -1 +1 @@ -Subproject commit a8f968adeba1995f161f7be0048188affc425079 +Subproject commit d9a75a7873aee0db28b87e3970d2ea16a2f37c6a diff --git a/go.mod b/go.mod index 1516cba81..a810e118c 100644 --- a/go.mod +++ b/go.mod @@ -41,7 +41,7 @@ require ( github.com/filecoin-project/specs-actors v0.9.12 github.com/filecoin-project/specs-actors/v2 v2.1.0 github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796 - github.com/filecoin-project/test-vectors/schema v0.0.5-0.20201014133607-1352e6bb4e71 + github.com/filecoin-project/test-vectors/schema v0.0.5 github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1 github.com/go-kit/kit v0.10.0 github.com/go-ole/go-ole v1.2.4 // indirect diff --git a/go.sum b/go.sum index 47301c784..3d543fab0 100644 --- a/go.sum +++ b/go.sum @@ -282,8 +282,8 @@ github.com/filecoin-project/specs-actors/v2 v2.1.0 h1:ocEuGz8DG2cUWw32c/tvF8D6xT github.com/filecoin-project/specs-actors/v2 v2.1.0/go.mod h1:E7fAX4CZkDVQvDNRCxfq+hc3nx56KcCKyuZf0hlQJ20= github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796 h1:dJsTPWpG2pcTeojO2pyn0c6l+x/3MZYCBgo/9d11JEk= github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g= -github.com/filecoin-project/test-vectors/schema v0.0.5-0.20201014133607-1352e6bb4e71 h1:qnleaW7X8Gi2e3QtqPMFdqVn/DUaNI5tCnq7wNVMnio= -github.com/filecoin-project/test-vectors/schema v0.0.5-0.20201014133607-1352e6bb4e71/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E= +github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= +github.com/filecoin-project/test-vectors/schema v0.0.5/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6 h1:u/UEqS66A5ckRmS4yNpjmVH56sVtS/RfclBAYocb4as= github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6/go.mod h1:1i71OnUq3iUe1ma7Lr6yG6/rjvM3emb6yoL7xLFzcVQ= From 1fb9ed1c9a53fc304151f65d8409ccb4ae072d71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Thu, 15 Oct 2020 12:58:43 +0100 Subject: [PATCH 141/313] remove TODO. --- cmd/tvx/codenames.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/cmd/tvx/codenames.go b/cmd/tvx/codenames.go index 1cb1b32fb..851e9d841 100644 --- a/cmd/tvx/codenames.go +++ b/cmd/tvx/codenames.go @@ -16,9 +16,6 @@ var ProtocolCodenames = []struct { name string }{ {0, "genesis"}, - // TODO there is some off-by-one trickery in GetNtwkVersion. Not sure if the - // protocol version really kicks in at the designated height, or at the - // following epoch. {build.UpgradeBreezeHeight + 1, "breeze"}, {build.UpgradeSmokeHeight + 1, "smoke"}, {build.UpgradeIgnitionHeight + 1, "ignition"}, From a931ff94e908a6467f35aaedf183f10f21dc5d9c Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Thu, 15 Oct 2020 08:54:36 -0700 Subject: [PATCH 142/313] fix message list api --- api/api_full.go | 7 ++++++- api/apistruct/struct.go | 4 ++-- cli/state.go | 2 +- node/impl/full/state.go | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index 65182078a..89a41dede 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -327,7 +327,7 @@ type FullNode interface { // StateReadState returns the indicated actor's state. StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*ActorState, error) // StateListMessages looks back and returns all messages with a matching to or from address, stopping at the given height. - StateListMessages(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) + StateListMessages(ctx context.Context, match *MessageMatch, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) // StateNetworkName returns the name of the network the node is synced to StateNetworkName(context.Context) (dtypes.NetworkName, error) @@ -918,3 +918,8 @@ type MsigVesting struct { StartEpoch abi.ChainEpoch UnlockDuration abi.ChainEpoch } + +type MessageMatch struct { + To address.Address + From address.Address +} diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 3854e1dd6..ba3a39516 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -206,7 +206,7 @@ type FullNodeStruct struct { StateChangedActors func(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error) `perm:"read"` StateGetReceipt func(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error) `perm:"read"` StateMinerSectorCount func(context.Context, address.Address, types.TipSetKey) (api.MinerSectors, error) `perm:"read"` - StateListMessages func(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"` + StateListMessages func(ctx context.Context, match *api.MessageMatch, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"` StateCompute func(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (*api.ComputeStateOutput, error) `perm:"read"` StateVerifierStatus func(context.Context, address.Address, types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` StateVerifiedClientStatus func(context.Context, address.Address, types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` @@ -948,7 +948,7 @@ func (c *FullNodeStruct) StateGetReceipt(ctx context.Context, msg cid.Cid, tsk t return c.Internal.StateGetReceipt(ctx, msg, tsk) } -func (c *FullNodeStruct) StateListMessages(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) { +func (c *FullNodeStruct) StateListMessages(ctx context.Context, match *api.MessageMatch, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) { return c.Internal.StateListMessages(ctx, match, tsk, toht) } diff --git a/cli/state.go b/cli/state.go index 1e7e24ddb..a02a70505 100644 --- a/cli/state.go +++ b/cli/state.go @@ -844,7 +844,7 @@ var stateListMessagesCmd = &cli.Command{ return err } - msgs, err := api.StateListMessages(ctx, &types.Message{To: toa, From: froma}, ts.Key(), abi.ChainEpoch(toh)) + msgs, err := api.StateListMessages(ctx, &lapi.MessageMatch{To: toa, From: froma}, ts.Key(), abi.ChainEpoch(toh)) if err != nil { return err } diff --git a/node/impl/full/state.go b/node/impl/full/state.go index 08ac62f2e..81947cbe3 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -760,7 +760,7 @@ func (a *StateAPI) StateSectorPartition(ctx context.Context, maddr address.Addre return mas.FindSector(sectorNumber) } -func (a *StateAPI) StateListMessages(ctx context.Context, match *types.Message, tsk types.TipSetKey, toheight abi.ChainEpoch) ([]cid.Cid, error) { +func (a *StateAPI) StateListMessages(ctx context.Context, match *api.MessageMatch, tsk types.TipSetKey, toheight abi.ChainEpoch) ([]cid.Cid, error) { ts, err := a.Chain.GetTipSetFromKey(tsk) if err != nil { return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) From 8c7d2efe72f864c7ebb483d047aee12138df7359 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Thu, 15 Oct 2020 11:51:40 -0400 Subject: [PATCH 143/313] Make audit balances capable of printing robust addresses --- cmd/lotus-shed/balances.go | 51 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/cmd/lotus-shed/balances.go b/cmd/lotus-shed/balances.go index dfdaf9fa9..b12c069f5 100644 --- a/cmd/lotus-shed/balances.go +++ b/cmd/lotus-shed/balances.go @@ -5,6 +5,10 @@ import ( "fmt" "strconv" + "github.com/filecoin-project/lotus/chain/gen/genesis" + + _init "github.com/filecoin-project/lotus/chain/actors/builtin/init" + "github.com/docker/go-units" "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/actors/builtin/multisig" @@ -136,6 +140,9 @@ var chainBalanceStateCmd = &cli.Command{ &cli.BoolFlag{ Name: "miner-info", }, + &cli.BoolFlag{ + Name: "robust-addresses", + }, }, Action: func(cctx *cli.Context) error { ctx := context.TODO() @@ -187,6 +194,33 @@ var chainBalanceStateCmd = &cli.Command{ minerInfo := cctx.Bool("miner-info") + robustMap := make(map[address.Address]address.Address) + if cctx.Bool("robust-addresses") { + iact, err := tree.GetActor(_init.Address) + if err != nil { + return xerrors.Errorf("failed to load init actor: %w", err) + } + + ist, err := _init.Load(store, iact) + if err != nil { + return xerrors.Errorf("failed to load init actor state: %w", err) + } + + err = ist.ForEachActor(func(id abi.ActorID, addr address.Address) error { + idAddr, err := address.NewIDAddress(uint64(id)) + if err != nil { + return xerrors.Errorf("failed to write to addr map: %w", err) + } + + robustMap[idAddr] = addr + + return nil + }) + if err != nil { + return xerrors.Errorf("failed to invert init address map: %w", err) + } + } + var infos []accountInfo err = tree.ForEach(func(addr address.Address, act *types.Actor) error { @@ -201,6 +235,23 @@ var chainBalanceStateCmd = &cli.Command{ VestingAmount: types.FIL(big.NewInt(0)), } + if cctx.Bool("robust-addresses") { + robust, found := robustMap[addr] + if found { + ai.Address = robust + } else { + id, err := address.IDFromAddress(addr) + if err != nil { + return xerrors.Errorf("failed to get ID address: %w", err) + } + + // TODO: This is not the correctest way to determine whether a robust address should exist + if id >= genesis.MinerStart { + return xerrors.Errorf("address doesn't have a robust address: %s", addr) + } + } + } + if minerInfo && builtin.IsStorageMinerActor(act.Code) { pow, _, _, err := stmgr.GetPowerRaw(ctx, sm, sroot, addr) if err != nil { From 0b7dc6971dbe1a1e5caae2678d5ed6606bb7dcdc Mon Sep 17 00:00:00 2001 From: Ingar Shu Date: Thu, 15 Oct 2020 09:24:48 -0700 Subject: [PATCH 144/313] Rebasing --- markets/dealfilter/cli.go | 68 ++++++++++++++++++++----------- node/builder.go | 6 ++- node/modules/dtypes/miner.go | 4 +- node/modules/storageminer.go | 78 +++++++++++++++++++++++------------- 4 files changed, 102 insertions(+), 54 deletions(-) diff --git a/markets/dealfilter/cli.go b/markets/dealfilter/cli.go index 2cb9d6c4f..af832bfa0 100644 --- a/markets/dealfilter/cli.go +++ b/markets/dealfilter/cli.go @@ -6,35 +6,57 @@ import ( "encoding/json" "os/exec" + "github.com/filecoin-project/go-fil-markets/retrievalmarket" "github.com/filecoin-project/go-fil-markets/storagemarket" "github.com/filecoin-project/lotus/node/modules/dtypes" ) -func CliDealFilter(cmd string) dtypes.DealFilter { - // TODO: run some checks on the cmd string - +func CliStorageDealFilter(cmd string) dtypes.StorageDealFilter { return func(ctx context.Context, deal storagemarket.MinerDeal) (bool, string, error) { - j, err := json.MarshalIndent(deal, "", " ") - if err != nil { - return false, "", err + d := struct { + storagemarket.MinerDeal + DealType string + }{ + MinerDeal: deal, + DealType: "storage", } - - var out bytes.Buffer - - c := exec.Command("sh", "-c", cmd) - c.Stdin = bytes.NewReader(j) - c.Stdout = &out - c.Stderr = &out - - switch err := c.Run().(type) { - case nil: - return true, "", nil - case *exec.ExitError: - return false, out.String(), nil - default: - return false, "filter cmd run error", err - } - + return runDealFilter(ctx, cmd, d) + } +} + +func CliRetrievalDealFilter(cmd string) dtypes.RetrievalDealFilter { + return func(ctx context.Context, deal retrievalmarket.ProviderDealState) (bool, string, error) { + d := struct { + retrievalmarket.ProviderDealState + DealType string + }{ + ProviderDealState: deal, + DealType: "retrieval", + } + return runDealFilter(ctx, cmd, d) + } +} + +func runDealFilter(ctx context.Context, cmd string, deal interface{}) (bool, string, error) { + j, err := json.MarshalIndent(deal, "", " ") + if err != nil { + return false, "", err + } + + var out bytes.Buffer + + c := exec.Command("sh", "-c", cmd) + c.Stdin = bytes.NewReader(j) + c.Stdout = &out + c.Stderr = &out + + switch err := c.Run().(type) { + case nil: + return true, "", nil + case *exec.ExitError: + return false, out.String(), nil + default: + return false, "filter cmd run error", err } } diff --git a/node/builder.go b/node/builder.go index f96505eec..b6b75ecc6 100644 --- a/node/builder.go +++ b/node/builder.go @@ -354,7 +354,8 @@ func Online() Option { Override(new(dtypes.ProviderDataTransfer), modules.NewProviderDAGServiceDataTransfer), Override(new(dtypes.ProviderPieceStore), modules.NewProviderPieceStore), Override(new(*storedask.StoredAsk), modules.NewStorageAsk), - Override(new(dtypes.DealFilter), modules.BasicDealFilter(nil)), + Override(new(dtypes.StorageDealFilter), modules.BasicDealFilter(nil)), + Override(new(dtypes.RetrievalDealFilter), modules.RetrievalDealFilter(nil)), Override(new(modules.ProviderDealFunds), modules.NewProviderDealFunds), Override(new(storagemarket.StorageProvider), modules.StorageProvider), Override(new(storagemarket.StorageProviderNode), storageadapter.NewProviderNodeAdapter(nil)), @@ -484,7 +485,8 @@ func ConfigStorageMiner(c interface{}) Option { ConfigCommon(&cfg.Common), If(cfg.Dealmaking.Filter != "", - Override(new(dtypes.DealFilter), modules.BasicDealFilter(dealfilter.CliDealFilter(cfg.Dealmaking.Filter))), + Override(new(dtypes.StorageDealFilter), modules.BasicDealFilter(dealfilter.CliStorageDealFilter(cfg.Dealmaking.Filter))), + Override(new(dtypes.RetrievalDealFilter), modules.RetrievalDealFilter(dealfilter.CliRetrievalDealFilter(cfg.Dealmaking.Filter))), ), Override(new(storagemarket.StorageProviderNode), storageadapter.NewProviderNodeAdapter(&cfg.Fees)), diff --git a/node/modules/dtypes/miner.go b/node/modules/dtypes/miner.go index 5bb439b4d..1ef157b7e 100644 --- a/node/modules/dtypes/miner.go +++ b/node/modules/dtypes/miner.go @@ -7,6 +7,7 @@ import ( "github.com/ipfs/go-cid" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-fil-markets/retrievalmarket" "github.com/filecoin-project/go-fil-markets/storagemarket" "github.com/filecoin-project/go-state-types/abi" @@ -71,4 +72,5 @@ type SetExpectedSealDurationFunc func(time.Duration) error // too determine how long sealing is expected to take type GetExpectedSealDurationFunc func() (time.Duration, error) -type DealFilter func(ctx context.Context, deal storagemarket.MinerDeal) (bool, string, error) +type StorageDealFilter func(ctx context.Context, deal storagemarket.MinerDeal) (bool, string, error) +type RetrievalDealFilter func(ctx context.Context, deal retrievalmarket.ProviderDealState) (bool, string, error) diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index adacf5405..74dfff5e1 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -412,16 +412,16 @@ func NewProviderDealFunds(ds dtypes.MetadataDS) (ProviderDealFunds, error) { return funds.NewDealFunds(ds, datastore.NewKey("/marketfunds/provider")) } -func BasicDealFilter(user dtypes.DealFilter) func(onlineOk dtypes.ConsiderOnlineStorageDealsConfigFunc, +func BasicDealFilter(user dtypes.StorageDealFilter) func(onlineOk dtypes.ConsiderOnlineStorageDealsConfigFunc, offlineOk dtypes.ConsiderOfflineStorageDealsConfigFunc, blocklistFunc dtypes.StorageDealPieceCidBlocklistConfigFunc, expectedSealTimeFunc dtypes.GetExpectedSealDurationFunc, - spn storagemarket.StorageProviderNode) dtypes.DealFilter { + spn storagemarket.StorageProviderNode) dtypes.StorageDealFilter { return func(onlineOk dtypes.ConsiderOnlineStorageDealsConfigFunc, offlineOk dtypes.ConsiderOfflineStorageDealsConfigFunc, blocklistFunc dtypes.StorageDealPieceCidBlocklistConfigFunc, expectedSealTimeFunc dtypes.GetExpectedSealDurationFunc, - spn storagemarket.StorageProviderNode) dtypes.DealFilter { + spn storagemarket.StorageProviderNode) dtypes.StorageDealFilter { return func(ctx context.Context, deal storagemarket.MinerDeal) (bool, string, error) { b, err := onlineOk() @@ -497,7 +497,7 @@ func StorageProvider(minerAddress dtypes.MinerAddress, pieceStore dtypes.ProviderPieceStore, dataTransfer dtypes.ProviderDataTransfer, spn storagemarket.StorageProviderNode, - df dtypes.DealFilter, + df dtypes.StorageDealFilter, funds ProviderDealFunds, ) (storagemarket.StorageProvider, error) { net := smnet.NewFromLibp2pHost(h) @@ -511,8 +511,52 @@ func StorageProvider(minerAddress dtypes.MinerAddress, return storageimpl.NewProvider(net, namespace.Wrap(ds, datastore.NewKey("/deals/provider")), store, mds, pieceStore, dataTransfer, spn, address.Address(minerAddress), ffiConfig.SealProofType, storedAsk, funds, opt) } +func RetrievalDealFilter(userFilter dtypes.RetrievalDealFilter) func(onlineOk dtypes.ConsiderOnlineRetrievalDealsConfigFunc, + offlineOk dtypes.ConsiderOfflineRetrievalDealsConfigFunc) dtypes.RetrievalDealFilter { + return func(onlineOk dtypes.ConsiderOnlineRetrievalDealsConfigFunc, + offlineOk dtypes.ConsiderOfflineRetrievalDealsConfigFunc) dtypes.RetrievalDealFilter { + return func(ctx context.Context, state retrievalmarket.ProviderDealState) (bool, string, error) { + b, err := onlineOk() + if err != nil { + return false, "miner error", err + } + + if !b { + log.Warn("online retrieval deal consideration disabled; rejecting retrieval deal proposal from client") + return false, "miner is not accepting online retrieval deals", nil + } + + b, err = offlineOk() + if err != nil { + return false, "miner error", err + } + + if !b { + log.Info("offline retrieval has not been implemented yet") + } + + if userFilter != nil { + return userFilter(ctx, state) + } + + return true, "", nil + } + } +} + // RetrievalProvider creates a new retrieval provider attached to the provider blockstore -func RetrievalProvider(h host.Host, miner *storage.Miner, sealer sectorstorage.SectorManager, full lapi.FullNode, ds dtypes.MetadataDS, pieceStore dtypes.ProviderPieceStore, mds dtypes.StagingMultiDstore, dt dtypes.ProviderDataTransfer, onlineOk dtypes.ConsiderOnlineRetrievalDealsConfigFunc, offlineOk dtypes.ConsiderOfflineRetrievalDealsConfigFunc) (retrievalmarket.RetrievalProvider, error) { +func RetrievalProvider(h host.Host, + miner *storage.Miner, + sealer sectorstorage.SectorManager, + full lapi.FullNode, + ds dtypes.MetadataDS, + pieceStore dtypes.ProviderPieceStore, + mds dtypes.StagingMultiDstore, + dt dtypes.ProviderDataTransfer, + onlineOk dtypes.ConsiderOnlineRetrievalDealsConfigFunc, + offlineOk dtypes.ConsiderOfflineRetrievalDealsConfigFunc, + userFilter dtypes.RetrievalDealFilter, +) (retrievalmarket.RetrievalProvider, error) { adapter := retrievaladapter.NewRetrievalProviderNode(miner, sealer, full) maddr, err := minerAddrFromDS(ds) @@ -521,29 +565,7 @@ func RetrievalProvider(h host.Host, miner *storage.Miner, sealer sectorstorage.S } netwk := rmnet.NewFromLibp2pHost(h) - - opt := retrievalimpl.DealDeciderOpt(func(ctx context.Context, state retrievalmarket.ProviderDealState) (bool, string, error) { - b, err := onlineOk() - if err != nil { - return false, "miner error", err - } - - if !b { - log.Warn("online retrieval deal consideration disabled; rejecting retrieval deal proposal from client") - return false, "miner is not accepting online retrieval deals", nil - } - - b, err = offlineOk() - if err != nil { - return false, "miner error", err - } - - if !b { - log.Info("offline retrieval has not been implemented yet") - } - - return true, "", nil - }) + opt := retrievalimpl.DealDeciderOpt(retrievalimpl.DealDecider(userFilter)) return retrievalimpl.NewProvider(maddr, adapter, netwk, pieceStore, mds, dt, namespace.Wrap(ds, datastore.NewKey("/retrievals/provider")), opt) } From 5bee85d57a43d45d77acc910800b1514b8e4517d Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Thu, 15 Oct 2020 09:38:27 -0700 Subject: [PATCH 145/313] incremental output for list-messages --- cli/state.go | 55 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/cli/state.go b/cli/state.go index a02a70505..99ace833a 100644 --- a/cli/state.go +++ b/cli/state.go @@ -837,33 +837,66 @@ var stateListMessagesCmd = &cli.Command{ froma = a } - toh := cctx.Uint64("toheight") + toh := abi.ChainEpoch(cctx.Uint64("toheight")) ts, err := LoadTipSet(ctx, cctx, api) if err != nil { return err } - msgs, err := api.StateListMessages(ctx, &lapi.MessageMatch{To: toa, From: froma}, ts.Key(), abi.ChainEpoch(toh)) - if err != nil { - return err + if ts == nil { + head, err := api.ChainHead(ctx) + if err != nil { + return err + } + ts = head } - for _, c := range msgs { - if cctx.Bool("cids") { - fmt.Println(c.String()) - continue + windowSize := abi.ChainEpoch(100) + + cur := ts + for cur.Height() > toh { + if ctx.Err() != nil { + return ctx.Err() } - m, err := api.ChainGetMessage(ctx, c) + end := toh + if cur.Height()-windowSize > end { + end = cur.Height() - windowSize + } + + msgs, err := api.StateListMessages(ctx, &lapi.MessageMatch{To: toa, From: froma}, cur.Key(), end) if err != nil { return err } - b, err := json.MarshalIndent(m, "", " ") + + for _, c := range msgs { + if cctx.Bool("cids") { + fmt.Println(c.String()) + continue + } + + m, err := api.ChainGetMessage(ctx, c) + if err != nil { + return err + } + b, err := json.MarshalIndent(m, "", " ") + if err != nil { + return err + } + fmt.Println(string(b)) + } + + if end <= 0 { + break + } + + next, err := api.ChainGetTipSetByHeight(ctx, end-1, cur.Key()) if err != nil { return err } - fmt.Println(string(b)) + + cur = next } return nil From eae7d62a2b416c7e51d0884a0a875c644a72431f Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Thu, 15 Oct 2020 12:07:41 -0700 Subject: [PATCH 146/313] docsgen --- documentation/en/api-methods.md | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index a905ef2e3..4c3bd44ff 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -3352,19 +3352,8 @@ Inputs: ```json [ { - "Version": 42, "To": "f01234", - "From": "f01234", - "Nonce": 42, - "Value": "0", - "GasLimit": 9, - "GasFeeCap": "0", - "GasPremium": "0", - "Method": 1, - "Params": "Ynl0ZSBhcnJheQ==", - "CID": { - "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" - } + "From": "f01234" }, [ { From 726eacbe037c02b5d5cd9648f0171e968dedf63e Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Thu, 15 Oct 2020 13:54:58 -0700 Subject: [PATCH 147/313] add endpoints needed by spacegap --- cmd/lotus-gateway/api.go | 57 ++++++++++++++++++++++++++++++++--- cmd/lotus-gateway/api_test.go | 3 ++ 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/cmd/lotus-gateway/api.go b/cmd/lotus-gateway/api.go index 1cdd37915..fe68018d8 100644 --- a/cmd/lotus-gateway/api.go +++ b/cmd/lotus-gateway/api.go @@ -6,10 +6,12 @@ import ( "time" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-bitfield" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/lib/sigs" _ "github.com/filecoin-project/lotus/lib/sigs/bls" @@ -44,6 +46,12 @@ type gatewayDepsAPI interface { StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) StateWaitMsgLimited(ctx context.Context, msg cid.Cid, confidence uint64, h abi.ChainEpoch) (*api.MsgLookup, error) StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error) + StateMinerPower(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error) + StateMinerFaults(context.Context, address.Address, types.TipSetKey) (bitfield.BitField, error) + StateMinerRecoveries(context.Context, address.Address, types.TipSetKey) (bitfield.BitField, error) + StateMinerInfo(context.Context, address.Address, types.TipSetKey) (miner.MinerInfo, error) + StateMinerDeadlines(context.Context, address.Address, types.TipSetKey) ([]api.Deadline, error) + StateMinerAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) } type GatewayAPI struct { @@ -198,10 +206,6 @@ func (a *GatewayAPI) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence u return a.api.StateWaitMsgLimited(ctx, msg, confidence, stateWaitLookbackLimit) } -func (a *GatewayAPI) WalletVerify(ctx context.Context, k address.Address, msg []byte, sig *crypto.Signature) (bool, error) { - return sigs.Verify(sig, k, msg) == nil, nil -} - func (a *GatewayAPI) StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error) { if err := a.checkTipsetKey(ctx, tsk); err != nil { return nil, err @@ -209,6 +213,51 @@ func (a *GatewayAPI) StateReadState(ctx context.Context, actor address.Address, return a.api.StateReadState(ctx, actor, tsk) } +func (a *GatewayAPI) StateMinerPower(ctx context.Context, m address.Address, tsk types.TipSetKey) (*api.MinerPower, error) { + if err := a.checkTipsetKey(ctx, tsk); err != nil { + return nil, err + } + return a.api.StateMinerPower(ctx, m, tsk) +} + +func (a *GatewayAPI) StateMinerFaults(ctx context.Context, m address.Address, tsk types.TipSetKey) (bitfield.BitField, error) { + if err := a.checkTipsetKey(ctx, tsk); err != nil { + return bitfield.BitField{}, err + } + return a.api.StateMinerFaults(ctx, m, tsk) +} +func (a *GatewayAPI) StateMinerRecoveries(ctx context.Context, m address.Address, tsk types.TipSetKey) (bitfield.BitField, error) { + if err := a.checkTipsetKey(ctx, tsk); err != nil { + return bitfield.BitField{}, err + } + return a.api.StateMinerRecoveries(ctx, m, tsk) +} + +func (a *GatewayAPI) StateMinerInfo(ctx context.Context, m address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) { + if err := a.checkTipsetKey(ctx, tsk); err != nil { + return miner.MinerInfo{}, err + } + return a.api.StateMinerInfo(ctx, m, tsk) +} + +func (a *GatewayAPI) StateMinerDeadlines(ctx context.Context, m address.Address, tsk types.TipSetKey) ([]api.Deadline, error) { + if err := a.checkTipsetKey(ctx, tsk); err != nil { + return nil, err + } + return a.api.StateMinerDeadlines(ctx, m, tsk) +} + +func (a *GatewayAPI) StateMinerAvailableBalance(ctx context.Context, m address.Address, tsk types.TipSetKey) (types.BigInt, error) { + if err := a.checkTipsetKey(ctx, tsk); err != nil { + return types.BigInt{}, err + } + return a.api.StateMinerAvailableBalance(ctx, m, tsk) +} + +func (a *GatewayAPI) WalletVerify(ctx context.Context, k address.Address, msg []byte, sig *crypto.Signature) (bool, error) { + return sigs.Verify(sig, k, msg) == nil, nil +} + var _ api.GatewayAPI = (*GatewayAPI)(nil) var _ full.ChainModuleAPI = (*GatewayAPI)(nil) var _ full.GasModuleAPI = (*GatewayAPI)(nil) diff --git a/cmd/lotus-gateway/api_test.go b/cmd/lotus-gateway/api_test.go index 4f10fe987..ae161945b 100644 --- a/cmd/lotus-gateway/api_test.go +++ b/cmd/lotus-gateway/api_test.go @@ -107,6 +107,9 @@ func TestGatewayAPIChainGetTipSetByHeight(t *testing.T) { type mockGatewayDepsAPI struct { lk sync.RWMutex tipsets []*types.TipSet + + gatewayDepsAPI // satisfies all interface requirements but will panic if + // methods are called. easier than filling out with panic stubs IMO } func (m *mockGatewayDepsAPI) ChainHasObj(context.Context, cid.Cid) (bool, error) { From cb801d47c7712898aa25a757ce225916f605a354 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Thu, 15 Oct 2020 18:48:51 -0400 Subject: [PATCH 148/313] Add GasCost to InvocResult --- api/api_full.go | 1 + chain/stmgr/call.go | 2 ++ chain/stmgr/stmgr.go | 1 + chain/stmgr/utils.go | 13 +++++++++++++ node/impl/full/state.go | 13 +++---------- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index 65182078a..130cba957 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -740,6 +740,7 @@ type InvocResult struct { MsgCid cid.Cid Msg *types.Message MsgRct *types.MessageReceipt + GasCost MsgGasCost ExecutionTrace types.ExecutionTrace Error string Duration time.Duration diff --git a/chain/stmgr/call.go b/chain/stmgr/call.go index 86035140b..5eaa2e16a 100644 --- a/chain/stmgr/call.go +++ b/chain/stmgr/call.go @@ -116,6 +116,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types. MsgCid: msg.Cid(), Msg: msg, MsgRct: &ret.MessageReceipt, + GasCost: MakeMsgGasCost(msg, ret), ExecutionTrace: ret.ExecutionTrace, Error: errs, Duration: ret.Duration, @@ -232,6 +233,7 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri MsgCid: msg.Cid(), Msg: msg, MsgRct: &ret.MessageReceipt, + GasCost: MakeMsgGasCost(msg, ret), ExecutionTrace: ret.ExecutionTrace, Error: errs, Duration: ret.Duration, diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index b7d5050e1..d5cb1958d 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -203,6 +203,7 @@ func traceFunc(trace *[]*api.InvocResult) func(mcid cid.Cid, msg *types.Message, MsgCid: mcid, Msg: msg, MsgRct: &ret.MessageReceipt, + GasCost: MakeMsgGasCost(msg, ret), ExecutionTrace: ret.ExecutionTrace, Duration: ret.Duration, } diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index cbc78ca5b..de4f947df 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -701,3 +701,16 @@ func CheckTotalFIL(ctx context.Context, sm *StateManager, ts *types.TipSet) (abi return sum, nil } + +func MakeMsgGasCost(msg *types.Message, ret *vm.ApplyRet) api.MsgGasCost { + return api.MsgGasCost{ + Message: msg.Cid(), + GasUsed: big.NewInt(ret.GasUsed), + BaseFeeBurn: ret.GasCosts.BaseFeeBurn, + OverEstimationBurn: ret.GasCosts.OverEstimationBurn, + MinerPenalty: ret.GasCosts.MinerPenalty, + MinerTip: ret.GasCosts.MinerTip, + Refund: ret.GasCosts.Refund, + TotalCost: big.Sub(msg.RequiredFunds(), ret.GasCosts.Refund), + } +} diff --git a/node/impl/full/state.go b/node/impl/full/state.go index 08ac62f2e..9558219c7 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -365,6 +365,7 @@ func (a *StateAPI) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid. MsgCid: mc, Msg: m, MsgRct: &r.MessageReceipt, + GasCost: stmgr.MakeMsgGasCost(m, r), ExecutionTrace: r.ExecutionTrace, Error: errstr, Duration: r.Duration, @@ -1304,14 +1305,6 @@ func (a *StateAPI) StateMsgGasCost(ctx context.Context, inputMsg cid.Cid, tsk ty return nil, err } - return &api.MsgGasCost{ - Message: msg, - GasUsed: big.NewInt(r.GasUsed), - BaseFeeBurn: r.GasCosts.BaseFeeBurn, - OverEstimationBurn: r.GasCosts.OverEstimationBurn, - MinerPenalty: r.GasCosts.MinerPenalty, - MinerTip: r.GasCosts.MinerTip, - Refund: r.GasCosts.Refund, - TotalCost: big.Sub(m.RequiredFunds(), r.GasCosts.Refund), - }, nil + gc := stmgr.MakeMsgGasCost(m, r) + return &gc, nil } From 7826cc0babf005dfb84f5c4ab7614ab3d1fa201b Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Thu, 15 Oct 2020 19:14:53 -0400 Subject: [PATCH 149/313] Rename StateReplay to StateTransplant --- api/api_full.go | 4 ++-- api/apistruct/struct.go | 6 +++--- cli/state.go | 27 ++++++++------------------- lotuspond/front/src/Block.js | 2 +- node/impl/full/state.go | 2 +- 5 files changed, 15 insertions(+), 26 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index 130cba957..9eaca53f9 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -320,8 +320,8 @@ type FullNode interface { // StateCall runs the given message and returns its result without any persisted changes. StateCall(context.Context, *types.Message, types.TipSetKey) (*InvocResult, error) - // StateReplay returns the result of executing the indicated message, assuming it was executed in the indicated tipset. - StateReplay(context.Context, types.TipSetKey, cid.Cid) (*InvocResult, error) + // StateTransplant returns the result of executing the indicated message, assuming it was executed in the indicated tipset. + StateTransplant(context.Context, types.TipSetKey, cid.Cid) (*InvocResult, error) // StateGetActor returns the indicated actor's nonce and balance. StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) // StateReadState returns the indicated actor's state. diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 3854e1dd6..3e474f596 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -188,7 +188,7 @@ type FullNodeStruct struct { StateSectorExpiration func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorExpiration, error) `perm:"read"` StateSectorPartition func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorLocation, error) `perm:"read"` StateCall func(context.Context, *types.Message, types.TipSetKey) (*api.InvocResult, error) `perm:"read"` - StateReplay func(context.Context, types.TipSetKey, cid.Cid) (*api.InvocResult, error) `perm:"read"` + StateTransplant func(context.Context, types.TipSetKey, cid.Cid) (*api.InvocResult, error) `perm:"read"` StateGetActor func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error) `perm:"read"` StateReadState func(context.Context, address.Address, types.TipSetKey) (*api.ActorState, error) `perm:"read"` StateMsgGasCost func(context.Context, cid.Cid, types.TipSetKey) (*api.MsgGasCost, error) `perm:"read"` @@ -880,8 +880,8 @@ func (c *FullNodeStruct) StateCall(ctx context.Context, msg *types.Message, tsk return c.Internal.StateCall(ctx, msg, tsk) } -func (c *FullNodeStruct) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid.Cid) (*api.InvocResult, error) { - return c.Internal.StateReplay(ctx, tsk, mc) +func (c *FullNodeStruct) StateTransplant(ctx context.Context, tsk types.TipSetKey, mc cid.Cid) (*api.InvocResult, error) { + return c.Internal.StateTransplant(ctx, tsk, mc) } func (c *FullNodeStruct) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) { diff --git a/cli/state.go b/cli/state.go index 1e7e24ddb..362e29636 100644 --- a/cli/state.go +++ b/cli/state.go @@ -60,7 +60,7 @@ var stateCmd = &cli.Command{ stateSectorCmd, stateGetActorCmd, stateLookupIDCmd, - stateReplaySetCmd, + stateTransplantCmd, stateSectorSizeCmd, stateReadStateCmd, stateListMessagesCmd, @@ -384,9 +384,9 @@ var stateExecTraceCmd = &cli.Command{ }, } -var stateReplaySetCmd = &cli.Command{ - Name: "replay", - Usage: "Replay a particular message within a tipset", +var stateTransplantCmd = &cli.Command{ + Name: "transplant", + Usage: "Play a particular message within a tipset", ArgsUsage: "[tipsetKey messageCid]", Action: func(cctx *cli.Context) error { if cctx.Args().Len() < 1 { @@ -437,30 +437,19 @@ var stateReplaySetCmd = &cli.Command{ return err } } else { - var r *api.MsgLookup - r, err = fapi.StateWaitMsg(ctx, mcid, build.MessageConfidence) - if err != nil { - return xerrors.Errorf("finding message in chain: %w", err) - } - - childTs, err := fapi.ChainGetTipSet(ctx, r.TipSet) - if err != nil { - return xerrors.Errorf("loading tipset: %w", err) - } - ts, err = fapi.ChainGetTipSet(ctx, childTs.Parents()) + ts, err = fapi.ChainHead(ctx) if err != nil { return err } } - } - res, err := fapi.StateReplay(ctx, ts.Key(), mcid) + res, err := fapi.StateTransplant(ctx, ts.Key(), mcid) if err != nil { - return xerrors.Errorf("replay call failed: %w", err) + return xerrors.Errorf("transplant call failed: %w", err) } - fmt.Println("Replay receipt:") + fmt.Println("Transplant receipt:") fmt.Printf("Exit code: %d\n", res.MsgRct.ExitCode) fmt.Printf("Return: %x\n", res.MsgRct.Return) fmt.Printf("Gas Used: %d\n", res.MsgRct.GasUsed) diff --git a/lotuspond/front/src/Block.js b/lotuspond/front/src/Block.js index 4bae57c81..cb8d25c9d 100644 --- a/lotuspond/front/src/Block.js +++ b/lotuspond/front/src/Block.js @@ -26,7 +26,7 @@ class Block extends React.Component { messages = await Promise.all(messages.map(async (msg, i) => { if (msg.receipt.ExitCode !== 0) { - let reply = await this.props.conn.call('Filecoin.StateReplay', [{Cids: [this.props.cid], Blocks: [header], Height: header.Height}, msg.Cid]) + let reply = await this.props.conn.call('Filecoin.StateTransplant', [{Cids: [this.props.cid], Blocks: [header], Height: header.Height}, msg.Cid]) if(!reply.Error) { reply.Error = "reply: no error" } diff --git a/node/impl/full/state.go b/node/impl/full/state.go index 9558219c7..349a4918b 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -346,7 +346,7 @@ func (a *StateAPI) StateCall(ctx context.Context, msg *types.Message, tsk types. return res, err } -func (a *StateAPI) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid.Cid) (*api.InvocResult, error) { +func (a *StateAPI) StateTransplant(ctx context.Context, tsk types.TipSetKey, mc cid.Cid) (*api.InvocResult, error) { ts, err := a.Chain.GetTipSetFromKey(tsk) if err != nil { return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) From 8351420404bc97e3e4eef0ad85db4e43eed11a11 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Thu, 15 Oct 2020 16:27:49 -0700 Subject: [PATCH 150/313] Add more endpoints for spacegap --- cmd/lotus-gateway/api.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/cmd/lotus-gateway/api.go b/cmd/lotus-gateway/api.go index fe68018d8..855dbe1e8 100644 --- a/cmd/lotus-gateway/api.go +++ b/cmd/lotus-gateway/api.go @@ -9,6 +9,7 @@ import ( "github.com/filecoin-project/go-bitfield" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/crypto" + "github.com/filecoin-project/go-state-types/dline" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" @@ -37,6 +38,7 @@ type gatewayDepsAPI interface { ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) ChainReadObj(context.Context, cid.Cid) ([]byte, error) + ChainGetNode(ctx context.Context, p string) (*api.IpldObject, error) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) MpoolPushUntrusted(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) @@ -52,6 +54,8 @@ type gatewayDepsAPI interface { StateMinerInfo(context.Context, address.Address, types.TipSetKey) (miner.MinerInfo, error) StateMinerDeadlines(context.Context, address.Address, types.TipSetKey) ([]api.Deadline, error) StateMinerAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) + StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*dline.Info, error) + StateCirculatingSupply(context.Context, types.TipSetKey) (abi.TokenAmount, error) } type GatewayAPI struct { @@ -146,6 +150,10 @@ func (a *GatewayAPI) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error return a.api.ChainReadObj(ctx, c) } +func (a *GatewayAPI) ChainGetNode(ctx context.Context, p string) (*api.IpldObject, error) { + return a.api.ChainGetNode(ctx, p) +} + func (a *GatewayAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) { if err := a.checkTipsetKey(ctx, tsk); err != nil { return nil, err @@ -254,6 +262,21 @@ func (a *GatewayAPI) StateMinerAvailableBalance(ctx context.Context, m address.A return a.api.StateMinerAvailableBalance(ctx, m, tsk) } +func (a *GatewayAPI) StateMinerProvingDeadline(ctx context.Context, m address.Address, tsk types.TipSetKey) (*dline.Info, error) { + if err := a.checkTipsetKey(ctx, tsk); err != nil { + return nil, err + } + return a.api.StateMinerProvingDeadline(ctx, m, tsk) +} + +func (a *GatewayAPI) StateCirculatingSupply(ctx context.Context, tsk types.TipSetKey) (abi.TokenAmount, error) { + if err := a.checkTipsetKey(ctx, tsk); err != nil { + return types.BigInt{}, err + } + return a.api.StateCirculatingSupply(ctx, tsk) + +} + func (a *GatewayAPI) WalletVerify(ctx context.Context, k address.Address, msg []byte, sig *crypto.Signature) (bool, error) { return sigs.Verify(sig, k, msg) == nil, nil } From af1a422ddd0773c9de68b7b9489d56ff456846a3 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Thu, 15 Oct 2020 16:36:45 -0700 Subject: [PATCH 151/313] statevminternal circ supply --- cmd/lotus-gateway/api.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cmd/lotus-gateway/api.go b/cmd/lotus-gateway/api.go index 855dbe1e8..86e49e62f 100644 --- a/cmd/lotus-gateway/api.go +++ b/cmd/lotus-gateway/api.go @@ -56,6 +56,7 @@ type gatewayDepsAPI interface { StateMinerAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*dline.Info, error) StateCirculatingSupply(context.Context, types.TipSetKey) (abi.TokenAmount, error) + StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (api.CirculatingSupply, error) } type GatewayAPI struct { @@ -277,6 +278,13 @@ func (a *GatewayAPI) StateCirculatingSupply(ctx context.Context, tsk types.TipSe } +func (a *GatewayAPI) StateVMCirculatingSupplyInternal(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) { + if err := a.checkTipsetKey(ctx, tsk); err != nil { + return api.CirculatingSupply{}, err + } + return a.api.StateVMCirculatingSupplyInternal(ctx, tsk) +} + func (a *GatewayAPI) WalletVerify(ctx context.Context, k address.Address, msg []byte, sig *crypto.Signature) (bool, error) { return sigs.Verify(sig, k, msg) == nil, nil } From 99c07703f8f60799e9e2637bffc30613267d14de Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Thu, 15 Oct 2020 19:47:02 -0400 Subject: [PATCH 152/313] Add a new StateReplay CLI/API endpoint --- api/api_full.go | 4 +- api/apistruct/struct.go | 5 +++ cli/state.go | 91 +++++++++++++++++++++++++++++++++++++++++ node/impl/full/state.go | 40 ++++++++++++++++++ 4 files changed, 139 insertions(+), 1 deletion(-) diff --git a/api/api_full.go b/api/api_full.go index 9eaca53f9..29688a5e6 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -315,13 +315,15 @@ type FullNode interface { // MethodGroup: State // The State methods are used to query, inspect, and interact with chain state. - // All methods take a TipSetKey as a parameter. The state looked up is the state at that tipset. + // Most methods take a TipSetKey as a parameter. The state looked up is the state at that tipset. // A nil TipSetKey can be provided as a param, this will cause the heaviest tipset in the chain to be used. // StateCall runs the given message and returns its result without any persisted changes. StateCall(context.Context, *types.Message, types.TipSetKey) (*InvocResult, error) // StateTransplant returns the result of executing the indicated message, assuming it was executed in the indicated tipset. StateTransplant(context.Context, types.TipSetKey, cid.Cid) (*InvocResult, error) + // StateReplay searches for where the given message was executed, and replays it in that tipset. + StateReplay(context.Context, cid.Cid) (*InvocResult, error) // StateGetActor returns the indicated actor's nonce and balance. StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) // StateReadState returns the indicated actor's state. diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 3e474f596..33670c276 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -189,6 +189,7 @@ type FullNodeStruct struct { StateSectorPartition func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorLocation, error) `perm:"read"` StateCall func(context.Context, *types.Message, types.TipSetKey) (*api.InvocResult, error) `perm:"read"` StateTransplant func(context.Context, types.TipSetKey, cid.Cid) (*api.InvocResult, error) `perm:"read"` + StateReplay func(context.Context, cid.Cid) (*api.InvocResult, error) `perm:"read"` StateGetActor func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error) `perm:"read"` StateReadState func(context.Context, address.Address, types.TipSetKey) (*api.ActorState, error) `perm:"read"` StateMsgGasCost func(context.Context, cid.Cid, types.TipSetKey) (*api.MsgGasCost, error) `perm:"read"` @@ -884,6 +885,10 @@ func (c *FullNodeStruct) StateTransplant(ctx context.Context, tsk types.TipSetKe return c.Internal.StateTransplant(ctx, tsk, mc) } +func (c *FullNodeStruct) StateReplay(ctx context.Context, mc cid.Cid) (*api.InvocResult, error) { + return c.Internal.StateReplay(ctx, mc) +} + func (c *FullNodeStruct) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) { return c.Internal.StateGetActor(ctx, actor, tsk) } diff --git a/cli/state.go b/cli/state.go index 362e29636..bff41e268 100644 --- a/cli/state.go +++ b/cli/state.go @@ -61,6 +61,7 @@ var stateCmd = &cli.Command{ stateGetActorCmd, stateLookupIDCmd, stateTransplantCmd, + stateReplayCmd, stateSectorSizeCmd, stateReadStateCmd, stateListMessagesCmd, @@ -388,6 +389,16 @@ var stateTransplantCmd = &cli.Command{ Name: "transplant", Usage: "Play a particular message within a tipset", ArgsUsage: "[tipsetKey messageCid]", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "show-trace", + Usage: "print out full execution trace for given message", + }, + &cli.BoolFlag{ + Name: "detailed-gas", + Usage: "print out detailed gas costs for given message", + }, + }, Action: func(cctx *cli.Context) error { if cctx.Args().Len() < 1 { fmt.Println("usage: [tipset] ") @@ -453,10 +464,90 @@ var stateTransplantCmd = &cli.Command{ fmt.Printf("Exit code: %d\n", res.MsgRct.ExitCode) fmt.Printf("Return: %x\n", res.MsgRct.Return) fmt.Printf("Gas Used: %d\n", res.MsgRct.GasUsed) + + if cctx.Bool("detailed-gas") { + fmt.Printf("Base Fee Burn: %d\n", res.GasCost.BaseFeeBurn) + fmt.Printf("Overestimaton Burn: %d\n", res.GasCost.OverEstimationBurn) + fmt.Printf("Miner Penalty: %d\n", res.GasCost.MinerPenalty) + fmt.Printf("Miner Tip: %d\n", res.GasCost.MinerTip) + fmt.Printf("Refund: %d\n", res.GasCost.Refund) + } + fmt.Printf("Total Message Cost: %d\n", res.GasCost.TotalCost) + if res.MsgRct.ExitCode != 0 { fmt.Printf("Error message: %q\n", res.Error) } + if cctx.Bool("show-trace") { + fmt.Printf("%s\t%s\t%s\t%d\t%x\t%d\t%x\n", res.Msg.From, res.Msg.To, res.Msg.Value, res.Msg.Method, res.Msg.Params, res.MsgRct.ExitCode, res.MsgRct.Return) + printInternalExecutions("\t", res.ExecutionTrace.Subcalls) + } + + return nil + }, +} + +var stateReplayCmd = &cli.Command{ + Name: "replay", + Usage: "Replay a particular message", + ArgsUsage: "", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "show-trace", + Usage: "print out full execution trace for given message", + }, + &cli.BoolFlag{ + Name: "detailed-gas", + Usage: "print out detailed gas costs for given message", + }, + }, + Action: func(cctx *cli.Context) error { + if cctx.Args().Len() != 1 { + fmt.Println("must provide cid of message to replay") + return nil + } + + mcid, err := cid.Decode(cctx.Args().First()) + if err != nil { + return fmt.Errorf("message cid was invalid: %s", err) + } + + fapi, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + + ctx := ReqContext(cctx) + + res, err := fapi.StateReplay(ctx, mcid) + if err != nil { + return xerrors.Errorf("replay call failed: %w", err) + } + + fmt.Println("Replay receipt:") + fmt.Printf("Exit code: %d\n", res.MsgRct.ExitCode) + fmt.Printf("Return: %x\n", res.MsgRct.Return) + fmt.Printf("Gas Used: %d\n", res.MsgRct.GasUsed) + + if cctx.Bool("detailed-gas") { + fmt.Printf("Base Fee Burn: %d\n", res.GasCost.BaseFeeBurn) + fmt.Printf("Overestimaton Burn: %d\n", res.GasCost.OverEstimationBurn) + fmt.Printf("Miner Penalty: %d\n", res.GasCost.MinerPenalty) + fmt.Printf("Miner Tip: %d\n", res.GasCost.MinerTip) + fmt.Printf("Refund: %d\n", res.GasCost.Refund) + } + fmt.Printf("Total Message Cost: %d\n", res.GasCost.TotalCost) + + if res.MsgRct.ExitCode != 0 { + fmt.Printf("Error message: %q\n", res.Error) + } + + if cctx.Bool("show-trace") { + fmt.Printf("%s\t%s\t%s\t%d\t%x\t%d\t%x\n", res.Msg.From, res.Msg.To, res.Msg.Value, res.Msg.Method, res.Msg.Params, res.MsgRct.ExitCode, res.MsgRct.Return) + printInternalExecutions("\t", res.ExecutionTrace.Subcalls) + } + return nil }, } diff --git a/node/impl/full/state.go b/node/impl/full/state.go index 349a4918b..959660085 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -372,6 +372,46 @@ func (a *StateAPI) StateTransplant(ctx context.Context, tsk types.TipSetKey, mc }, nil } +func (a *StateAPI) StateReplay(ctx context.Context, mc cid.Cid) (*api.InvocResult, error) { + mlkp, err := a.StateSearchMsg(ctx, mc) + if err != nil { + return nil, xerrors.Errorf("searching for msg %s: %w", mc, err) + } + if mlkp == nil { + return nil, xerrors.Errorf("didn't find msg %s", mc) + } + + executionTs, err := a.Chain.GetTipSetFromKey(mlkp.TipSet) + if err != nil { + return nil, xerrors.Errorf("loading tipset %s: %w", mlkp.TipSet, err) + } + + ts, err := a.Chain.LoadTipSet(executionTs.Parents()) + if err != nil { + return nil, xerrors.Errorf("loading parent tipset %s: %w", mlkp.TipSet, err) + } + + m, r, err := a.StateManager.Replay(ctx, ts, mlkp.Message) + if err != nil { + return nil, err + } + + var errstr string + if r.ActorErr != nil { + errstr = r.ActorErr.Error() + } + + return &api.InvocResult{ + MsgCid: mlkp.Message, + Msg: m, + MsgRct: &r.MessageReceipt, + GasCost: stmgr.MakeMsgGasCost(m, r), + ExecutionTrace: r.ExecutionTrace, + Error: errstr, + Duration: r.Duration, + }, nil +} + func stateForTs(ctx context.Context, ts *types.TipSet, cstore *store.ChainStore, smgr *stmgr.StateManager) (*state.StateTree, error) { if ts == nil { ts = cstore.GetHeaviestTipSet() From a71fbee2d13e83c9fbe49a3dd59d27fa39a711c7 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Thu, 15 Oct 2020 16:49:25 -0700 Subject: [PATCH 153/313] bump lookback limit to 12 hours --- cmd/lotus-gateway/api.go | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/cmd/lotus-gateway/api.go b/cmd/lotus-gateway/api.go index 86e49e62f..105f8881e 100644 --- a/cmd/lotus-gateway/api.go +++ b/cmd/lotus-gateway/api.go @@ -22,7 +22,7 @@ import ( ) const ( - LookbackCap = time.Hour + LookbackCap = time.Hour * 12 stateWaitLookbackLimit = abi.ChainEpoch(20) ) @@ -129,9 +129,19 @@ func (a *GatewayAPI) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (* } func (a *GatewayAPI) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) { - ts, err := a.api.ChainGetTipSet(ctx, tsk) - if err != nil { - return nil, err + var ts *types.TipSet + if tsk.IsEmpty() { + head, err := a.api.ChainHead(ctx) + if err != nil { + return nil, err + } + ts = head + } else { + gts, err := a.api.ChainGetTipSet(ctx, tsk) + if err != nil { + return nil, err + } + ts = gts } // Check if the tipset key refers to a tipset that's too far in the past From 6f86b95f62bd59b38f1499ee381b93643247500b Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Thu, 15 Oct 2020 21:00:47 -0400 Subject: [PATCH 154/313] Remove StateMsgGasCost --- api/api_full.go | 2 - api/apistruct/struct.go | 5 - cli/state.go | 55 ----------- documentation/en/api-methods.md | 169 ++++++++++++++++++++++---------- node/impl/full/state.go | 41 -------- 5 files changed, 119 insertions(+), 153 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index 29688a5e6..88bcb3cba 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -372,8 +372,6 @@ type FullNode interface { StateSectorPartition(ctx context.Context, maddr address.Address, sectorNumber abi.SectorNumber, tok types.TipSetKey) (*miner.SectorLocation, error) // StateSearchMsg searches for a message in the chain, and returns its receipt and the tipset where it was executed StateSearchMsg(context.Context, cid.Cid) (*MsgLookup, error) - // StateMsgGasCost searches for a message in the chain, and returns details of the messages gas costs, including the penalty and miner tip - StateMsgGasCost(context.Context, cid.Cid, types.TipSetKey) (*MsgGasCost, error) // StateWaitMsg looks back in the chain for a message. If not found, it blocks until the // message arrives on chain, and gets to the indicated confidence depth. StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64) (*MsgLookup, error) diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 33670c276..0279e8c8a 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -192,7 +192,6 @@ type FullNodeStruct struct { StateReplay func(context.Context, cid.Cid) (*api.InvocResult, error) `perm:"read"` StateGetActor func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error) `perm:"read"` StateReadState func(context.Context, address.Address, types.TipSetKey) (*api.ActorState, error) `perm:"read"` - StateMsgGasCost func(context.Context, cid.Cid, types.TipSetKey) (*api.MsgGasCost, error) `perm:"read"` StateWaitMsg func(ctx context.Context, cid cid.Cid, confidence uint64) (*api.MsgLookup, error) `perm:"read"` StateWaitMsgLimited func(context.Context, cid.Cid, uint64, abi.ChainEpoch) (*api.MsgLookup, error) `perm:"read"` StateSearchMsg func(context.Context, cid.Cid) (*api.MsgLookup, error) `perm:"read"` @@ -897,10 +896,6 @@ func (c *FullNodeStruct) StateReadState(ctx context.Context, addr address.Addres return c.Internal.StateReadState(ctx, addr, tsk) } -func (c *FullNodeStruct) StateMsgGasCost(ctx context.Context, msgc cid.Cid, tsk types.TipSetKey) (*api.MsgGasCost, error) { - return c.Internal.StateMsgGasCost(ctx, msgc, tsk) -} - func (c *FullNodeStruct) StateWaitMsg(ctx context.Context, msgc cid.Cid, confidence uint64) (*api.MsgLookup, error) { return c.Internal.StateWaitMsg(ctx, msgc, confidence) } diff --git a/cli/state.go b/cli/state.go index bff41e268..38454ec27 100644 --- a/cli/state.go +++ b/cli/state.go @@ -70,7 +70,6 @@ var stateCmd = &cli.Command{ stateGetDealSetCmd, stateWaitMsgCmd, stateSearchMsgCmd, - stateMsgCostCmd, stateMinerInfo, stateMarketCmd, stateExecTraceCmd, @@ -1504,60 +1503,6 @@ var stateSearchMsgCmd = &cli.Command{ }, } -var stateMsgCostCmd = &cli.Command{ - Name: "msg-cost", - Usage: "Get the detailed gas costs of a message", - ArgsUsage: "[messageCid]", - Action: func(cctx *cli.Context) error { - if !cctx.Args().Present() { - return fmt.Errorf("must specify message cid to get gas costs for") - } - - api, closer, err := GetFullNodeAPI(cctx) - if err != nil { - return err - } - defer closer() - - ctx := ReqContext(cctx) - - msg, err := cid.Decode(cctx.Args().First()) - if err != nil { - return err - } - - tsk := types.EmptyTSK - - ts, err := LoadTipSet(ctx, cctx, api) - if err != nil { - return err - } - - if ts != nil { - tsk = ts.Key() - } - - mgc, err := api.StateMsgGasCost(ctx, msg, tsk) - if err != nil { - return err - } - - if mgc != nil { - fmt.Printf("Message CID: %s", mgc.Message) - fmt.Printf("\nGas Used: %d", mgc.GasUsed) - fmt.Printf("\nBase Fee Burn: %d", mgc.BaseFeeBurn) - fmt.Printf("\nOverestimation Burn: %d", mgc.OverEstimationBurn) - fmt.Printf("\nMiner Tip: %d", mgc.MinerTip) - fmt.Printf("\nRefund: %d", mgc.Refund) - fmt.Printf("\nTotal Cost: %d", mgc.TotalCost) - fmt.Printf("\nMiner Penalty: %d", mgc.MinerPenalty) - } else { - fmt.Print("message was not found on chain") - } - return nil - }, -} - var stateCallCmd = &cli.Command{ Name: "call", Usage: "Invoke a method on an actor locally", diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index a905ef2e3..9be12722d 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -156,7 +156,6 @@ * [StateMinerRecoveries](#StateMinerRecoveries) * [StateMinerSectorCount](#StateMinerSectorCount) * [StateMinerSectors](#StateMinerSectors) - * [StateMsgGasCost](#StateMsgGasCost) * [StateNetworkName](#StateNetworkName) * [StateNetworkVersion](#StateNetworkVersion) * [StateReadState](#StateReadState) @@ -166,6 +165,7 @@ * [StateSectorGetInfo](#StateSectorGetInfo) * [StateSectorPartition](#StateSectorPartition) * [StateSectorPreCommitInfo](#StateSectorPreCommitInfo) + * [StateTransplant](#StateTransplant) * [StateVMCirculatingSupplyInternal](#StateVMCirculatingSupplyInternal) * [StateVerifiedClientStatus](#StateVerifiedClientStatus) * [StateVerifiedRegistryRootKey](#StateVerifiedRegistryRootKey) @@ -2989,7 +2989,7 @@ Response: ## State The State methods are used to query, inspect, and interact with chain state. -All methods take a TipSetKey as a parameter. The state looked up is the state at that tipset. +Most methods take a TipSetKey as a parameter. The state looked up is the state at that tipset. A nil TipSetKey can be provided as a param, this will cause the heaviest tipset in the chain to be used. @@ -3100,6 +3100,18 @@ Response: "Return": "Ynl0ZSBhcnJheQ==", "GasUsed": 9 }, + "GasCost": { + "Message": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "GasUsed": "0", + "BaseFeeBurn": "0", + "OverEstimationBurn": "0", + "MinerPenalty": "0", + "MinerTip": "0", + "Refund": "0", + "TotalCost": "0" + }, "ExecutionTrace": { "Msg": { "Version": 42, @@ -3974,45 +3986,6 @@ Inputs: Response: `null` -### StateMsgGasCost -StateMsgGasCost searches for a message in the chain, and returns details of the messages gas costs, including the penalty and miner tip - - -Perms: read - -Inputs: -```json -[ - { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" - }, - [ - { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" - }, - { - "/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve" - } - ] -] -``` - -Response: -```json -{ - "Message": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" - }, - "GasUsed": "0", - "BaseFeeBurn": "0", - "OverEstimationBurn": "0", - "MinerPenalty": "0", - "MinerTip": "0", - "Refund": "0", - "TotalCost": "0" -} -``` - ### StateNetworkName StateNetworkName returns the name of the network the node is synced to @@ -4075,7 +4048,7 @@ Response: ``` ### StateReplay -StateReplay returns the result of executing the indicated message, assuming it was executed in the indicated tipset. +StateReplay searches for where the given message was executed, and replays it in that tipset. Perms: read @@ -4083,14 +4056,6 @@ Perms: read Inputs: ```json [ - [ - { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" - }, - { - "/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve" - } - ], { "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" } @@ -4123,6 +4088,18 @@ Response: "Return": "Ynl0ZSBhcnJheQ==", "GasUsed": 9 }, + "GasCost": { + "Message": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "GasUsed": "0", + "BaseFeeBurn": "0", + "OverEstimationBurn": "0", + "MinerPenalty": "0", + "MinerTip": "0", + "Refund": "0", + "TotalCost": "0" + }, "ExecutionTrace": { "Msg": { "Version": 42, @@ -4342,6 +4319,98 @@ Response: } ``` +### StateTransplant +StateTransplant returns the result of executing the indicated message, assuming it was executed in the indicated tipset. + + +Perms: read + +Inputs: +```json +[ + [ + { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + { + "/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve" + } + ], + { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + } +] +``` + +Response: +```json +{ + "MsgCid": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Msg": { + "Version": 42, + "To": "f01234", + "From": "f01234", + "Nonce": 42, + "Value": "0", + "GasLimit": 9, + "GasFeeCap": "0", + "GasPremium": "0", + "Method": 1, + "Params": "Ynl0ZSBhcnJheQ==", + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" + } + }, + "MsgRct": { + "ExitCode": 0, + "Return": "Ynl0ZSBhcnJheQ==", + "GasUsed": 9 + }, + "GasCost": { + "Message": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "GasUsed": "0", + "BaseFeeBurn": "0", + "OverEstimationBurn": "0", + "MinerPenalty": "0", + "MinerTip": "0", + "Refund": "0", + "TotalCost": "0" + }, + "ExecutionTrace": { + "Msg": { + "Version": 42, + "To": "f01234", + "From": "f01234", + "Nonce": 42, + "Value": "0", + "GasLimit": 9, + "GasFeeCap": "0", + "GasPremium": "0", + "Method": 1, + "Params": "Ynl0ZSBhcnJheQ==", + "CID": { + "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" + } + }, + "MsgRct": { + "ExitCode": 0, + "Return": "Ynl0ZSBhcnJheQ==", + "GasUsed": 9 + }, + "Error": "string value", + "Duration": 60000000000, + "GasCharges": null, + "Subcalls": null + }, + "Error": "string value", + "Duration": 60000000000 +} +``` + ### StateVMCirculatingSupplyInternal StateVMCirculatingSupplyInternal returns an approximation of the circulating supply of Filecoin at the given tipset. This is the value reported by the runtime interface to actors code. diff --git a/node/impl/full/state.go b/node/impl/full/state.go index 959660085..a63ac8c67 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -1307,44 +1307,3 @@ func (a *StateAPI) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) return a.StateManager.GetNtwkVersion(ctx, ts.Height()), nil } - -func (a *StateAPI) StateMsgGasCost(ctx context.Context, inputMsg cid.Cid, tsk types.TipSetKey) (*api.MsgGasCost, error) { - var msg cid.Cid - var ts *types.TipSet - var err error - if tsk != types.EmptyTSK { - msg = inputMsg - ts, err = a.Chain.LoadTipSet(tsk) - if err != nil { - return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) - } - } else { - mlkp, err := a.StateSearchMsg(ctx, inputMsg) - if err != nil { - return nil, xerrors.Errorf("searching for msg %s: %w", inputMsg, err) - } - if mlkp == nil { - return nil, xerrors.Errorf("didn't find msg %s", inputMsg) - } - - executionTs, err := a.Chain.GetTipSetFromKey(mlkp.TipSet) - if err != nil { - return nil, xerrors.Errorf("loading tipset %s: %w", mlkp.TipSet, err) - } - - ts, err = a.Chain.LoadTipSet(executionTs.Parents()) - if err != nil { - return nil, xerrors.Errorf("loading parent tipset %s: %w", mlkp.TipSet, err) - } - - msg = mlkp.Message - } - - m, r, err := a.StateManager.Replay(ctx, ts, msg) - if err != nil { - return nil, err - } - - gc := stmgr.MakeMsgGasCost(m, r) - return &gc, nil -} From 89f46cb5ccd7a19b72c7432404f658eb1d7ecfb5 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Thu, 15 Oct 2020 21:12:38 -0400 Subject: [PATCH 155/313] Make ApplyRet's GasOutputs a pointer, return nil when unused --- chain/stmgr/call.go | 1 - chain/stmgr/forks.go | 4 ++-- chain/stmgr/stmgr.go | 4 +++- chain/vm/vm.go | 16 ++++++++-------- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/chain/stmgr/call.go b/chain/stmgr/call.go index 5eaa2e16a..3d7d284bc 100644 --- a/chain/stmgr/call.go +++ b/chain/stmgr/call.go @@ -116,7 +116,6 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types. MsgCid: msg.Cid(), Msg: msg, MsgRct: &ret.MessageReceipt, - GasCost: MakeMsgGasCost(msg, ret), ExecutionTrace: ret.ExecutionTrace, Error: errs, Duration: ret.Duration, diff --git a/chain/stmgr/forks.go b/chain/stmgr/forks.go index 156c68783..488f84167 100644 --- a/chain/stmgr/forks.go +++ b/chain/stmgr/forks.go @@ -498,7 +498,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal Subcalls: subcalls, }, Duration: 0, - GasCosts: vm.ZeroGasOutputs(), + GasCosts: nil, }); err != nil { return cid.Undef, xerrors.Errorf("recording transfers: %w", err) } @@ -799,7 +799,7 @@ func splitGenesisMultisig(ctx context.Context, cb ExecCallback, addr address.Add Subcalls: subcalls, }, Duration: 0, - GasCosts: vm.ZeroGasOutputs(), + GasCosts: nil, }); err != nil { return xerrors.Errorf("recording transfers: %w", err) } diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index d5cb1958d..be14797d9 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -203,13 +203,15 @@ func traceFunc(trace *[]*api.InvocResult) func(mcid cid.Cid, msg *types.Message, MsgCid: mcid, Msg: msg, MsgRct: &ret.MessageReceipt, - GasCost: MakeMsgGasCost(msg, ret), ExecutionTrace: ret.ExecutionTrace, Duration: ret.Duration, } if ret.ActorErr != nil { ir.Error = ret.ActorErr.Error() } + if ret.GasCosts != nil { + ir.GasCost = MakeMsgGasCost(msg, ret) + } *trace = append(*trace, ir) return nil } diff --git a/chain/vm/vm.go b/chain/vm/vm.go index a4efccb29..72ad731aa 100644 --- a/chain/vm/vm.go +++ b/chain/vm/vm.go @@ -214,7 +214,7 @@ type ApplyRet struct { ActorErr aerrors.ActorError ExecutionTrace types.ExecutionTrace Duration time.Duration - GasCosts GasOutputs + GasCosts *GasOutputs } func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime, @@ -361,7 +361,7 @@ func (vm *VM) ApplyImplicitMessage(ctx context.Context, msg *types.Message) (*Ap }, ActorErr: actorErr, ExecutionTrace: rt.executionTrace, - GasCosts: GasOutputs{}, + GasCosts: nil, Duration: time.Since(start), }, actorErr } @@ -397,7 +397,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, ExitCode: exitcode.SysErrOutOfGas, GasUsed: 0, }, - GasCosts: gasOutputs, + GasCosts: &gasOutputs, Duration: time.Since(start), }, nil } @@ -417,7 +417,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, GasUsed: 0, }, ActorErr: aerrors.Newf(exitcode.SysErrSenderInvalid, "actor not found: %s", msg.From), - GasCosts: gasOutputs, + GasCosts: &gasOutputs, Duration: time.Since(start), }, nil } @@ -434,7 +434,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, GasUsed: 0, }, ActorErr: aerrors.Newf(exitcode.SysErrSenderInvalid, "send from not account actor: %s", fromActor.Code), - GasCosts: gasOutputs, + GasCosts: &gasOutputs, Duration: time.Since(start), }, nil } @@ -450,7 +450,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, ActorErr: aerrors.Newf(exitcode.SysErrSenderStateInvalid, "actor nonce invalid: msg:%d != state:%d", msg.Nonce, fromActor.Nonce), - GasCosts: gasOutputs, + GasCosts: &gasOutputs, Duration: time.Since(start), }, nil } @@ -466,7 +466,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, }, ActorErr: aerrors.Newf(exitcode.SysErrSenderStateInvalid, "actor balance less than needed: %s < %s", types.FIL(fromActor.Balance), types.FIL(gascost)), - GasCosts: gasOutputs, + GasCosts: &gasOutputs, Duration: time.Since(start), }, nil } @@ -560,7 +560,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, }, ActorErr: actorErr, ExecutionTrace: rt.executionTrace, - GasCosts: gasOutputs, + GasCosts: &gasOutputs, Duration: time.Since(start), }, nil } From 2fd4a976984bb3b51e8b227b3175ed0c5eb61af3 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Thu, 15 Oct 2020 22:45:11 -0400 Subject: [PATCH 156/313] Remove StateTransplant, modify StateReplay --- api/api_full.go | 7 +-- api/apistruct/struct.go | 11 +--- cli/state.go | 105 +------------------------------- documentation/en/api-methods.md | 104 +++---------------------------- lotuspond/front/src/Block.js | 2 +- node/impl/full/state.go | 74 +++++++++------------- 6 files changed, 46 insertions(+), 257 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index 88bcb3cba..1946ca28f 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -320,10 +320,9 @@ type FullNode interface { // StateCall runs the given message and returns its result without any persisted changes. StateCall(context.Context, *types.Message, types.TipSetKey) (*InvocResult, error) - // StateTransplant returns the result of executing the indicated message, assuming it was executed in the indicated tipset. - StateTransplant(context.Context, types.TipSetKey, cid.Cid) (*InvocResult, error) - // StateReplay searches for where the given message was executed, and replays it in that tipset. - StateReplay(context.Context, cid.Cid) (*InvocResult, error) + // StateReplay replays a given message, assuming it was included in a block in the specified tipset. + // If no tipset key is provided, the appropriate tipset is looked up. + StateReplay(context.Context, types.TipSetKey, cid.Cid) (*InvocResult, error) // StateGetActor returns the indicated actor's nonce and balance. StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) // StateReadState returns the indicated actor's state. diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 0279e8c8a..6effcf727 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -188,8 +188,7 @@ type FullNodeStruct struct { StateSectorExpiration func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorExpiration, error) `perm:"read"` StateSectorPartition func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorLocation, error) `perm:"read"` StateCall func(context.Context, *types.Message, types.TipSetKey) (*api.InvocResult, error) `perm:"read"` - StateTransplant func(context.Context, types.TipSetKey, cid.Cid) (*api.InvocResult, error) `perm:"read"` - StateReplay func(context.Context, cid.Cid) (*api.InvocResult, error) `perm:"read"` + StateReplay func(context.Context, types.TipSetKey, cid.Cid) (*api.InvocResult, error) `perm:"read"` StateGetActor func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error) `perm:"read"` StateReadState func(context.Context, address.Address, types.TipSetKey) (*api.ActorState, error) `perm:"read"` StateWaitMsg func(ctx context.Context, cid cid.Cid, confidence uint64) (*api.MsgLookup, error) `perm:"read"` @@ -880,12 +879,8 @@ func (c *FullNodeStruct) StateCall(ctx context.Context, msg *types.Message, tsk return c.Internal.StateCall(ctx, msg, tsk) } -func (c *FullNodeStruct) StateTransplant(ctx context.Context, tsk types.TipSetKey, mc cid.Cid) (*api.InvocResult, error) { - return c.Internal.StateTransplant(ctx, tsk, mc) -} - -func (c *FullNodeStruct) StateReplay(ctx context.Context, mc cid.Cid) (*api.InvocResult, error) { - return c.Internal.StateReplay(ctx, mc) +func (c *FullNodeStruct) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid.Cid) (*api.InvocResult, error) { + return c.Internal.StateReplay(ctx, tsk, mc) } func (c *FullNodeStruct) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) { diff --git a/cli/state.go b/cli/state.go index 38454ec27..0fb3ecde6 100644 --- a/cli/state.go +++ b/cli/state.go @@ -60,7 +60,6 @@ var stateCmd = &cli.Command{ stateSectorCmd, stateGetActorCmd, stateLookupIDCmd, - stateTransplantCmd, stateReplayCmd, stateSectorSizeCmd, stateReadStateCmd, @@ -384,108 +383,6 @@ var stateExecTraceCmd = &cli.Command{ }, } -var stateTransplantCmd = &cli.Command{ - Name: "transplant", - Usage: "Play a particular message within a tipset", - ArgsUsage: "[tipsetKey messageCid]", - Flags: []cli.Flag{ - &cli.BoolFlag{ - Name: "show-trace", - Usage: "print out full execution trace for given message", - }, - &cli.BoolFlag{ - Name: "detailed-gas", - Usage: "print out detailed gas costs for given message", - }, - }, - Action: func(cctx *cli.Context) error { - if cctx.Args().Len() < 1 { - fmt.Println("usage: [tipset] ") - fmt.Println("The last cid passed will be used as the message CID") - fmt.Println("All preceding ones will be used as the tipset") - return nil - } - - args := cctx.Args().Slice() - mcid, err := cid.Decode(args[len(args)-1]) - if err != nil { - return fmt.Errorf("message cid was invalid: %s", err) - } - - fapi, closer, err := GetFullNodeAPI(cctx) - if err != nil { - return err - } - defer closer() - - ctx := ReqContext(cctx) - - var ts *types.TipSet - { - var tscids []cid.Cid - for _, s := range args[:len(args)-1] { - c, err := cid.Decode(s) - if err != nil { - return fmt.Errorf("tipset cid was invalid: %s", err) - } - tscids = append(tscids, c) - } - - if len(tscids) > 0 { - var headers []*types.BlockHeader - for _, c := range tscids { - h, err := fapi.ChainGetBlock(ctx, c) - if err != nil { - return err - } - - headers = append(headers, h) - } - - ts, err = types.NewTipSet(headers) - if err != nil { - return err - } - } else { - ts, err = fapi.ChainHead(ctx) - if err != nil { - return err - } - } - } - - res, err := fapi.StateTransplant(ctx, ts.Key(), mcid) - if err != nil { - return xerrors.Errorf("transplant call failed: %w", err) - } - - fmt.Println("Transplant receipt:") - fmt.Printf("Exit code: %d\n", res.MsgRct.ExitCode) - fmt.Printf("Return: %x\n", res.MsgRct.Return) - fmt.Printf("Gas Used: %d\n", res.MsgRct.GasUsed) - - if cctx.Bool("detailed-gas") { - fmt.Printf("Base Fee Burn: %d\n", res.GasCost.BaseFeeBurn) - fmt.Printf("Overestimaton Burn: %d\n", res.GasCost.OverEstimationBurn) - fmt.Printf("Miner Penalty: %d\n", res.GasCost.MinerPenalty) - fmt.Printf("Miner Tip: %d\n", res.GasCost.MinerTip) - fmt.Printf("Refund: %d\n", res.GasCost.Refund) - } - fmt.Printf("Total Message Cost: %d\n", res.GasCost.TotalCost) - - if res.MsgRct.ExitCode != 0 { - fmt.Printf("Error message: %q\n", res.Error) - } - - if cctx.Bool("show-trace") { - fmt.Printf("%s\t%s\t%s\t%d\t%x\t%d\t%x\n", res.Msg.From, res.Msg.To, res.Msg.Value, res.Msg.Method, res.Msg.Params, res.MsgRct.ExitCode, res.MsgRct.Return) - printInternalExecutions("\t", res.ExecutionTrace.Subcalls) - } - - return nil - }, -} - var stateReplayCmd = &cli.Command{ Name: "replay", Usage: "Replay a particular message", @@ -519,7 +416,7 @@ var stateReplayCmd = &cli.Command{ ctx := ReqContext(cctx) - res, err := fapi.StateReplay(ctx, mcid) + res, err := fapi.StateReplay(ctx, types.EmptyTSK, mcid) if err != nil { return xerrors.Errorf("replay call failed: %w", err) } diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index 9be12722d..9c2a82cad 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -165,7 +165,6 @@ * [StateSectorGetInfo](#StateSectorGetInfo) * [StateSectorPartition](#StateSectorPartition) * [StateSectorPreCommitInfo](#StateSectorPreCommitInfo) - * [StateTransplant](#StateTransplant) * [StateVMCirculatingSupplyInternal](#StateVMCirculatingSupplyInternal) * [StateVerifiedClientStatus](#StateVerifiedClientStatus) * [StateVerifiedRegistryRootKey](#StateVerifiedRegistryRootKey) @@ -4048,7 +4047,8 @@ Response: ``` ### StateReplay -StateReplay searches for where the given message was executed, and replays it in that tipset. +StateReplay replays a given message, assuming it was included in a block in the specified tipset. +If no tipset key is provided, the appropriate tipset is looked up. Perms: read @@ -4056,6 +4056,14 @@ Perms: read Inputs: ```json [ + [ + { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + { + "/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve" + } + ], { "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" } @@ -4319,98 +4327,6 @@ Response: } ``` -### StateTransplant -StateTransplant returns the result of executing the indicated message, assuming it was executed in the indicated tipset. - - -Perms: read - -Inputs: -```json -[ - [ - { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" - }, - { - "/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve" - } - ], - { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" - } -] -``` - -Response: -```json -{ - "MsgCid": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" - }, - "Msg": { - "Version": 42, - "To": "f01234", - "From": "f01234", - "Nonce": 42, - "Value": "0", - "GasLimit": 9, - "GasFeeCap": "0", - "GasPremium": "0", - "Method": 1, - "Params": "Ynl0ZSBhcnJheQ==", - "CID": { - "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" - } - }, - "MsgRct": { - "ExitCode": 0, - "Return": "Ynl0ZSBhcnJheQ==", - "GasUsed": 9 - }, - "GasCost": { - "Message": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" - }, - "GasUsed": "0", - "BaseFeeBurn": "0", - "OverEstimationBurn": "0", - "MinerPenalty": "0", - "MinerTip": "0", - "Refund": "0", - "TotalCost": "0" - }, - "ExecutionTrace": { - "Msg": { - "Version": 42, - "To": "f01234", - "From": "f01234", - "Nonce": 42, - "Value": "0", - "GasLimit": 9, - "GasFeeCap": "0", - "GasPremium": "0", - "Method": 1, - "Params": "Ynl0ZSBhcnJheQ==", - "CID": { - "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" - } - }, - "MsgRct": { - "ExitCode": 0, - "Return": "Ynl0ZSBhcnJheQ==", - "GasUsed": 9 - }, - "Error": "string value", - "Duration": 60000000000, - "GasCharges": null, - "Subcalls": null - }, - "Error": "string value", - "Duration": 60000000000 -} -``` - ### StateVMCirculatingSupplyInternal StateVMCirculatingSupplyInternal returns an approximation of the circulating supply of Filecoin at the given tipset. This is the value reported by the runtime interface to actors code. diff --git a/lotuspond/front/src/Block.js b/lotuspond/front/src/Block.js index cb8d25c9d..4bae57c81 100644 --- a/lotuspond/front/src/Block.js +++ b/lotuspond/front/src/Block.js @@ -26,7 +26,7 @@ class Block extends React.Component { messages = await Promise.all(messages.map(async (msg, i) => { if (msg.receipt.ExitCode !== 0) { - let reply = await this.props.conn.call('Filecoin.StateTransplant', [{Cids: [this.props.cid], Blocks: [header], Height: header.Height}, msg.Cid]) + let reply = await this.props.conn.call('Filecoin.StateReplay', [{Cids: [this.props.cid], Blocks: [header], Height: header.Height}, msg.Cid]) if(!reply.Error) { reply.Error = "reply: no error" } diff --git a/node/impl/full/state.go b/node/impl/full/state.go index a63ac8c67..221b83e3a 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -346,12 +346,34 @@ func (a *StateAPI) StateCall(ctx context.Context, msg *types.Message, tsk types. return res, err } -func (a *StateAPI) StateTransplant(ctx context.Context, tsk types.TipSetKey, mc cid.Cid) (*api.InvocResult, error) { - ts, err := a.Chain.GetTipSetFromKey(tsk) - if err != nil { - return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) +func (a *StateAPI) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid.Cid) (*api.InvocResult, error) { + msgToReplay := mc + var ts *types.TipSet + if tsk == types.EmptyTSK { + mlkp, err := a.StateSearchMsg(ctx, mc) + if err != nil { + return nil, xerrors.Errorf("searching for msg %s: %w", mc, err) + } + if mlkp == nil { + return nil, xerrors.Errorf("didn't find msg %s", mc) + } + + msgToReplay = mlkp.Message + + executionTs, err := a.Chain.GetTipSetFromKey(mlkp.TipSet) + if err != nil { + return nil, xerrors.Errorf("loading tipset %s: %w", mlkp.TipSet, err) + } + + ts, err = a.Chain.LoadTipSet(executionTs.Parents()) + if err != nil { + return nil, xerrors.Errorf("loading parent tipset %s: %w", mlkp.TipSet, err) + } + } else { + ts = a.Chain.GetHeaviestTipSet() } - m, r, err := a.StateManager.Replay(ctx, ts, mc) + + m, r, err := a.StateManager.Replay(ctx, ts, msgToReplay) if err != nil { return nil, err } @@ -362,47 +384,7 @@ func (a *StateAPI) StateTransplant(ctx context.Context, tsk types.TipSetKey, mc } return &api.InvocResult{ - MsgCid: mc, - Msg: m, - MsgRct: &r.MessageReceipt, - GasCost: stmgr.MakeMsgGasCost(m, r), - ExecutionTrace: r.ExecutionTrace, - Error: errstr, - Duration: r.Duration, - }, nil -} - -func (a *StateAPI) StateReplay(ctx context.Context, mc cid.Cid) (*api.InvocResult, error) { - mlkp, err := a.StateSearchMsg(ctx, mc) - if err != nil { - return nil, xerrors.Errorf("searching for msg %s: %w", mc, err) - } - if mlkp == nil { - return nil, xerrors.Errorf("didn't find msg %s", mc) - } - - executionTs, err := a.Chain.GetTipSetFromKey(mlkp.TipSet) - if err != nil { - return nil, xerrors.Errorf("loading tipset %s: %w", mlkp.TipSet, err) - } - - ts, err := a.Chain.LoadTipSet(executionTs.Parents()) - if err != nil { - return nil, xerrors.Errorf("loading parent tipset %s: %w", mlkp.TipSet, err) - } - - m, r, err := a.StateManager.Replay(ctx, ts, mlkp.Message) - if err != nil { - return nil, err - } - - var errstr string - if r.ActorErr != nil { - errstr = r.ActorErr.Error() - } - - return &api.InvocResult{ - MsgCid: mlkp.Message, + MsgCid: msgToReplay, Msg: m, MsgRct: &r.MessageReceipt, GasCost: stmgr.MakeMsgGasCost(m, r), From d0e4150ceaf036f4af367261b8b983a3e0c51e68 Mon Sep 17 00:00:00 2001 From: Ingar Shu Date: Fri, 16 Oct 2020 08:30:55 -0700 Subject: [PATCH 157/313] Use separate config for Retrieval Filter --- node/builder.go | 5 ++++- node/config/def.go | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/node/builder.go b/node/builder.go index b6b75ecc6..1dc12e80a 100644 --- a/node/builder.go +++ b/node/builder.go @@ -486,7 +486,10 @@ func ConfigStorageMiner(c interface{}) Option { If(cfg.Dealmaking.Filter != "", Override(new(dtypes.StorageDealFilter), modules.BasicDealFilter(dealfilter.CliStorageDealFilter(cfg.Dealmaking.Filter))), - Override(new(dtypes.RetrievalDealFilter), modules.RetrievalDealFilter(dealfilter.CliRetrievalDealFilter(cfg.Dealmaking.Filter))), + ), + + If(cfg.Dealmaking.RetrievalFilter != "", + Override(new(dtypes.RetrievalDealFilter), modules.RetrievalDealFilter(dealfilter.CliRetrievalDealFilter(cfg.Dealmaking.RetrievalFilter))), ), Override(new(storagemarket.StorageProviderNode), storageadapter.NewProviderNodeAdapter(&cfg.Fees)), diff --git a/node/config/def.go b/node/config/def.go index 7eb7e19f0..a1b57286c 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -45,7 +45,8 @@ type DealmakingConfig struct { PieceCidBlocklist []cid.Cid ExpectedSealDuration Duration - Filter string + Filter string + RetrievalFilter string } type SealingConfig struct { From 4de8f506424ad9664b15459f0e96a834e4727e69 Mon Sep 17 00:00:00 2001 From: Travis Person Date: Fri, 16 Oct 2020 19:13:33 +0000 Subject: [PATCH 158/313] replace bootstrap peers --- build/bootstrap/bootstrappers.pi | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/build/bootstrap/bootstrappers.pi b/build/bootstrap/bootstrappers.pi index f3f8b8a55..886ac8e99 100644 --- a/build/bootstrap/bootstrappers.pi +++ b/build/bootstrap/bootstrappers.pi @@ -1,9 +1,12 @@ -/dns4/bootstrap-0.testnet.fildev.network/tcp/1347/p2p/12D3KooWJTUBUjtzWJGWU1XSiY21CwmHaCNLNYn2E7jqHEHyZaP7 -/dns4/bootstrap-1.testnet.fildev.network/tcp/1347/p2p/12D3KooW9yeKXha4hdrJKq74zEo99T8DhriQdWNoojWnnQbsgB3v -/dns4/bootstrap-2.testnet.fildev.network/tcp/1347/p2p/12D3KooWCrx8yVG9U9Kf7w8KLN3Edkj5ZKDhgCaeMqQbcQUoB6CT -/dns4/bootstrap-4.testnet.fildev.network/tcp/1347/p2p/12D3KooWPkL9LrKRQgHtq7kn9ecNhGU9QaziG8R5tX8v9v7t3h34 -/dns4/bootstrap-3.testnet.fildev.network/tcp/1347/p2p/12D3KooWKYSsbpgZ3HAjax5M1BXCwXLa6gVkUARciz7uN3FNtr7T -/dns4/bootstrap-5.testnet.fildev.network/tcp/1347/p2p/12D3KooWQYzqnLASJAabyMpPb1GcWZvNSe7JDcRuhdRqonFoiK9W +/dns4/bootstrap-0.mainnet.filops.net/tcp/1347/p2p/12D3KooWCVe8MmsEMes2FzgTpt9fXtmCY7wrq91GRiaC8PHSCCBj +/dns4/bootstrap-1.mainnet.filops.net/tcp/1347/p2p/12D3KooWCwevHg1yLCvktf2nvLu7L9894mcrJR4MsBCcm4syShVc +/dns4/bootstrap-2.mainnet.filops.net/tcp/1347/p2p/12D3KooWEWVwHGn2yR36gKLozmb4YjDJGerotAPGxmdWZx2nxMC4 +/dns4/bootstrap-3.mainnet.filops.net/tcp/1347/p2p/12D3KooWKhgq8c7NQ9iGjbyK7v7phXvG6492HQfiDaGHLHLQjk7R +/dns4/bootstrap-4.mainnet.filops.net/tcp/1347/p2p/12D3KooWL6PsFNPhYftrJzGgF5U18hFoaVhfGk7xwzD8yVrHJ3Uc +/dns4/bootstrap-5.mainnet.filops.net/tcp/1347/p2p/12D3KooWLFynvDQiUpXoHroV1YxKHhPJgysQGH2k3ZGwtWzR4dFH +/dns4/bootstrap-6.mainnet.filops.net/tcp/1347/p2p/12D3KooWP5MwCiqdMETF9ub1P3MbCvQCcfconnYHbWg6sUJcDRQQ +/dns4/bootstrap-7.mainnet.filops.net/tcp/1347/p2p/12D3KooWRs3aY1p3juFjPy8gPN95PEQChm2QKGUCAdcDCC4EBMKf +/dns4/bootstrap-8.mainnet.filops.net/tcp/1347/p2p/12D3KooWScFR7385LTyR4zU1bYdzSiiAb5rnNABfVahPvVSzyTkR /dns4/lotus-bootstrap.forceup.cn/tcp/41778/p2p/12D3KooWFQsv3nRMUevZNWWsY1Wu6NUzUbawnWU5NcRhgKuJA37C /dns4/bootstrap-0.starpool.in/tcp/12757/p2p/12D3KooWGHpBMeZbestVEWkfdnC9u7p6uFHXL1n7m1ZBqsEmiUzz /dns4/bootstrap-1.starpool.in/tcp/12757/p2p/12D3KooWQZrGH1PxSNZPum99M1zNvjNFM33d1AAu5DcvdHptuU7u From 70e2170e3e225d79b64f8942eae5834848931ffa Mon Sep 17 00:00:00 2001 From: austinabell Date: Fri, 16 Oct 2020 21:14:36 -0400 Subject: [PATCH 159/313] Fix circ supply default in conformance --- conformance/driver.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conformance/driver.go b/conformance/driver.go index fbb7dda6d..95b6f2659 100644 --- a/conformance/driver.go +++ b/conformance/driver.go @@ -248,7 +248,7 @@ func BaseFeeOrDefault(basefee *gobig.Int) abi.TokenAmount { // DefaultCirculatingSupply. func CircSupplyOrDefault(circSupply *gobig.Int) abi.TokenAmount { if circSupply == nil { - return DefaultBaseFee + return DefaultCirculatingSupply } return big.NewFromGo(circSupply) } From 68be28ca6dfce8d77120f90450c25b98d675de08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sat, 17 Oct 2020 12:53:42 +0200 Subject: [PATCH 160/313] Add Session API --- api/api_common.go | 5 +++++ api/apistruct/struct.go | 9 +++++++-- node/impl/common/common.go | 10 ++++++++-- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/api/api_common.go b/api/api_common.go index f8fcbe8c5..5b036d1f6 100644 --- a/api/api_common.go +++ b/api/api_common.go @@ -4,6 +4,8 @@ import ( "context" "fmt" + "github.com/google/uuid" + "github.com/filecoin-project/go-jsonrpc/auth" metrics "github.com/libp2p/go-libp2p-core/metrics" "github.com/libp2p/go-libp2p-core/network" @@ -58,6 +60,9 @@ type Common interface { // trigger graceful shutdown Shutdown(context.Context) error + // Session returns a random UUID of api provider session + Session(context.Context) (uuid.UUID, error) + Closing(context.Context) (<-chan struct{}, error) } diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index edf119114..b664f594f 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -5,8 +5,7 @@ import ( "io" "time" - stnetwork "github.com/filecoin-project/go-state-types/network" - + "github.com/google/uuid" "github.com/ipfs/go-cid" metrics "github.com/libp2p/go-libp2p-core/metrics" "github.com/libp2p/go-libp2p-core/network" @@ -24,6 +23,7 @@ import ( "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/dline" + stnetwork "github.com/filecoin-project/go-state-types/network" "github.com/filecoin-project/lotus/extern/sector-storage/fsutil" "github.com/filecoin-project/lotus/extern/sector-storage/sealtasks" "github.com/filecoin-project/lotus/extern/sector-storage/stores" @@ -67,6 +67,7 @@ type CommonStruct struct { LogSetLevel func(context.Context, string, string) error `perm:"write"` Shutdown func(context.Context) error `perm:"admin"` + Session func(context.Context) (uuid.UUID, error) `perm:"read"` Closing func(context.Context) (<-chan struct{}, error) `perm:"read"` } } @@ -487,6 +488,10 @@ func (c *CommonStruct) Shutdown(ctx context.Context) error { return c.Internal.Shutdown(ctx) } +func (c *CommonStruct) Session(ctx context.Context) (uuid.UUID, error) { + return c.Internal.Session(ctx) +} + func (c *CommonStruct) Closing(ctx context.Context) (<-chan struct{}, error) { return c.Internal.Closing(ctx) } diff --git a/node/impl/common/common.go b/node/impl/common/common.go index da7cfff25..79478e489 100644 --- a/node/impl/common/common.go +++ b/node/impl/common/common.go @@ -5,9 +5,9 @@ import ( "sort" "strings" - logging "github.com/ipfs/go-log/v2" - "github.com/gbrlsnchs/jwt/v3" + "github.com/google/uuid" + logging "github.com/ipfs/go-log/v2" "github.com/libp2p/go-libp2p-core/host" metrics "github.com/libp2p/go-libp2p-core/metrics" "github.com/libp2p/go-libp2p-core/network" @@ -27,6 +27,8 @@ import ( "github.com/filecoin-project/lotus/node/modules/lp2p" ) +var session = uuid.New() + type CommonAPI struct { fx.In @@ -202,6 +204,10 @@ func (a *CommonAPI) Shutdown(ctx context.Context) error { return nil } +func (a *CommonAPI) Session(ctx context.Context) (uuid.UUID, error) { + return session, nil +} + func (a *CommonAPI) Closing(ctx context.Context) (<-chan struct{}, error) { return make(chan struct{}), nil // relies on jsonrpc closing } From 8d06cca073a49911a7018296b11951aceb32b484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sun, 18 Oct 2020 12:35:44 +0200 Subject: [PATCH 161/313] sched: Handle workers using sessions instead of connections --- api/api_storage.go | 5 +- api/api_worker.go | 4 +- api/apistruct/struct.go | 16 +- cmd/lotus-seal-worker/main.go | 2 +- cmd/lotus-storage-miner/sealing.go | 15 +- extern/sector-storage/manager.go | 21 +- extern/sector-storage/sched.go | 317 +++++++++++++++------- extern/sector-storage/sched_test.go | 32 +-- extern/sector-storage/sched_watch.go | 100 ------- extern/sector-storage/stats.go | 22 +- extern/sector-storage/storiface/worker.go | 3 +- extern/sector-storage/testworker_test.go | 8 +- extern/sector-storage/worker_local.go | 11 +- node/impl/storminer.go | 5 +- storage/wdpost_run_test.go | 6 +- 15 files changed, 294 insertions(+), 273 deletions(-) delete mode 100644 extern/sector-storage/sched_watch.go diff --git a/api/api_storage.go b/api/api_storage.go index 79d538fe5..5520ad114 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -5,6 +5,7 @@ import ( "context" "time" + "github.com/google/uuid" "github.com/ipfs/go-cid" "github.com/filecoin-project/go-address" @@ -62,8 +63,8 @@ type StorageMiner interface { // WorkerConnect tells the node to connect to workers RPC WorkerConnect(context.Context, string) error - WorkerStats(context.Context) (map[uint64]storiface.WorkerStats, error) - WorkerJobs(context.Context) (map[int64][]storiface.WorkerJob, error) + WorkerStats(context.Context) (map[uuid.UUID]storiface.WorkerStats, error) + WorkerJobs(context.Context) (map[uuid.UUID][]storiface.WorkerJob, error) storiface.WorkerReturn // SealingSchedDiag dumps internal sealing scheduler state diff --git a/api/api_worker.go b/api/api_worker.go index 42eea9289..036748ec6 100644 --- a/api/api_worker.go +++ b/api/api_worker.go @@ -3,6 +3,8 @@ package api import ( "context" + "github.com/google/uuid" + "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/lotus/extern/sector-storage/sealtasks" "github.com/filecoin-project/lotus/extern/sector-storage/stores" @@ -26,5 +28,5 @@ type WorkerAPI interface { StorageAddLocal(ctx context.Context, path string) error - Closing(context.Context) (<-chan struct{}, error) + Session(context.Context) (uuid.UUID, error) } diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 180570742..70eb518e4 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -296,9 +296,9 @@ type StorageMinerStruct struct { SectorRemove func(context.Context, abi.SectorNumber) error `perm:"admin"` SectorMarkForUpgrade func(ctx context.Context, id abi.SectorNumber) error `perm:"admin"` - WorkerConnect func(context.Context, string) error `perm:"admin" retry:"true"` // TODO: worker perm - WorkerStats func(context.Context) (map[uint64]storiface.WorkerStats, error) `perm:"admin"` - WorkerJobs func(context.Context) (map[int64][]storiface.WorkerJob, error) `perm:"admin"` + WorkerConnect func(context.Context, string) error `perm:"admin" retry:"true"` // TODO: worker perm + WorkerStats func(context.Context) (map[uuid.UUID]storiface.WorkerStats, error) `perm:"admin"` + WorkerJobs func(context.Context) (map[uuid.UUID][]storiface.WorkerJob, error) `perm:"admin"` ReturnAddPiece func(ctx context.Context, callID storiface.CallID, pi abi.PieceInfo, err string) error `perm:"admin" retry:"true"` ReturnSealPreCommit1 func(ctx context.Context, callID storiface.CallID, p1o storage.PreCommit1Out, err string) error `perm:"admin" retry:"true"` @@ -376,7 +376,7 @@ type WorkerStruct struct { Remove func(ctx context.Context, sector abi.SectorID) error `perm:"admin"` StorageAddLocal func(ctx context.Context, path string) error `perm:"admin"` - Closing func(context.Context) (<-chan struct{}, error) `perm:"admin"` + Session func(context.Context) (uuid.UUID, error) `perm:"admin"` } } @@ -1200,11 +1200,11 @@ func (c *StorageMinerStruct) WorkerConnect(ctx context.Context, url string) erro return c.Internal.WorkerConnect(ctx, url) } -func (c *StorageMinerStruct) WorkerStats(ctx context.Context) (map[uint64]storiface.WorkerStats, error) { +func (c *StorageMinerStruct) WorkerStats(ctx context.Context) (map[uuid.UUID]storiface.WorkerStats, error) { return c.Internal.WorkerStats(ctx) } -func (c *StorageMinerStruct) WorkerJobs(ctx context.Context) (map[int64][]storiface.WorkerJob, error) { +func (c *StorageMinerStruct) WorkerJobs(ctx context.Context) (map[uuid.UUID][]storiface.WorkerJob, error) { return c.Internal.WorkerJobs(ctx) } @@ -1490,8 +1490,8 @@ func (w *WorkerStruct) StorageAddLocal(ctx context.Context, path string) error { return w.Internal.StorageAddLocal(ctx, path) } -func (w *WorkerStruct) Closing(ctx context.Context) (<-chan struct{}, error) { - return w.Internal.Closing(ctx) +func (w *WorkerStruct) Session(ctx context.Context) (uuid.UUID, error) { + return w.Internal.Session(ctx) } func (g GatewayStruct) ChainHasObj(ctx context.Context, c cid.Cid) (bool, error) { diff --git a/cmd/lotus-seal-worker/main.go b/cmd/lotus-seal-worker/main.go index bf7ce1e52..3472192e8 100644 --- a/cmd/lotus-seal-worker/main.go +++ b/cmd/lotus-seal-worker/main.go @@ -449,7 +449,7 @@ var runCmd = &cli.Command{ // TODO: we could get rid of this, but that requires tracking resources for restarted tasks correctly workerApi.LocalWorker.WaitQuiet() - if err := nodeApi.WorkerConnect(ctx, "ws://"+address+"/rpc/v0"); err != nil { + if err := nodeApi.WorkerConnect(ctx, "http://"+address+"/rpc/v0"); err != nil { log.Errorf("Registering worker failed: %+v", err) cancel() return diff --git a/cmd/lotus-storage-miner/sealing.go b/cmd/lotus-storage-miner/sealing.go index 3e33f2185..8649ad7d4 100644 --- a/cmd/lotus-storage-miner/sealing.go +++ b/cmd/lotus-storage-miner/sealing.go @@ -11,6 +11,7 @@ import ( "time" "github.com/fatih/color" + "github.com/google/uuid" "github.com/urfave/cli/v2" "golang.org/x/xerrors" @@ -53,7 +54,7 @@ var sealingWorkersCmd = &cli.Command{ } type sortableStat struct { - id uint64 + id uuid.UUID storiface.WorkerStats } @@ -63,7 +64,7 @@ var sealingWorkersCmd = &cli.Command{ } sort.Slice(st, func(i, j int) bool { - return st[i].id < st[j].id + return st[i].id.String() < st[j].id.String() }) for _, stat := range st { @@ -74,7 +75,7 @@ var sealingWorkersCmd = &cli.Command{ gpuUse = "" } - fmt.Printf("Worker %d, host %s\n", stat.id, color.MagentaString(stat.Info.Hostname)) + fmt.Printf("Worker %s, host %s\n", stat.id, color.MagentaString(stat.Info.Hostname)) var barCols = uint64(64) cpuBars := int(stat.CpuUse * barCols / stat.Info.Resources.CPUs) @@ -140,7 +141,7 @@ var sealingJobsCmd = &cli.Command{ type line struct { storiface.WorkerJob - wid int64 + wid uuid.UUID } lines := make([]line, 0) @@ -165,7 +166,7 @@ var sealingJobsCmd = &cli.Command{ return lines[i].Start.Before(lines[j].Start) }) - workerHostnames := map[int64]string{} + workerHostnames := map[uuid.UUID]string{} wst, err := nodeApi.WorkerStats(ctx) if err != nil { @@ -173,7 +174,7 @@ var sealingJobsCmd = &cli.Command{ } for wid, st := range wst { - workerHostnames[int64(wid)] = st.Info.Hostname + workerHostnames[wid] = st.Info.Hostname } tw := tabwriter.NewWriter(os.Stdout, 2, 4, 2, ' ', 0) @@ -192,7 +193,7 @@ var sealingJobsCmd = &cli.Command{ dur = time.Now().Sub(l.Start).Truncate(time.Millisecond * 100).String() } - _, _ = fmt.Fprintf(tw, "%s\t%d\t%d\t%s\t%s\t%s\t%s\n", hex.EncodeToString(l.ID.ID[10:]), l.Sector.Number, l.wid, workerHostnames[l.wid], l.Task.Short(), state, dur) + _, _ = fmt.Fprintf(tw, "%s\t%d\t%s\t%s\t%s\t%s\t%s\n", hex.EncodeToString(l.ID.ID[10:]), l.Sector.Number, l.wid, workerHostnames[l.wid], l.Task.Short(), state, dur) } return tw.Flush() diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index 9445bdd2a..0a8ff4339 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -7,6 +7,7 @@ import ( "net/http" "sync" + "github.com/google/uuid" "github.com/hashicorp/go-multierror" "github.com/ipfs/go-cid" logging "github.com/ipfs/go-log/v2" @@ -40,8 +41,7 @@ type Worker interface { Info(context.Context) (storiface.WorkerInfo, error) - // returns channel signalling worker shutdown - Closing(context.Context) (<-chan struct{}, error) + Session(context.Context) (uuid.UUID, error) Close() error // TODO: do we need this? } @@ -57,7 +57,8 @@ type SectorManager interface { FaultTracker } -type WorkerID int64 +type WorkerID uuid.UUID // worker session UUID +var ClosedWorkerID = uuid.UUID{} type Manager struct { scfg *ffiwrapper.Config @@ -190,19 +191,7 @@ func (m *Manager) AddLocalStorage(ctx context.Context, path string) error { } func (m *Manager) AddWorker(ctx context.Context, w Worker) error { - info, err := w.Info(ctx) - if err != nil { - return xerrors.Errorf("getting worker info: %w", err) - } - - m.sched.newWorkers <- &workerHandle{ - w: w, - - info: info, - preparing: &activeResources{}, - active: &activeResources{}, - } - return nil + return m.sched.runWorker(ctx, w) } func (m *Manager) ServeHTTP(w http.ResponseWriter, r *http.Request) { diff --git a/extern/sector-storage/sched.go b/extern/sector-storage/sched.go index e91c92525..a4e6a6239 100644 --- a/extern/sector-storage/sched.go +++ b/extern/sector-storage/sched.go @@ -2,7 +2,6 @@ package sectorstorage import ( "context" - "fmt" "math/rand" "sort" "sync" @@ -13,6 +12,7 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/lotus/extern/sector-storage/sealtasks" + "github.com/filecoin-project/lotus/extern/sector-storage/stores" "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) @@ -53,17 +53,13 @@ type WorkerSelector interface { type scheduler struct { spt abi.RegisteredSealProof - workersLk sync.RWMutex - nextWorker WorkerID - workers map[WorkerID]*workerHandle - - newWorkers chan *workerHandle - - watchClosing chan WorkerID - workerClosing chan WorkerID + workersLk sync.RWMutex + workers map[WorkerID]*workerHandle schedule chan *workerRequest windowRequests chan *schedWindowRequest + workerChange chan struct{} // worker added / changed/freed resources + workerDisable chan workerDisableReq // owned by the sh.runSched goroutine schedQueue *requestQueue @@ -91,6 +87,8 @@ type workerHandle struct { wndLk sync.Mutex activeWindows []*schedWindow + enabled bool + // for sync manager goroutine closing cleanupStarted bool closedMgr chan struct{} @@ -108,6 +106,12 @@ type schedWindow struct { todo []*workerRequest } +type workerDisableReq struct { + activeWindows []*schedWindow + wid WorkerID + done func() +} + type activeResources struct { memUsedMin uint64 memUsedMax uint64 @@ -143,16 +147,12 @@ func newScheduler(spt abi.RegisteredSealProof) *scheduler { return &scheduler{ spt: spt, - nextWorker: 0, - workers: map[WorkerID]*workerHandle{}, - - newWorkers: make(chan *workerHandle), - - watchClosing: make(chan WorkerID), - workerClosing: make(chan WorkerID), + workers: map[WorkerID]*workerHandle{}, schedule: make(chan *workerRequest), windowRequests: make(chan *schedWindowRequest, 20), + workerChange: make(chan struct{}, 20), + workerDisable: make(chan workerDisableReq), schedQueue: &requestQueue{}, @@ -224,21 +224,19 @@ type SchedDiagInfo struct { func (sh *scheduler) runSched() { defer close(sh.closed) - go sh.runWorkerWatcher() - iw := time.After(InitWait) var initialised bool for { var doSched bool + var toDisable []workerDisableReq select { - case w := <-sh.newWorkers: - sh.newWorker(w) - - case wid := <-sh.workerClosing: - sh.dropWorker(wid) - + case <-sh.workerChange: + doSched = true + case dreq := <-sh.workerDisable: + toDisable = append(toDisable, dreq) + doSched = true case req := <-sh.schedule: sh.schedQueue.Push(req) doSched = true @@ -267,6 +265,9 @@ func (sh *scheduler) runSched() { loop: for { select { + case <-sh.workerChange: + case dreq := <-sh.workerDisable: + toDisable = append(toDisable, dreq) case req := <-sh.schedule: sh.schedQueue.Push(req) if sh.testSync != nil { @@ -279,6 +280,28 @@ func (sh *scheduler) runSched() { } } + for _, req := range toDisable { + for _, window := range req.activeWindows { + for _, request := range window.todo { + sh.schedQueue.Push(request) + } + } + + openWindows := make([]*schedWindowRequest, 0, len(sh.openWindows)) + for _, window := range sh.openWindows { + if window.worker != req.wid { + openWindows = append(openWindows, window) + } + } + sh.openWindows = openWindows + + sh.workersLk.Lock() + sh.workers[req.wid].enabled = false + sh.workersLk.Unlock() + + req.done() + } + sh.trySched() } @@ -298,6 +321,9 @@ func (sh *scheduler) diag() SchedDiagInfo { }) } + sh.workersLk.RLock() + defer sh.workersLk.RUnlock() + for _, window := range sh.openWindows { out.OpenWindows = append(out.OpenWindows, window.worker) } @@ -322,13 +348,14 @@ func (sh *scheduler) trySched() { */ + sh.workersLk.RLock() + defer sh.workersLk.RUnlock() + windows := make([]schedWindow, len(sh.openWindows)) acceptableWindows := make([][]int, sh.schedQueue.Len()) log.Debugf("SCHED %d queued; %d open windows", sh.schedQueue.Len(), len(windows)) - sh.workersLk.RLock() - defer sh.workersLk.RUnlock() if len(sh.openWindows) == 0 { // nothing to schedule on return @@ -357,11 +384,16 @@ func (sh *scheduler) trySched() { for wnd, windowRequest := range sh.openWindows { worker, ok := sh.workers[windowRequest.worker] if !ok { - log.Errorf("worker referenced by windowRequest not found (worker: %d)", windowRequest.worker) + log.Errorf("worker referenced by windowRequest not found (worker: %s)", windowRequest.worker) // TODO: How to move forward here? continue } + if !worker.enabled { + log.Debugw("skipping disabled worker", "worker", windowRequest.worker) + continue + } + // TODO: allow bigger windows if !windows[wnd].allocated.canHandleRequest(needRes, windowRequest.worker, "schedAcceptable", worker.info.Resources) { continue @@ -499,21 +531,48 @@ func (sh *scheduler) trySched() { sh.openWindows = newOpenWindows } -func (sh *scheduler) runWorker(wid WorkerID) { - var ready sync.WaitGroup - ready.Add(1) - defer ready.Wait() +// context only used for startup +func (sh *scheduler) runWorker(ctx context.Context, w Worker) error { + info, err := w.Info(ctx) + if err != nil { + return xerrors.Errorf("getting worker info: %w", err) + } + + sessID, err := w.Session(ctx) + if err != nil { + return xerrors.Errorf("getting worker session: %w", err) + } + if sessID == ClosedWorkerID { + return xerrors.Errorf("worker already closed") + } + + worker := &workerHandle{ + w: w, + info: info, + + preparing: &activeResources{}, + active: &activeResources{}, + enabled: true, + + closingMgr: make(chan struct{}), + closedMgr: make(chan struct{}), + } + + wid := WorkerID(sessID) + + sh.workersLk.Lock() + _, exist := sh.workers[wid] + if exist { + // this is ok, we're already handling this worker in a different goroutine + return nil + } + + sh.workers[wid] = worker + sh.workersLk.Unlock() go func() { - sh.workersLk.RLock() - worker, found := sh.workers[wid] - sh.workersLk.RUnlock() - - ready.Done() - - if !found { - panic(fmt.Sprintf("worker %d not found", wid)) - } + ctx, cancel := context.WithCancel(context.TODO()) + defer cancel() defer close(worker.closedMgr) @@ -521,23 +580,60 @@ func (sh *scheduler) runWorker(wid WorkerID) { taskDone := make(chan struct{}, 1) windowsRequested := 0 - ctx, cancel := context.WithCancel(context.TODO()) - defer cancel() + disable := func(ctx context.Context) error { + done := make(chan struct{}) - workerClosing, err := worker.w.Closing(ctx) - if err != nil { - return + // request cleanup in the main scheduler goroutine + select { + case sh.workerDisable <- workerDisableReq{ + activeWindows: worker.activeWindows, + wid: wid, + done: func() { + close(done) + }, + }: + case <-ctx.Done(): + return ctx.Err() + case <-sh.closing: + return nil + } + + // wait for cleanup to complete + select { + case <-done: + case <-ctx.Done(): + return ctx.Err() + case <-sh.closing: + return nil + } + + worker.activeWindows = worker.activeWindows[:0] + windowsRequested = 0 + return nil } defer func() { - log.Warnw("Worker closing", "workerid", wid) + log.Warnw("Worker closing", "workerid", sessID) - // TODO: close / return all queued tasks + if err := disable(ctx); err != nil { + log.Warnw("failed to disable worker", "worker", wid, "error", err) + } + + sh.workersLk.Lock() + delete(sh.workers, wid) + sh.workersLk.Unlock() }() + heartbeatTimer := time.NewTicker(stores.HeartbeatInterval) + defer heartbeatTimer.Stop() + for { - // ask for more windows if we need them - for ; windowsRequested < SchedWindows; windowsRequested++ { + sh.workersLk.Lock() + enabled := worker.enabled + sh.workersLk.Unlock() + + // ask for more windows if we need them (non-blocking) + for ; enabled && windowsRequested < SchedWindows; windowsRequested++ { select { case sh.windowRequests <- &schedWindowRequest{ worker: wid, @@ -545,33 +641,90 @@ func (sh *scheduler) runWorker(wid WorkerID) { }: case <-sh.closing: return - case <-workerClosing: - return case <-worker.closingMgr: return } } - select { - case w := <-scheduledWindows: - worker.wndLk.Lock() - worker.activeWindows = append(worker.activeWindows, w) - worker.wndLk.Unlock() - case <-taskDone: - log.Debugw("task done", "workerid", wid) - case <-sh.closing: - return - case <-workerClosing: - return - case <-worker.closingMgr: - return + // wait for more windows to come in, or for tasks to get finished (blocking) + for { + + // first ping the worker and check session + { + sctx, scancel := context.WithTimeout(ctx, stores.HeartbeatInterval/2) + curSes, err := worker.w.Session(sctx) + scancel() + if err != nil { + // Likely temporary error + + log.Warnw("failed to check worker session", "error", err) + + if err := disable(ctx); err != nil { + log.Warnw("failed to disable worker with session error", "worker", wid, "error", err) + } + + select { + case <-heartbeatTimer.C: + continue + case w := <-scheduledWindows: + // was in flight when initially disabled, return + worker.wndLk.Lock() + worker.activeWindows = append(worker.activeWindows, w) + worker.wndLk.Unlock() + + if err := disable(ctx); err != nil { + log.Warnw("failed to disable worker with session error", "worker", wid, "error", err) + } + case <-sh.closing: + return + case <-worker.closingMgr: + return + } + continue + } + + if curSes != sessID { + if curSes != ClosedWorkerID { + // worker restarted + log.Warnw("worker session changed (worker restarted?)", "initial", sessID, "current", curSes) + } + + return + } + + // session looks good + if !enabled { + sh.workersLk.Lock() + worker.enabled = true + sh.workersLk.Unlock() + + // we'll send window requests on the next loop + } + } + + select { + case <-heartbeatTimer.C: + continue + case w := <-scheduledWindows: + worker.wndLk.Lock() + worker.activeWindows = append(worker.activeWindows, w) + worker.wndLk.Unlock() + case <-taskDone: + log.Debugw("task done", "workerid", wid) + case <-sh.closing: + return + case <-worker.closingMgr: + return + } + + break } + // process assigned windows (non-blocking) sh.workersLk.RLock() worker.wndLk.Lock() windowsRequested -= sh.workerCompactWindows(worker, wid) - assignLoop: // process windows in order for len(worker.activeWindows) > 0 { @@ -622,6 +775,8 @@ func (sh *scheduler) runWorker(wid WorkerID) { sh.workersLk.RUnlock() } }() + + return nil } func (sh *scheduler) workerCompactWindows(worker *workerHandle, wid WorkerID) int { @@ -745,38 +900,6 @@ func (sh *scheduler) assignWorker(taskDone chan struct{}, wid WorkerID, w *worke return nil } -func (sh *scheduler) newWorker(w *workerHandle) { - w.closedMgr = make(chan struct{}) - w.closingMgr = make(chan struct{}) - - sh.workersLk.Lock() - - id := sh.nextWorker - sh.workers[id] = w - sh.nextWorker++ - - sh.workersLk.Unlock() - - sh.runWorker(id) - - select { - case sh.watchClosing <- id: - case <-sh.closing: - return - } -} - -func (sh *scheduler) dropWorker(wid WorkerID) { - sh.workersLk.Lock() - defer sh.workersLk.Unlock() - - w := sh.workers[wid] - - sh.workerCleanup(wid, w) - - delete(sh.workers, wid) -} - func (sh *scheduler) workerCleanup(wid WorkerID, w *workerHandle) { select { case <-w.closingMgr: diff --git a/extern/sector-storage/sched_test.go b/extern/sector-storage/sched_test.go index 3a198bad5..1afa92b64 100644 --- a/extern/sector-storage/sched_test.go +++ b/extern/sector-storage/sched_test.go @@ -10,6 +10,7 @@ import ( "testing" "time" + "github.com/google/uuid" "github.com/ipfs/go-cid" logging "github.com/ipfs/go-log/v2" "github.com/stretchr/testify/require" @@ -43,7 +44,7 @@ type schedTestWorker struct { paths []stores.StoragePath closed bool - closing chan struct{} + session uuid.UUID } func (s *schedTestWorker) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storiface.CallID, error) { @@ -121,15 +122,15 @@ func (s *schedTestWorker) Info(ctx context.Context) (storiface.WorkerInfo, error }, nil } -func (s *schedTestWorker) Closing(ctx context.Context) (<-chan struct{}, error) { - return s.closing, nil +func (s *schedTestWorker) Session(context.Context) (uuid.UUID, error) { + return s.session, nil } func (s *schedTestWorker) Close() error { if !s.closed { log.Info("close schedTestWorker") s.closed = true - close(s.closing) + s.session = uuid.UUID{} } return nil } @@ -142,7 +143,7 @@ func addTestWorker(t *testing.T, sched *scheduler, index *stores.Index, name str taskTypes: taskTypes, paths: []stores.StoragePath{{ID: "bb-8", Weight: 2, LocalPath: "food", CanSeal: true, CanStore: true}}, - closing: make(chan struct{}), + session: uuid.New(), } for _, path := range w.paths { @@ -160,16 +161,7 @@ func addTestWorker(t *testing.T, sched *scheduler, index *stores.Index, name str require.NoError(t, err) } - info, err := w.Info(context.TODO()) - require.NoError(t, err) - - sched.newWorkers <- &workerHandle{ - w: w, - - info: info, - preparing: &activeResources{}, - active: &activeResources{}, - } + require.NoError(t, sched.runWorker(context.TODO(), w)) } func TestSchedStartStop(t *testing.T) { @@ -433,7 +425,7 @@ func TestSched(t *testing.T) { type line struct { storiface.WorkerJob - wid uint64 + wid uuid.UUID } lines := make([]line, 0) @@ -442,7 +434,7 @@ func TestSched(t *testing.T) { for _, job := range jobs { lines = append(lines, line{ WorkerJob: job, - wid: uint64(wid), + wid: wid, }) } } @@ -537,7 +529,7 @@ func BenchmarkTrySched(b *testing.B) { b.StopTimer() sched := newScheduler(spt) - sched.workers[0] = &workerHandle{ + sched.workers[WorkerID{}] = &workerHandle{ w: nil, info: storiface.WorkerInfo{ Hostname: "t", @@ -549,7 +541,7 @@ func BenchmarkTrySched(b *testing.B) { for i := 0; i < windows; i++ { sched.openWindows = append(sched.openWindows, &schedWindowRequest{ - worker: 0, + worker: WorkerID{}, done: make(chan *schedWindow, 1000), }) } @@ -599,7 +591,7 @@ func TestWindowCompact(t *testing.T) { wh.activeWindows = append(wh.activeWindows, window) } - n := sh.workerCompactWindows(wh, 0) + n := sh.workerCompactWindows(wh, WorkerID{}) require.Equal(t, len(start)-len(expect), n) for wi, tasks := range expect { diff --git a/extern/sector-storage/sched_watch.go b/extern/sector-storage/sched_watch.go deleted file mode 100644 index 2dd9875d7..000000000 --- a/extern/sector-storage/sched_watch.go +++ /dev/null @@ -1,100 +0,0 @@ -package sectorstorage - -import ( - "context" - "reflect" -) - -func (sh *scheduler) runWorkerWatcher() { - ctx, cancel := context.WithCancel(context.TODO()) - defer cancel() - - nilch := reflect.ValueOf(new(chan struct{})).Elem() - - cases := []reflect.SelectCase{ - { - Dir: reflect.SelectRecv, - Chan: reflect.ValueOf(sh.closing), - }, - { - Dir: reflect.SelectRecv, - Chan: reflect.ValueOf(sh.watchClosing), - }, - } - - caseToWorker := map[int]WorkerID{} - - for { - n, rv, ok := reflect.Select(cases) - - switch { - case n == 0: // sh.closing - return - case n == 1: // sh.watchClosing - if !ok { - log.Errorf("watchClosing channel closed") - return - } - - wid, ok := rv.Interface().(WorkerID) - if !ok { - panic("got a non-WorkerID message") - } - - sh.workersLk.Lock() - workerClosing, err := sh.workers[wid].w.Closing(ctx) - sh.workersLk.Unlock() - if err != nil { - log.Errorf("getting worker closing channel: %+v", err) - select { - case sh.workerClosing <- wid: - case <-sh.closing: - return - } - - continue - } - - toSet := -1 - for i, sc := range cases { - if sc.Chan == nilch { - toSet = i - break - } - } - if toSet == -1 { - toSet = len(cases) - cases = append(cases, reflect.SelectCase{}) - } - - cases[toSet] = reflect.SelectCase{ - Dir: reflect.SelectRecv, - Chan: reflect.ValueOf(workerClosing), - } - - caseToWorker[toSet] = wid - default: - wid, found := caseToWorker[n] - if !found { - log.Errorf("worker ID not found for case %d", n) - continue - } - - delete(caseToWorker, n) - cases[n] = reflect.SelectCase{ - Dir: reflect.SelectRecv, - Chan: nilch, - } - - log.Warnf("worker %d dropped", wid) - // send in a goroutine to avoid a deadlock between workerClosing / watchClosing - go func() { - select { - case sh.workerClosing <- wid: - case <-sh.closing: - return - } - }() - } - } -} diff --git a/extern/sector-storage/stats.go b/extern/sector-storage/stats.go index bba47d169..f9d96fc5d 100644 --- a/extern/sector-storage/stats.go +++ b/extern/sector-storage/stats.go @@ -3,18 +3,22 @@ package sectorstorage import ( "time" + "github.com/google/uuid" + "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) -func (m *Manager) WorkerStats() map[uint64]storiface.WorkerStats { +func (m *Manager) WorkerStats() map[uuid.UUID]storiface.WorkerStats { m.sched.workersLk.RLock() defer m.sched.workersLk.RUnlock() - out := map[uint64]storiface.WorkerStats{} + out := map[uuid.UUID]storiface.WorkerStats{} for id, handle := range m.sched.workers { - out[uint64(id)] = storiface.WorkerStats{ - Info: handle.info, + out[uuid.UUID(id)] = storiface.WorkerStats{ + Info: handle.info, + Enabled: handle.enabled, + MemUsedMin: handle.active.memUsedMin, MemUsedMax: handle.active.memUsedMax, GpuUsed: handle.active.gpuUsed, @@ -25,12 +29,12 @@ func (m *Manager) WorkerStats() map[uint64]storiface.WorkerStats { return out } -func (m *Manager) WorkerJobs() map[int64][]storiface.WorkerJob { - out := map[int64][]storiface.WorkerJob{} +func (m *Manager) WorkerJobs() map[uuid.UUID][]storiface.WorkerJob { + out := map[uuid.UUID][]storiface.WorkerJob{} calls := map[storiface.CallID]struct{}{} for _, t := range m.sched.wt.Running() { - out[int64(t.worker)] = append(out[int64(t.worker)], t.job) + out[uuid.UUID(t.worker)] = append(out[uuid.UUID(t.worker)], t.job) calls[t.job.ID] = struct{}{} } @@ -40,7 +44,7 @@ func (m *Manager) WorkerJobs() map[int64][]storiface.WorkerJob { handle.wndLk.Lock() for wi, window := range handle.activeWindows { for _, request := range window.todo { - out[int64(id)] = append(out[int64(id)], storiface.WorkerJob{ + out[uuid.UUID(id)] = append(out[uuid.UUID(id)], storiface.WorkerJob{ ID: storiface.UndefCall, Sector: request.sector, Task: request.taskType, @@ -63,7 +67,7 @@ func (m *Manager) WorkerJobs() map[int64][]storiface.WorkerJob { continue } - out[-1] = append(out[-1], storiface.WorkerJob{ + out[uuid.UUID{}] = append(out[uuid.UUID{}], storiface.WorkerJob{ ID: id, Sector: id.Sector, Task: work.Method, diff --git a/extern/sector-storage/storiface/worker.go b/extern/sector-storage/storiface/worker.go index e6ab2246f..bbc9ca554 100644 --- a/extern/sector-storage/storiface/worker.go +++ b/extern/sector-storage/storiface/worker.go @@ -32,7 +32,8 @@ type WorkerResources struct { } type WorkerStats struct { - Info WorkerInfo + Info WorkerInfo + Enabled bool MemUsedMin uint64 MemUsedMax uint64 diff --git a/extern/sector-storage/testworker_test.go b/extern/sector-storage/testworker_test.go index 94a87cdd2..fda25643a 100644 --- a/extern/sector-storage/testworker_test.go +++ b/extern/sector-storage/testworker_test.go @@ -27,6 +27,8 @@ type testWorker struct { pc1s int pc1lk sync.Mutex pc1wait *sync.WaitGroup + + session uuid.UUID } func newTestWorker(wcfg WorkerConfig, lstor *stores.Local, ret storiface.WorkerReturn) *testWorker { @@ -46,6 +48,8 @@ func newTestWorker(wcfg WorkerConfig, lstor *stores.Local, ret storiface.WorkerR ret: ret, mockSeal: mock.NewMockSectorMgr(ssize, nil), + + session: uuid.New(), } } @@ -158,8 +162,8 @@ func (t *testWorker) Info(ctx context.Context) (storiface.WorkerInfo, error) { }, nil } -func (t *testWorker) Closing(ctx context.Context) (<-chan struct{}, error) { - return ctx.Done(), nil +func (t *testWorker) Session(context.Context) (uuid.UUID, error) { + return t.session, nil } func (t *testWorker) Close() error { diff --git a/extern/sector-storage/worker_local.go b/extern/sector-storage/worker_local.go index e38b84d40..739f70fa0 100644 --- a/extern/sector-storage/worker_local.go +++ b/extern/sector-storage/worker_local.go @@ -48,6 +48,7 @@ type LocalWorker struct { acceptTasks map[sealtasks.TaskType]struct{} running sync.WaitGroup + session uuid.UUID closing chan struct{} } @@ -73,6 +74,7 @@ func newLocalWorker(executor func() (ffiwrapper.Storage, error), wcfg WorkerConf executor: executor, noSwap: wcfg.NoSwap, + session: uuid.New(), closing: make(chan struct{}), } @@ -465,8 +467,13 @@ func (l *LocalWorker) Info(context.Context) (storiface.WorkerInfo, error) { }, nil } -func (l *LocalWorker) Closing(ctx context.Context) (<-chan struct{}, error) { - return l.closing, nil +func (l *LocalWorker) Session(ctx context.Context) (uuid.UUID, error) { + select { + case <-l.closing: + return ClosedWorkerID, nil + default: + return l.session, nil + } } func (l *LocalWorker) Close() error { diff --git a/node/impl/storminer.go b/node/impl/storminer.go index f7da91711..b27ea9edb 100644 --- a/node/impl/storminer.go +++ b/node/impl/storminer.go @@ -8,6 +8,7 @@ import ( "strconv" "time" + "github.com/google/uuid" "github.com/ipfs/go-cid" "github.com/libp2p/go-libp2p-core/host" "golang.org/x/xerrors" @@ -85,11 +86,11 @@ func (sm *StorageMinerAPI) ServeRemote(w http.ResponseWriter, r *http.Request) { sm.StorageMgr.ServeHTTP(w, r) } -func (sm *StorageMinerAPI) WorkerStats(context.Context) (map[uint64]storiface.WorkerStats, error) { +func (sm *StorageMinerAPI) WorkerStats(context.Context) (map[uuid.UUID]storiface.WorkerStats, error) { return sm.StorageMgr.WorkerStats(), nil } -func (sm *StorageMinerAPI) WorkerJobs(ctx context.Context) (map[int64][]storiface.WorkerJob, error) { +func (sm *StorageMinerAPI) WorkerJobs(ctx context.Context) (map[uuid.UUID][]storiface.WorkerJob, error) { return sm.StorageMgr.WorkerJobs(), nil } diff --git a/storage/wdpost_run_test.go b/storage/wdpost_run_test.go index dd7ac4c24..10dfbd281 100644 --- a/storage/wdpost_run_test.go +++ b/storage/wdpost_run_test.go @@ -16,7 +16,6 @@ import ( "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/dline" - "github.com/filecoin-project/go-state-types/network" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" proof0 "github.com/filecoin-project/specs-actors/actors/runtime/proof" @@ -31,6 +30,7 @@ import ( type mockStorageMinerAPI struct { partitions []api.Partition pushedMessages chan *types.Message + storageMinerApi } func newMockStorageMinerAPI() *mockStorageMinerAPI { @@ -46,10 +46,6 @@ func (m *mockStorageMinerAPI) StateMinerInfo(ctx context.Context, a address.Addr }, nil } -func (m *mockStorageMinerAPI) StateNetworkVersion(ctx context.Context, key types.TipSetKey) (network.Version, error) { - panic("implement me") -} - func (m *mockStorageMinerAPI) ChainGetRandomnessFromTickets(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) { return abi.Randomness("ticket rand"), nil } From f933e1d2b7c847dfa733aed0c8d0f1c65d36d02f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sun, 18 Oct 2020 13:03:17 +0200 Subject: [PATCH 162/313] miner cli: Update to uuid worker IDs --- cmd/lotus-storage-miner/sealing.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/cmd/lotus-storage-miner/sealing.go b/cmd/lotus-storage-miner/sealing.go index 8649ad7d4..440d4aaea 100644 --- a/cmd/lotus-storage-miner/sealing.go +++ b/cmd/lotus-storage-miner/sealing.go @@ -75,7 +75,12 @@ var sealingWorkersCmd = &cli.Command{ gpuUse = "" } - fmt.Printf("Worker %s, host %s\n", stat.id, color.MagentaString(stat.Info.Hostname)) + var disabled string + if !stat.Enabled { + disabled = color.RedString(" (disabled)") + } + + fmt.Printf("Worker %s, host %s%s\n", stat.id, color.MagentaString(stat.Info.Hostname), disabled) var barCols = uint64(64) cpuBars := int(stat.CpuUse * barCols / stat.Info.Resources.CPUs) @@ -193,7 +198,14 @@ var sealingJobsCmd = &cli.Command{ dur = time.Now().Sub(l.Start).Truncate(time.Millisecond * 100).String() } - _, _ = fmt.Fprintf(tw, "%s\t%d\t%s\t%s\t%s\t%s\t%s\n", hex.EncodeToString(l.ID.ID[10:]), l.Sector.Number, l.wid, workerHostnames[l.wid], l.Task.Short(), state, dur) + _, _ = fmt.Fprintf(tw, "%s\t%d\t%s\t%s\t%s\t%s\t%s\n", + hex.EncodeToString(l.ID.ID[10:]), + l.Sector.Number, + hex.EncodeToString(l.wid[5:]), + workerHostnames[l.wid], + l.Task.Short(), + state, + dur) } return tw.Flush() From cf4dfa3a051f46afd95a3637ccec79c64b37c6ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sun, 18 Oct 2020 13:59:38 +0200 Subject: [PATCH 163/313] worker: Use http rpc for miner API --- cli/cmd.go | 36 +++++++++++++++++++++++++++++++++-- cmd/lotus-seal-worker/main.go | 7 +------ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/cli/cmd.go b/cli/cmd.go index eef73b241..02ef06002 100644 --- a/cli/cmd.go +++ b/cli/cmd.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "net/http" + "net/url" "os" "os/signal" "strings" @@ -206,7 +207,22 @@ func GetFullNodeAPI(ctx *cli.Context) (api.FullNode, jsonrpc.ClientCloser, error return client.NewFullNodeRPC(ctx.Context, addr, headers) } -func GetStorageMinerAPI(ctx *cli.Context, opts ...jsonrpc.Option) (api.StorageMiner, jsonrpc.ClientCloser, error) { +type GetStorageMinerOptions struct { + PreferHttp bool +} + +type GetStorageMinerOption func(*GetStorageMinerOptions) + +func StorageMinerUseHttp(opts *GetStorageMinerOptions) { + opts.PreferHttp = true +} + +func GetStorageMinerAPI(ctx *cli.Context, opts ...GetStorageMinerOption) (api.StorageMiner, jsonrpc.ClientCloser, error) { + var options GetStorageMinerOptions + for _, opt := range opts { + opt(&options) + } + if tn, ok := ctx.App.Metadata["testnode-storage"]; ok { return tn.(api.StorageMiner), func() {}, nil } @@ -216,7 +232,23 @@ func GetStorageMinerAPI(ctx *cli.Context, opts ...jsonrpc.Option) (api.StorageMi return nil, nil, err } - return client.NewStorageMinerRPC(ctx.Context, addr, headers, opts...) + if options.PreferHttp { + u, err := url.Parse(addr) + if err != nil { + return nil, nil, xerrors.Errorf("parsing miner api URL: %w", err) + } + + switch u.Scheme { + case "ws": + u.Scheme = "http" + case "wss": + u.Scheme = "https" + } + + addr = u.String() + } + + return client.NewStorageMinerRPC(ctx.Context, addr, headers) } func GetWorkerAPI(ctx *cli.Context) (api.WorkerAPI, jsonrpc.ClientCloser, error) { diff --git a/cmd/lotus-seal-worker/main.go b/cmd/lotus-seal-worker/main.go index 3472192e8..454f1efe2 100644 --- a/cmd/lotus-seal-worker/main.go +++ b/cmd/lotus-seal-worker/main.go @@ -176,7 +176,7 @@ var runCmd = &cli.Command{ var closer func() var err error for { - nodeApi, closer, err = lcli.GetStorageMinerAPI(cctx, jsonrpc.WithTimeout(30*time.Second)) + nodeApi, closer, err = lcli.GetStorageMinerAPI(cctx, lcli.StorageMinerUseHttp) if err == nil { break } @@ -457,11 +457,6 @@ var runCmd = &cli.Command{ log.Info("Worker registered successfully, waiting for tasks") - closing, err := nodeApi.Closing(ctx) - if err != nil { - log.Errorf("failed to get remote closing channel: %+v", err) - } - select { case <-closing: case <-ctx.Done(): From 879aa9512daa58a0c518d0c6ade1463e3b7ed3c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sun, 18 Oct 2020 17:56:29 +0200 Subject: [PATCH 164/313] worker: Use miner session for connectivity check --- cmd/lotus-seal-worker/main.go | 58 ++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/cmd/lotus-seal-worker/main.go b/cmd/lotus-seal-worker/main.go index 454f1efe2..5575679dd 100644 --- a/cmd/lotus-seal-worker/main.go +++ b/cmd/lotus-seal-worker/main.go @@ -431,17 +431,33 @@ var runCmd = &cli.Command{ } } + minerSession, err := nodeApi.Session(ctx) + if err != nil { + return xerrors.Errorf("getting miner session: %w", err) + } + go func() { - var reconnect bool + heartbeats := time.NewTicker(stores.HeartbeatInterval) + defer heartbeats.Stop() + + var connected, reconnect bool for { + // If we're reconnecting, redeclare storage first if reconnect { log.Info("Redeclaring local storage") if err := localStore.Redeclare(ctx); err != nil { log.Errorf("Redeclaring local storage failed: %+v", err) - cancel() - return + + select { + case <-ctx.Done(): + return // graceful shutdown + case <-heartbeats.C: + } + continue } + + connected = false } log.Info("Making sure no local tasks are running") @@ -449,21 +465,33 @@ var runCmd = &cli.Command{ // TODO: we could get rid of this, but that requires tracking resources for restarted tasks correctly workerApi.LocalWorker.WaitQuiet() - if err := nodeApi.WorkerConnect(ctx, "http://"+address+"/rpc/v0"); err != nil { - log.Errorf("Registering worker failed: %+v", err) - cancel() - return - } + for { + curSession, err := nodeApi.Session(ctx) + if err != nil { + log.Errorf("heartbeat: checking remote session failed: %+v", err) + } else { + if curSession != minerSession { + minerSession = curSession + break + } - log.Info("Worker registered successfully, waiting for tasks") + if !connected { + if err := nodeApi.WorkerConnect(ctx, "http://"+address+"/rpc/v0"); err != nil { + log.Errorf("Registering worker failed: %+v", err) + cancel() + return + } - select { - case <-closing: - case <-ctx.Done(): - } + log.Info("Worker registered successfully, waiting for tasks") + connected = true + } + } - if ctx.Err() != nil { - return // graceful shutdown + select { + case <-ctx.Done(): + return // graceful shutdown + case <-heartbeats.C: + } } log.Errorf("LOTUS-MINER CONNECTION LOST") From dbb421c4f725dc90c232b6643fc8cfd2762accaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sun, 18 Oct 2020 19:09:13 +0200 Subject: [PATCH 165/313] localworker: Use better context for calling returnFunc --- extern/sector-storage/worker_local.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/extern/sector-storage/worker_local.go b/extern/sector-storage/worker_local.go index 739f70fa0..9733fc76f 100644 --- a/extern/sector-storage/worker_local.go +++ b/extern/sector-storage/worker_local.go @@ -215,10 +215,12 @@ func (l *LocalWorker) asyncCall(ctx context.Context, sector abi.SectorID, rt Ret go func() { defer l.running.Done() - res, err := work(&wctx{ + ctx := &wctx{ vals: ctx, closing: l.closing, - }, ci) + } + + res, err := work(ctx, ci) { rb, err := json.Marshal(res) From 8c86ea6b75acdfe81bd4879a45e18e44eb60cde1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sun, 18 Oct 2020 19:45:11 +0200 Subject: [PATCH 166/313] localworker: Try very hard to get ruselts to manager --- extern/sector-storage/worker_local.go | 47 +++++++++++++++++++-------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/extern/sector-storage/worker_local.go b/extern/sector-storage/worker_local.go index 9733fc76f..ec027b4e2 100644 --- a/extern/sector-storage/worker_local.go +++ b/extern/sector-storage/worker_local.go @@ -92,13 +92,12 @@ func newLocalWorker(executor func() (ffiwrapper.Storage, error), wcfg WorkerConf for _, call := range unfinished { err := xerrors.Errorf("worker restarted") - if err := returnFunc[call.RetType](context.TODO(), call.ID, ret, nil, err); err != nil { - log.Errorf("return error: %s: %+v", call.RetType, err) - continue - } + // TODO: Handle restarting PC1 once support is merged - if err := w.ct.onReturned(call.ID); err != nil { - log.Errorf("marking call as returned failed: %s: %+v", call.RetType, err) + if doReturn(context.TODO(), call.RetType, call.ID, ret, nil, err) { + if err := w.ct.onReturned(call.ID); err != nil { + log.Errorf("marking call as returned failed: %s: %+v", call.RetType, err) + } } } }() @@ -231,22 +230,42 @@ func (l *LocalWorker) asyncCall(ctx context.Context, sector abi.SectorID, rt Ret log.Errorf("tracking call (done): %+v", err) } } - } - if err := returnFunc[rt](ctx, ci, l.ret, res, err); err != nil { - log.Errorf("return error: %s: %+v", rt, err) - return - } - - if err := l.ct.onReturned(ci); err != nil { - log.Errorf("tracking call (done): %+v", err) + if doReturn(ctx, rt, ci, l.ret, res, err) { + if err := l.ct.onReturned(ci); err != nil { + log.Errorf("tracking call (done): %+v", err) + } } }() return ci, nil } +// doReturn tries to send the result to manager, returns true if successful +func doReturn(ctx context.Context, rt ReturnType, ci storiface.CallID, ret storiface.WorkerReturn, res interface{}, rerr error) bool { + for { + err := returnFunc[rt](ctx, ci, ret, res, rerr) + if err == nil { + break + } + + log.Errorf("return error, will retry in 5s: %s: %+v", rt, err) + select { + case <-time.After(5 * time.Second): + case <-ctx.Done(): + log.Errorf("failed to return results: %s", ctx.Err()) + + // fine to just return, worker is most likely shutting down, and + // we didn't mark the result as returned yet, so we'll try to + // re-submit it on restart + return false + } + } + + return true +} + func errstr(err error) string { if err != nil { return err.Error() From 1a10f95973caaf7869b100228210aa612c57d49f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sun, 18 Oct 2020 19:53:23 +0200 Subject: [PATCH 167/313] worker: Better miner connectivity check on startup --- cmd/lotus-seal-worker/main.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cmd/lotus-seal-worker/main.go b/cmd/lotus-seal-worker/main.go index 5575679dd..9073c860e 100644 --- a/cmd/lotus-seal-worker/main.go +++ b/cmd/lotus-seal-worker/main.go @@ -172,13 +172,18 @@ var runCmd = &cli.Command{ } // Connect to storage-miner + ctx := lcli.ReqContext(cctx) + var nodeApi api.StorageMiner var closer func() var err error for { nodeApi, closer, err = lcli.GetStorageMinerAPI(cctx, lcli.StorageMinerUseHttp) if err == nil { - break + _, err = nodeApi.Version(ctx) + if err == nil { + break + } } fmt.Printf("\r\x1b[0KConnecting to miner API... (%s)", err) time.Sleep(time.Second) @@ -186,7 +191,6 @@ var runCmd = &cli.Command{ } defer closer() - ctx := lcli.ReqContext(cctx) ctx, cancel := context.WithCancel(ctx) defer cancel() From 268d29222a100fccc8fba0680d1c1b774b0059c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sun, 18 Oct 2020 20:10:39 +0200 Subject: [PATCH 168/313] docsgen --- documentation/en/api-methods.md | 35 +++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index c5bc24b04..74f132d66 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -1,6 +1,7 @@ # Groups * [](#) * [Closing](#Closing) + * [Session](#Session) * [Shutdown](#Shutdown) * [Version](#Version) * [Auth](#Auth) @@ -154,6 +155,7 @@ * [StateMinerPreCommitDepositForPower](#StateMinerPreCommitDepositForPower) * [StateMinerProvingDeadline](#StateMinerProvingDeadline) * [StateMinerRecoveries](#StateMinerRecoveries) + * [StateMinerSectorAllocated](#StateMinerSectorAllocated) * [StateMinerSectorCount](#StateMinerSectorCount) * [StateMinerSectors](#StateMinerSectors) * [StateNetworkName](#StateNetworkName) @@ -207,6 +209,15 @@ Inputs: `null` Response: `{}` +### Session + + +Perms: read + +Inputs: `null` + +Response: `"07070707-0707-0707-0707-070707070707"` + ### Shutdown @@ -3918,6 +3929,30 @@ Response: ] ``` +### StateMinerSectorAllocated +StateMinerSectorAllocated checks if a sector is allocated + + +Perms: read + +Inputs: +```json +[ + "f01234", + 9, + [ + { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + { + "/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve" + } + ] +] +``` + +Response: `true` + ### StateMinerSectorCount StateMinerSectorCount returns the number of sectors in a miner's sector set and proving set From 869d71446d7fe8d5bb31ae587070ed76155db33c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 19 Oct 2020 16:08:33 +0200 Subject: [PATCH 169/313] miner: fix init --create-worker-key --- cmd/lotus-storage-miner/init.go | 35 ++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/cmd/lotus-storage-miner/init.go b/cmd/lotus-storage-miner/init.go index 326a39e5e..baf71a2c7 100644 --- a/cmd/lotus-storage-miner/init.go +++ b/cmd/lotus-storage-miner/init.go @@ -601,8 +601,6 @@ func configureStorageMiner(ctx context.Context, api lapi.FullNode, addr address. } func createStorageMiner(ctx context.Context, api lapi.FullNode, peerid peer.ID, gasPrice types.BigInt, cctx *cli.Context) (address.Address, error) { - log.Info("Creating StorageMarket.CreateStorageMiner message") - var err error var owner address.Address if cctx.String("owner") != "" { @@ -625,9 +623,32 @@ func createStorageMiner(ctx context.Context, api lapi.FullNode, peerid peer.ID, } else if cctx.Bool("create-worker-key") { // TODO: Do we need to force this if owner is Secpk? worker, err = api.WalletNew(ctx, types.KTBLS) } - // TODO: Transfer some initial funds to worker if err != nil { - return address.Undef, err + return address.Address{}, err + } + + // make sure the worker account exists on chain + _, err = api.StateLookupID(ctx, worker, types.EmptyTSK) + if err != nil { + signed, err := api.MpoolPushMessage(ctx, &types.Message{ + From: owner, + To: worker, + Value: types.NewInt(0), + }, nil) + if err != nil { + return address.Undef, xerrors.Errorf("push worker init: %w", err) + } + + log.Infof("Initializing worker account %s, message: %s", worker, signed.Cid()) + log.Infof("Waiting for confirmation") + + mw, err := api.StateWaitMsg(ctx, signed.Cid(), build.MessageConfidence) + if err != nil { + return address.Undef, xerrors.Errorf("waiting for worker init: %w", err) + } + if mw.Receipt.ExitCode != 0 { + return address.Undef, xerrors.Errorf("initializing worker account failed: exit code %d", mw.Receipt.ExitCode) + } } spt, err := ffiwrapper.SealProofTypeFromSectorSize(abi.SectorSize(ssize)) @@ -668,15 +689,15 @@ func createStorageMiner(ctx context.Context, api lapi.FullNode, peerid peer.ID, signed, err := api.MpoolPushMessage(ctx, createStorageMinerMsg, nil) if err != nil { - return address.Undef, err + return address.Undef, xerrors.Errorf("pushing createMiner message: %w", err) } - log.Infof("Pushed StorageMarket.CreateStorageMiner, %s to Mpool", signed.Cid()) + log.Infof("Pushed CreateMiner message: %s", signed.Cid()) log.Infof("Waiting for confirmation") mw, err := api.StateWaitMsg(ctx, signed.Cid(), build.MessageConfidence) if err != nil { - return address.Undef, err + return address.Undef, xerrors.Errorf("waiting for createMiner message: %w", err) } if mw.Receipt.ExitCode != 0 { From d24d3e420d66d4ef2a3f0cd530bbd6ffa21511a1 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Mon, 19 Oct 2020 14:27:04 -0400 Subject: [PATCH 170/313] Fix StateReplay to use provided tipset --- node/impl/full/state.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/node/impl/full/state.go b/node/impl/full/state.go index b2e9c3e51..a6564296b 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -349,6 +349,7 @@ func (a *StateAPI) StateCall(ctx context.Context, msg *types.Message, tsk types. func (a *StateAPI) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid.Cid) (*api.InvocResult, error) { msgToReplay := mc var ts *types.TipSet + var err error if tsk == types.EmptyTSK { mlkp, err := a.StateSearchMsg(ctx, mc) if err != nil { @@ -370,7 +371,10 @@ func (a *StateAPI) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid. return nil, xerrors.Errorf("loading parent tipset %s: %w", mlkp.TipSet, err) } } else { - ts = a.Chain.GetHeaviestTipSet() + ts, err = a.Chain.LoadTipSet(tsk) + if err != nil { + return nil, xerrors.Errorf("loading specified tipset %s: %w", tsk, err) + } } m, r, err := a.StateManager.Replay(ctx, ts, msgToReplay) From 1974490ab05fd005619ea0f1b8eac9802d31ed53 Mon Sep 17 00:00:00 2001 From: Ingar Shu Date: Mon, 19 Oct 2020 13:12:28 -0700 Subject: [PATCH 171/313] Don't overwrite previously-configured maxPieceSize for a persisted ask --- node/modules/storageminer.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index bcc38898e..7f510aa70 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -398,8 +398,6 @@ func NewStorageAsk(ctx helpers.MetricsCtx, fapi lapi.FullNode, ds dtypes.Metadat if err != nil { return nil, err } - a := storedAsk.GetAsk().Ask - err = storedAsk.SetAsk(a.Price, a.VerifiedPrice, a.Expiry-a.Timestamp) if err != nil { return storedAsk, err } From be42dd824b696a1195290348359577753ac7fb15 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Mon, 19 Oct 2020 22:32:05 +0200 Subject: [PATCH 172/313] state: optimize state snapshot address cache Signed-off-by: Jakub Sztandera --- chain/state/statetree.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/chain/state/statetree.go b/chain/state/statetree.go index e9b76ea77..35760fdf9 100644 --- a/chain/state/statetree.go +++ b/chain/state/statetree.go @@ -35,7 +35,8 @@ type StateTree struct { } type stateSnaps struct { - layers []*stateSnapLayer + layers []*stateSnapLayer + lastMaybeNonEmptyResolveCache int } type stateSnapLayer struct { @@ -67,7 +68,12 @@ func (ss *stateSnaps) addLayer() { func (ss *stateSnaps) dropLayer() { ss.layers[len(ss.layers)-1] = nil // allow it to be GCed + ss.layers = ss.layers[:len(ss.layers)-1] + + if ss.lastMaybeNonEmptyResolveCache == len(ss.layers) { + ss.lastMaybeNonEmptyResolveCache = len(ss.layers) - 1 + } } func (ss *stateSnaps) mergeLastLayer() { @@ -86,7 +92,13 @@ func (ss *stateSnaps) mergeLastLayer() { } func (ss *stateSnaps) resolveAddress(addr address.Address) (address.Address, bool) { - for i := len(ss.layers) - 1; i >= 0; i-- { + for i := ss.lastMaybeNonEmptyResolveCache; i >= 0; i-- { + if len(ss.layers[i].resolveCache) == 0 { + if ss.lastMaybeNonEmptyResolveCache == i { + ss.lastMaybeNonEmptyResolveCache = i - 1 + } + continue + } resa, ok := ss.layers[i].resolveCache[addr] if ok { return resa, true @@ -97,6 +109,7 @@ func (ss *stateSnaps) resolveAddress(addr address.Address) (address.Address, boo func (ss *stateSnaps) cacheResolveAddress(addr, resa address.Address) { ss.layers[len(ss.layers)-1].resolveCache[addr] = resa + ss.lastMaybeNonEmptyResolveCache = len(ss.layers) - 1 } func (ss *stateSnaps) getActor(addr address.Address) (*types.Actor, error) { From cb0513f4c1a978f18391dc6a28e0f4bb9051bb67 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Tue, 20 Oct 2020 01:25:41 +0200 Subject: [PATCH 173/313] Add test Signed-off-by: Jakub Sztandera --- chain/state/statetree.go | 50 +++++++++++------- chain/state/statetree_test.go | 98 +++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+), 19 deletions(-) diff --git a/chain/state/statetree.go b/chain/state/statetree.go index 35760fdf9..7fa55b31c 100644 --- a/chain/state/statetree.go +++ b/chain/state/statetree.go @@ -26,10 +26,11 @@ var log = logging.Logger("statetree") // StateTree stores actors state by their ID. type StateTree struct { - root adt.Map - version types.StateTreeVersion - info cid.Cid - Store cbor.IpldStore + root adt.Map + version types.StateTreeVersion + info cid.Cid + Store cbor.IpldStore + lookupIDFun func(address.Address) (address.Address, error) snaps *stateSnaps } @@ -173,13 +174,15 @@ func NewStateTree(cst cbor.IpldStore, ver types.StateTreeVersion) (*StateTree, e return nil, err } - return &StateTree{ + s := &StateTree{ root: root, info: info, version: ver, Store: cst, snaps: newStateSnaps(), - }, nil + } + s.lookupIDFun = s.lookupIDinternal + return s, nil } func LoadStateTree(cst cbor.IpldStore, c cid.Cid) (*StateTree, error) { @@ -203,13 +206,15 @@ func LoadStateTree(cst cbor.IpldStore, c cid.Cid) (*StateTree, error) { return nil, err } - return &StateTree{ + s := &StateTree{ root: nd, info: root.Info, version: root.Version, Store: cst, snaps: newStateSnaps(), - }, nil + } + s.lookupIDFun = s.lookupIDinternal + return s, nil default: return nil, xerrors.Errorf("unsupported state tree version: %d", root.Version) } @@ -226,17 +231,7 @@ func (st *StateTree) SetActor(addr address.Address, act *types.Actor) error { return nil } -// LookupID gets the ID address of this actor's `addr` stored in the `InitActor`. -func (st *StateTree) LookupID(addr address.Address) (address.Address, error) { - if addr.Protocol() == address.ID { - return addr, nil - } - - resa, ok := st.snaps.resolveAddress(addr) - if ok { - return resa, nil - } - +func (st *StateTree) lookupIDinternal(addr address.Address) (address.Address, error) { act, err := st.GetActor(init_.Address) if err != nil { return address.Undef, xerrors.Errorf("getting init actor: %w", err) @@ -254,6 +249,23 @@ func (st *StateTree) LookupID(addr address.Address) (address.Address, error) { if err != nil { return address.Undef, xerrors.Errorf("resolve address %s: %w", addr, err) } + return a, err +} + +// LookupID gets the ID address of this actor's `addr` stored in the `InitActor`. +func (st *StateTree) LookupID(addr address.Address) (address.Address, error) { + if addr.Protocol() == address.ID { + return addr, nil + } + + resa, ok := st.snaps.resolveAddress(addr) + if ok { + return resa, nil + } + a, err := st.lookupIDFun(addr) + if err != nil { + return a, err + } st.snaps.cacheResolveAddress(addr, a) diff --git a/chain/state/statetree_test.go b/chain/state/statetree_test.go index ed1fb1889..584d9ba7e 100644 --- a/chain/state/statetree_test.go +++ b/chain/state/statetree_test.go @@ -73,6 +73,104 @@ func BenchmarkStateTreeSetFlush(b *testing.B) { } } +func TestResolveCache(t *testing.T) { + cst := cbor.NewMemCborStore() + st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion)) + if err != nil { + t.Fatal(err) + } + nonId := address.NewForTestGetter()() + id, _ := address.NewIDAddress(1000) + + st.lookupIDFun = func(a address.Address) (address.Address, error) { + if a == nonId { + return id, nil + } else { + return address.Undef, types.ErrActorNotFound + } + } + + err = st.SetActor(nonId, &types.Actor{Nonce: 1}) + if err != nil { + t.Fatal(err) + } + + { + err = st.Snapshot(context.TODO()) + if err != nil { + t.Fatal(err) + } + act, err := st.GetActor(nonId) + if err != nil { + t.Fatal(err) + } + if act.Nonce != 1 { + t.Fatalf("expected nonce 1, got %d", act.Nonce) + } + err = st.SetActor(nonId, &types.Actor{Nonce: 2}) + if err != nil { + t.Fatal(err) + } + + act, err = st.GetActor(nonId) + if err != nil { + t.Fatal(err) + } + if act.Nonce != 2 { + t.Fatalf("expected nonce 2, got %d", act.Nonce) + } + + if err := st.Revert(); err != nil { + t.Fatal(err) + } + st.ClearSnapshot() + } + + act, err := st.GetActor(nonId) + if err != nil { + t.Fatal(err) + } + if act.Nonce != 1 { + t.Fatalf("expected nonce 1, got %d", act.Nonce) + } + + { + err = st.Snapshot(context.TODO()) + if err != nil { + t.Fatal(err) + } + act, err := st.GetActor(nonId) + if err != nil { + t.Fatal(err) + } + if act.Nonce != 1 { + t.Fatalf("expected nonce 1, got %d", act.Nonce) + } + err = st.SetActor(nonId, &types.Actor{Nonce: 2}) + if err != nil { + t.Fatal(err) + } + + act, err = st.GetActor(nonId) + if err != nil { + t.Fatal(err) + } + if act.Nonce != 2 { + t.Fatalf("expected nonce 2, got %d", act.Nonce) + } + st.ClearSnapshot() + } + + act, err = st.GetActor(nonId) + if err != nil { + t.Fatal(err) + } + if act.Nonce != 2 { + t.Fatalf("expected nonce 2, got %d", act.Nonce) + } + +} + func BenchmarkStateTree10kGetActor(b *testing.B) { cst := cbor.NewMemCborStore() st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion)) From a055540c254d13648031d5f873acb653d71c06f5 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Tue, 20 Oct 2020 01:32:51 +0200 Subject: [PATCH 174/313] Fix lint Signed-off-by: Jakub Sztandera --- chain/state/statetree_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/chain/state/statetree_test.go b/chain/state/statetree_test.go index 584d9ba7e..61e7d8c22 100644 --- a/chain/state/statetree_test.go +++ b/chain/state/statetree_test.go @@ -85,9 +85,8 @@ func TestResolveCache(t *testing.T) { st.lookupIDFun = func(a address.Address) (address.Address, error) { if a == nonId { return id, nil - } else { - return address.Undef, types.ErrActorNotFound } + return address.Undef, types.ErrActorNotFound } err = st.SetActor(nonId, &types.Actor{Nonce: 1}) From 1ee9fb44e237da3490115eba8aea97a7a03f4eb7 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Sat, 17 Oct 2020 19:06:12 -0400 Subject: [PATCH 175/313] Lotus version 1.0.0 --- CHANGELOG.md | 31 +++++++++++++++++++++++++++++++ build/version.go | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 701f221b0..76aa51de2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,36 @@ # Lotus changelog +# 1.0.0 / 2020-10-19 + +It's 1.0.0! This is an optional release of Lotus that introduces some UX improvements to the 0.10 series. + +This very small release is largely cosmetic, and intended to flag the code that the Filecoin mainnet was launched with. + +## API changes + +- `StateMsgGasCost` has been removed. The equivalent information can be gained by calling `StateReplay`. +- A `GasCost` field has been added to the `InvocResult` type, meaning detailed gas costs will be returned when calling `StateReplay`, `StateCompute`, and `StateCall`. +- The behaviour of `StateReplay` in response to an empty tipset key has been changed. Instead of simply using the heaviest tipset (which is almost guaranteed to be an unsuccessful replay), we search now search the chain for the tipset that included the message, and replay the message in that tipset (we fail if no such tipset is found). + +## Changes + +- Increase code coverage! (https://github.com/filecoin-project/lotus/pull/4410) +- Mpool: Don't block node startup loading messages (https://github.com/filecoin-project/lotus/pull/4411) +- Improve the UX of multisig approves (https://github.com/filecoin-project/lotus/pull/4398) +- Use build.BlockDelaySecs for deal start buffer (https://github.com/filecoin-project/lotus/pull/4415) +- Conformance: support multiple protocol versions (https://github.com/filecoin-project/lotus/pull/4393) +- Ensure msig inspect cli works with lotus-lite (https://github.com/filecoin-project/lotus/pull/4421) +- Add command to (slowly) prune lotus chain datastore (https://github.com/filecoin-project/lotus/pull/3876) +- Add WalletVerify to lotus-gateway (https://github.com/filecoin-project/lotus/pull/4373) +- Improve StateMsg APIs (https://github.com/filecoin-project/lotus/pull/4429) +- Add endpoints needed by spacegap (https://github.com/filecoin-project/lotus/pull/4426) +- Make audit balances capable of printing robust addresses (https://github.com/filecoin-project/lotus/pull/4423) +- Custom filters for retrieval deals (https://github.com/filecoin-project/lotus/pull/4424) +- Fix message list api (https://github.com/filecoin-project/lotus/pull/4422) +- Replace bootstrap peers (https://github.com/filecoin-project/lotus/pull/4447) +- Don't overwrite previously-configured maxPieceSize for a persisted ask (https://github.com/filecoin-project/lotus/pull/4480) +- State: optimize state snapshot address cache (https://github.com/filecoin-project/lotus/pull/4481) + # 0.10.2 / 2020-10-14 This is an optional release of Lotus that updates markets to 0.9.1, which fixes an issue affecting deals that were mid-transfer when the node was upgraded to 0.9.0. This release also includes some tweaks to default gas values and minor performance improvements. diff --git a/build/version.go b/build/version.go index df1fe28de..352fa9b0e 100644 --- a/build/version.go +++ b/build/version.go @@ -29,7 +29,7 @@ func buildType() string { } // BuildVersion is the local build version, set by build system -const BuildVersion = "0.10.2" +const BuildVersion = "1.0.0" func UserVersion() string { return BuildVersion + buildType() + CurrentCommit From 608010c35deffb4e82b1928c8b4e1c70fe2273be Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Mon, 19 Oct 2020 19:09:49 -0700 Subject: [PATCH 176/313] add some extra logging to try and debug sync issues --- chain/sync.go | 5 +++-- chain/sync_manager.go | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/chain/sync.go b/chain/sync.go index 97915d8df..2c7408113 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -268,14 +268,15 @@ func (syncer *Syncer) InformNewHead(from peer.ID, fts *store.FullTipSet) bool { syncer.Exchange.AddPeer(from) - bestPweight := syncer.store.GetHeaviestTipSet().ParentWeight() + hts := syncer.store.GetHeaviestTipSet() + bestPweight := hts.ParentWeight() targetWeight := fts.TipSet().ParentWeight() if targetWeight.LessThan(bestPweight) { var miners []string for _, blk := range fts.TipSet().Blocks() { miners = append(miners, blk.Miner.String()) } - log.Infof("incoming tipset from %s does not appear to be better than our best chain, ignoring for now", miners) + log.Infow("incoming tipset does not appear to be better than our best chain, ignoring for now", "miners", miners, "bestPweight", bestPweight, "bestTS", hts.Cids(), "incomingWeight", targetWeight, "incomingTS", fts.TipSet().Cids()) return false } diff --git a/chain/sync_manager.go b/chain/sync_manager.go index c7fdea726..17cec78d7 100644 --- a/chain/sync_manager.go +++ b/chain/sync_manager.go @@ -257,6 +257,7 @@ func (stb *syncTargetBucket) add(ts *types.TipSet) { func (stb *syncTargetBucket) heaviestTipSet() *types.TipSet { if stb == nil { + log.Warn("sync target bucket was nil when heaviestTipSet got called on it") return nil } From e7a68dba58d7583c0d3e337a8e0794d5d29773c4 Mon Sep 17 00:00:00 2001 From: jennijuju Date: Tue, 20 Oct 2020 02:28:43 -0400 Subject: [PATCH 177/313] Add a comment to BlockMessages to address #4446. --- api/api_full.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/api_full.go b/api/api_full.go index 772a0d709..57ca5bcfd 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -591,6 +591,8 @@ type MsgGasCost struct { TotalCost abi.TokenAmount } +// BlsMessages[x].cid = Cids[x] +// SecpkMessages[y].cid = Cids[BlsMessages.length + y] type BlockMessages struct { BlsMessages []*types.Message SecpkMessages []*types.SignedMessage From 09e92f98fff1651b70c00854f9b9adf09b010c0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 20 Oct 2020 12:52:52 +0200 Subject: [PATCH 178/313] circle: Run tests for some subsystems separately --- .circleci/config.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index acd447f69..f82008e9b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -188,6 +188,14 @@ jobs: command: | bash <(curl -s https://codecov.io/bash) + test-chain: + <<: *test + test-node: + <<: *test + test-storage: + <<: *test + test-cli: + <<: *test test-short: <<: *test test-window-post: @@ -428,6 +436,22 @@ workflows: - test: codecov-upload: true test-suite-name: full + - test-chain: + codecov-upload: true + test-suite-name: chain + packages: "./chain/..." + - test-node: + codecov-upload: true + test-suite-name: node + packages: "./node/..." + - test-storage: + codecov-upload: true + test-suite-name: storage + packages: "./storage/... ./extern/..." + - test-cli: + codecov-upload: true + test-suite-name: cli + packages: "./cli/... ./cmd/... ./api/..." - test-window-post: go-test-flags: "-run=TestWindowedPost" winpost-test: "1" From ee0078f7c16110c2211a823827fae1792005da1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 20 Oct 2020 13:21:42 +0200 Subject: [PATCH 179/313] make: Drop npm calls from buildall --- Makefile | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 79f7fa81e..093f62ef6 100644 --- a/Makefile +++ b/Makefile @@ -133,18 +133,30 @@ benchmarks: lotus-pond: 2k go build -o lotus-pond ./lotuspond - (cd lotuspond/front && npm i && CI=false npm run build) .PHONY: lotus-pond BINS+=lotus-pond +lotus-pond-front: + (cd lotuspond/front && npm i && CI=false npm run build) +.PHONY: lotus-pond-front + +lotus-pond-app: lotus-pond-front lotus-pond +.PHONY: lotus-pond-app + lotus-townhall: rm -f lotus-townhall go build -o lotus-townhall ./cmd/lotus-townhall - (cd ./cmd/lotus-townhall/townhall && npm i && npm run build) - go run github.com/GeertJohan/go.rice/rice append --exec lotus-townhall -i ./cmd/lotus-townhall -i ./build .PHONY: lotus-townhall BINS+=lotus-townhall +lotus-townhall-front: + (cd ./cmd/lotus-townhall/townhall && npm i && npm run build) +.PHONY: lotus-townhall-front + +lotus-townhall-app: lotus-touch lotus-townhall-front + go run github.com/GeertJohan/go.rice/rice append --exec lotus-townhall -i ./cmd/lotus-townhall -i ./build +.PHONY: lotus-townhall-app + lotus-fountain: rm -f lotus-fountain go build -o lotus-fountain ./cmd/lotus-fountain From 580980d149906644606dc54c2f10fc0ee23477ae Mon Sep 17 00:00:00 2001 From: vyzo Date: Tue, 20 Oct 2020 19:13:17 +0300 Subject: [PATCH 180/313] make push and addLocal atomic --- chain/messagepool/messagepool.go | 65 ++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index cc26be0b5..79ab572ba 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -432,9 +432,14 @@ func (mp *MessagePool) runLoop() { } } -func (mp *MessagePool) addLocal(m *types.SignedMessage, msgb []byte) error { +func (mp *MessagePool) addLocal(m *types.SignedMessage) error { mp.localAddrs[m.Message.From] = struct{}{} + msgb, err := m.Serialize() + if err != nil { + return xerrors.Errorf("error serializing message: %w", err) + } + if err := mp.localMsgs.Put(datastore.NewKey(string(m.Cid().Bytes())), msgb); err != nil { return xerrors.Errorf("persisting local message: %w", err) } @@ -507,11 +512,6 @@ func (mp *MessagePool) Push(m *types.SignedMessage) (cid.Cid, error) { <-mp.addSema }() - msgb, err := m.Serialize() - if err != nil { - return cid.Undef, err - } - mp.curTsLk.Lock() publish, err := mp.addTs(m, mp.curTs, true, false) if err != nil { @@ -520,18 +520,19 @@ func (mp *MessagePool) Push(m *types.SignedMessage) (cid.Cid, error) { } mp.curTsLk.Unlock() - mp.lk.Lock() - if err := mp.addLocal(m, msgb); err != nil { - mp.lk.Unlock() - return cid.Undef, err - } - mp.lk.Unlock() - if publish { + msgb, err := m.Serialize() + if err != nil { + return cid.Undef, xerrors.Errorf("error serializing message: %w", err) + } + err = mp.api.PubSubPublish(build.MessagesTopic(mp.netName), msgb) + if err != nil { + return cid.Undef, xerrors.Errorf("error publishing message: %w", err) + } } - return m.Cid(), err + return m.Cid(), nil } func (mp *MessagePool) checkMessage(m *types.SignedMessage) error { @@ -670,7 +671,19 @@ func (mp *MessagePool) addTs(m *types.SignedMessage, curTs *types.TipSet, local, return false, err } - return publish, mp.addLocked(m, !local, untrusted) + err = mp.addLocked(m, !local, untrusted) + if err != nil { + return false, err + } + + if local { + err = mp.addLocal(m) + if err != nil { + return false, xerrors.Errorf("error persisting local message: %w", err) + } + } + + return publish, nil } func (mp *MessagePool) addLoaded(m *types.SignedMessage) error { @@ -837,11 +850,6 @@ func (mp *MessagePool) PushUntrusted(m *types.SignedMessage) (cid.Cid, error) { <-mp.addSema }() - msgb, err := m.Serialize() - if err != nil { - return cid.Undef, err - } - mp.curTsLk.Lock() publish, err := mp.addTs(m, mp.curTs, false, true) if err != nil { @@ -850,18 +858,19 @@ func (mp *MessagePool) PushUntrusted(m *types.SignedMessage) (cid.Cid, error) { } mp.curTsLk.Unlock() - mp.lk.Lock() - if err := mp.addLocal(m, msgb); err != nil { - mp.lk.Unlock() - return cid.Undef, err - } - mp.lk.Unlock() - if publish { + msgb, err := m.Serialize() + if err != nil { + return cid.Undef, xerrors.Errorf("error serializing message: %w", err) + } + err = mp.api.PubSubPublish(build.MessagesTopic(mp.netName), msgb) + if err != nil { + return cid.Undef, xerrors.Errorf("error publishing message: %w", err) + } } - return m.Cid(), err + return m.Cid(), nil } func (mp *MessagePool) Remove(from address.Address, nonce uint64, applied bool) { From 6bc56c549a16b470f2019c743393fdf818cd2e47 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Tue, 20 Oct 2020 10:04:51 -0700 Subject: [PATCH 181/313] add some methods that oni needs --- cmd/lotus-gateway/api.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/cmd/lotus-gateway/api.go b/cmd/lotus-gateway/api.go index 105f8881e..a0febef2c 100644 --- a/cmd/lotus-gateway/api.go +++ b/cmd/lotus-gateway/api.go @@ -10,6 +10,7 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/dline" + "github.com/filecoin-project/go-state-types/network" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" @@ -33,6 +34,8 @@ var ( // gatewayDepsAPI defines the API methods that the GatewayAPI depends on // (to make it easy to mock for tests) type gatewayDepsAPI interface { + Version(context.Context) (api.Version, error) + ChainHasObj(context.Context, cid.Cid) (bool, error) ChainHead(ctx context.Context) (*types.TipSet, error) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) @@ -57,6 +60,7 @@ type gatewayDepsAPI interface { StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*dline.Info, error) StateCirculatingSupply(context.Context, types.TipSetKey) (abi.TokenAmount, error) StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (api.CirculatingSupply, error) + StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error) } type GatewayAPI struct { @@ -114,6 +118,10 @@ func (a *GatewayAPI) checkTimestamp(at time.Time) error { return nil } +func (a *GatewayAPI) Version(ctx context.Context) (api.Version, error) { + return a.api.Version(ctx) +} + func (a *GatewayAPI) ChainHasObj(ctx context.Context, c cid.Cid) (bool, error) { return a.api.ChainHasObj(ctx, c) } @@ -295,6 +303,13 @@ func (a *GatewayAPI) StateVMCirculatingSupplyInternal(ctx context.Context, tsk t return a.api.StateVMCirculatingSupplyInternal(ctx, tsk) } +func (a *GatewayAPI) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (network.Version, error) { + if err := a.checkTipsetKey(ctx, tsk); err != nil { + return 0, err + } + return a.api.StateNetworkVersion(ctx, tsk) +} + func (a *GatewayAPI) WalletVerify(ctx context.Context, k address.Address, msg []byte, sig *crypto.Signature) (bool, error) { return sigs.Verify(sig, k, msg) == nil, nil } From abc3e783ffc3cdf04dc9c2b4748930829e31e898 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Tue, 20 Oct 2020 10:09:21 -0700 Subject: [PATCH 182/313] bump lookback cap to 24 hours --- cmd/lotus-gateway/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/lotus-gateway/api.go b/cmd/lotus-gateway/api.go index a0febef2c..7fc004327 100644 --- a/cmd/lotus-gateway/api.go +++ b/cmd/lotus-gateway/api.go @@ -23,7 +23,7 @@ import ( ) const ( - LookbackCap = time.Hour * 12 + LookbackCap = time.Hour * 24 stateWaitLookbackLimit = abi.ChainEpoch(20) ) From dc40469cb3edbb32f9d7815a3fb5cbd676feed48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 20 Oct 2020 21:54:19 +0200 Subject: [PATCH 183/313] Miner finder for interactive client deal CLI --- cli/client.go | 498 ++++++++++++++++++++++++++++++++++++++++---------- go.mod | 1 + go.sum | 3 + 3 files changed, 406 insertions(+), 96 deletions(-) diff --git a/cli/client.go b/cli/client.go index 7035fb64b..01de8801c 100644 --- a/cli/client.go +++ b/cli/client.go @@ -1,19 +1,25 @@ package cli import ( + "bufio" "context" "encoding/json" "errors" "fmt" "io" + "math/rand" "os" "path/filepath" "sort" "strconv" + "strings" + "sync" + "sync/atomic" "text/tabwriter" "time" tm "github.com/buger/goterm" + "github.com/chzyer/readline" "github.com/docker/go-units" "github.com/fatih/color" datatransfer "github.com/filecoin-project/go-data-transfer" @@ -74,6 +80,7 @@ var clientCmd = &cli.Command{ WithCategory("storage", clientQueryAskCmd), WithCategory("storage", clientListDeals), WithCategory("storage", clientGetDealCmd), + WithCategory("storage", clientListAsksCmd), WithCategory("data", clientImportCmd), WithCategory("data", clientDropCmd), WithCategory("data", clientLocalCmd), @@ -468,16 +475,26 @@ func interactiveDeal(cctx *cli.Context) error { } defer closer() ctx := ReqContext(cctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() state := "import" + gib := types.NewInt(1 << 30) var data cid.Cid var days int - var maddr address.Address - var ask storagemarket.StorageAsk - var epochPrice big.Int + var maddrs []address.Address + var ask []storagemarket.StorageAsk + var epochPrices []big.Int + var dur time.Duration var epochs abi.ChainEpoch var verified bool + var ds lapi.DataSize + + // find + var candidateAsks []*storagemarket.StorageAsk + var budget types.FIL + var dealCount int64 var a address.Address if from := cctx.String("from"); from != "" { @@ -494,10 +511,24 @@ func interactiveDeal(cctx *cli.Context) error { a = def } + fromBal, err := api.WalletBalance(ctx, a) + if err != nil { + return xerrors.Errorf("checking from address balance: %w", err) + } + printErr := func(err error) { fmt.Printf("%s %s\n", color.RedString("Error:"), err.Error()) } + cs := readline.NewCancelableStdin(os.Stdin) + go func() { + <-ctx.Done() + cs.Close() // nolint:errcheck + }() + + rl := bufio.NewReader(cs) + +uiLoop: for { // TODO: better exit handling if err := ctx.Err(); err != nil { @@ -508,8 +539,8 @@ func interactiveDeal(cctx *cli.Context) error { case "import": fmt.Print("Data CID (from " + color.YellowString("lotus client import") + "): ") - var cidStr string - _, err := fmt.Scan(&cidStr) + _cidStr, _, err := rl.ReadLine() + cidStr := string(_cidStr) if err != nil { printErr(xerrors.Errorf("reading cid string: %w", err)) continue @@ -521,11 +552,23 @@ func interactiveDeal(cctx *cli.Context) error { continue } + color.Blue(".. calculating data size\n") + ds, err = api.ClientDealSize(ctx, data) + if err != nil { + return err + } + state = "duration" case "duration": fmt.Print("Deal duration (days): ") - _, err := fmt.Scan(&days) + _daystr, _, err := rl.ReadLine() + daystr := string(_daystr) + if err != nil { + return err + } + + _, err = fmt.Sscan(daystr, &days) if err != nil { printErr(xerrors.Errorf("parsing duration: %w", err)) continue @@ -536,44 +579,9 @@ func interactiveDeal(cctx *cli.Context) error { continue } - state = "miner" - case "miner": - fmt.Print("Miner Address (f0..): ") - var maddrStr string + dur = 24 * time.Hour * time.Duration(days) + epochs = abi.ChainEpoch(dur / (time.Duration(build.BlockDelaySecs) * time.Second)) - _, err := fmt.Scan(&maddrStr) - if err != nil { - printErr(xerrors.Errorf("reading miner address: %w", err)) - continue - } - - maddr, err = address.NewFromString(maddrStr) - if err != nil { - printErr(xerrors.Errorf("parsing miner address: %w", err)) - continue - } - - state = "query" - case "query": - color.Blue(".. querying miner ask") - - mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK) - if err != nil { - printErr(xerrors.Errorf("failed to get peerID for miner: %w", err)) - state = "miner" - continue - } - - a, err := api.ClientQueryAsk(ctx, *mi.PeerId, maddr) - if err != nil { - printErr(xerrors.Errorf("failed to query ask: %w", err)) - state = "miner" - continue - } - - ask = *a - - // TODO: run more validation state = "verified" case "verified": ts, err := api.ChainHead(ctx) @@ -587,26 +595,20 @@ func interactiveDeal(cctx *cli.Context) error { } if dcap == nil { - state = "confirm" + state = "miner" continue } - color.Blue(".. checking verified deal eligibility\n") - ds, err := api.ClientDealSize(ctx, data) - if err != nil { - return err - } - if dcap.Uint64() < uint64(ds.PieceSize) { color.Yellow(".. not enough DataCap available for a verified deal\n") - state = "confirm" + state = "miner" continue } fmt.Print("\nMake this a verified deal? (yes/no): ") - var yn string - _, err = fmt.Scan(&yn) + _yn, _, err := rl.ReadLine() + yn := string(_yn) if err != nil { return err } @@ -621,34 +623,162 @@ func interactiveDeal(cctx *cli.Context) error { continue } - state = "confirm" - case "confirm": - fromBal, err := api.WalletBalance(ctx, a) + state = "miner" + case "miner": + fmt.Print("Miner Addresses (f0.. f0..), none to find: ") + + _maddrsStr, _, err := rl.ReadLine() + maddrsStr := string(_maddrsStr) if err != nil { - return xerrors.Errorf("checking from address balance: %w", err) + printErr(xerrors.Errorf("reading miner address: %w", err)) + continue } - color.Blue(".. calculating data size\n") - ds, err := api.ClientDealSize(ctx, data) + for _, s := range strings.Fields(maddrsStr) { + maddr, err := address.NewFromString(strings.TrimSpace(s)) + if err != nil { + printErr(xerrors.Errorf("parsing miner address: %w", err)) + continue uiLoop + } + + maddrs = append(maddrs, maddr) + } + + state = "query" + if len(maddrs) == 0 { + state = "find" + } + case "find": + asks, err := getAsks(ctx, api) if err != nil { return err } - dur := 24 * time.Hour * time.Duration(days) - - epochs = abi.ChainEpoch(dur / (time.Duration(build.BlockDelaySecs) * time.Second)) - // TODO: do some more or epochs math (round to miner PP, deal start buffer) - - pricePerGib := ask.Price - if verified { - pricePerGib = ask.VerifiedPrice + for _, ask := range asks { + if ask.MinPieceSize > ds.PieceSize { + continue + } + if ask.MaxPieceSize < ds.PieceSize { + continue + } + candidateAsks = append(candidateAsks, ask) } - gib := types.NewInt(1 << 30) + fmt.Printf("Found %d candidate asks\n", len(candidateAsks)) + state = "find-budget" + case "find-budget": + fmt.Printf("Proposing from %s, Current Balance: %s\n", a, types.FIL(fromBal)) + fmt.Print("Maximum budget (FIL): ") // TODO: Propose some default somehow? - // TODO: price is based on PaddedPieceSize, right? - epochPrice = types.BigDiv(types.BigMul(pricePerGib, types.NewInt(uint64(ds.PieceSize))), gib) - totalPrice := types.BigMul(epochPrice, types.NewInt(uint64(epochs))) + _budgetStr, _, err := rl.ReadLine() + budgetStr := string(_budgetStr) + if err != nil { + printErr(xerrors.Errorf("reading miner address: %w", err)) + continue + } + + budget, err = types.ParseFIL(budgetStr) + if err != nil { + printErr(xerrors.Errorf("parsing FIL: %w", err)) + continue uiLoop + } + + var goodAsks []*storagemarket.StorageAsk + for _, ask := range candidateAsks { + p := ask.Price + if verified { + p = ask.VerifiedPrice + } + + epochPrice := types.BigDiv(types.BigMul(p, types.NewInt(uint64(ds.PieceSize))), gib) + totalPrice := types.BigMul(epochPrice, types.NewInt(uint64(epochs))) + + if totalPrice.LessThan(abi.TokenAmount(budget)) { + goodAsks = append(goodAsks, ask) + } + } + candidateAsks = goodAsks + fmt.Printf("%d asks within budget\n", len(candidateAsks)) + state = "find-count" + case "find-count": + fmt.Print("Deals to make (1): ") + dealcStr, _, err := rl.ReadLine() + if err != nil { + printErr(xerrors.Errorf("reading deal count: %w", err)) + continue + } + + dealCount, err = strconv.ParseInt(string(dealcStr), 10, 64) + if err != nil { + return err + } + + color.Blue(".. Picking miners") + + // TODO: some better strategy (this tries to pick randomly) + var pickedAsks []*storagemarket.StorageAsk + pickLoop: + for i := 0; i < 64; i++ { + rand.Shuffle(len(candidateAsks), func(i, j int) { + candidateAsks[i], candidateAsks[j] = candidateAsks[j], candidateAsks[i] + }) + + remainingBudget := abi.TokenAmount(budget) + pickedAsks = []*storagemarket.StorageAsk{} + + for _, ask := range candidateAsks { + p := ask.Price + if verified { + p = ask.VerifiedPrice + } + + epochPrice := types.BigDiv(types.BigMul(p, types.NewInt(uint64(ds.PieceSize))), gib) + totalPrice := types.BigMul(epochPrice, types.NewInt(uint64(epochs))) + + if totalPrice.GreaterThan(remainingBudget) { + continue + } + + pickedAsks = append(pickedAsks, ask) + remainingBudget = big.Sub(remainingBudget, totalPrice) + + if len(pickedAsks) == int(dealCount) { + break pickLoop + } + } + } + + for _, pickedAsk := range pickedAsks { + maddrs = append(maddrs, pickedAsk.Miner) + ask = append(ask, *pickedAsk) + } + + state = "confirm" + case "query": + color.Blue(".. querying miner asks") + + for _, maddr := range maddrs { + mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK) + if err != nil { + printErr(xerrors.Errorf("failed to get peerID for miner: %w", err)) + state = "miner" + continue uiLoop + } + + a, err := api.ClientQueryAsk(ctx, *mi.PeerId, maddr) + if err != nil { + printErr(xerrors.Errorf("failed to query ask: %w", err)) + state = "miner" + continue uiLoop + } + + ask = append(ask, *a) + } + + // TODO: run more validation + state = "confirm" + case "confirm": + // TODO: do some more or epochs math (round to miner PP, deal start buffer) fmt.Printf("-----\n") fmt.Printf("Proposing from %s\n", a) @@ -656,15 +786,41 @@ func interactiveDeal(cctx *cli.Context) error { fmt.Printf("\n") fmt.Printf("Piece size: %s (Payload size: %s)\n", units.BytesSize(float64(ds.PieceSize)), units.BytesSize(float64(ds.PayloadSize))) fmt.Printf("Duration: %s\n", dur) - fmt.Printf("Total price: ~%s (%s per epoch)\n", types.FIL(totalPrice), types.FIL(epochPrice)) + + pricePerGib := big.Zero() + for _, a := range ask { + p := a.Price + if verified { + p = a.VerifiedPrice + } + pricePerGib = big.Add(pricePerGib, p) + epochPrice := types.BigDiv(types.BigMul(p, types.NewInt(uint64(ds.PieceSize))), gib) + epochPrices = append(epochPrices, epochPrice) + + mpow, err := api.StateMinerPower(ctx, a.Miner, types.EmptyTSK) + if err != nil { + return xerrors.Errorf("getting power (%s): %w", a.Miner, err) + } + + if len(ask) > 1 { + totalPrice := types.BigMul(epochPrice, types.NewInt(uint64(epochs))) + fmt.Printf("Miner %s (Power:%s) price: ~%s (%s per epoch)\n", color.YellowString(a.Miner.String()), color.GreenString(types.SizeStr(mpow.MinerPower.QualityAdjPower)), color.BlueString(types.FIL(totalPrice).String()), types.FIL(epochPrice)) + } + } + + // TODO: price is based on PaddedPieceSize, right? + epochPrice := types.BigDiv(types.BigMul(pricePerGib, types.NewInt(uint64(ds.PieceSize))), gib) + totalPrice := types.BigMul(epochPrice, types.NewInt(uint64(epochs))) + + fmt.Printf("Total price: ~%s (%s per epoch)\n", color.CyanString(types.FIL(totalPrice).String()), types.FIL(epochPrice)) fmt.Printf("Verified: %v\n", verified) state = "accept" case "accept": fmt.Print("\nAccept (yes/no): ") - var yn string - _, err := fmt.Scan(&yn) + _yn, _, err := rl.ReadLine() + yn := string(_yn) if err != nil { return err } @@ -680,30 +836,34 @@ func interactiveDeal(cctx *cli.Context) error { state = "execute" case "execute": - color.Blue(".. executing") - proposal, err := api.ClientStartDeal(ctx, &lapi.StartDealParams{ - Data: &storagemarket.DataRef{ - TransferType: storagemarket.TTGraphsync, - Root: data, - }, - Wallet: a, - Miner: maddr, - EpochPrice: epochPrice, - MinBlocksDuration: uint64(epochs), - DealStartEpoch: abi.ChainEpoch(cctx.Int64("start-epoch")), - FastRetrieval: cctx.Bool("fast-retrieval"), - VerifiedDeal: verified, - }) - if err != nil { - return err + color.Blue(".. executing\n") + + for i, maddr := range maddrs { + proposal, err := api.ClientStartDeal(ctx, &lapi.StartDealParams{ + Data: &storagemarket.DataRef{ + TransferType: storagemarket.TTGraphsync, + Root: data, + }, + Wallet: a, + Miner: maddr, + EpochPrice: epochPrices[i], + MinBlocksDuration: uint64(epochs), + DealStartEpoch: abi.ChainEpoch(cctx.Int64("start-epoch")), + FastRetrieval: cctx.Bool("fast-retrieval"), + VerifiedDeal: verified, + }) + if err != nil { + return err + } + + encoder, err := GetCidEncoder(cctx) + if err != nil { + return err + } + + fmt.Printf("Deal (%s) CID: %s\n", maddr, color.GreenString(encoder.Encode(*proposal))) } - encoder, err := GetCidEncoder(cctx) - if err != nil { - return err - } - - fmt.Println("\nDeal CID:", color.GreenString(encoder.Encode(*proposal))) return nil default: return xerrors.Errorf("unknown state: %s", state) @@ -944,6 +1104,152 @@ var clientRetrieveCmd = &cli.Command{ }, } +var clientListAsksCmd = &cli.Command{ + Name: "list-asks", + Usage: "List asks for top miners", + Action: func(cctx *cli.Context) error { + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + asks, err := getAsks(ctx, api) + if err != nil { + return err + } + + for _, ask := range asks { + fmt.Printf("%s: min:%s max:%s price:%s/GiB/Epoch verifiedPrice:%s/GiB/Epoch\n", ask.Miner, + types.SizeStr(types.NewInt(uint64(ask.MinPieceSize))), + types.SizeStr(types.NewInt(uint64(ask.MaxPieceSize))), + types.FIL(ask.Price), + types.FIL(ask.VerifiedPrice), + ) + } + + return nil + }, +} + +func getAsks(ctx context.Context, api lapi.FullNode) ([]*storagemarket.StorageAsk, error) { + color.Blue(".. getting miner list") + miners, err := api.StateListMiners(ctx, types.EmptyTSK) + if err != nil { + return nil, xerrors.Errorf("getting miner list: %w", err) + } + + var lk sync.Mutex + var found int64 + var withMinPower []address.Address + done := make(chan struct{}) + + go func() { + defer close(done) + + var wg sync.WaitGroup + wg.Add(len(miners)) + + throttle := make(chan struct{}, 50) + for _, miner := range miners { + throttle <- struct{}{} + go func(miner address.Address) { + defer wg.Done() + defer func() { + <-throttle + }() + + power, err := api.StateMinerPower(ctx, miner, types.EmptyTSK) + if err != nil { + return + } + + if power.HasMinPower { // TODO: Lower threshold + atomic.AddInt64(&found, 1) + lk.Lock() + withMinPower = append(withMinPower, miner) + lk.Unlock() + } + }(miner) + } + }() + +loop: + for { + select { + case <-time.After(150 * time.Millisecond): + fmt.Printf("\r* Found %d miners with power", atomic.LoadInt64(&found)) + case <-done: + break loop + } + } + fmt.Printf("\r* Found %d miners with power\n", atomic.LoadInt64(&found)) + + color.Blue(".. querying asks") + + var asks []*storagemarket.StorageAsk + var queried, got int64 + + done = make(chan struct{}) + go func() { + defer close(done) + + var wg sync.WaitGroup + wg.Add(len(withMinPower)) + + throttle := make(chan struct{}, 50) + for _, miner := range withMinPower { + throttle <- struct{}{} + go func(miner address.Address) { + defer wg.Done() + defer func() { + <-throttle + atomic.AddInt64(&queried, 1) + }() + + ctx, cancel := context.WithTimeout(ctx, 4*time.Second) + defer cancel() + + mi, err := api.StateMinerInfo(ctx, miner, types.EmptyTSK) + if err != nil { + return + } + if mi.PeerId == nil { + return + } + + ask, err := api.ClientQueryAsk(ctx, *mi.PeerId, miner) + if err != nil { + return + } + + atomic.AddInt64(&got, 1) + lk.Lock() + asks = append(asks, ask) + lk.Unlock() + }(miner) + } + }() + +loop2: + for { + select { + case <-time.After(150 * time.Millisecond): + fmt.Printf("\r* Queried %d asks, got %d responses", atomic.LoadInt64(&queried), atomic.LoadInt64(&got)) + case <-done: + break loop2 + } + } + fmt.Printf("\r* Queried %d asks, got %d responses\n", atomic.LoadInt64(&queried), atomic.LoadInt64(&got)) + + sort.Slice(asks, func(i, j int) bool { + return asks[i].Price.LessThan(asks[j].Price) + }) + + return asks, nil +} + var clientQueryAskCmd = &cli.Command{ Name: "query-ask", Usage: "Find a miners ask", diff --git a/go.mod b/go.mod index a6a074e49..b648523d1 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129 + github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e github.com/cockroachdb/pebble v0.0.0-20200916222308-4e219a90ba5b github.com/coreos/go-systemd/v22 v22.0.0 github.com/detailyang/go-fallocate v0.0.0-20180908115635-432fa640bd2e diff --git a/go.sum b/go.sum index 4cf7b3628..b7a717c18 100644 --- a/go.sum +++ b/go.sum @@ -120,8 +120,11 @@ github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= +github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= From e08032da93b9cc4efa3eb139ec0443fe99bdb53f Mon Sep 17 00:00:00 2001 From: hannahhoward Date: Tue, 20 Oct 2020 13:56:13 -0700 Subject: [PATCH 184/313] feat(markets): update markets v1.0.0 --- go.mod | 4 ++-- go.sum | 10 ++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index a6a074e49..35b627415 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 github.com/filecoin-project/go-data-transfer v0.9.0 github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f - github.com/filecoin-project/go-fil-markets v0.9.1 + github.com/filecoin-project/go-fil-markets v1.0.0 github.com/filecoin-project/go-jsonrpc v0.1.2-0.20201008195726-68c6a2704e49 github.com/filecoin-project/go-multistore v0.0.3 github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20 @@ -66,7 +66,7 @@ require ( github.com/ipfs/go-ds-pebble v0.0.2-0.20200921225637-ce220f8ac459 github.com/ipfs/go-filestore v1.0.0 github.com/ipfs/go-fs-lock v0.0.6 - github.com/ipfs/go-graphsync v0.3.0 + github.com/ipfs/go-graphsync v0.3.1 github.com/ipfs/go-ipfs-blockstore v1.0.1 github.com/ipfs/go-ipfs-chunker v0.0.5 github.com/ipfs/go-ipfs-ds-help v1.0.0 diff --git a/go.sum b/go.sum index 4cf7b3628..991a6c5a2 100644 --- a/go.sum +++ b/go.sum @@ -246,8 +246,8 @@ github.com/filecoin-project/go-ds-versioning v0.1.0 h1:y/X6UksYTsK8TLCI7rttCKEvl github.com/filecoin-project/go-ds-versioning v0.1.0/go.mod h1:mp16rb4i2QPmxBnmanUx8i/XANp+PFCCJWiAb+VW4/s= github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f h1:GxJzR3oRIMTPtpZ0b7QF8FKPK6/iPAc7trhlL5k/g+s= github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= -github.com/filecoin-project/go-fil-markets v0.9.1 h1:MgO+UkpreD6x8DV2Zkw2xlBogixfpw9/wf4+nBii7bU= -github.com/filecoin-project/go-fil-markets v0.9.1/go.mod h1:h+bJ/IUnYjnW5HMKyt9JQSnhslqetkpuzwwugc3K8vM= +github.com/filecoin-project/go-fil-markets v1.0.0 h1:np9+tlnWXh9xYG4oZfha6HZFLYOaAZoMGR3V4w6DM48= +github.com/filecoin-project/go-fil-markets v1.0.0/go.mod h1:lXExJyYHwpMMddCqhEdNrc7euYJKNkp04K76NZqJLGg= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= @@ -376,6 +376,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -540,6 +542,8 @@ github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28 github.com/ipfs/go-graphsync v0.1.0/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CEGevngQbmE= github.com/ipfs/go-graphsync v0.3.0 h1:I6Y20kSuCWkUvPoUWo4V3am704/9QjgDVVkf0zIV8+8= github.com/ipfs/go-graphsync v0.3.0/go.mod h1:gEBvJUNelzMkaRPJTpg/jaKN4AQW/7wDWu0K92D8o10= +github.com/ipfs/go-graphsync v0.3.1 h1:dJLYrck4oyJDfMVhGEKiWHxaY8oYMWko4m2Fi+4bofo= +github.com/ipfs/go-graphsync v0.3.1/go.mod h1:bw4LiLM5Oq/uLdzEtih9LK8GrwSijv+XqYiWCTxHMqs= github.com/ipfs/go-hamt-ipld v0.1.1 h1:0IQdvwnAAUKmDE+PMJa5y1QiwOPHpI9+eAbQEEEYthk= github.com/ipfs/go-hamt-ipld v0.1.1/go.mod h1:1EZCr2v0jlCnhpa+aZ0JZYp8Tt2w16+JJOAVz17YcDk= github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= @@ -1818,6 +1822,8 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 556f92a8235e1b608a5842324693856d08deb26a Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Fri, 16 Oct 2020 20:35:46 -0400 Subject: [PATCH 185/313] Update to actors v2.2.0 at PostLiftoff epoch --- build/params_2k.go | 2 ++ build/params_mainnet.go | 3 +++ build/params_shared_vals.go | 2 +- build/params_testground.go | 1 + chain/stmgr/forks.go | 4 ++++ cmd/tvx/codenames.go | 1 + documentation/en/api-methods.md | 2 +- go.mod | 4 ++-- go.sum | 8 ++++---- 9 files changed, 19 insertions(+), 8 deletions(-) diff --git a/build/params_2k.go b/build/params_2k.go index b09b60fae..5a0e8fd61 100644 --- a/build/params_2k.go +++ b/build/params_2k.go @@ -22,6 +22,8 @@ const UpgradeTapeHeight = -4 var UpgradeActorsV2Height = abi.ChainEpoch(10) var UpgradeLiftoffHeight = abi.ChainEpoch(-5) +const UpgradeKumquatHeight = -6 + var DrandSchedule = map[abi.ChainEpoch]DrandEnum{ 0: DrandMainnet, } diff --git a/build/params_mainnet.go b/build/params_mainnet.go index 54f50ac6e..9d5c48ff6 100644 --- a/build/params_mainnet.go +++ b/build/params_mainnet.go @@ -37,6 +37,9 @@ const UpgradeTapeHeight = 140760 // We still have upgrades and state changes to do, but can happen after signaling timing here. const UpgradeLiftoffHeight = 148888 +// TODO: Confirm epoch +const UpgradeKumquatHeight = 170000 + func init() { policy.SetConsensusMinerMinPower(abi.NewStoragePower(10 << 40)) policy.SetSupportedProofTypes( diff --git a/build/params_shared_vals.go b/build/params_shared_vals.go index ede40c0e3..b80472594 100644 --- a/build/params_shared_vals.go +++ b/build/params_shared_vals.go @@ -25,7 +25,7 @@ const UnixfsLinksPerLevel = 1024 // Consensus / Network const AllowableClockDriftSecs = uint64(1) -const NewestNetworkVersion = network.Version5 +const NewestNetworkVersion = network.Version6 const ActorUpgradeNetworkVersion = network.Version4 // Epochs diff --git a/build/params_testground.go b/build/params_testground.go index 7ef034234..beee1c727 100644 --- a/build/params_testground.go +++ b/build/params_testground.go @@ -86,6 +86,7 @@ var ( UpgradeTapeHeight abi.ChainEpoch = -4 UpgradeActorsV2Height abi.ChainEpoch = 10 UpgradeLiftoffHeight abi.ChainEpoch = -5 + UpgradeKumquatHeight abi.ChainEpoch = -6 DrandSchedule = map[abi.ChainEpoch]DrandEnum{ 0: DrandMainnet, diff --git a/chain/stmgr/forks.go b/chain/stmgr/forks.go index 488f84167..5d6cac51f 100644 --- a/chain/stmgr/forks.go +++ b/chain/stmgr/forks.go @@ -86,6 +86,10 @@ func DefaultUpgradeSchedule() UpgradeSchedule { Height: build.UpgradeLiftoffHeight, Network: network.Version5, Migration: UpgradeLiftoff, + }, { + Height: build.UpgradeKumquatHeight, + Network: network.Version6, + Migration: nil, }} if build.UpgradeActorsV2Height == math.MaxInt64 { // disable actors upgrade diff --git a/cmd/tvx/codenames.go b/cmd/tvx/codenames.go index 851e9d841..b9f590914 100644 --- a/cmd/tvx/codenames.go +++ b/cmd/tvx/codenames.go @@ -23,6 +23,7 @@ var ProtocolCodenames = []struct { {build.UpgradeActorsV2Height + 1, "actorsv2"}, {build.UpgradeTapeHeight + 1, "tape"}, {build.UpgradeLiftoffHeight + 1, "liftoff"}, + {build.UpgradeKumquatHeight + 1, "postliftoff"}, } // GetProtocolCodename gets the protocol codename associated with a height. diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index c5bc24b04..3aeb6c096 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -4004,7 +4004,7 @@ Inputs: ] ``` -Response: `5` +Response: `6` ### StateReadState StateReadState returns the indicated actor's state. diff --git a/go.mod b/go.mod index 35b627415..cb8d5d3f3 100644 --- a/go.mod +++ b/go.mod @@ -34,12 +34,12 @@ require ( github.com/filecoin-project/go-multistore v0.0.3 github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20 github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261 - github.com/filecoin-project/go-state-types v0.0.0-20201003010437-c33112184a2b + github.com/filecoin-project/go-state-types v0.0.0-20201013222834-41ea465f274f github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe github.com/filecoin-project/go-statestore v0.1.0 github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b github.com/filecoin-project/specs-actors v0.9.12 - github.com/filecoin-project/specs-actors/v2 v2.1.0 + github.com/filecoin-project/specs-actors/v2 v2.2.0 github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796 github.com/filecoin-project/test-vectors/schema v0.0.5 github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1 diff --git a/go.sum b/go.sum index 991a6c5a2..37694572c 100644 --- a/go.sum +++ b/go.sum @@ -266,8 +266,8 @@ github.com/filecoin-project/go-state-types v0.0.0-20200903145444-247639ffa6ad/go github.com/filecoin-project/go-state-types v0.0.0-20200904021452-1883f36ca2f4/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I= github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab h1:cEDC5Ei8UuT99hPWhCjA72SM9AuRtnpvdSTIYbnzN8I= github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= -github.com/filecoin-project/go-state-types v0.0.0-20201003010437-c33112184a2b h1:bMUfG6Sy6YSMbsjQAO1Q2vEZldbSdsbRy/FX3OlTck0= -github.com/filecoin-project/go-state-types v0.0.0-20201003010437-c33112184a2b/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= +github.com/filecoin-project/go-state-types v0.0.0-20201013222834-41ea465f274f h1:TZDTu4MtBKSFLXWGKLy+cvC3nHfMFIrVgWLAz/+GgZQ= +github.com/filecoin-project/go-state-types v0.0.0-20201013222834-41ea465f274f/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe h1:dF8u+LEWeIcTcfUcCf3WFVlc81Fr2JKg8zPzIbBDKDw= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= github.com/filecoin-project/go-statestore v0.1.0 h1:t56reH59843TwXHkMcwyuayStBIiWBRilQjQ+5IiwdQ= @@ -278,8 +278,8 @@ github.com/filecoin-project/specs-actors v0.9.4/go.mod h1:BStZQzx5x7TmCkLv0Bpa07 github.com/filecoin-project/specs-actors v0.9.12 h1:iIvk58tuMtmloFNHhAOQHG+4Gci6Lui0n7DYQGi3cJk= github.com/filecoin-project/specs-actors v0.9.12/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= github.com/filecoin-project/specs-actors/v2 v2.0.1/go.mod h1:v2NZVYinNIKA9acEMBm5wWXxqv5+frFEbekBFemYghY= -github.com/filecoin-project/specs-actors/v2 v2.1.0 h1:ocEuGz8DG2cUWw32c/tvF8D6xT+dGVWJTr5yDevU00g= -github.com/filecoin-project/specs-actors/v2 v2.1.0/go.mod h1:E7fAX4CZkDVQvDNRCxfq+hc3nx56KcCKyuZf0hlQJ20= +github.com/filecoin-project/specs-actors/v2 v2.2.0 h1:IyCICb0NHYeD0sdSqjVGwWydn/7r7xXuxdpvGAcRCGY= +github.com/filecoin-project/specs-actors/v2 v2.2.0/go.mod h1:rlv5Mx9wUhV8Qsz+vUezZNm+zL4tK08O0HreKKPB2Wc= github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796 h1:dJsTPWpG2pcTeojO2pyn0c6l+x/3MZYCBgo/9d11JEk= github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= From 277d3e9ab43daf23d5c833761472997df57387a9 Mon Sep 17 00:00:00 2001 From: jennijuju Date: Tue, 20 Oct 2020 17:19:42 -0400 Subject: [PATCH 186/313] Add terminate sectors based on 1475's #4433 implementation in lotus-shed: - Moving the cmd to lotus-shed so that miners can use this right away without waiting for fsm changes.- Note: this should only be used when the miner is 100% sure that they want to terminate the sector on chain and they will be lose the power and pay a big one-time termination penalty for the sectors. - Only live sectors can be terminated. - To use, run `./lotus-shed sectors terminate --really-do-it=true sectorNum1 sectorNum2`. - A message will be sent and after the message is landed on chain, miner can run `lotus-miner sectors status --on-chain-info `, and check Expiration Info at the bottom. Both `OnTime` and `Early` are 0 indicates the sector is terminated. --- cmd/lotus-shed/main.go | 1 + cmd/lotus-shed/sectors.go | 121 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 cmd/lotus-shed/sectors.go diff --git a/cmd/lotus-shed/main.go b/cmd/lotus-shed/main.go index 29a105355..987118f46 100644 --- a/cmd/lotus-shed/main.go +++ b/cmd/lotus-shed/main.go @@ -42,6 +42,7 @@ func main() { stateTreePruneCmd, datastoreCmd, ledgerCmd, + sectorsCmd, } app := &cli.App{ diff --git a/cmd/lotus-shed/sectors.go b/cmd/lotus-shed/sectors.go new file mode 100644 index 000000000..45af36118 --- /dev/null +++ b/cmd/lotus-shed/sectors.go @@ -0,0 +1,121 @@ +package main + +import ( + "fmt" + "github.com/filecoin-project/go-bitfield" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/big" + "github.com/filecoin-project/lotus/chain/actors" + "golang.org/x/xerrors" + "strconv" + + "github.com/filecoin-project/lotus/chain/types" + lcli "github.com/filecoin-project/lotus/cli" + "github.com/filecoin-project/specs-actors/actors/builtin" + miner0 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" + "github.com/urfave/cli/v2" +) + +var sectorsCmd = &cli.Command{ + Name: "sectors", + Usage: "Tools for interacting with sectors", + Flags: []cli.Flag{}, + Subcommands: []*cli.Command{ + terminateSectorCmd, + }, +} + +var terminateSectorCmd = &cli.Command{ + Name: "terminate", + Usage: "Forcefully terminate a sector (WARNING: This means losing power and pay a one-time termination penalty(including collateral) for the terminated sector)", + ArgsUsage: "[sectorNum1 sectorNum2 ...]", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "really-do-it", + Usage: "pass this flag if you know what you are doing", + }, + }, + Action: func(cctx *cli.Context) error { + if cctx.Args().Len() < 1 { + return fmt.Errorf("at least one sector must be specified") + } + + if !cctx.Bool("really-do-it") { + return fmt.Errorf("this is a command for advanced users, only use it if you are sure of what you are doing") + } + + nodeApi, closer, err := lcli.GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + + api, acloser, err := lcli.GetStorageMinerAPI(cctx) + if err != nil { + return err + } + defer acloser() + + ctx := lcli.ReqContext(cctx) + + maddr, err := api.ActorAddress(ctx) + if err != nil { + return err + } + + mi, err := nodeApi.StateMinerInfo(ctx, maddr, types.EmptyTSK) + if err != nil { + return err + } + + terminationDeclarationParams := []miner0.TerminationDeclaration{} + + for _, sn := range cctx.Args().Slice() { + sectorNum, err := strconv.ParseUint(sn, 10, 64) + if err != nil { + return fmt.Errorf("could not parse sector number: %w", err) + } + + sectorbit := bitfield.New() + sectorbit.Set(sectorNum) + + loca, err := nodeApi.StateSectorPartition(ctx, maddr, abi.SectorNumber(sectorNum), types.EmptyTSK) + if err != nil { + return fmt.Errorf("get state sector partition %s", err) + } + + para := miner0.TerminationDeclaration{ + Deadline: loca.Deadline, + Partition: loca.Partition, + Sectors: sectorbit, + } + + terminationDeclarationParams = append(terminationDeclarationParams, para) + } + + terminateSectorParams := &miner0.TerminateSectorsParams{ + Terminations: terminationDeclarationParams, + } + + sp, err := actors.SerializeParams(terminateSectorParams) + if err != nil { + return xerrors.Errorf("serializing params: %w", err) + } + + smsg, err := nodeApi.MpoolPushMessage(ctx, &types.Message{ + From: mi.Owner, + To: maddr, + Method: builtin.MethodsMiner.TerminateSectors, + + Value: big.Zero(), + Params: sp, + }, nil) + if err != nil { + return xerrors.Errorf("mpool push message: %w", err) + } + + fmt.Println("Message CID:", smsg.Cid()) + + return nil + }, +} From ed1645109af83e2b6492a8435e955d468c8217b4 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 20 Oct 2020 14:16:32 -0700 Subject: [PATCH 187/313] Add lotus storage miner API support to lotus-shed --- cmd/lotus-shed/main.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cmd/lotus-shed/main.go b/cmd/lotus-shed/main.go index 987118f46..5acaa3218 100644 --- a/cmd/lotus-shed/main.go +++ b/cmd/lotus-shed/main.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "os" logging "github.com/ipfs/go-log/v2" @@ -57,6 +58,13 @@ func main() { Hidden: true, Value: "~/.lotus", // TODO: Consider XDG_DATA_HOME }, + &cli.StringFlag{ + Name: "miner-repo", + Aliases: []string{"storagerepo"}, + EnvVars: []string{"LOTUS_MINER_PATH", "LOTUS_STORAGE_PATH"}, + Value: "~/.lotusminer", // TODO: Consider XDG_DATA_HOME + Usage: fmt.Sprintf("Specify miner repo path. flag storagerepo and env LOTUS_STORAGE_PATH are DEPRECATION, will REMOVE SOON"), + }, &cli.StringFlag{ Name: "log-level", Value: "info", From 65304319957d7ede184336cffdcc3c8eeb50bce8 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Tue, 20 Oct 2020 23:54:35 +0200 Subject: [PATCH 188/313] MinerGetBaseInfo: if miner is not found in lookback, check current If miner is found in current state, just return nil base info as miner cannot mine if he is not found in the lookback. Signed-off-by: Jakub Sztandera --- chain/stmgr/utils.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index de4f947df..d573f385b 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -461,12 +461,21 @@ func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcs beacon.Schedule return nil, xerrors.Errorf("getting lookback miner actor state: %w", err) } + // TODO: load the state instead of computing it? lbst, _, err := sm.TipSetState(ctx, lbts) if err != nil { return nil, err } act, err := sm.LoadActorRaw(ctx, maddr, lbst) + if xerrors.Is(err, types.ErrActorNotFound) { + _, err := sm.LoadActor(ctx, maddr, ts) + if err != nil { + return nil, xerrors.Errorf("loading miner in current state: %w", err) + } + + return nil, nil + } if err != nil { return nil, xerrors.Errorf("failed to load miner actor: %w", err) } From 7f46ad19ac0b2b471362b30d18230452d7e674f4 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Mon, 19 Oct 2020 13:26:07 -0400 Subject: [PATCH 189/313] VM: Enforce a call depth limit --- build/params_mainnet.go | 1 - chain/actors/version.go | 2 +- chain/gen/genesis/miners.go | 2 +- chain/vm/runtime.go | 1 + chain/vm/vm.go | 42 ++++++++++++++++++++----------------- 5 files changed, 26 insertions(+), 22 deletions(-) diff --git a/build/params_mainnet.go b/build/params_mainnet.go index 9d5c48ff6..71e96e614 100644 --- a/build/params_mainnet.go +++ b/build/params_mainnet.go @@ -37,7 +37,6 @@ const UpgradeTapeHeight = 140760 // We still have upgrades and state changes to do, but can happen after signaling timing here. const UpgradeLiftoffHeight = 148888 -// TODO: Confirm epoch const UpgradeKumquatHeight = 170000 func init() { diff --git a/chain/actors/version.go b/chain/actors/version.go index 2efd903bb..fe16d521e 100644 --- a/chain/actors/version.go +++ b/chain/actors/version.go @@ -18,7 +18,7 @@ func VersionForNetwork(version network.Version) Version { switch version { case network.Version0, network.Version1, network.Version2, network.Version3: return Version0 - case network.Version4, network.Version5: + case network.Version4, network.Version5, network.Version6: return Version2 default: panic(fmt.Sprintf("unsupported network version %d", version)) diff --git a/chain/gen/genesis/miners.go b/chain/gen/genesis/miners.go index 1023e5efa..6f0c136a3 100644 --- a/chain/gen/genesis/miners.go +++ b/chain/gen/genesis/miners.go @@ -405,7 +405,7 @@ func circSupply(ctx context.Context, vmi *vm.VM, maddr address.Address) abi.Toke rt := unsafeVM.MakeRuntime(ctx, &types.Message{ GasLimit: 1_000_000_000, From: maddr, - }, maddr, 0, 0, 0) + }) return rt.TotalFilCircSupply() } diff --git a/chain/vm/runtime.go b/chain/vm/runtime.go index 8f124247c..ed5501fe9 100644 --- a/chain/vm/runtime.go +++ b/chain/vm/runtime.go @@ -72,6 +72,7 @@ type Runtime struct { originNonce uint64 executionTrace types.ExecutionTrace + depth uint64 numActorsCreated uint64 allowInternal bool callerValidated bool diff --git a/chain/vm/vm.go b/chain/vm/vm.go index 72ad731aa..a7aa05719 100644 --- a/chain/vm/vm.go +++ b/chain/vm/vm.go @@ -38,6 +38,8 @@ import ( "github.com/filecoin-project/lotus/lib/bufbstore" ) +const MaxCallDepth = 4096 + var log = logging.Logger("vm") var actorLog = logging.Logger("actors") var gasOnActorExec = newGasCharge("OnActorExec", 0, 0) @@ -97,24 +99,37 @@ func (bs *gasChargingBlocks) Put(blk block.Block) error { return nil } -func (vm *VM) makeRuntime(ctx context.Context, msg *types.Message, origin address.Address, originNonce uint64, usedGas int64, nac uint64) *Runtime { +func (vm *VM) makeRuntime(ctx context.Context, msg *types.Message, parent *Runtime) *Runtime { rt := &Runtime{ ctx: ctx, vm: vm, state: vm.cstate, - origin: origin, - originNonce: originNonce, + origin: msg.From, + originNonce: msg.Nonce, height: vm.blockHeight, - gasUsed: usedGas, + gasUsed: 0, gasAvailable: msg.GasLimit, - numActorsCreated: nac, + depth: 0, + numActorsCreated: 0, pricelist: PricelistByEpoch(vm.blockHeight), allowInternal: true, callerValidated: false, executionTrace: types.ExecutionTrace{Msg: msg}, } + if parent != nil { + rt.gasUsed = parent.gasUsed + rt.origin = parent.origin + rt.originNonce = parent.originNonce + rt.numActorsCreated = parent.numActorsCreated + rt.depth = parent.depth + 1 + } + + if rt.depth > MaxCallDepth && rt.NetworkVersion() >= network.Version6 { + rt.Abortf(exitcode.SysErrForbidden, "message execution exceeds call depth") + } + rt.cst = &cbor.BasicIpldStore{ Blocks: &gasChargingBlocks{rt.chargeGasFunc(2), rt.pricelist, vm.cst.Blocks}, Atlas: vm.cst.Atlas, @@ -148,8 +163,8 @@ type UnsafeVM struct { VM *VM } -func (vm *UnsafeVM) MakeRuntime(ctx context.Context, msg *types.Message, origin address.Address, originNonce uint64, usedGas int64, nac uint64) *Runtime { - return vm.VM.makeRuntime(ctx, msg, origin, originNonce, usedGas, nac) +func (vm *UnsafeVM) MakeRuntime(ctx context.Context, msg *types.Message) *Runtime { + return vm.VM.makeRuntime(ctx, msg, nil) } type CircSupplyCalculator func(context.Context, abi.ChainEpoch, *state.StateTree) (abi.TokenAmount, error) @@ -224,18 +239,7 @@ func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime, st := vm.cstate - origin := msg.From - on := msg.Nonce - var nac uint64 = 0 - var gasUsed int64 - if parent != nil { - gasUsed = parent.gasUsed - origin = parent.origin - on = parent.originNonce - nac = parent.numActorsCreated - } - - rt := vm.makeRuntime(ctx, msg, origin, on, gasUsed, nac) + rt := vm.makeRuntime(ctx, msg, parent) if EnableGasTracing { rt.lastGasChargeTime = start if parent != nil { From ee5dcbc1d825081558f2f89841fe7ef7a5615da4 Mon Sep 17 00:00:00 2001 From: jennijuju Date: Tue, 20 Oct 2020 18:26:17 -0400 Subject: [PATCH 190/313] Add wait message --- cmd/lotus-shed/sectors.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/cmd/lotus-shed/sectors.go b/cmd/lotus-shed/sectors.go index 45af36118..11e678642 100644 --- a/cmd/lotus-shed/sectors.go +++ b/cmd/lotus-shed/sectors.go @@ -2,12 +2,13 @@ package main import ( "fmt" + "strconv" + "github.com/filecoin-project/go-bitfield" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/lotus/chain/actors" "golang.org/x/xerrors" - "strconv" "github.com/filecoin-project/lotus/chain/types" lcli "github.com/filecoin-project/lotus/cli" @@ -114,7 +115,16 @@ var terminateSectorCmd = &cli.Command{ return xerrors.Errorf("mpool push message: %w", err) } - fmt.Println("Message CID:", smsg.Cid()) + fmt.Println("sent termination message:", smsg.Cid()) + + wait, err := nodeApi.StateWaitMsg(ctx, smsg.Cid(), uint64(cctx.Int("confidence"))) + if err != nil { + return err + } + + if wait.Receipt.ExitCode != 0 { + return fmt.Errorf("terminate sectors message returned exit %d", wait.Receipt.ExitCode) + } return nil }, From d78dd42ed471bc7f1fe1dff3a51d13de115a5020 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Tue, 20 Oct 2020 17:29:17 -0400 Subject: [PATCH 191/313] Lotus version 1.1.0 --- CHANGELOG.md | 13 +++++++++++++ build/version.go | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76aa51de2..c21ffb685 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Lotus changelog +# 1.1.0 / 2020-10-20 + +This is a mandatory release that introduces the first post-liftoff upgrade to the Filecoin network. The changes that break consensus are an upgrade to specs-actors v2.2.0 at epoch 170000. + +## Changes + +- Introduce Network version 6 (https://github.com/filecoin-project/lotus/pull/4506) +- Update markets v1.0.0 (https://github.com/filecoin-project/lotus/pull/4505) +- Add some extra logging to try and debug sync issues (https://github.com/filecoin-project/lotus/pull/4486) +- Circle: Run tests for some subsystems separately (https://github.com/filecoin-project/lotus/pull/4496) +- Add a terminate sectors command to lotus-shed (https://github.com/filecoin-project/lotus/pull/4507) +- Add a comment to BlockMessages to address #4446 (https://github.com/filecoin-project/lotus/pull/4491) + # 1.0.0 / 2020-10-19 It's 1.0.0! This is an optional release of Lotus that introduces some UX improvements to the 0.10 series. diff --git a/build/version.go b/build/version.go index 352fa9b0e..2d01526b9 100644 --- a/build/version.go +++ b/build/version.go @@ -29,7 +29,7 @@ func buildType() string { } // BuildVersion is the local build version, set by build system -const BuildVersion = "1.0.0" +const BuildVersion = "1.1.0" func UserVersion() string { return BuildVersion + buildType() + CurrentCommit From 00dcb1bce94e1bef65608525457adf656e56cf1d Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 20 Oct 2020 18:30:56 -0700 Subject: [PATCH 192/313] Manage sectors by size instead of proof type. * We may have multiple sectors with the same size and different proof types, but all these management functions stay the same. * This simplifies PoSt logic. --- api/apistruct/struct.go | 32 +++++++++++----------- build/version.go | 2 +- extern/sector-storage/faults.go | 8 +++--- extern/sector-storage/localworker.go | 14 ++++++++-- extern/sector-storage/manager.go | 2 +- extern/sector-storage/manager_test.go | 2 +- extern/sector-storage/mock/mock.go | 2 +- extern/sector-storage/roprov.go | 7 ++++- extern/sector-storage/selector_alloc.go | 7 ++++- extern/sector-storage/selector_existing.go | 7 ++++- extern/sector-storage/stores/filetype.go | 7 +---- extern/sector-storage/stores/index.go | 12 ++++---- extern/sector-storage/stores/interface.go | 4 +-- extern/sector-storage/stores/local.go | 19 +++++-------- extern/sector-storage/stores/remote.go | 14 +++++----- storage/wdpost_run.go | 7 +---- storage/wdpost_run_test.go | 2 +- 17 files changed, 78 insertions(+), 70 deletions(-) diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index e302aa8dc..547373e71 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -300,18 +300,18 @@ type StorageMinerStruct struct { SealingSchedDiag func(context.Context) (interface{}, error) `perm:"admin"` - StorageList func(context.Context) (map[stores.ID][]stores.Decl, error) `perm:"admin"` - StorageLocal func(context.Context) (map[stores.ID]string, error) `perm:"admin"` - StorageStat func(context.Context, stores.ID) (fsutil.FsStat, error) `perm:"admin"` - StorageAttach func(context.Context, stores.StorageInfo, fsutil.FsStat) error `perm:"admin"` - StorageDeclareSector func(context.Context, stores.ID, abi.SectorID, stores.SectorFileType, bool) error `perm:"admin"` - StorageDropSector func(context.Context, stores.ID, abi.SectorID, stores.SectorFileType) error `perm:"admin"` - StorageFindSector func(context.Context, abi.SectorID, stores.SectorFileType, abi.RegisteredSealProof, bool) ([]stores.SectorStorageInfo, error) `perm:"admin"` - StorageInfo func(context.Context, stores.ID) (stores.StorageInfo, error) `perm:"admin"` - StorageBestAlloc func(ctx context.Context, allocate stores.SectorFileType, spt abi.RegisteredSealProof, sealing stores.PathType) ([]stores.StorageInfo, error) `perm:"admin"` - StorageReportHealth func(ctx context.Context, id stores.ID, report stores.HealthReport) error `perm:"admin"` - StorageLock func(ctx context.Context, sector abi.SectorID, read stores.SectorFileType, write stores.SectorFileType) error `perm:"admin"` - StorageTryLock func(ctx context.Context, sector abi.SectorID, read stores.SectorFileType, write stores.SectorFileType) (bool, error) `perm:"admin"` + StorageList func(context.Context) (map[stores.ID][]stores.Decl, error) `perm:"admin"` + StorageLocal func(context.Context) (map[stores.ID]string, error) `perm:"admin"` + StorageStat func(context.Context, stores.ID) (fsutil.FsStat, error) `perm:"admin"` + StorageAttach func(context.Context, stores.StorageInfo, fsutil.FsStat) error `perm:"admin"` + StorageDeclareSector func(context.Context, stores.ID, abi.SectorID, stores.SectorFileType, bool) error `perm:"admin"` + StorageDropSector func(context.Context, stores.ID, abi.SectorID, stores.SectorFileType) error `perm:"admin"` + StorageFindSector func(context.Context, abi.SectorID, stores.SectorFileType, abi.SectorSize, bool) ([]stores.SectorStorageInfo, error) `perm:"admin"` + StorageInfo func(context.Context, stores.ID) (stores.StorageInfo, error) `perm:"admin"` + StorageBestAlloc func(ctx context.Context, allocate stores.SectorFileType, ssize abi.SectorSize, sealing stores.PathType) ([]stores.StorageInfo, error) `perm:"admin"` + StorageReportHealth func(ctx context.Context, id stores.ID, report stores.HealthReport) error `perm:"admin"` + StorageLock func(ctx context.Context, sector abi.SectorID, read stores.SectorFileType, write stores.SectorFileType) error `perm:"admin"` + StorageTryLock func(ctx context.Context, sector abi.SectorID, read stores.SectorFileType, write stores.SectorFileType) (bool, error) `perm:"admin"` DealsImportData func(ctx context.Context, dealPropCid cid.Cid, file string) error `perm:"write"` DealsList func(ctx context.Context) ([]api.MarketDeal, error) `perm:"read"` @@ -1203,8 +1203,8 @@ func (c *StorageMinerStruct) StorageDropSector(ctx context.Context, storageId st return c.Internal.StorageDropSector(ctx, storageId, s, ft) } -func (c *StorageMinerStruct) StorageFindSector(ctx context.Context, si abi.SectorID, types stores.SectorFileType, spt abi.RegisteredSealProof, allowFetch bool) ([]stores.SectorStorageInfo, error) { - return c.Internal.StorageFindSector(ctx, si, types, spt, allowFetch) +func (c *StorageMinerStruct) StorageFindSector(ctx context.Context, si abi.SectorID, types stores.SectorFileType, ssize abi.SectorSize, allowFetch bool) ([]stores.SectorStorageInfo, error) { + return c.Internal.StorageFindSector(ctx, si, types, ssize, allowFetch) } func (c *StorageMinerStruct) StorageList(ctx context.Context) (map[stores.ID][]stores.Decl, error) { @@ -1223,8 +1223,8 @@ func (c *StorageMinerStruct) StorageInfo(ctx context.Context, id stores.ID) (sto return c.Internal.StorageInfo(ctx, id) } -func (c *StorageMinerStruct) StorageBestAlloc(ctx context.Context, allocate stores.SectorFileType, spt abi.RegisteredSealProof, pt stores.PathType) ([]stores.StorageInfo, error) { - return c.Internal.StorageBestAlloc(ctx, allocate, spt, pt) +func (c *StorageMinerStruct) StorageBestAlloc(ctx context.Context, allocate stores.SectorFileType, ssize abi.SectorSize, pt stores.PathType) ([]stores.StorageInfo, error) { + return c.Internal.StorageBestAlloc(ctx, allocate, ssize, pt) } func (c *StorageMinerStruct) StorageReportHealth(ctx context.Context, id stores.ID, report stores.HealthReport) error { diff --git a/build/version.go b/build/version.go index 2d01526b9..b8941cb7a 100644 --- a/build/version.go +++ b/build/version.go @@ -84,7 +84,7 @@ func VersionForType(nodeType NodeType) (Version, error) { // semver versions of the rpc api exposed var ( FullAPIVersion = newVer(0, 17, 0) - MinerAPIVersion = newVer(0, 15, 0) + MinerAPIVersion = newVer(0, 16, 0) WorkerAPIVersion = newVer(0, 15, 0) ) diff --git a/extern/sector-storage/faults.go b/extern/sector-storage/faults.go index 31a1a3690..6a4be200f 100644 --- a/extern/sector-storage/faults.go +++ b/extern/sector-storage/faults.go @@ -14,14 +14,14 @@ import ( // FaultTracker TODO: Track things more actively type FaultTracker interface { - CheckProvable(ctx context.Context, spt abi.RegisteredSealProof, sectors []abi.SectorID) ([]abi.SectorID, error) + CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []abi.SectorID) ([]abi.SectorID, error) } // CheckProvable returns unprovable sectors -func (m *Manager) CheckProvable(ctx context.Context, spt abi.RegisteredSealProof, sectors []abi.SectorID) ([]abi.SectorID, error) { +func (m *Manager) CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []abi.SectorID) ([]abi.SectorID, error) { var bad []abi.SectorID - ssize, err := spt.SectorSize() + ssize, err := pp.SectorSize() if err != nil { return nil, err } @@ -43,7 +43,7 @@ func (m *Manager) CheckProvable(ctx context.Context, spt abi.RegisteredSealProof return nil } - lp, _, err := m.localStore.AcquireSector(ctx, sector, spt, stores.FTSealed|stores.FTCache, stores.FTNone, stores.PathStorage, stores.AcquireMove) + lp, _, err := m.localStore.AcquireSector(ctx, sector, ssize, stores.FTSealed|stores.FTCache, stores.FTNone, stores.PathStorage, stores.AcquireMove) if err != nil { log.Warnw("CheckProvable Sector FAULT: acquire sector in checkProvable", "sector", sector, "error", err) bad = append(bad, sector) diff --git a/extern/sector-storage/localworker.go b/extern/sector-storage/localworker.go index b1193a2e2..0033b5d59 100644 --- a/extern/sector-storage/localworker.go +++ b/extern/sector-storage/localworker.go @@ -65,12 +65,16 @@ type localWorkerPathProvider struct { func (l *localWorkerPathProvider) AcquireSector(ctx context.Context, sector abi.SectorID, existing stores.SectorFileType, allocate stores.SectorFileType, sealing stores.PathType) (stores.SectorPaths, func(), error) { - paths, storageIDs, err := l.w.storage.AcquireSector(ctx, sector, l.w.scfg.SealProofType, existing, allocate, sealing, l.op) + ssize, err := l.w.scfg.SealProofType.SectorSize() + if err != nil { + return stores.SectorPaths{}, nil, err + } + paths, storageIDs, err := l.w.storage.AcquireSector(ctx, sector, ssize, existing, allocate, sealing, l.op) if err != nil { return stores.SectorPaths{}, nil, err } - releaseStorage, err := l.w.localStore.Reserve(ctx, sector, l.w.scfg.SealProofType, allocate, storageIDs, stores.FSOverheadSeal) + releaseStorage, err := l.w.localStore.Reserve(ctx, sector, ssize, allocate, storageIDs, stores.FSOverheadSeal) if err != nil { return stores.SectorPaths{}, nil, xerrors.Errorf("reserving storage space: %w", err) } @@ -212,7 +216,11 @@ func (l *LocalWorker) Remove(ctx context.Context, sector abi.SectorID) error { } func (l *LocalWorker) MoveStorage(ctx context.Context, sector abi.SectorID, types stores.SectorFileType) error { - if err := l.storage.MoveStorage(ctx, sector, l.scfg.SealProofType, types); err != nil { + ssize, err := l.scfg.SealProofType.SectorSize() + if err != nil { + return err + } + if err := l.storage.MoveStorage(ctx, sector, ssize, types); err != nil { return xerrors.Errorf("moving sealed data to storage: %w", err) } diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index 73a5eb51e..a17a5ba99 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -95,7 +95,7 @@ func New(ctx context.Context, ls stores.LocalStorage, si stores.SectorIndex, cfg return nil, err } - prover, err := ffiwrapper.New(&readonlyProvider{stor: lstor, index: si}, cfg) + prover, err := ffiwrapper.New(&readonlyProvider{stor: lstor, index: si, spt: cfg.SealProofType}, cfg) if err != nil { return nil, xerrors.Errorf("creating prover instance: %w", err) } diff --git a/extern/sector-storage/manager_test.go b/extern/sector-storage/manager_test.go index ee704cb5a..fbd712be4 100644 --- a/extern/sector-storage/manager_test.go +++ b/extern/sector-storage/manager_test.go @@ -92,7 +92,7 @@ func newTestMgr(ctx context.Context, t *testing.T) (*Manager, *stores.Local, *st lstor, err := stores.NewLocal(ctx, st, si, nil) require.NoError(t, err) - prover, err := ffiwrapper.New(&readonlyProvider{stor: lstor}, cfg) + prover, err := ffiwrapper.New(&readonlyProvider{stor: lstor, spt: cfg.SealProofType}, cfg) require.NoError(t, err) stor := stores.NewRemote(lstor, si, nil, 6000) diff --git a/extern/sector-storage/mock/mock.go b/extern/sector-storage/mock/mock.go index 001c7159c..3791cc6e2 100644 --- a/extern/sector-storage/mock/mock.go +++ b/extern/sector-storage/mock/mock.go @@ -392,7 +392,7 @@ func (mgr *SectorMgr) Remove(ctx context.Context, sector abi.SectorID) error { return nil } -func (mgr *SectorMgr) CheckProvable(ctx context.Context, spt abi.RegisteredSealProof, ids []abi.SectorID) ([]abi.SectorID, error) { +func (mgr *SectorMgr) CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, ids []abi.SectorID) ([]abi.SectorID, error) { var bad []abi.SectorID for _, sid := range ids { diff --git a/extern/sector-storage/roprov.go b/extern/sector-storage/roprov.go index 2b009c63b..e8e2bf4f4 100644 --- a/extern/sector-storage/roprov.go +++ b/extern/sector-storage/roprov.go @@ -21,6 +21,11 @@ func (l *readonlyProvider) AcquireSector(ctx context.Context, id abi.SectorID, e return stores.SectorPaths{}, nil, xerrors.New("read-only storage") } + ssize, err := l.spt.SectorSize() + if err != nil { + return stores.SectorPaths{}, nil, xerrors.Errorf("failed to determine sector size: %w", err) + } + ctx, cancel := context.WithCancel(ctx) // use TryLock to avoid blocking @@ -34,7 +39,7 @@ func (l *readonlyProvider) AcquireSector(ctx context.Context, id abi.SectorID, e return stores.SectorPaths{}, nil, xerrors.Errorf("failed to acquire sector lock") } - p, _, err := l.stor.AcquireSector(ctx, id, l.spt, existing, allocate, sealing, stores.AcquireMove) + p, _, err := l.stor.AcquireSector(ctx, id, ssize, existing, allocate, sealing, stores.AcquireMove) return p, cancel, err } diff --git a/extern/sector-storage/selector_alloc.go b/extern/sector-storage/selector_alloc.go index b891383fb..15de1142f 100644 --- a/extern/sector-storage/selector_alloc.go +++ b/extern/sector-storage/selector_alloc.go @@ -44,7 +44,12 @@ func (s *allocSelector) Ok(ctx context.Context, task sealtasks.TaskType, spt abi have[path.ID] = struct{}{} } - best, err := s.index.StorageBestAlloc(ctx, s.alloc, spt, s.ptype) + ssize, err := spt.SectorSize() + if err != nil { + return false, xerrors.Errorf("getting sector size: %w", err) + } + + best, err := s.index.StorageBestAlloc(ctx, s.alloc, ssize, s.ptype) if err != nil { return false, xerrors.Errorf("finding best alloc storage: %w", err) } diff --git a/extern/sector-storage/selector_existing.go b/extern/sector-storage/selector_existing.go index fb161f085..1afdddf7b 100644 --- a/extern/sector-storage/selector_existing.go +++ b/extern/sector-storage/selector_existing.go @@ -46,7 +46,12 @@ func (s *existingSelector) Ok(ctx context.Context, task sealtasks.TaskType, spt have[path.ID] = struct{}{} } - best, err := s.index.StorageFindSector(ctx, s.sector, s.alloc, spt, s.allowFetch) + ssize, err := spt.SectorSize() + if err != nil { + return false, xerrors.Errorf("getting sector size: %w", err) + } + + best, err := s.index.StorageFindSector(ctx, s.sector, s.alloc, ssize, s.allowFetch) if err != nil { return false, xerrors.Errorf("finding best storage: %w", err) } diff --git a/extern/sector-storage/stores/filetype.go b/extern/sector-storage/stores/filetype.go index 90cc1d160..0b2d02e80 100644 --- a/extern/sector-storage/stores/filetype.go +++ b/extern/sector-storage/stores/filetype.go @@ -53,12 +53,7 @@ func (t SectorFileType) Has(singleType SectorFileType) bool { return t&singleType == singleType } -func (t SectorFileType) SealSpaceUse(spt abi.RegisteredSealProof) (uint64, error) { - ssize, err := spt.SectorSize() - if err != nil { - return 0, xerrors.Errorf("getting sector size: %w", err) - } - +func (t SectorFileType) SealSpaceUse(ssize abi.SectorSize) (uint64, error) { var need uint64 for _, pathType := range PathTypes { if !t.Has(pathType) { diff --git a/extern/sector-storage/stores/index.go b/extern/sector-storage/stores/index.go index e2bd7e4ee..198dc0b84 100644 --- a/extern/sector-storage/stores/index.go +++ b/extern/sector-storage/stores/index.go @@ -55,9 +55,9 @@ type SectorIndex interface { // part of storage-miner api StorageDeclareSector(ctx context.Context, storageID ID, s abi.SectorID, ft SectorFileType, primary bool) error StorageDropSector(ctx context.Context, storageID ID, s abi.SectorID, ft SectorFileType) error - StorageFindSector(ctx context.Context, sector abi.SectorID, ft SectorFileType, spt abi.RegisteredSealProof, allowFetch bool) ([]SectorStorageInfo, error) + StorageFindSector(ctx context.Context, sector abi.SectorID, ft SectorFileType, ssize abi.SectorSize, allowFetch bool) ([]SectorStorageInfo, error) - StorageBestAlloc(ctx context.Context, allocate SectorFileType, spt abi.RegisteredSealProof, pathType PathType) ([]StorageInfo, error) + StorageBestAlloc(ctx context.Context, allocate SectorFileType, ssize abi.SectorSize, pathType PathType) ([]StorageInfo, error) // atomically acquire locks on all sector file types. close ctx to unlock StorageLock(ctx context.Context, sector abi.SectorID, read SectorFileType, write SectorFileType) error @@ -246,7 +246,7 @@ func (i *Index) StorageDropSector(ctx context.Context, storageID ID, s abi.Secto return nil } -func (i *Index) StorageFindSector(ctx context.Context, s abi.SectorID, ft SectorFileType, spt abi.RegisteredSealProof, allowFetch bool) ([]SectorStorageInfo, error) { +func (i *Index) StorageFindSector(ctx context.Context, s abi.SectorID, ft SectorFileType, ssize abi.SectorSize, allowFetch bool) ([]SectorStorageInfo, error) { i.lk.RLock() defer i.lk.RUnlock() @@ -297,7 +297,7 @@ func (i *Index) StorageFindSector(ctx context.Context, s abi.SectorID, ft Sector } if allowFetch { - spaceReq, err := ft.SealSpaceUse(spt) + spaceReq, err := ft.SealSpaceUse(ssize) if err != nil { return nil, xerrors.Errorf("estimating required space: %w", err) } @@ -365,13 +365,13 @@ func (i *Index) StorageInfo(ctx context.Context, id ID) (StorageInfo, error) { return *si.info, nil } -func (i *Index) StorageBestAlloc(ctx context.Context, allocate SectorFileType, spt abi.RegisteredSealProof, pathType PathType) ([]StorageInfo, error) { +func (i *Index) StorageBestAlloc(ctx context.Context, allocate SectorFileType, ssize abi.SectorSize, pathType PathType) ([]StorageInfo, error) { i.lk.RLock() defer i.lk.RUnlock() var candidates []storageEntry - spaceReq, err := allocate.SealSpaceUse(spt) + spaceReq, err := allocate.SealSpaceUse(ssize) if err != nil { return nil, xerrors.Errorf("estimating required space: %w", err) } diff --git a/extern/sector-storage/stores/interface.go b/extern/sector-storage/stores/interface.go index 875754fc5..6a8691ff7 100644 --- a/extern/sector-storage/stores/interface.go +++ b/extern/sector-storage/stores/interface.go @@ -22,7 +22,7 @@ const ( ) type Store interface { - AcquireSector(ctx context.Context, s abi.SectorID, spt abi.RegisteredSealProof, existing SectorFileType, allocate SectorFileType, sealing PathType, op AcquireMode) (paths SectorPaths, stores SectorPaths, err error) + AcquireSector(ctx context.Context, s abi.SectorID, ssize abi.SectorSize, existing SectorFileType, allocate SectorFileType, sealing PathType, op AcquireMode) (paths SectorPaths, stores SectorPaths, err error) Remove(ctx context.Context, s abi.SectorID, types SectorFileType, force bool) error // like remove, but doesn't remove the primary sector copy, nor the last @@ -30,7 +30,7 @@ type Store interface { RemoveCopies(ctx context.Context, s abi.SectorID, types SectorFileType) error // move sectors into storage - MoveStorage(ctx context.Context, s abi.SectorID, spt abi.RegisteredSealProof, types SectorFileType) error + MoveStorage(ctx context.Context, s abi.SectorID, ssize abi.SectorSize, types SectorFileType) error FsStat(ctx context.Context, id ID) (fsutil.FsStat, error) } diff --git a/extern/sector-storage/stores/local.go b/extern/sector-storage/stores/local.go index 50968e7bd..b2431dbee 100644 --- a/extern/sector-storage/stores/local.go +++ b/extern/sector-storage/stores/local.go @@ -269,12 +269,7 @@ func (st *Local) reportHealth(ctx context.Context) { } } -func (st *Local) Reserve(ctx context.Context, sid abi.SectorID, spt abi.RegisteredSealProof, ft SectorFileType, storageIDs SectorPaths, overheadTab map[SectorFileType]int) (func(), error) { - ssize, err := spt.SectorSize() - if err != nil { - return nil, xerrors.Errorf("getting sector size: %w", err) - } - +func (st *Local) Reserve(ctx context.Context, sid abi.SectorID, ssize abi.SectorSize, ft SectorFileType, storageIDs SectorPaths, overheadTab map[SectorFileType]int) (func(), error) { st.localLk.Lock() done := func() {} @@ -324,7 +319,7 @@ func (st *Local) Reserve(ctx context.Context, sid abi.SectorID, spt abi.Register return done, nil } -func (st *Local) AcquireSector(ctx context.Context, sid abi.SectorID, spt abi.RegisteredSealProof, existing SectorFileType, allocate SectorFileType, pathType PathType, op AcquireMode) (SectorPaths, SectorPaths, error) { +func (st *Local) AcquireSector(ctx context.Context, sid abi.SectorID, ssize abi.SectorSize, existing SectorFileType, allocate SectorFileType, pathType PathType, op AcquireMode) (SectorPaths, SectorPaths, error) { if existing|allocate != existing^allocate { return SectorPaths{}, SectorPaths{}, xerrors.New("can't both find and allocate a sector") } @@ -340,7 +335,7 @@ func (st *Local) AcquireSector(ctx context.Context, sid abi.SectorID, spt abi.Re continue } - si, err := st.index.StorageFindSector(ctx, sid, fileType, spt, false) + si, err := st.index.StorageFindSector(ctx, sid, fileType, ssize, false) if err != nil { log.Warnf("finding existing sector %d(t:%d) failed: %+v", sid, fileType, err) continue @@ -370,7 +365,7 @@ func (st *Local) AcquireSector(ctx context.Context, sid abi.SectorID, spt abi.Re continue } - sis, err := st.index.StorageBestAlloc(ctx, fileType, spt, pathType) + sis, err := st.index.StorageBestAlloc(ctx, fileType, ssize, pathType) if err != nil { return SectorPaths{}, SectorPaths{}, xerrors.Errorf("finding best storage for allocating : %w", err) } @@ -525,13 +520,13 @@ func (st *Local) removeSector(ctx context.Context, sid abi.SectorID, typ SectorF return nil } -func (st *Local) MoveStorage(ctx context.Context, s abi.SectorID, spt abi.RegisteredSealProof, types SectorFileType) error { - dest, destIds, err := st.AcquireSector(ctx, s, spt, FTNone, types, PathStorage, AcquireMove) +func (st *Local) MoveStorage(ctx context.Context, s abi.SectorID, ssize abi.SectorSize, types SectorFileType) error { + dest, destIds, err := st.AcquireSector(ctx, s, ssize, FTNone, types, PathStorage, AcquireMove) if err != nil { return xerrors.Errorf("acquire dest storage: %w", err) } - src, srcIds, err := st.AcquireSector(ctx, s, spt, types, FTNone, PathStorage, AcquireMove) + src, srcIds, err := st.AcquireSector(ctx, s, ssize, types, FTNone, PathStorage, AcquireMove) if err != nil { return xerrors.Errorf("acquire src storage: %w", err) } diff --git a/extern/sector-storage/stores/remote.go b/extern/sector-storage/stores/remote.go index b9d241b5f..188fd3be2 100644 --- a/extern/sector-storage/stores/remote.go +++ b/extern/sector-storage/stores/remote.go @@ -58,7 +58,7 @@ func NewRemote(local *Local, index SectorIndex, auth http.Header, fetchLimit int } } -func (r *Remote) AcquireSector(ctx context.Context, s abi.SectorID, spt abi.RegisteredSealProof, existing SectorFileType, allocate SectorFileType, pathType PathType, op AcquireMode) (SectorPaths, SectorPaths, error) { +func (r *Remote) AcquireSector(ctx context.Context, s abi.SectorID, ssize abi.SectorSize, existing SectorFileType, allocate SectorFileType, pathType PathType, op AcquireMode) (SectorPaths, SectorPaths, error) { if existing|allocate != existing^allocate { return SectorPaths{}, SectorPaths{}, xerrors.New("can't both find and allocate a sector") } @@ -90,7 +90,7 @@ func (r *Remote) AcquireSector(ctx context.Context, s abi.SectorID, spt abi.Regi r.fetchLk.Unlock() }() - paths, stores, err := r.local.AcquireSector(ctx, s, spt, existing, allocate, pathType, op) + paths, stores, err := r.local.AcquireSector(ctx, s, ssize, existing, allocate, pathType, op) if err != nil { return SectorPaths{}, SectorPaths{}, xerrors.Errorf("local acquire error: %w", err) } @@ -106,7 +106,7 @@ func (r *Remote) AcquireSector(ctx context.Context, s abi.SectorID, spt abi.Regi } } - apaths, ids, err := r.local.AcquireSector(ctx, s, spt, FTNone, toFetch, pathType, op) + apaths, ids, err := r.local.AcquireSector(ctx, s, ssize, FTNone, toFetch, pathType, op) if err != nil { return SectorPaths{}, SectorPaths{}, xerrors.Errorf("allocate local sector for fetching: %w", err) } @@ -116,7 +116,7 @@ func (r *Remote) AcquireSector(ctx context.Context, s abi.SectorID, spt abi.Regi odt = FsOverheadFinalized } - releaseStorage, err := r.local.Reserve(ctx, s, spt, toFetch, ids, odt) + releaseStorage, err := r.local.Reserve(ctx, s, ssize, toFetch, ids, odt) if err != nil { return SectorPaths{}, SectorPaths{}, xerrors.Errorf("reserving storage space: %w", err) } @@ -281,14 +281,14 @@ func (r *Remote) fetch(ctx context.Context, url, outname string) error { } } -func (r *Remote) MoveStorage(ctx context.Context, s abi.SectorID, spt abi.RegisteredSealProof, types SectorFileType) error { +func (r *Remote) MoveStorage(ctx context.Context, s abi.SectorID, ssize abi.SectorSize, types SectorFileType) error { // Make sure we have the data local - _, _, err := r.AcquireSector(ctx, s, spt, types, FTNone, PathStorage, AcquireMove) + _, _, err := r.AcquireSector(ctx, s, ssize, types, FTNone, PathStorage, AcquireMove) if err != nil { return xerrors.Errorf("acquire src storage (remote): %w", err) } - return r.local.MoveStorage(ctx, s, spt, types) + return r.local.MoveStorage(ctx, s, ssize, types) } func (r *Remote) Remove(ctx context.Context, sid abi.SectorID, typ SectorFileType, force bool) error { diff --git a/storage/wdpost_run.go b/storage/wdpost_run.go index d4ed4d64c..80873d70b 100644 --- a/storage/wdpost_run.go +++ b/storage/wdpost_run.go @@ -181,11 +181,6 @@ func (s *WindowPoStScheduler) runSubmitPoST( } func (s *WindowPoStScheduler) checkSectors(ctx context.Context, check bitfield.BitField) (bitfield.BitField, error) { - spt, err := s.proofType.RegisteredSealProof() - if err != nil { - return bitfield.BitField{}, xerrors.Errorf("getting seal proof type: %w", err) - } - mid, err := address.IDFromAddress(s.actor) if err != nil { return bitfield.BitField{}, err @@ -207,7 +202,7 @@ func (s *WindowPoStScheduler) checkSectors(ctx context.Context, check bitfield.B return bitfield.BitField{}, xerrors.Errorf("iterating over bitfield: %w", err) } - bad, err := s.faultTracker.CheckProvable(ctx, spt, tocheck) + bad, err := s.faultTracker.CheckProvable(ctx, s.proofType, tocheck) if err != nil { return bitfield.BitField{}, xerrors.Errorf("checking provable sectors: %w", err) } diff --git a/storage/wdpost_run_test.go b/storage/wdpost_run_test.go index dd7ac4c24..8c145498c 100644 --- a/storage/wdpost_run_test.go +++ b/storage/wdpost_run_test.go @@ -114,7 +114,7 @@ func (m *mockProver) GenerateWindowPoSt(ctx context.Context, aid abi.ActorID, si type mockFaultTracker struct { } -func (m mockFaultTracker) CheckProvable(ctx context.Context, spt abi.RegisteredSealProof, sectors []abi.SectorID) ([]abi.SectorID, error) { +func (m mockFaultTracker) CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []abi.SectorID) ([]abi.SectorID, error) { // Returns "bad" sectors so just return nil meaning all sectors are good return nil, nil } From 3a46c15c4ac31a5098c1f01cf752630fcef1b819 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Wed, 21 Oct 2020 04:22:49 +0200 Subject: [PATCH 193/313] Disable blockstore bloom filter Signed-off-by: Jakub Sztandera --- lib/blockstore/blockstore.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/blockstore/blockstore.go b/lib/blockstore/blockstore.go index f274cd708..99d849188 100644 --- a/lib/blockstore/blockstore.go +++ b/lib/blockstore/blockstore.go @@ -50,9 +50,16 @@ type GCLocker = blockstore.GCLocker var NewGCLocker = blockstore.NewGCLocker var NewGCBlockstore = blockstore.NewGCBlockstore -var DefaultCacheOpts = blockstore.DefaultCacheOpts var ErrNotFound = blockstore.ErrNotFound +func DefaultCacheOpts() CacheOpts { + return CacheOpts{ + HasBloomFilterSize: 0, + HasBloomFilterHashes: 0, + HasARCCacheSize: 512 << 10, + } +} + func CachedBlockstore(ctx context.Context, bs Blockstore, opts CacheOpts) (Blockstore, error) { bs, err := blockstore.CachedBlockstore(ctx, bs, opts) if err != nil { From 3e767ca5c8357c430f246433cdf2f89008e74554 Mon Sep 17 00:00:00 2001 From: lanzafame Date: Wed, 21 Oct 2020 18:10:27 +1000 Subject: [PATCH 194/313] wrap api in metrics proxy --- cmd/lotus/rpc.go | 3 ++- metrics/metrics.go | 19 ++++++++++++++ metrics/proxy.go | 65 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 metrics/proxy.go diff --git a/cmd/lotus/rpc.go b/cmd/lotus/rpc.go index 9718deb3a..28af47ad7 100644 --- a/cmd/lotus/rpc.go +++ b/cmd/lotus/rpc.go @@ -22,6 +22,7 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api/apistruct" + "github.com/filecoin-project/lotus/metrics" "github.com/filecoin-project/lotus/node" "github.com/filecoin-project/lotus/node/impl" ) @@ -30,7 +31,7 @@ var log = logging.Logger("main") func serveRPC(a api.FullNode, stop node.StopFunc, addr multiaddr.Multiaddr, shutdownCh <-chan struct{}) error { rpcServer := jsonrpc.NewServer() - rpcServer.Register("Filecoin", apistruct.PermissionedFullAPI(a)) + rpcServer.Register("Filecoin", apistruct.PermissionedFullAPI(metrics.MetricedFullAPI(a))) ah := &auth.Handler{ Verify: a.AuthVerify, diff --git a/metrics/metrics.go b/metrics/metrics.go index 5dd865263..8de6afc1e 100644 --- a/metrics/metrics.go +++ b/metrics/metrics.go @@ -1,6 +1,7 @@ package metrics import ( + "context" "time" "go.opencensus.io/stats" @@ -24,6 +25,8 @@ var ( MessageTo, _ = tag.NewKey("message_to") MessageNonce, _ = tag.NewKey("message_nonce") ReceivedFrom, _ = tag.NewKey("received_from") + Endpoint, _ = tag.NewKey("endpoint") + APIInterface, _ = tag.NewKey("api") // to distinguish between gateway api and full node api endpoint calls ) // Measures @@ -49,6 +52,7 @@ var ( PubsubRecvRPC = stats.Int64("pubsub/recv_rpc", "Counter for total received RPCs", stats.UnitDimensionless) PubsubSendRPC = stats.Int64("pubsub/send_rpc", "Counter for total sent RPCs", stats.UnitDimensionless) PubsubDropRPC = stats.Int64("pubsub/drop_rpc", "Counter for total dropped RPCs", stats.UnitDimensionless) + APIRequestDuration = stats.Float64("api/request_duration_ms", "Duration of API requests", stats.UnitMilliseconds) ) var ( @@ -137,6 +141,11 @@ var ( Measure: PubsubDropRPC, Aggregation: view.Count(), } + APIRequestDurationView = &view.View{ + Measure: APIRequestDuration, + Aggregation: defaultMillisecondsDistribution, + TagKeys: []tag.Key{APIInterface, Endpoint}, + } ) // DefaultViews is an array of OpenCensus views for metric gathering purposes @@ -161,6 +170,7 @@ var DefaultViews = append([]*view.View{ PubsubRecvRPCView, PubsubSendRPCView, PubsubDropRPCView, + APIRequestDurationView, }, rpcmetrics.DefaultViews...) @@ -168,3 +178,12 @@ var DefaultViews = append([]*view.View{ func SinceInMilliseconds(startTime time.Time) float64 { return float64(time.Since(startTime).Nanoseconds()) / 1e6 } + +// Timer is a function stopwatch, calling it starts the timer, +// calling the returned function will record the duration. +func Timer(ctx context.Context, m *stats.Float64Measure) func() { + start := time.Now() + return func() { + stats.Record(ctx, m.M(SinceInMilliseconds(start))) + } +} \ No newline at end of file diff --git a/metrics/proxy.go b/metrics/proxy.go new file mode 100644 index 000000000..cafcaad89 --- /dev/null +++ b/metrics/proxy.go @@ -0,0 +1,65 @@ +package metrics + +import ( + "context" + "reflect" + + "go.opencensus.io/tag" + + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/api/apistruct" +) + +func MetricedStorMinerAPI(a api.StorageMiner) api.StorageMiner { + var out apistruct.StorageMinerStruct + proxy(a, &out.Internal) + proxy(a, &out.CommonStruct.Internal) + return &out +} + +func MetricedFullAPI(a api.FullNode) api.FullNode { + var out apistruct.FullNodeStruct + proxy(a, &out.Internal) + proxy(a, &out.CommonStruct.Internal) + return &out +} + +func MetricedWorkerAPI(a api.WorkerAPI) api.WorkerAPI { + var out apistruct.WorkerStruct + proxy(a, &out.Internal) + return &out +} + +func MetricedWalletAPI(a api.WalletAPI) api.WalletAPI { + var out apistruct.WalletStruct + proxy(a, &out.Internal) + return &out +} + +func MetricedGatewayAPI(a api.GatewayAPI) api.GatewayAPI { + var out apistruct.GatewayStruct + proxy(a, &out.Internal) + return &out +} + +func proxy(in interface{}, out interface{}) { + rint := reflect.ValueOf(out).Elem() + ra := reflect.ValueOf(in) + + for f := 0; f < rint.NumField(); f++ { + field := rint.Type().Field(f) + fn := ra.MethodByName(field.Name) + + rint.Field(f).Set(reflect.MakeFunc(field.Type, func(args []reflect.Value) (results []reflect.Value) { + ctx := args[0].Interface().(context.Context) + // upsert function name into context + ctx, _ = tag.New(ctx, tag.Upsert(Endpoint, field.Name)) + stop := Timer(ctx, APIRequestDuration) + defer stop() + // pass tagged ctx back into function call + args[0] = reflect.ValueOf(ctx) + return fn.Call(args) + })) + + } +} \ No newline at end of file From 7a33d5bb3424041aa50bb914a16708010fe2e1bc Mon Sep 17 00:00:00 2001 From: lanzafame Date: Wed, 21 Oct 2020 18:37:50 +1000 Subject: [PATCH 195/313] register all apis with metric wrapper --- cmd/lotus-gateway/main.go | 15 ++++++++++++++- cmd/lotus-seal-worker/main.go | 13 ++++++++++++- cmd/lotus-storage-miner/run.go | 21 +++++++++++++++++++-- cmd/lotus-wallet/main.go | 13 ++++++++++++- cmd/lotus/rpc.go | 10 +++++++++- 5 files changed, 66 insertions(+), 6 deletions(-) diff --git a/cmd/lotus-gateway/main.go b/cmd/lotus-gateway/main.go index 34e068ffd..3fed88468 100644 --- a/cmd/lotus-gateway/main.go +++ b/cmd/lotus-gateway/main.go @@ -7,10 +7,15 @@ import ( "os" "github.com/filecoin-project/go-jsonrpc" + "go.opencensus.io/tag" + "github.com/filecoin-project/lotus/build" lcli "github.com/filecoin-project/lotus/cli" "github.com/filecoin-project/lotus/lib/lotuslog" + "github.com/filecoin-project/lotus/metrics" + logging "github.com/ipfs/go-log" + "go.opencensus.io/stats/view" "github.com/gorilla/mux" "github.com/urfave/cli/v2" @@ -64,6 +69,13 @@ var runCmd = &cli.Command{ ctx, cancel := context.WithCancel(ctx) defer cancel() + // Register all metric views + if err := view.Register( + metrics.DefaultViews..., + ); err != nil { + log.Fatalf("Cannot register the view: %v", err) + } + api, closer, err := lcli.GetFullNodeAPI(cctx) if err != nil { return err @@ -76,7 +88,7 @@ var runCmd = &cli.Command{ log.Info("Setting up API endpoint at " + address) rpcServer := jsonrpc.NewServer() - rpcServer.Register("Filecoin", NewGatewayAPI(api)) + rpcServer.Register("Filecoin", metrics.MetricedGatewayAPI(NewGatewayAPI(api))) mux.Handle("/rpc/v0", rpcServer) mux.PathPrefix("/").Handler(http.DefaultServeMux) @@ -89,6 +101,7 @@ var runCmd = &cli.Command{ srv := &http.Server{ Handler: mux, BaseContext: func(listener net.Listener) context.Context { + ctx, _ := tag.New(context.Background(), tag.Upsert(metrics.APIInterface, "lotus-gateway")) return ctx }, } diff --git a/cmd/lotus-seal-worker/main.go b/cmd/lotus-seal-worker/main.go index d2c57e680..9c2ad6319 100644 --- a/cmd/lotus-seal-worker/main.go +++ b/cmd/lotus-seal-worker/main.go @@ -18,6 +18,8 @@ import ( logging "github.com/ipfs/go-log/v2" manet "github.com/multiformats/go-multiaddr/net" "github.com/urfave/cli/v2" + "go.opencensus.io/stats/view" + "go.opencensus.io/tag" "golang.org/x/xerrors" "github.com/filecoin-project/go-jsonrpc" @@ -34,6 +36,7 @@ import ( "github.com/filecoin-project/lotus/extern/sector-storage/stores" "github.com/filecoin-project/lotus/lib/lotuslog" "github.com/filecoin-project/lotus/lib/rpcenc" + "github.com/filecoin-project/lotus/metrics" "github.com/filecoin-project/lotus/node/repo" ) @@ -190,6 +193,13 @@ var runCmd = &cli.Command{ ctx, cancel := context.WithCancel(ctx) defer cancel() + // Register all metric views + if err := view.Register( + metrics.DefaultViews..., + ); err != nil { + log.Fatalf("Cannot register the view: %v", err) + } + v, err := nodeApi.Version(ctx) if err != nil { return err @@ -363,7 +373,7 @@ var runCmd = &cli.Command{ readerHandler, readerServerOpt := rpcenc.ReaderParamDecoder() rpcServer := jsonrpc.NewServer(readerServerOpt) - rpcServer.Register("Filecoin", apistruct.PermissionedWorkerAPI(workerApi)) + rpcServer.Register("Filecoin", apistruct.PermissionedWorkerAPI(metrics.MetricedWorkerAPI(workerApi))) mux.Handle("/rpc/v0", rpcServer) mux.Handle("/rpc/streams/v0/push/{uuid}", readerHandler) @@ -378,6 +388,7 @@ var runCmd = &cli.Command{ srv := &http.Server{ Handler: ah, BaseContext: func(listener net.Listener) context.Context { + ctx, _ := tag.New(context.Background(), tag.Upsert(metrics.APIInterface, "lotus-worker")) return ctx }, } diff --git a/cmd/lotus-storage-miner/run.go b/cmd/lotus-storage-miner/run.go index c043bd903..0c2fba8b3 100644 --- a/cmd/lotus-storage-miner/run.go +++ b/cmd/lotus-storage-miner/run.go @@ -2,6 +2,7 @@ package main import ( "context" + "net" "net/http" _ "net/http/pprof" "os" @@ -12,6 +13,8 @@ import ( "github.com/multiformats/go-multiaddr" manet "github.com/multiformats/go-multiaddr/net" "github.com/urfave/cli/v2" + "go.opencensus.io/stats/view" + "go.opencensus.io/tag" "golang.org/x/xerrors" "github.com/filecoin-project/go-jsonrpc" @@ -22,6 +25,7 @@ import ( "github.com/filecoin-project/lotus/build" lcli "github.com/filecoin-project/lotus/cli" "github.com/filecoin-project/lotus/lib/ulimit" + "github.com/filecoin-project/lotus/metrics" "github.com/filecoin-project/lotus/node" "github.com/filecoin-project/lotus/node/impl" "github.com/filecoin-project/lotus/node/modules/dtypes" @@ -66,6 +70,13 @@ var runCmd = &cli.Command{ defer ncloser() ctx := lcli.DaemonContext(cctx) + // Register all metric views + if err := view.Register( + metrics.DefaultViews..., + ); err != nil { + log.Fatalf("Cannot register the view: %v", err) + } + v, err := nodeApi.Version(ctx) if err != nil { return err @@ -147,7 +158,7 @@ var runCmd = &cli.Command{ mux := mux.NewRouter() rpcServer := jsonrpc.NewServer() - rpcServer.Register("Filecoin", apistruct.PermissionedStorMinerAPI(minerapi)) + rpcServer.Register("Filecoin", apistruct.PermissionedStorMinerAPI(metrics.MetricedStorMinerAPI(minerapi))) mux.Handle("/rpc/v0", rpcServer) mux.PathPrefix("/remote").HandlerFunc(minerapi.(*impl.StorageMinerAPI).ServeRemote) @@ -158,7 +169,13 @@ var runCmd = &cli.Command{ Next: mux.ServeHTTP, } - srv := &http.Server{Handler: ah} + srv := &http.Server{ + Handler: ah, + BaseContext: func(listener net.Listener) context.Context { + ctx, _ := tag.New(context.Background(), tag.Upsert(metrics.APIInterface, "lotus-miner")) + return ctx + }, + } sigChan := make(chan os.Signal, 2) go func() { diff --git a/cmd/lotus-wallet/main.go b/cmd/lotus-wallet/main.go index 3285b13e7..25b89eb9d 100644 --- a/cmd/lotus-wallet/main.go +++ b/cmd/lotus-wallet/main.go @@ -9,6 +9,8 @@ import ( "github.com/gorilla/mux" logging "github.com/ipfs/go-log/v2" "github.com/urfave/cli/v2" + "go.opencensus.io/stats/view" + "go.opencensus.io/tag" "github.com/filecoin-project/go-jsonrpc" @@ -18,6 +20,7 @@ import ( ledgerwallet "github.com/filecoin-project/lotus/chain/wallet/ledger" lcli "github.com/filecoin-project/lotus/cli" "github.com/filecoin-project/lotus/lib/lotuslog" + "github.com/filecoin-project/lotus/metrics" "github.com/filecoin-project/lotus/node/repo" ) @@ -75,6 +78,13 @@ var runCmd = &cli.Command{ ctx, cancel := context.WithCancel(ctx) defer cancel() + // Register all metric views + if err := view.Register( + metrics.DefaultViews..., + ); err != nil { + log.Fatalf("Cannot register the view: %v", err) + } + repoPath := cctx.String(FlagWalletRepo) r, err := repo.NewFS(repoPath) if err != nil { @@ -125,7 +135,7 @@ var runCmd = &cli.Command{ log.Info("Setting up API endpoint at " + address) rpcServer := jsonrpc.NewServer() - rpcServer.Register("Filecoin", &LoggedWallet{under: w}) + rpcServer.Register("Filecoin", &LoggedWallet{under: metrics.MetricedWalletAPI(w)}) mux.Handle("/rpc/v0", rpcServer) mux.PathPrefix("/").Handler(http.DefaultServeMux) // pprof @@ -138,6 +148,7 @@ var runCmd = &cli.Command{ srv := &http.Server{ Handler: mux, BaseContext: func(listener net.Listener) context.Context { + ctx, _ := tag.New(context.Background(), tag.Upsert(metrics.APIInterface, "lotus-wallet")) return ctx }, } diff --git a/cmd/lotus/rpc.go b/cmd/lotus/rpc.go index 28af47ad7..4f68ac85a 100644 --- a/cmd/lotus/rpc.go +++ b/cmd/lotus/rpc.go @@ -3,6 +3,7 @@ package main import ( "context" "encoding/json" + "net" "net/http" _ "net/http/pprof" "os" @@ -13,6 +14,7 @@ import ( logging "github.com/ipfs/go-log/v2" "github.com/multiformats/go-multiaddr" manet "github.com/multiformats/go-multiaddr/net" + "go.opencensus.io/tag" "golang.org/x/xerrors" "contrib.go.opencensus.io/exporter/prometheus" @@ -61,7 +63,13 @@ func serveRPC(a api.FullNode, stop node.StopFunc, addr multiaddr.Multiaddr, shut return xerrors.Errorf("could not listen: %w", err) } - srv := &http.Server{Handler: http.DefaultServeMux} + srv := &http.Server{ + Handler: http.DefaultServeMux, + BaseContext: func(listener net.Listener) context.Context { + ctx, _ := tag.New(context.Background(), tag.Upsert(metrics.APIInterface, "lotus-daemon")) + return ctx + }, + } sigCh := make(chan os.Signal, 2) shutdownDone := make(chan struct{}) From 7cbd4d49c379a1c30cf6222ab8bd2ceaeb65b406 Mon Sep 17 00:00:00 2001 From: lanzafame Date: Wed, 21 Oct 2020 18:39:57 +1000 Subject: [PATCH 196/313] gofmt --- metrics/metrics.go | 2 +- metrics/proxy.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/metrics/metrics.go b/metrics/metrics.go index 8de6afc1e..33d9e9174 100644 --- a/metrics/metrics.go +++ b/metrics/metrics.go @@ -186,4 +186,4 @@ func Timer(ctx context.Context, m *stats.Float64Measure) func() { return func() { stats.Record(ctx, m.M(SinceInMilliseconds(start))) } -} \ No newline at end of file +} diff --git a/metrics/proxy.go b/metrics/proxy.go index cafcaad89..f3714ec2e 100644 --- a/metrics/proxy.go +++ b/metrics/proxy.go @@ -62,4 +62,4 @@ func proxy(in interface{}, out interface{}) { })) } -} \ No newline at end of file +} From f0d966a5954158baa53a6666e9ebcb192f3621e1 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Wed, 21 Oct 2020 19:40:51 +0200 Subject: [PATCH 197/313] Fix lotus-shed ledger list Signed-off-by: Jakub Sztandera --- cmd/lotus-shed/ledger.go | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/cmd/lotus-shed/ledger.go b/cmd/lotus-shed/ledger.go index f64916534..ecb13ec64 100644 --- a/cmd/lotus-shed/ledger.go +++ b/cmd/lotus-shed/ledger.go @@ -7,9 +7,9 @@ import ( "strings" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/big" "github.com/urfave/cli/v2" ledgerfil "github.com/whyrusleeping/ledger-filecoin-go" - "golang.org/x/xerrors" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/types" @@ -76,15 +76,22 @@ var ledgerListAddressesCmd = &cli.Command{ } if cctx.Bool("print-balances") && api != nil { // api check makes linter happier - b, err := api.WalletBalance(ctx, addr) + a, err := api.StateGetActor(ctx, addr, types.EmptyTSK) if err != nil { - return xerrors.Errorf("getting balance: %w", err) - } - if !b.IsZero() { - end = i + 21 // BIP32 spec, stop after 20 empty addresses + if strings.Contains(err.Error(), "actor not found") { + a = nil + } else { + return err + } } - fmt.Printf("%s %s %s\n", addr, printHDPath(p), types.FIL(b)) + balance := big.Zero() + if a != nil { + balance = a.Balance + end = i + 20 + 1 + } + + fmt.Printf("%s %s %s\n", addr, printHDPath(p), types.FIL(balance)) } else { fmt.Printf("%s %s\n", addr, printHDPath(p)) } From 4e730b5ec89c068cacf9bb1f613dd2d38609c545 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 7 Oct 2020 18:09:33 -0700 Subject: [PATCH 198/313] port to v2 imports --- api/test/paych.go | 9 +- build/params_mainnet.go | 4 +- build/params_shared_funcs.go | 23 ---- build/params_shared_vals.go | 12 +- build/params_testground.go | 9 +- chain/actors/adt/diff_adt_test.go | 73 +++++----- chain/actors/builtin/builtin.go | 10 ++ chain/actors/policy/policy.go | 36 +++++ chain/actors/policy/policy_test.go | 20 +++ chain/events/state/predicates_test.go | 130 ++++++++++-------- chain/gen/gen.go | 19 ++- chain/gen/genesis/miners.go | 27 ++-- chain/gen/mining.go | 6 +- chain/market/fundmgr.go | 4 +- chain/market/fundmgr_test.go | 6 +- chain/messagepool/messagepool_test.go | 20 +-- chain/messagepool/repub_test.go | 8 +- chain/messagepool/selection_test.go | 27 ++-- chain/state/statetree_test.go | 28 ++-- chain/stmgr/forks.go | 18 +-- chain/stmgr/forks_test.go | 21 +-- chain/stmgr/stmgr.go | 53 ++++--- chain/stmgr/utils.go | 8 +- chain/store/store.go | 8 +- chain/sub/incoming.go | 8 +- chain/sync.go | 22 +-- chain/sync_test.go | 8 +- chain/types/blockheader.go | 4 +- chain/types/blockheader_test.go | 4 +- chain/types/message_test.go | 28 ++-- chain/vm/gas.go | 18 +-- chain/vm/gas_v0.go | 12 +- chain/vm/invoker_test.go | 13 +- chain/vm/mkactor.go | 3 +- chain/vm/runtime.go | 4 +- chain/vm/syscalls.go | 34 ++--- cli/client.go | 2 +- cli/multisig.go | 16 +-- cmd/lotus-bench/caching_verifier.go | 9 +- cmd/lotus-bench/main.go | 24 ++-- cmd/lotus-chainwatch/processor/processor.go | 18 +-- cmd/lotus-gateway/endtoend_test.go | 10 +- cmd/lotus-pcr/main.go | 15 +- cmd/lotus-seed/seed/seed.go | 5 +- cmd/lotus-shed/mempool-stats.go | 4 +- cmd/lotus-shed/proofs.go | 4 +- cmd/lotus-shed/sectors.go | 4 +- cmd/lotus-shed/verifreg.go | 12 +- cmd/lotus-storage-miner/actor.go | 21 ++- cmd/lotus-storage-miner/init.go | 26 ++-- cmd/lotus-storage-miner/sectors.go | 5 +- cmd/tvx/extract.go | 3 +- conformance/chaos/actor.go | 49 +++---- conformance/chaos/actor_test.go | 90 ++++++------ conformance/chaos/cbor_gen.go | 4 +- .../sector-storage/ffiwrapper/sealer_test.go | 10 +- extern/sector-storage/ffiwrapper/types.go | 8 +- .../sector-storage/ffiwrapper/verifier_cgo.go | 14 +- extern/sector-storage/mock/mock.go | 20 +-- extern/storage-sealing/checks.go | 4 +- extern/storage-sealing/states_sealing.go | 7 +- extern/storage-sealing/types.go | 4 +- extern/storage-sealing/types_test.go | 4 +- genesis/types.go | 5 +- markets/storageadapter/client.go | 32 ++--- markets/storageadapter/provider.go | 16 +-- miner/miner.go | 4 +- node/impl/full/gas.go | 4 +- node/impl/full/multisig.go | 24 ++-- node/modules/storageminer.go | 2 +- node/test/builder.go | 19 +-- paychmgr/paych_test.go | 12 +- paychmgr/paychvoucherfunds_test.go | 26 ++-- paychmgr/settler/settler.go | 4 +- storage/adapter_storage_miner.go | 8 +- storage/miner.go | 11 +- storage/mockstorage/preseal.go | 4 +- storage/wdpost_run.go | 39 +++--- storage/wdpost_run_test.go | 42 +++--- 79 files changed, 724 insertions(+), 657 deletions(-) diff --git a/api/test/paych.go b/api/test/paych.go index 43401554d..69def18bb 100644 --- a/api/test/paych.go +++ b/api/test/paych.go @@ -8,9 +8,6 @@ import ( "testing" "time" - builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" - paych0 "github.com/filecoin-project/specs-actors/actors/builtin/paych" - "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" "github.com/ipfs/go-cid" @@ -22,7 +19,9 @@ import ( "github.com/filecoin-project/lotus/api/apibstore" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/actors/builtin/paych" + "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/events" "github.com/filecoin-project/lotus/chain/events/state" "github.com/filecoin-project/lotus/chain/types" @@ -227,7 +226,7 @@ func TestPaymentChannels(t *testing.T, b APIBuilder, blocktime time.Duration) { } // wait for the settlement period to pass before collecting - waitForBlocks(ctx, t, bm, paymentReceiver, receiverAddr, paych0.SettleDelay) + waitForBlocks(ctx, t, bm, paymentReceiver, receiverAddr, policy.PaychSettleDelay) creatorPreCollectBalance, err := paymentCreator.WalletBalance(ctx, createrAddr) if err != nil { @@ -283,7 +282,7 @@ func waitForBlocks(ctx context.Context, t *testing.T, bm *BlockMiner, paymentRec // Add a real block m, err := paymentReceiver.MpoolPushMessage(ctx, &types.Message{ - To: builtin0.BurntFundsActorAddr, + To: builtin.BurntFundsActorAddr, From: receiverAddr, Value: types.NewInt(0), }, nil) diff --git a/build/params_mainnet.go b/build/params_mainnet.go index 71e96e614..94deedfec 100644 --- a/build/params_mainnet.go +++ b/build/params_mainnet.go @@ -12,7 +12,7 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/lotus/chain/actors/policy" - builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" ) var DrandSchedule = map[abi.ChainEpoch]DrandEnum{ @@ -57,6 +57,6 @@ func init() { Devnet = false } -const BlockDelaySecs = uint64(builtin0.EpochDurationSeconds) +const BlockDelaySecs = uint64(builtin2.EpochDurationSeconds) const PropagationDelaySecs = uint64(6) diff --git a/build/params_shared_funcs.go b/build/params_shared_funcs.go index 40ccca50b..c48b3c507 100644 --- a/build/params_shared_funcs.go +++ b/build/params_shared_funcs.go @@ -1,36 +1,13 @@ package build import ( - "sort" - "github.com/filecoin-project/go-address" "github.com/libp2p/go-libp2p-core/protocol" - "github.com/filecoin-project/go-state-types/abi" - miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" - "github.com/filecoin-project/lotus/node/modules/dtypes" ) -func DefaultSectorSize() abi.SectorSize { - szs := make([]abi.SectorSize, 0, len(miner0.SupportedProofTypes)) - for spt := range miner0.SupportedProofTypes { - ss, err := spt.SectorSize() - if err != nil { - panic(err) - } - - szs = append(szs, ss) - } - - sort.Slice(szs, func(i, j int) bool { - return szs[i] < szs[j] - }) - - return szs[0] -} - // Core network constants func BlocksTopic(netName dtypes.NetworkName) string { return "/fil/blocks/" + string(netName) } diff --git a/build/params_shared_vals.go b/build/params_shared_vals.go index b80472594..5070777bd 100644 --- a/build/params_shared_vals.go +++ b/build/params_shared_vals.go @@ -7,12 +7,12 @@ import ( "os" "github.com/filecoin-project/go-address" - "github.com/filecoin-project/lotus/chain/actors/policy" - + "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/network" - "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/specs-actors/actors/builtin" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + + "github.com/filecoin-project/lotus/chain/actors/policy" ) // ///// @@ -32,7 +32,7 @@ const ActorUpgradeNetworkVersion = network.Version4 const ForkLengthThreshold = Finality // Blocks (e) -var BlocksPerEpoch = uint64(builtin.ExpectedLeadersPerEpoch) +var BlocksPerEpoch = uint64(builtin2.ExpectedLeadersPerEpoch) // Epochs const Finality = policy.ChainFinality @@ -116,4 +116,4 @@ const PackingEfficiencyDenom = 5 // Actor consts // TODO: Pull from actors when its made not private -var MinDealDuration = abi.ChainEpoch(180 * builtin.EpochsInDay) +var MinDealDuration = abi.ChainEpoch(180 * builtin2.EpochsInDay) diff --git a/build/params_testground.go b/build/params_testground.go index beee1c727..d9893a5f5 100644 --- a/build/params_testground.go +++ b/build/params_testground.go @@ -12,7 +12,8 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/network" - "github.com/filecoin-project/specs-actors/actors/builtin" + + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" "github.com/filecoin-project/lotus/chain/actors/policy" ) @@ -21,14 +22,14 @@ var ( UnixfsChunkSize = uint64(1 << 20) UnixfsLinksPerLevel = 1024 - BlocksPerEpoch = uint64(builtin.ExpectedLeadersPerEpoch) + BlocksPerEpoch = uint64(builtin2.ExpectedLeadersPerEpoch) BlockMessageLimit = 512 BlockGasLimit = int64(100_000_000_000) BlockGasTarget = int64(BlockGasLimit / 2) BaseFeeMaxChangeDenom = int64(8) // 12.5% InitialBaseFee = int64(100e6) MinimumBaseFee = int64(100) - BlockDelaySecs = uint64(builtin.EpochDurationSeconds) + BlockDelaySecs = uint64(builtin2.EpochDurationSeconds) PropagationDelaySecs = uint64(6) AllowableClockDriftSecs = uint64(1) @@ -72,7 +73,7 @@ var ( // Actor consts // TODO: Pull from actors when its made not private - MinDealDuration = abi.ChainEpoch(180 * builtin.EpochsInDay) + MinDealDuration = abi.ChainEpoch(180 * builtin2.EpochsInDay) PackingEfficiencyNum int64 = 4 PackingEfficiencyDenom int64 = 5 diff --git a/chain/actors/adt/diff_adt_test.go b/chain/actors/adt/diff_adt_test.go index 1c0726003..a187c9f35 100644 --- a/chain/actors/adt/diff_adt_test.go +++ b/chain/actors/adt/diff_adt_test.go @@ -12,8 +12,9 @@ import ( typegen "github.com/whyrusleeping/cbor-gen" "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/specs-actors/actors/runtime" - adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" + + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt" bstore "github.com/filecoin-project/lotus/lib/blockstore" ) @@ -22,24 +23,24 @@ func TestDiffAdtArray(t *testing.T) { ctxstoreA := newContextStore() ctxstoreB := newContextStore() - arrA := adt0.MakeEmptyArray(ctxstoreA) - arrB := adt0.MakeEmptyArray(ctxstoreB) + arrA := adt2.MakeEmptyArray(ctxstoreA) + arrB := adt2.MakeEmptyArray(ctxstoreB) - require.NoError(t, arrA.Set(0, runtime.CBORBytes([]byte{0}))) // delete + require.NoError(t, arrA.Set(0, builtin2.CBORBytes([]byte{0}))) // delete - require.NoError(t, arrA.Set(1, runtime.CBORBytes([]byte{0}))) // modify - require.NoError(t, arrB.Set(1, runtime.CBORBytes([]byte{1}))) + require.NoError(t, arrA.Set(1, builtin2.CBORBytes([]byte{0}))) // modify + require.NoError(t, arrB.Set(1, builtin2.CBORBytes([]byte{1}))) - require.NoError(t, arrA.Set(2, runtime.CBORBytes([]byte{1}))) // delete + require.NoError(t, arrA.Set(2, builtin2.CBORBytes([]byte{1}))) // delete - require.NoError(t, arrA.Set(3, runtime.CBORBytes([]byte{0}))) // noop - require.NoError(t, arrB.Set(3, runtime.CBORBytes([]byte{0}))) + require.NoError(t, arrA.Set(3, builtin2.CBORBytes([]byte{0}))) // noop + require.NoError(t, arrB.Set(3, builtin2.CBORBytes([]byte{0}))) - require.NoError(t, arrA.Set(4, runtime.CBORBytes([]byte{0}))) // modify - require.NoError(t, arrB.Set(4, runtime.CBORBytes([]byte{6}))) + require.NoError(t, arrA.Set(4, builtin2.CBORBytes([]byte{0}))) // modify + require.NoError(t, arrB.Set(4, builtin2.CBORBytes([]byte{6}))) - require.NoError(t, arrB.Set(5, runtime.CBORBytes{8})) // add - require.NoError(t, arrB.Set(6, runtime.CBORBytes{9})) // add + require.NoError(t, arrB.Set(5, builtin2.CBORBytes{8})) // add + require.NoError(t, arrB.Set(6, builtin2.CBORBytes{9})) // add changes := new(TestDiffArray) @@ -76,24 +77,24 @@ func TestDiffAdtMap(t *testing.T) { ctxstoreA := newContextStore() ctxstoreB := newContextStore() - mapA := adt0.MakeEmptyMap(ctxstoreA) - mapB := adt0.MakeEmptyMap(ctxstoreB) + mapA := adt2.MakeEmptyMap(ctxstoreA) + mapB := adt2.MakeEmptyMap(ctxstoreB) - require.NoError(t, mapA.Put(abi.UIntKey(0), runtime.CBORBytes([]byte{0}))) // delete + require.NoError(t, mapA.Put(abi.UIntKey(0), builtin2.CBORBytes([]byte{0}))) // delete - require.NoError(t, mapA.Put(abi.UIntKey(1), runtime.CBORBytes([]byte{0}))) // modify - require.NoError(t, mapB.Put(abi.UIntKey(1), runtime.CBORBytes([]byte{1}))) + require.NoError(t, mapA.Put(abi.UIntKey(1), builtin2.CBORBytes([]byte{0}))) // modify + require.NoError(t, mapB.Put(abi.UIntKey(1), builtin2.CBORBytes([]byte{1}))) - require.NoError(t, mapA.Put(abi.UIntKey(2), runtime.CBORBytes([]byte{1}))) // delete + require.NoError(t, mapA.Put(abi.UIntKey(2), builtin2.CBORBytes([]byte{1}))) // delete - require.NoError(t, mapA.Put(abi.UIntKey(3), runtime.CBORBytes([]byte{0}))) // noop - require.NoError(t, mapB.Put(abi.UIntKey(3), runtime.CBORBytes([]byte{0}))) + require.NoError(t, mapA.Put(abi.UIntKey(3), builtin2.CBORBytes([]byte{0}))) // noop + require.NoError(t, mapB.Put(abi.UIntKey(3), builtin2.CBORBytes([]byte{0}))) - require.NoError(t, mapA.Put(abi.UIntKey(4), runtime.CBORBytes([]byte{0}))) // modify - require.NoError(t, mapB.Put(abi.UIntKey(4), runtime.CBORBytes([]byte{6}))) + require.NoError(t, mapA.Put(abi.UIntKey(4), builtin2.CBORBytes([]byte{0}))) // modify + require.NoError(t, mapB.Put(abi.UIntKey(4), builtin2.CBORBytes([]byte{6}))) - require.NoError(t, mapB.Put(abi.UIntKey(5), runtime.CBORBytes{8})) // add - require.NoError(t, mapB.Put(abi.UIntKey(6), runtime.CBORBytes{9})) // add + require.NoError(t, mapB.Put(abi.UIntKey(5), builtin2.CBORBytes{8})) // add + require.NoError(t, mapB.Put(abi.UIntKey(6), builtin2.CBORBytes{9})) // add changes := new(TestDiffMap) @@ -144,7 +145,7 @@ func (t *TestDiffMap) AsKey(key string) (abi.Keyer, error) { } func (t *TestDiffMap) Add(key string, val *typegen.Deferred) error { - v := new(runtime.CBORBytes) + v := new(builtin2.CBORBytes) err := v.UnmarshalCBOR(bytes.NewReader(val.Raw)) if err != nil { return err @@ -161,13 +162,13 @@ func (t *TestDiffMap) Add(key string, val *typegen.Deferred) error { } func (t *TestDiffMap) Modify(key string, from, to *typegen.Deferred) error { - vFrom := new(runtime.CBORBytes) + vFrom := new(builtin2.CBORBytes) err := vFrom.UnmarshalCBOR(bytes.NewReader(from.Raw)) if err != nil { return err } - vTo := new(runtime.CBORBytes) + vTo := new(builtin2.CBORBytes) err = vTo.UnmarshalCBOR(bytes.NewReader(to.Raw)) if err != nil { return err @@ -194,7 +195,7 @@ func (t *TestDiffMap) Modify(key string, from, to *typegen.Deferred) error { } func (t *TestDiffMap) Remove(key string, val *typegen.Deferred) error { - v := new(runtime.CBORBytes) + v := new(builtin2.CBORBytes) err := v.UnmarshalCBOR(bytes.NewReader(val.Raw)) if err != nil { return err @@ -212,7 +213,7 @@ func (t *TestDiffMap) Remove(key string, val *typegen.Deferred) error { type adtMapDiffResult struct { key uint64 - val runtime.CBORBytes + val builtin2.CBORBytes } type TestAdtMapDiffModified struct { @@ -222,7 +223,7 @@ type TestAdtMapDiffModified struct { type adtArrayDiffResult struct { key uint64 - val runtime.CBORBytes + val builtin2.CBORBytes } type TestDiffArray struct { @@ -239,7 +240,7 @@ type TestAdtArrayDiffModified struct { } func (t *TestDiffArray) Add(key uint64, val *typegen.Deferred) error { - v := new(runtime.CBORBytes) + v := new(builtin2.CBORBytes) err := v.UnmarshalCBOR(bytes.NewReader(val.Raw)) if err != nil { return err @@ -252,13 +253,13 @@ func (t *TestDiffArray) Add(key uint64, val *typegen.Deferred) error { } func (t *TestDiffArray) Modify(key uint64, from, to *typegen.Deferred) error { - vFrom := new(runtime.CBORBytes) + vFrom := new(builtin2.CBORBytes) err := vFrom.UnmarshalCBOR(bytes.NewReader(from.Raw)) if err != nil { return err } - vTo := new(runtime.CBORBytes) + vTo := new(builtin2.CBORBytes) err = vTo.UnmarshalCBOR(bytes.NewReader(to.Raw)) if err != nil { return err @@ -280,7 +281,7 @@ func (t *TestDiffArray) Modify(key uint64, from, to *typegen.Deferred) error { } func (t *TestDiffArray) Remove(key uint64, val *typegen.Deferred) error { - v := new(runtime.CBORBytes) + v := new(builtin2.CBORBytes) err := v.UnmarshalCBOR(bytes.NewReader(val.Raw)) if err != nil { return err diff --git a/chain/actors/builtin/builtin.go b/chain/actors/builtin/builtin.go index 350b3a9a6..52d1375b4 100644 --- a/chain/actors/builtin/builtin.go +++ b/chain/actors/builtin/builtin.go @@ -27,6 +27,16 @@ var SaftAddress = makeAddress("t0122") var ReserveAddress = makeAddress("t090") var RootVerifierAddress = makeAddress("t080") +var ( + ExpectedLeadersPerEpoch = builtin0.ExpectedLeadersPerEpoch +) + +const ( + EpochDurationSeconds = builtin0.EpochDurationSeconds + EpochsInDay = builtin0.EpochsInDay + SecondsInDay = builtin0.SecondsInDay +) + // TODO: Why does actors have 2 different versions of this? type SectorInfo = proof0.SectorInfo type PoStProof = proof0.PoStProof diff --git a/chain/actors/policy/policy.go b/chain/actors/policy/policy.go index ba09e4424..c1a971db5 100644 --- a/chain/actors/policy/policy.go +++ b/chain/actors/policy/policy.go @@ -1,6 +1,8 @@ package policy import ( + "sort" + "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/network" "github.com/filecoin-project/lotus/chain/actors" @@ -11,12 +13,14 @@ import ( builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market" miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" + paych2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/paych" verifreg2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/verifreg" ) const ( ChainFinality = miner0.ChainFinality SealRandomnessLookback = ChainFinality + PaychSettleDelay = paych2.SettleDelay ) // SetSupportedProofTypes sets supported proof types, across all actor versions. @@ -114,3 +118,35 @@ func GetWinningPoStSectorSetLookback(nwVer network.Version) abi.ChainEpoch { return ChainFinality } + +func GetMaxSectorExpirationExtension() abi.ChainEpoch { + return miner0.MaxSectorExpirationExtension +} + +// TODO: we'll probably need to abstract over this better in the future. +func GetMaxPoStPartitions(p abi.RegisteredPoStProof) (int, error) { + sectorsPerPart, err := builtin2.PoStProofWindowPoStPartitionSectors(p) + if err != nil { + return 0, err + } + return int(miner2.AddressedSectorsMax / sectorsPerPart), nil +} + +func GetDefaultSectorSize() abi.SectorSize { + // supported proof types are the same across versions. + szs := make([]abi.SectorSize, 0, len(miner2.SupportedProofTypes)) + for spt := range miner2.SupportedProofTypes { + ss, err := spt.SectorSize() + if err != nil { + panic(err) + } + + szs = append(szs, ss) + } + + sort.Slice(szs, func(i, j int) bool { + return szs[i] < szs[j] + }) + + return szs[0] +} diff --git a/chain/actors/policy/policy_test.go b/chain/actors/policy/policy_test.go index 62e7f8964..af600cc75 100644 --- a/chain/actors/policy/policy_test.go +++ b/chain/actors/policy/policy_test.go @@ -6,9 +6,13 @@ import ( "github.com/stretchr/testify/require" "github.com/filecoin-project/go-state-types/abi" + builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" + paych0 "github.com/filecoin-project/specs-actors/actors/builtin/paych" verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" + paych2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/paych" verifreg2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/verifreg" ) @@ -42,9 +46,25 @@ func TestSupportedProofTypes(t *testing.T) { func TestAssumptions(t *testing.T) { require.EqualValues(t, miner0.SupportedProofTypes, miner2.SupportedProofTypes) require.Equal(t, miner0.PreCommitChallengeDelay, miner2.PreCommitChallengeDelay) + require.Equal(t, miner0.MaxSectorExpirationExtension, miner2.MaxSectorExpirationExtension) require.Equal(t, miner0.ChainFinality, miner2.ChainFinality) require.Equal(t, miner0.WPoStChallengeWindow, miner2.WPoStChallengeWindow) require.Equal(t, miner0.WPoStProvingPeriod, miner2.WPoStProvingPeriod) require.Equal(t, miner0.WPoStPeriodDeadlines, miner2.WPoStPeriodDeadlines) + require.Equal(t, miner0.AddressedSectorsMax, miner2.AddressedSectorsMax) + require.Equal(t, paych0.SettleDelay, paych2.SettleDelay) require.True(t, verifreg0.MinVerifiedDealSize.Equals(verifreg2.MinVerifiedDealSize)) } + +func TestPartitionSizes(t *testing.T) { + for p := range abi.PoStSealProofTypes { + sizeNew, err := builtin2.PoStProofWindowPoStPartitionSectors(p) + require.NoError(t, err) + sizeOld, err := builtin0.PoStProofWindowPoStPartitionSectors(p) + if err != nil { + // new proof type. + continue + } + require.Equal(t, sizeOld, sizeNew) + } +} diff --git a/chain/events/state/predicates_test.go b/chain/events/state/predicates_test.go index 461ac4997..9b393f6e4 100644 --- a/chain/events/state/predicates_test.go +++ b/chain/events/state/predicates_test.go @@ -18,14 +18,14 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/crypto" + + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market" + miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" + adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt" + tutils "github.com/filecoin-project/specs-actors/v2/support/testing" + "github.com/filecoin-project/lotus/chain/actors/builtin/market" - builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" - market0 "github.com/filecoin-project/specs-actors/actors/builtin/market" - - miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" - "github.com/filecoin-project/specs-actors/actors/util/adt" - tutils "github.com/filecoin-project/specs-actors/support/testing" - "github.com/filecoin-project/lotus/chain/types" bstore "github.com/filecoin-project/lotus/lib/blockstore" ) @@ -72,24 +72,24 @@ func (m mockAPI) setActor(tsk types.TipSetKey, act *types.Actor) { func TestMarketPredicates(t *testing.T) { ctx := context.Background() bs := bstore.NewTemporarySync() - store := adt.WrapStore(ctx, cbornode.NewCborStore(bs)) + store := adt2.WrapStore(ctx, cbornode.NewCborStore(bs)) - oldDeal1 := &market0.DealState{ + oldDeal1 := &market2.DealState{ SectorStartEpoch: 1, LastUpdatedEpoch: 2, SlashEpoch: 0, } - oldDeal2 := &market0.DealState{ + oldDeal2 := &market2.DealState{ SectorStartEpoch: 4, LastUpdatedEpoch: 5, SlashEpoch: 0, } - oldDeals := map[abi.DealID]*market0.DealState{ + oldDeals := map[abi.DealID]*market2.DealState{ abi.DealID(1): oldDeal1, abi.DealID(2): oldDeal2, } - oldProp1 := &market0.DealProposal{ + oldProp1 := &market2.DealProposal{ PieceCID: dummyCid, PieceSize: 0, VerifiedDeal: false, @@ -101,7 +101,7 @@ func TestMarketPredicates(t *testing.T) { ProviderCollateral: big.Zero(), ClientCollateral: big.Zero(), } - oldProp2 := &market0.DealProposal{ + oldProp2 := &market2.DealProposal{ PieceCID: dummyCid, PieceSize: 0, VerifiedDeal: false, @@ -113,7 +113,7 @@ func TestMarketPredicates(t *testing.T) { ProviderCollateral: big.Zero(), ClientCollateral: big.Zero(), } - oldProps := map[abi.DealID]*market0.DealProposal{ + oldProps := map[abi.DealID]*market2.DealProposal{ abi.DealID(1): oldProp1, abi.DealID(2): oldProp2, } @@ -127,7 +127,7 @@ func TestMarketPredicates(t *testing.T) { oldStateC := createMarketState(ctx, t, store, oldDeals, oldProps, oldBalances) - newDeal1 := &market0.DealState{ + newDeal1 := &market2.DealState{ SectorStartEpoch: 1, LastUpdatedEpoch: 3, SlashEpoch: 0, @@ -136,19 +136,19 @@ func TestMarketPredicates(t *testing.T) { // deal 2 removed // added - newDeal3 := &market0.DealState{ + newDeal3 := &market2.DealState{ SectorStartEpoch: 1, LastUpdatedEpoch: 2, SlashEpoch: 3, } - newDeals := map[abi.DealID]*market0.DealState{ + newDeals := map[abi.DealID]*market2.DealState{ abi.DealID(1): newDeal1, // deal 2 was removed abi.DealID(3): newDeal3, } // added - newProp3 := &market0.DealProposal{ + newProp3 := &market2.DealProposal{ PieceCID: dummyCid, PieceSize: 0, VerifiedDeal: false, @@ -160,7 +160,7 @@ func TestMarketPredicates(t *testing.T) { ProviderCollateral: big.Zero(), ClientCollateral: big.Zero(), } - newProps := map[abi.DealID]*market0.DealProposal{ + newProps := map[abi.DealID]*market2.DealProposal{ abi.DealID(1): oldProp1, // 1 was persisted // prop 2 was removed abi.DealID(3): newProp3, // new @@ -183,8 +183,8 @@ func TestMarketPredicates(t *testing.T) { require.NoError(t, err) api := newMockAPI(bs) - api.setActor(oldState.Key(), &types.Actor{Code: builtin0.StorageMarketActorCodeID, Head: oldStateC}) - api.setActor(newState.Key(), &types.Actor{Code: builtin0.StorageMarketActorCodeID, Head: newStateC}) + api.setActor(oldState.Key(), &types.Actor{Code: builtin2.StorageMarketActorCodeID, Head: oldStateC}) + api.setActor(newState.Key(), &types.Actor{Code: builtin2.StorageMarketActorCodeID, Head: newStateC}) t.Run("deal ID predicate", func(t *testing.T) { preds := NewStatePredicates(api) @@ -243,7 +243,7 @@ func TestMarketPredicates(t *testing.T) { marketCid, err := store.Put(ctx, marketState0) require.NoError(t, err) marketState, err := market.Load(store, &types.Actor{ - Code: builtin0.StorageMarketActorCodeID, + Code: builtin2.StorageMarketActorCodeID, Head: marketCid, }) require.NoError(t, err) @@ -356,7 +356,7 @@ func TestMarketPredicates(t *testing.T) { marketCid, err := store.Put(ctx, marketState0) require.NoError(t, err) marketState, err := market.Load(store, &types.Actor{ - Code: builtin0.StorageMarketActorCodeID, + Code: builtin2.StorageMarketActorCodeID, Head: marketCid, }) require.NoError(t, err) @@ -370,7 +370,7 @@ func TestMarketPredicates(t *testing.T) { func TestMinerSectorChange(t *testing.T) { ctx := context.Background() bs := bstore.NewTemporarySync() - store := adt.WrapStore(ctx, cbornode.NewCborStore(bs)) + store := adt2.WrapStore(ctx, cbornode.NewCborStore(bs)) nextID := uint64(0) nextIDAddrF := func() address.Address { @@ -379,12 +379,12 @@ func TestMinerSectorChange(t *testing.T) { } owner, worker := nextIDAddrF(), nextIDAddrF() - si0 := newSectorOnChainInfo(0, tutils.MakeCID("0", &miner0.SealedCIDPrefix), big.NewInt(0), abi.ChainEpoch(0), abi.ChainEpoch(10)) - si1 := newSectorOnChainInfo(1, tutils.MakeCID("1", &miner0.SealedCIDPrefix), big.NewInt(1), abi.ChainEpoch(1), abi.ChainEpoch(11)) - si2 := newSectorOnChainInfo(2, tutils.MakeCID("2", &miner0.SealedCIDPrefix), big.NewInt(2), abi.ChainEpoch(2), abi.ChainEpoch(11)) + si0 := newSectorOnChainInfo(0, tutils.MakeCID("0", &miner2.SealedCIDPrefix), big.NewInt(0), abi.ChainEpoch(0), abi.ChainEpoch(10)) + si1 := newSectorOnChainInfo(1, tutils.MakeCID("1", &miner2.SealedCIDPrefix), big.NewInt(1), abi.ChainEpoch(1), abi.ChainEpoch(11)) + si2 := newSectorOnChainInfo(2, tutils.MakeCID("2", &miner2.SealedCIDPrefix), big.NewInt(2), abi.ChainEpoch(2), abi.ChainEpoch(11)) oldMinerC := createMinerState(ctx, t, store, owner, worker, []miner.SectorOnChainInfo{si0, si1, si2}) - si3 := newSectorOnChainInfo(3, tutils.MakeCID("3", &miner0.SealedCIDPrefix), big.NewInt(3), abi.ChainEpoch(3), abi.ChainEpoch(12)) + si3 := newSectorOnChainInfo(3, tutils.MakeCID("3", &miner2.SealedCIDPrefix), big.NewInt(3), abi.ChainEpoch(3), abi.ChainEpoch(12)) // 0 delete // 1 extend // 2 same @@ -400,8 +400,8 @@ func TestMinerSectorChange(t *testing.T) { require.NoError(t, err) api := newMockAPI(bs) - api.setActor(oldState.Key(), &types.Actor{Head: oldMinerC, Code: builtin0.StorageMinerActorCodeID}) - api.setActor(newState.Key(), &types.Actor{Head: newMinerC, Code: builtin0.StorageMinerActorCodeID}) + api.setActor(oldState.Key(), &types.Actor{Head: oldMinerC, Code: builtin2.StorageMinerActorCodeID}) + api.setActor(newState.Key(), &types.Actor{Head: newMinerC, Code: builtin2.StorageMinerActorCodeID}) preds := NewStatePredicates(api) @@ -467,7 +467,7 @@ type balance struct { locked abi.TokenAmount } -func createMarketState(ctx context.Context, t *testing.T, store adt.Store, deals map[abi.DealID]*market0.DealState, props map[abi.DealID]*market0.DealProposal, balances map[address.Address]balance) cid.Cid { +func createMarketState(ctx context.Context, t *testing.T, store adt2.Store, deals map[abi.DealID]*market2.DealState, props map[abi.DealID]*market2.DealProposal, balances map[address.Address]balance) cid.Cid { dealRootCid := createDealAMT(ctx, t, store, deals) propRootCid := createProposalAMT(ctx, t, store, props) balancesCids := createBalanceTable(ctx, t, store, balances) @@ -482,16 +482,16 @@ func createMarketState(ctx context.Context, t *testing.T, store adt.Store, deals return stateC } -func createEmptyMarketState(t *testing.T, store adt.Store) *market0.State { - emptyArrayCid, err := adt.MakeEmptyArray(store).Root() +func createEmptyMarketState(t *testing.T, store adt2.Store) *market2.State { + emptyArrayCid, err := adt2.MakeEmptyArray(store).Root() require.NoError(t, err) - emptyMap, err := adt.MakeEmptyMap(store).Root() + emptyMap, err := adt2.MakeEmptyMap(store).Root() require.NoError(t, err) - return market0.ConstructState(emptyArrayCid, emptyMap, emptyMap) + return market2.ConstructState(emptyArrayCid, emptyMap, emptyMap) } -func createDealAMT(ctx context.Context, t *testing.T, store adt.Store, deals map[abi.DealID]*market0.DealState) cid.Cid { - root := adt.MakeEmptyArray(store) +func createDealAMT(ctx context.Context, t *testing.T, store adt2.Store, deals map[abi.DealID]*market2.DealState) cid.Cid { + root := adt2.MakeEmptyArray(store) for dealID, dealState := range deals { err := root.Set(uint64(dealID), dealState) require.NoError(t, err) @@ -501,8 +501,8 @@ func createDealAMT(ctx context.Context, t *testing.T, store adt.Store, deals map return rootCid } -func createProposalAMT(ctx context.Context, t *testing.T, store adt.Store, props map[abi.DealID]*market0.DealProposal) cid.Cid { - root := adt.MakeEmptyArray(store) +func createProposalAMT(ctx context.Context, t *testing.T, store adt2.Store, props map[abi.DealID]*market2.DealProposal) cid.Cid { + root := adt2.MakeEmptyArray(store) for dealID, prop := range props { err := root.Set(uint64(dealID), prop) require.NoError(t, err) @@ -512,16 +512,16 @@ func createProposalAMT(ctx context.Context, t *testing.T, store adt.Store, props return rootCid } -func createBalanceTable(ctx context.Context, t *testing.T, store adt.Store, balances map[address.Address]balance) [2]cid.Cid { - escrowMapRoot := adt.MakeEmptyMap(store) +func createBalanceTable(ctx context.Context, t *testing.T, store adt2.Store, balances map[address.Address]balance) [2]cid.Cid { + escrowMapRoot := adt2.MakeEmptyMap(store) escrowMapRootCid, err := escrowMapRoot.Root() require.NoError(t, err) - escrowRoot, err := adt.AsBalanceTable(store, escrowMapRootCid) + escrowRoot, err := adt2.AsBalanceTable(store, escrowMapRootCid) require.NoError(t, err) - lockedMapRoot := adt.MakeEmptyMap(store) + lockedMapRoot := adt2.MakeEmptyMap(store) lockedMapRootCid, err := lockedMapRoot.Root() require.NoError(t, err) - lockedRoot, err := adt.AsBalanceTable(store, lockedMapRootCid) + lockedRoot, err := adt2.AsBalanceTable(store, lockedMapRootCid) require.NoError(t, err) for addr, balance := range balances { @@ -538,7 +538,7 @@ func createBalanceTable(ctx context.Context, t *testing.T, store adt.Store, bala return [2]cid.Cid{escrowRootCid, lockedRootCid} } -func createMinerState(ctx context.Context, t *testing.T, store adt.Store, owner, worker address.Address, sectors []miner.SectorOnChainInfo) cid.Cid { +func createMinerState(ctx context.Context, t *testing.T, store adt2.Store, owner, worker address.Address, sectors []miner.SectorOnChainInfo) cid.Cid { rootCid := createSectorsAMT(ctx, t, store, sectors) state := createEmptyMinerState(ctx, t, store, owner, worker) @@ -549,20 +549,20 @@ func createMinerState(ctx context.Context, t *testing.T, store adt.Store, owner, return stateC } -func createEmptyMinerState(ctx context.Context, t *testing.T, store adt.Store, owner, worker address.Address) *miner0.State { - emptyArrayCid, err := adt.MakeEmptyArray(store).Root() +func createEmptyMinerState(ctx context.Context, t *testing.T, store adt2.Store, owner, worker address.Address) *miner2.State { + emptyArrayCid, err := adt2.MakeEmptyArray(store).Root() require.NoError(t, err) - emptyMap, err := adt.MakeEmptyMap(store).Root() + emptyMap, err := adt2.MakeEmptyMap(store).Root() require.NoError(t, err) - emptyDeadline, err := store.Put(store.Context(), miner0.ConstructDeadline(emptyArrayCid)) + emptyDeadline, err := store.Put(store.Context(), miner2.ConstructDeadline(emptyArrayCid)) require.NoError(t, err) - emptyVestingFunds := miner0.ConstructVestingFunds() + emptyVestingFunds := miner2.ConstructVestingFunds() emptyVestingFundsCid, err := store.Put(store.Context(), emptyVestingFunds) require.NoError(t, err) - emptyDeadlines := miner0.ConstructDeadlines(emptyDeadline) + emptyDeadlines := miner2.ConstructDeadlines(emptyDeadline) emptyDeadlinesCid, err := store.Put(store.Context(), emptyDeadlines) require.NoError(t, err) @@ -572,16 +572,30 @@ func createEmptyMinerState(ctx context.Context, t *testing.T, store adt.Store, o emptyBitfieldCid, err := store.Put(store.Context(), emptyBitfield) require.NoError(t, err) - state, err := miner0.ConstructState(minerInfo, 123, emptyBitfieldCid, emptyArrayCid, emptyMap, emptyDeadlinesCid, emptyVestingFundsCid) + state, err := miner2.ConstructState(minerInfo, 123, 4, emptyBitfieldCid, emptyArrayCid, emptyMap, emptyDeadlinesCid, emptyVestingFundsCid) require.NoError(t, err) return state } -func createSectorsAMT(ctx context.Context, t *testing.T, store adt.Store, sectors []miner.SectorOnChainInfo) cid.Cid { - root := adt.MakeEmptyArray(store) +func createSectorsAMT(ctx context.Context, t *testing.T, store adt2.Store, sectors []miner.SectorOnChainInfo) cid.Cid { + root := adt2.MakeEmptyArray(store) for _, sector := range sectors { - sector := (miner0.SectorOnChainInfo)(sector) + sector := miner2.SectorOnChainInfo{ + SectorNumber: sector.SectorNumber, + SealProof: sector.SealProof, + SealedCID: sector.SealedCID, + DealIDs: sector.DealIDs, + Activation: sector.Activation, + Expiration: sector.Expiration, + DealWeight: sector.DealWeight, + VerifiedDealWeight: sector.VerifiedDealWeight, + InitialPledge: sector.InitialPledge, + ExpectedDayReward: sector.ExpectedDayReward, + ExpectedStoragePledge: sector.ExpectedStoragePledge, + ReplacedSectorAge: 0, + ReplacedDayReward: big.NewInt(0), + } err := root.Set(uint64(sector.SectorNumber), §or) require.NoError(t, err) } @@ -614,8 +628,8 @@ const ( ) // returns a unique SectorPreCommitInfo with each invocation with SectorNumber set to `sectorNo`. -func newSectorPreCommitInfo(sectorNo abi.SectorNumber, sealed cid.Cid, expiration abi.ChainEpoch) *miner0.SectorPreCommitInfo { - return &miner0.SectorPreCommitInfo{ +func newSectorPreCommitInfo(sectorNo abi.SectorNumber, sealed cid.Cid, expiration abi.ChainEpoch) *miner2.SectorPreCommitInfo { + return &miner2.SectorPreCommitInfo{ SealProof: abi.RegisteredSealProof_StackedDrg32GiBV1, SectorNumber: sectorNo, SealedCID: sealed, @@ -625,7 +639,7 @@ func newSectorPreCommitInfo(sectorNo abi.SectorNumber, sealed cid.Cid, expiratio } } -func dealEquality(expected market0.DealState, actual market.DealState) bool { +func dealEquality(expected market2.DealState, actual market.DealState) bool { return expected.LastUpdatedEpoch == actual.LastUpdatedEpoch && expected.SectorStartEpoch == actual.SectorStartEpoch && expected.SlashEpoch == actual.SlashEpoch diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 288c84219..f2c3832c1 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -8,8 +8,7 @@ import ( "sync/atomic" "time" - "github.com/filecoin-project/specs-actors/actors/runtime/proof" - "github.com/google/uuid" + proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" @@ -50,7 +49,7 @@ const msgsPerBlock = 20 //nolint:deadcode,varcheck var log = logging.Logger("gen") -var ValidWpostForTesting = []proof.PoStProof{{ +var ValidWpostForTesting = []proof2.PoStProof{{ ProofBytes: []byte("valid proof"), }} @@ -227,7 +226,7 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) { }, VerifregRootKey: DefaultVerifregRootkeyActor, RemainderAccount: DefaultRemainderAccountActor, - NetworkName: uuid.New().String(), + NetworkName: "", Timestamp: uint64(build.Clock.Now().Add(-500 * time.Duration(build.BlockDelaySecs) * time.Second).Unix()), } @@ -467,7 +466,7 @@ func (cg *ChainGen) NextTipSetFromMinersWithMessages(base *types.TipSet, miners func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, vrfticket *types.Ticket, eticket *types.ElectionProof, bvals []types.BeaconEntry, height abi.ChainEpoch, - wpost []proof.PoStProof, msgs []*types.SignedMessage) (*types.FullBlock, error) { + wpost []proof2.PoStProof, msgs []*types.SignedMessage) (*types.FullBlock, error) { var ts uint64 if cg.Timestamper != nil { @@ -605,7 +604,7 @@ func (mca mca) WalletSign(ctx context.Context, a address.Address, v []byte) (*cr type WinningPoStProver interface { GenerateCandidates(context.Context, abi.PoStRandomness, uint64) ([]uint64, error) - ComputeProof(context.Context, []proof.SectorInfo, abi.PoStRandomness) ([]proof.PoStProof, error) + ComputeProof(context.Context, []proof2.SectorInfo, abi.PoStRandomness) ([]proof2.PoStProof, error) } type wppProvider struct{} @@ -614,7 +613,7 @@ func (wpp *wppProvider) GenerateCandidates(ctx context.Context, _ abi.PoStRandom return []uint64{0}, nil } -func (wpp *wppProvider) ComputeProof(context.Context, []proof.SectorInfo, abi.PoStRandomness) ([]proof.PoStProof, error) { +func (wpp *wppProvider) ComputeProof(context.Context, []proof2.SectorInfo, abi.PoStRandomness) ([]proof2.PoStProof, error) { return ValidWpostForTesting, nil } @@ -681,15 +680,15 @@ type genFakeVerifier struct{} var _ ffiwrapper.Verifier = (*genFakeVerifier)(nil) -func (m genFakeVerifier) VerifySeal(svi proof.SealVerifyInfo) (bool, error) { +func (m genFakeVerifier) VerifySeal(svi proof2.SealVerifyInfo) (bool, error) { return true, nil } -func (m genFakeVerifier) VerifyWinningPoSt(ctx context.Context, info proof.WinningPoStVerifyInfo) (bool, error) { +func (m genFakeVerifier) VerifyWinningPoSt(ctx context.Context, info proof2.WinningPoStVerifyInfo) (bool, error) { panic("not supported") } -func (m genFakeVerifier) VerifyWindowPoSt(ctx context.Context, info proof.WindowPoStVerifyInfo) (bool, error) { +func (m genFakeVerifier) VerifyWindowPoSt(ctx context.Context, info proof2.WindowPoStVerifyInfo) (bool, error) { panic("not supported") } diff --git a/chain/gen/genesis/miners.go b/chain/gen/genesis/miners.go index 6f0c136a3..49e09d792 100644 --- a/chain/gen/genesis/miners.go +++ b/chain/gen/genesis/miners.go @@ -24,11 +24,12 @@ import ( "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" - "github.com/filecoin-project/specs-actors/actors/builtin" + + builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" power0 "github.com/filecoin-project/specs-actors/actors/builtin/power" reward0 "github.com/filecoin-project/specs-actors/actors/builtin/reward" - "github.com/filecoin-project/specs-actors/actors/runtime" + runtime2 "github.com/filecoin-project/specs-actors/v2/actors/runtime" "github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/store" @@ -47,7 +48,7 @@ func MinerAddress(genesisIndex uint64) address.Address { } type fakedSigSyscalls struct { - runtime.Syscalls + runtime2.Syscalls } func (fss *fakedSigSyscalls) VerifySignature(signature crypto.Signature, signer address.Address, plaintext []byte) error { @@ -55,7 +56,7 @@ func (fss *fakedSigSyscalls) VerifySignature(signature crypto.Signature, signer } func mkFakedSigSyscalls(base vm.SyscallBuilder) vm.SyscallBuilder { - return func(ctx context.Context, cstate *state.StateTree, cst cbor.IpldStore) runtime.Syscalls { + return func(ctx context.Context, cstate *state.StateTree, cst cbor.IpldStore) runtime2.Syscalls { return &fakedSigSyscalls{ base(ctx, cstate, cst), } @@ -114,7 +115,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid } params := mustEnc(constructorParams) - rval, err := doExecValue(ctx, vm, power.Address, m.Owner, m.PowerBalance, builtin.MethodsPower.CreateMiner, params) + rval, err := doExecValue(ctx, vm, power.Address, m.Owner, m.PowerBalance, builtin0.MethodsPower.CreateMiner, params) if err != nil { return cid.Undef, xerrors.Errorf("failed to create genesis miner: %w", err) } @@ -146,7 +147,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid if m.MarketBalance.GreaterThan(big.Zero()) { params := mustEnc(&minerInfos[i].maddr) - _, err := doExecValue(ctx, vm, market.Address, m.Worker, m.MarketBalance, builtin.MethodsMarket.AddBalance, params) + _, err := doExecValue(ctx, vm, market.Address, m.Worker, m.MarketBalance, builtin0.MethodsMarket.AddBalance, params) if err != nil { return cid.Undef, xerrors.Errorf("failed to create genesis miner (add balance): %w", err) } @@ -158,7 +159,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid publish := func(params *market.PublishStorageDealsParams) error { fmt.Printf("publishing %d storage deals on miner %s with worker %s\n", len(params.Deals), params.Deals[0].Proposal.Provider, m.Worker) - ret, err := doExecValue(ctx, vm, market.Address, m.Worker, big.Zero(), builtin.MethodsMarket.PublishStorageDeals, mustEnc(params)) + ret, err := doExecValue(ctx, vm, market.Address, m.Worker, big.Zero(), builtin0.MethodsMarket.PublishStorageDeals, mustEnc(params)) if err != nil { return xerrors.Errorf("failed to create genesis miner (publish deals): %w", err) } @@ -290,17 +291,17 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid pledge = big.Add(pcd, pledge) fmt.Println(types.FIL(pledge)) - _, err = doExecValue(ctx, vm, minerInfos[i].maddr, m.Worker, pledge, builtin.MethodsMiner.PreCommitSector, mustEnc(params)) + _, err = doExecValue(ctx, vm, minerInfos[i].maddr, m.Worker, pledge, builtin0.MethodsMiner.PreCommitSector, mustEnc(params)) if err != nil { return cid.Undef, xerrors.Errorf("failed to confirm presealed sectors: %w", err) } // Commit one-by-one, otherwise pledge math tends to explode - confirmParams := &builtin.ConfirmSectorProofsParams{ + confirmParams := &builtin0.ConfirmSectorProofsParams{ Sectors: []abi.SectorNumber{preseal.SectorID}, } - _, err = doExecValue(ctx, vm, minerInfos[i].maddr, power.Address, big.Zero(), builtin.MethodsMiner.ConfirmSectorProofsValid, mustEnc(confirmParams)) + _, err = doExecValue(ctx, vm, minerInfos[i].maddr, power.Address, big.Zero(), builtin0.MethodsMiner.ConfirmSectorProofsValid, mustEnc(confirmParams)) if err != nil { return cid.Undef, xerrors.Errorf("failed to confirm presealed sectors: %w", err) } @@ -349,7 +350,7 @@ func (fr *fakeRand) GetBeaconRandomness(ctx context.Context, personalization cry } func currentTotalPower(ctx context.Context, vm *vm.VM, maddr address.Address) (*power0.CurrentTotalPowerReturn, error) { - pwret, err := doExecValue(ctx, vm, power.Address, maddr, big.Zero(), builtin.MethodsPower.CurrentTotalPower, nil) + pwret, err := doExecValue(ctx, vm, power.Address, maddr, big.Zero(), builtin0.MethodsPower.CurrentTotalPower, nil) if err != nil { return nil, err } @@ -373,7 +374,7 @@ func dealWeight(ctx context.Context, vm *vm.VM, maddr address.Address, dealIDs [ market.Address, maddr, abi.NewTokenAmount(0), - builtin.MethodsMarket.VerifyDealsForActivation, + builtin0.MethodsMarket.VerifyDealsForActivation, mustEnc(params), ) if err != nil { @@ -387,7 +388,7 @@ func dealWeight(ctx context.Context, vm *vm.VM, maddr address.Address, dealIDs [ } func currentEpochBlockReward(ctx context.Context, vm *vm.VM, maddr address.Address) (*reward0.ThisEpochRewardReturn, error) { - rwret, err := doExecValue(ctx, vm, reward.Address, maddr, big.Zero(), builtin.MethodsReward.ThisEpochReward, nil) + rwret, err := doExecValue(ctx, vm, reward.Address, maddr, big.Zero(), builtin0.MethodsReward.ThisEpochReward, nil) if err != nil { return nil, err } diff --git a/chain/gen/mining.go b/chain/gen/mining.go index 45a089452..94776c5f4 100644 --- a/chain/gen/mining.go +++ b/chain/gen/mining.go @@ -4,7 +4,7 @@ import ( "context" "github.com/filecoin-project/go-state-types/crypto" - "github.com/filecoin-project/specs-actors/actors/util/adt" + blockadt "github.com/filecoin-project/specs-actors/actors/util/adt" cid "github.com/ipfs/go-cid" cbor "github.com/ipfs/go-ipld-cbor" cbg "github.com/whyrusleeping/cbor-gen" @@ -181,8 +181,8 @@ func aggregateSignatures(sigs []crypto.Signature) (*crypto.Signature, error) { }, nil } -func toArray(store adt.Store, cids []cid.Cid) (cid.Cid, error) { - arr := adt.MakeEmptyArray(store) +func toArray(store blockadt.Store, cids []cid.Cid) (cid.Cid, error) { + arr := blockadt.MakeEmptyArray(store) for i, c := range cids { oc := cbg.CborCid(c) if err := arr.Set(uint64(i), &oc); err != nil { diff --git a/chain/market/fundmgr.go b/chain/market/fundmgr.go index 8b5f85a12..c65547285 100644 --- a/chain/market/fundmgr.go +++ b/chain/market/fundmgr.go @@ -8,7 +8,7 @@ import ( "github.com/filecoin-project/go-state-types/big" "go.uber.org/fx" - "github.com/filecoin-project/specs-actors/actors/builtin" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" "github.com/ipfs/go-cid" logging "github.com/ipfs/go-log" @@ -156,7 +156,7 @@ func (fm *FundMgr) EnsureAvailable(ctx context.Context, addr, wallet address.Add To: market.Address, From: wallet, Value: toAdd, - Method: builtin.MethodsMarket.AddBalance, + Method: builtin2.MethodsMarket.AddBalance, Params: params, }, nil) if err != nil { diff --git a/chain/market/fundmgr_test.go b/chain/market/fundmgr_test.go index f5936f73d..7f163201e 100644 --- a/chain/market/fundmgr_test.go +++ b/chain/market/fundmgr_test.go @@ -12,8 +12,8 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/crypto" - "github.com/filecoin-project/specs-actors/actors/builtin" - tutils "github.com/filecoin-project/specs-actors/support/testing" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + tutils "github.com/filecoin-project/specs-actors/v2/support/testing" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/actors" @@ -51,7 +51,7 @@ func addFundsMsg(toAdd abi.TokenAmount, addr address.Address, wallet address.Add To: market.Address, From: wallet, Value: toAdd, - Method: builtin.MethodsMarket.AddBalance, + Method: builtin2.MethodsMarket.AddBalance, Params: params, } } diff --git a/chain/messagepool/messagepool_test.go b/chain/messagepool/messagepool_test.go index 8f6613cad..e31df936c 100644 --- a/chain/messagepool/messagepool_test.go +++ b/chain/messagepool/messagepool_test.go @@ -8,16 +8,18 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + "github.com/ipfs/go-cid" + "github.com/ipfs/go-datastore" + logging "github.com/ipfs/go-log/v2" + + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + "github.com/filecoin-project/lotus/chain/messagepool/gasguess" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types/mock" "github.com/filecoin-project/lotus/chain/wallet" _ "github.com/filecoin-project/lotus/lib/sigs/bls" _ "github.com/filecoin-project/lotus/lib/sigs/secp" - "github.com/filecoin-project/specs-actors/actors/builtin" - "github.com/ipfs/go-cid" - "github.com/ipfs/go-datastore" - logging "github.com/ipfs/go-log/v2" ) func init() { @@ -142,7 +144,7 @@ func (tma *testMpoolAPI) GetActorAfter(addr address.Address, ts *types.TipSet) ( } return &types.Actor{ - Code: builtin.StorageMarketActorCodeID, + Code: builtin2.StorageMarketActorCodeID, Nonce: nonce, Balance: balance, }, nil @@ -449,7 +451,7 @@ func TestLoadLocal(t *testing.T) { tma.setBalance(a1, 1) // in FIL tma.setBalance(a2, 1) // in FIL - gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin.StorageMarketActorCodeID, M: 2}] + gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin2.StorageMarketActorCodeID, M: 2}] msgs := make(map[cid.Cid]struct{}) for i := 0; i < 10; i++ { m := makeTestMessage(w1, a1, a2, uint64(i), gasLimit, uint64(i+1)) @@ -521,7 +523,7 @@ func TestClearAll(t *testing.T) { tma.setBalance(a1, 1) // in FIL tma.setBalance(a2, 1) // in FIL - gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin.StorageMarketActorCodeID, M: 2}] + gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin2.StorageMarketActorCodeID, M: 2}] for i := 0; i < 10; i++ { m := makeTestMessage(w1, a1, a2, uint64(i), gasLimit, uint64(i+1)) _, err := mp.Push(m) @@ -576,7 +578,7 @@ func TestClearNonLocal(t *testing.T) { tma.setBalance(a1, 1) // in FIL tma.setBalance(a2, 1) // in FIL - gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin.StorageMarketActorCodeID, M: 2}] + gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin2.StorageMarketActorCodeID, M: 2}] for i := 0; i < 10; i++ { m := makeTestMessage(w1, a1, a2, uint64(i), gasLimit, uint64(i+1)) _, err := mp.Push(m) @@ -642,7 +644,7 @@ func TestUpdates(t *testing.T) { t.Fatal(err) } - gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin.StorageMarketActorCodeID, M: 2}] + gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin2.StorageMarketActorCodeID, M: 2}] tma.setBalance(a1, 1) // in FIL tma.setBalance(a2, 1) // in FIL diff --git a/chain/messagepool/repub_test.go b/chain/messagepool/repub_test.go index 9cadf24c7..8da64f974 100644 --- a/chain/messagepool/repub_test.go +++ b/chain/messagepool/repub_test.go @@ -5,11 +5,13 @@ import ( "testing" "time" + "github.com/ipfs/go-datastore" + + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + "github.com/filecoin-project/lotus/chain/messagepool/gasguess" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/wallet" - "github.com/filecoin-project/specs-actors/actors/builtin" - "github.com/ipfs/go-datastore" ) func TestRepubMessages(t *testing.T) { @@ -48,7 +50,7 @@ func TestRepubMessages(t *testing.T) { t.Fatal(err) } - gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin.StorageMarketActorCodeID, M: 2}] + gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin2.StorageMarketActorCodeID, M: 2}] tma.setBalance(a1, 1) // in FIL diff --git a/chain/messagepool/selection_test.go b/chain/messagepool/selection_test.go index 37c2f2dc0..08cf286c8 100644 --- a/chain/messagepool/selection_test.go +++ b/chain/messagepool/selection_test.go @@ -13,17 +13,18 @@ import ( "sort" "testing" + "github.com/filecoin-project/go-address" "github.com/ipfs/go-cid" "github.com/ipfs/go-datastore" logging "github.com/ipfs/go-log" - "github.com/filecoin-project/go-address" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/messagepool/gasguess" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types/mock" "github.com/filecoin-project/lotus/chain/wallet" - "github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/lotus/api" _ "github.com/filecoin-project/lotus/lib/sigs/bls" @@ -94,7 +95,7 @@ func TestMessageChains(t *testing.T) { block := tma.nextBlock() ts := mock.TipSet(block) - gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin.StorageMarketActorCodeID, M: 2}] + gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin2.StorageMarketActorCodeID, M: 2}] tma.setBalance(a1, 1) // in FIL @@ -332,7 +333,7 @@ func TestMessageChainSkipping(t *testing.T) { block := tma.nextBlock() ts := mock.TipSet(block) - gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin.StorageMarketActorCodeID, M: 2}] + gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin2.StorageMarketActorCodeID, M: 2}] baseFee := types.NewInt(0) tma.setBalance(a1, 1) // in FIL @@ -409,7 +410,7 @@ func TestBasicMessageSelection(t *testing.T) { ts := mock.TipSet(block) tma.applyBlock(t, block) - gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin.StorageMarketActorCodeID, M: 2}] + gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin2.StorageMarketActorCodeID, M: 2}] tma.setBalance(a1, 1) // in FIL tma.setBalance(a2, 1) // in FIL @@ -553,7 +554,7 @@ func TestMessageSelectionTrimming(t *testing.T) { ts := mock.TipSet(block) tma.applyBlock(t, block) - gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin.StorageMarketActorCodeID, M: 2}] + gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin2.StorageMarketActorCodeID, M: 2}] tma.setBalance(a1, 1) // in FIL tma.setBalance(a2, 1) // in FIL @@ -616,7 +617,7 @@ func TestPriorityMessageSelection(t *testing.T) { ts := mock.TipSet(block) tma.applyBlock(t, block) - gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin.StorageMarketActorCodeID, M: 2}] + gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin2.StorageMarketActorCodeID, M: 2}] tma.setBalance(a1, 1) // in FIL tma.setBalance(a2, 1) // in FIL @@ -695,7 +696,7 @@ func TestPriorityMessageSelection2(t *testing.T) { ts := mock.TipSet(block) tma.applyBlock(t, block) - gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin.StorageMarketActorCodeID, M: 2}] + gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin2.StorageMarketActorCodeID, M: 2}] tma.setBalance(a1, 1) // in FIL tma.setBalance(a2, 1) // in FIL @@ -764,7 +765,7 @@ func TestPriorityMessageSelection3(t *testing.T) { ts := mock.TipSet(block) tma.applyBlock(t, block) - gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin.StorageMarketActorCodeID, M: 2}] + gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin2.StorageMarketActorCodeID, M: 2}] tma.setBalance(a1, 1) // in FIL tma.setBalance(a2, 1) // in FIL @@ -861,7 +862,7 @@ func TestOptimalMessageSelection1(t *testing.T) { ts := mock.TipSet(block) tma.applyBlock(t, block) - gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin.StorageMarketActorCodeID, M: 2}] + gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin2.StorageMarketActorCodeID, M: 2}] tma.setBalance(a1, 1) // in FIL tma.setBalance(a2, 1) // in FIL @@ -928,7 +929,7 @@ func TestOptimalMessageSelection2(t *testing.T) { ts := mock.TipSet(block) tma.applyBlock(t, block) - gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin.StorageMarketActorCodeID, M: 2}] + gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin2.StorageMarketActorCodeID, M: 2}] tma.setBalance(a1, 1) // in FIL tma.setBalance(a2, 1) // in FIL @@ -1006,7 +1007,7 @@ func TestOptimalMessageSelection3(t *testing.T) { ts := mock.TipSet(block) tma.applyBlock(t, block) - gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin.StorageMarketActorCodeID, M: 2}] + gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin2.StorageMarketActorCodeID, M: 2}] for _, a := range actors { tma.setBalance(a, 1) // in FIL @@ -1086,7 +1087,7 @@ func testCompetitiveMessageSelection(t *testing.T, rng *rand.Rand, getPremium fu ts := mock.TipSet(block) tma.applyBlock(t, block) - gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin.StorageMarketActorCodeID, M: 2}] + gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin2.StorageMarketActorCodeID, M: 2}] baseFee := types.NewInt(0) for _, a := range actors { diff --git a/chain/state/statetree_test.go b/chain/state/statetree_test.go index 61e7d8c22..91674337b 100644 --- a/chain/state/statetree_test.go +++ b/chain/state/statetree_test.go @@ -10,7 +10,7 @@ import ( address "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/network" - "github.com/filecoin-project/specs-actors/actors/builtin" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/types" @@ -18,7 +18,7 @@ import ( func BenchmarkStateTreeSet(b *testing.B) { cst := cbor.NewMemCborStore() - st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion)) + st, err := NewStateTree(cst, types.StateTreeVersion1) if err != nil { b.Fatal(err) } @@ -33,8 +33,8 @@ func BenchmarkStateTreeSet(b *testing.B) { } err = st.SetActor(a, &types.Actor{ Balance: types.NewInt(1258812523), - Code: builtin.StorageMinerActorCodeID, - Head: builtin.AccountActorCodeID, + Code: builtin2.StorageMinerActorCodeID, + Head: builtin2.AccountActorCodeID, Nonce: uint64(i), }) if err != nil { @@ -60,8 +60,8 @@ func BenchmarkStateTreeSetFlush(b *testing.B) { } err = st.SetActor(a, &types.Actor{ Balance: types.NewInt(1258812523), - Code: builtin.StorageMinerActorCodeID, - Head: builtin.AccountActorCodeID, + Code: builtin2.StorageMinerActorCodeID, + Head: builtin2.AccountActorCodeID, Nonce: uint64(i), }) if err != nil { @@ -183,8 +183,8 @@ func BenchmarkStateTree10kGetActor(b *testing.B) { } err = st.SetActor(a, &types.Actor{ Balance: types.NewInt(1258812523 + uint64(i)), - Code: builtin.StorageMinerActorCodeID, - Head: builtin.AccountActorCodeID, + Code: builtin2.StorageMinerActorCodeID, + Head: builtin2.AccountActorCodeID, Nonce: uint64(i), }) if err != nil { @@ -226,8 +226,8 @@ func TestSetCache(t *testing.T) { act := &types.Actor{ Balance: types.NewInt(0), - Code: builtin.StorageMinerActorCodeID, - Head: builtin.AccountActorCodeID, + Code: builtin2.StorageMinerActorCodeID, + Head: builtin2.AccountActorCodeID, Nonce: 0, } @@ -270,7 +270,7 @@ func TestSnapshots(t *testing.T) { t.Fatal(err) } - if err := st.SetActor(addrs[0], &types.Actor{Code: builtin.AccountActorCodeID, Head: builtin.AccountActorCodeID, Balance: types.NewInt(55)}); err != nil { + if err := st.SetActor(addrs[0], &types.Actor{Code: builtin2.AccountActorCodeID, Head: builtin2.AccountActorCodeID, Balance: types.NewInt(55)}); err != nil { t.Fatal(err) } @@ -279,7 +279,7 @@ func TestSnapshots(t *testing.T) { t.Fatal(err) } - if err := st.SetActor(addrs[1], &types.Actor{Code: builtin.AccountActorCodeID, Head: builtin.AccountActorCodeID, Balance: types.NewInt(77)}); err != nil { + if err := st.SetActor(addrs[1], &types.Actor{Code: builtin2.AccountActorCodeID, Head: builtin2.AccountActorCodeID, Balance: types.NewInt(77)}); err != nil { t.Fatal(err) } @@ -290,7 +290,7 @@ func TestSnapshots(t *testing.T) { } // more operations in top level call... - if err := st.SetActor(addrs[2], &types.Actor{Code: builtin.AccountActorCodeID, Head: builtin.AccountActorCodeID, Balance: types.NewInt(123)}); err != nil { + if err := st.SetActor(addrs[2], &types.Actor{Code: builtin2.AccountActorCodeID, Head: builtin2.AccountActorCodeID, Balance: types.NewInt(123)}); err != nil { t.Fatal(err) } @@ -299,7 +299,7 @@ func TestSnapshots(t *testing.T) { t.Fatal(err) } - if err := st.SetActor(addrs[3], &types.Actor{Code: builtin.AccountActorCodeID, Head: builtin.AccountActorCodeID, Balance: types.NewInt(5)}); err != nil { + if err := st.SetActor(addrs[3], &types.Actor{Code: builtin2.AccountActorCodeID, Head: builtin2.AccountActorCodeID, Balance: types.NewInt(5)}); err != nil { t.Fatal(err) } diff --git a/chain/stmgr/forks.go b/chain/stmgr/forks.go index 5d6cac51f..e089a1084 100644 --- a/chain/stmgr/forks.go +++ b/chain/stmgr/forks.go @@ -543,17 +543,17 @@ func UpgradeIgnition(ctx context.Context, sm *StateManager, cb ExecCallback, roo return cid.Undef, xerrors.Errorf("second split address: %w", err) } - err = resetGenesisMsigs(ctx, sm, store, tree, build.UpgradeLiftoffHeight) + err = resetGenesisMsigs0(ctx, sm, store, tree, build.UpgradeLiftoffHeight) if err != nil { return cid.Undef, xerrors.Errorf("resetting genesis msig start epochs: %w", err) } - err = splitGenesisMultisig(ctx, cb, split1, store, tree, 50, epoch) + err = splitGenesisMultisig0(ctx, cb, split1, store, tree, 50, epoch) if err != nil { return cid.Undef, xerrors.Errorf("splitting first msig: %w", err) } - err = splitGenesisMultisig(ctx, cb, split2, store, tree, 50, epoch) + err = splitGenesisMultisig0(ctx, cb, split2, store, tree, 50, epoch) if err != nil { return cid.Undef, xerrors.Errorf("splitting second msig: %w", err) } @@ -574,17 +574,17 @@ func UpgradeRefuel(ctx context.Context, sm *StateManager, cb ExecCallback, root return cid.Undef, xerrors.Errorf("getting state tree: %w", err) } - err = resetMultisigVesting(ctx, store, tree, builtin.SaftAddress, 0, 0, big.Zero()) + err = resetMultisigVesting0(ctx, store, tree, builtin.SaftAddress, 0, 0, big.Zero()) if err != nil { return cid.Undef, xerrors.Errorf("tweaking msig vesting: %w", err) } - err = resetMultisigVesting(ctx, store, tree, builtin.ReserveAddress, 0, 0, big.Zero()) + err = resetMultisigVesting0(ctx, store, tree, builtin.ReserveAddress, 0, 0, big.Zero()) if err != nil { return cid.Undef, xerrors.Errorf("tweaking msig vesting: %w", err) } - err = resetMultisigVesting(ctx, store, tree, builtin.RootVerifierAddress, 0, 0, big.Zero()) + err = resetMultisigVesting0(ctx, store, tree, builtin.RootVerifierAddress, 0, 0, big.Zero()) if err != nil { return cid.Undef, xerrors.Errorf("tweaking msig vesting: %w", err) } @@ -679,7 +679,7 @@ func setNetworkName(ctx context.Context, store adt.Store, tree *state.StateTree, return nil } -func splitGenesisMultisig(ctx context.Context, cb ExecCallback, addr address.Address, store adt0.Store, tree *state.StateTree, portions uint64, epoch abi.ChainEpoch) error { +func splitGenesisMultisig0(ctx context.Context, cb ExecCallback, addr address.Address, store adt0.Store, tree *state.StateTree, portions uint64, epoch abi.ChainEpoch) error { if portions < 1 { return xerrors.Errorf("cannot split into 0 portions") } @@ -835,7 +835,7 @@ func makeKeyAddr(splitAddr address.Address, count uint64) (address.Address, erro } // TODO: After the Liftoff epoch, refactor this to use resetMultisigVesting -func resetGenesisMsigs(ctx context.Context, sm *StateManager, store adt0.Store, tree *state.StateTree, startEpoch abi.ChainEpoch) error { +func resetGenesisMsigs0(ctx context.Context, sm *StateManager, store adt0.Store, tree *state.StateTree, startEpoch abi.ChainEpoch) error { gb, err := sm.cs.GetGenesis() if err != nil { return xerrors.Errorf("getting genesis block: %w", err) @@ -885,7 +885,7 @@ func resetGenesisMsigs(ctx context.Context, sm *StateManager, store adt0.Store, return nil } -func resetMultisigVesting(ctx context.Context, store adt0.Store, tree *state.StateTree, addr address.Address, startEpoch abi.ChainEpoch, duration abi.ChainEpoch, balance abi.TokenAmount) error { +func resetMultisigVesting0(ctx context.Context, store adt0.Store, tree *state.StateTree, addr address.Address, startEpoch abi.ChainEpoch, duration abi.ChainEpoch, balance abi.TokenAmount) error { act, err := tree.GetActor(addr) if err != nil { return xerrors.Errorf("getting actor: %w", err) diff --git a/chain/stmgr/forks_test.go b/chain/stmgr/forks_test.go index 0388af6ad..3e9e9e8c0 100644 --- a/chain/stmgr/forks_test.go +++ b/chain/stmgr/forks_test.go @@ -16,9 +16,10 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/cbor" - "github.com/filecoin-project/specs-actors/actors/builtin" - init0 "github.com/filecoin-project/specs-actors/actors/builtin/init" - "github.com/filecoin-project/specs-actors/actors/runtime" + + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + init2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/init" + rt2 "github.com/filecoin-project/specs-actors/v2/actors/runtime" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/actors" @@ -45,7 +46,7 @@ type testActor struct { } // must use existing actor that an account is allowed to exec. -func (testActor) Code() cid.Cid { return builtin.PaymentChannelActorCodeID } +func (testActor) Code() cid.Cid { return builtin2.PaymentChannelActorCodeID } func (testActor) State() cbor.Er { return new(testActorState) } type testActorState struct { @@ -75,7 +76,7 @@ func (ta testActor) Exports() []interface{} { } } -func (ta *testActor) Constructor(rt runtime.Runtime, params *abi.EmptyValue) *abi.EmptyValue { +func (ta *testActor) Constructor(rt rt2.Runtime, params *abi.EmptyValue) *abi.EmptyValue { rt.ValidateImmediateCallerAcceptAny() rt.StateCreate(&testActorState{11}) //fmt.Println("NEW ACTOR ADDRESS IS: ", rt.Receiver()) @@ -83,7 +84,7 @@ func (ta *testActor) Constructor(rt runtime.Runtime, params *abi.EmptyValue) *ab return abi.Empty } -func (ta *testActor) TestMethod(rt runtime.Runtime, params *abi.EmptyValue) *abi.EmptyValue { +func (ta *testActor) TestMethod(rt rt2.Runtime, params *abi.EmptyValue) *abi.EmptyValue { rt.ValidateImmediateCallerAcceptAny() var st testActorState rt.StateReadonly(&st) @@ -175,7 +176,7 @@ func TestForkHeightTriggers(t *testing.T) { var msgs []*types.SignedMessage - enc, err := actors.SerializeParams(&init0.ExecParams{CodeCID: (testActor{}).Code()}) + enc, err := actors.SerializeParams(&init2.ExecParams{CodeCID: (testActor{}).Code()}) if err != nil { t.Fatal(err) } @@ -183,7 +184,7 @@ func TestForkHeightTriggers(t *testing.T) { m := &types.Message{ From: cg.Banker(), To: lotusinit.Address, - Method: builtin.MethodsInit.Exec, + Method: builtin2.MethodsInit.Exec, Params: enc, GasLimit: types.TestGasLimit, } @@ -273,7 +274,7 @@ func TestForkRefuseCall(t *testing.T) { cg.SetStateManager(sm) - enc, err := actors.SerializeParams(&init0.ExecParams{CodeCID: (testActor{}).Code()}) + enc, err := actors.SerializeParams(&init2.ExecParams{CodeCID: (testActor{}).Code()}) if err != nil { t.Fatal(err) } @@ -281,7 +282,7 @@ func TestForkRefuseCall(t *testing.T) { m := &types.Message{ From: cg.Banker(), To: lotusinit.Address, - Method: builtin.MethodsInit.Exec, + Method: builtin2.MethodsInit.Exec, Params: enc, GasLimit: types.TestGasLimit, Value: types.NewInt(0), diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index be14797d9..6558b1ea8 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -6,16 +6,6 @@ import ( "fmt" "sync" - "github.com/filecoin-project/lotus/chain/actors/builtin" - "github.com/filecoin-project/lotus/chain/actors/builtin/verifreg" - - _init "github.com/filecoin-project/lotus/chain/actors/builtin/init" - - "github.com/filecoin-project/lotus/chain/actors/builtin/miner" - - builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" - msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig" - "github.com/ipfs/go-cid" cbor "github.com/ipfs/go-ipld-cbor" logging "github.com/ipfs/go-log/v2" @@ -28,15 +18,24 @@ import ( "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/network" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + + // Used for genesis. + msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig" + "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/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin" + _init "github.com/filecoin-project/lotus/chain/actors/builtin/init" "github.com/filecoin-project/lotus/chain/actors/builtin/market" + "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/actors/builtin/multisig" "github.com/filecoin-project/lotus/chain/actors/builtin/paych" "github.com/filecoin-project/lotus/chain/actors/builtin/power" "github.com/filecoin-project/lotus/chain/actors/builtin/reward" + "github.com/filecoin-project/lotus/chain/actors/builtin/verifreg" "github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" @@ -254,14 +253,14 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp runCron := func(epoch abi.ChainEpoch) error { cronMsg := &types.Message{ - To: builtin0.CronActorAddr, - From: builtin0.SystemActorAddr, + To: builtin2.CronActorAddr, + From: builtin2.SystemActorAddr, Nonce: uint64(epoch), Value: types.NewInt(0), GasFeeCap: types.NewInt(0), GasPremium: types.NewInt(0), GasLimit: build.BlockGasLimit * 10000, // Make super sure this is never too little - Method: builtin0.MethodsCron.EpochTick, + Method: builtin2.MethodsCron.EpochTick, Params: nil, } ret, err := vmi.ApplyImplicitMessage(ctx, cronMsg) @@ -350,14 +349,14 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp } rwMsg := &types.Message{ - From: builtin0.SystemActorAddr, + From: builtin2.SystemActorAddr, To: reward.Address, Nonce: uint64(epoch), Value: types.NewInt(0), GasFeeCap: types.NewInt(0), GasPremium: types.NewInt(0), GasLimit: 1 << 30, - Method: builtin0.MethodsReward.AwardBlockReward, + Method: builtin2.MethodsReward.AwardBlockReward, Params: params, } ret, actErr := vmi.ApplyImplicitMessage(ctx, rwMsg) @@ -974,7 +973,7 @@ func (sm *StateManager) setupGenesisActors(ctx context.Context) error { } else if builtin.IsAccountActor(act.Code) { // should exclude burnt funds actor and "remainder account actor" // should only ever be "faucet" accounts in testnets - if kaddr == builtin0.BurntFundsActorAddr { + if kaddr == builtin2.BurntFundsActorAddr { return nil } @@ -1052,24 +1051,24 @@ func (sm *StateManager) setupPreIgnitionGenesisActorsTestnet(ctx context.Context totalsByEpoch := make(map[abi.ChainEpoch]abi.TokenAmount) // 6 months - sixMonths := abi.ChainEpoch(183 * builtin0.EpochsInDay) + sixMonths := abi.ChainEpoch(183 * builtin2.EpochsInDay) totalsByEpoch[sixMonths] = big.NewInt(49_929_341) totalsByEpoch[sixMonths] = big.Add(totalsByEpoch[sixMonths], big.NewInt(32_787_700)) // 1 year - oneYear := abi.ChainEpoch(365 * builtin0.EpochsInDay) + oneYear := abi.ChainEpoch(365 * builtin2.EpochsInDay) totalsByEpoch[oneYear] = big.NewInt(22_421_712) // 2 years - twoYears := abi.ChainEpoch(2 * 365 * builtin0.EpochsInDay) + twoYears := abi.ChainEpoch(2 * 365 * builtin2.EpochsInDay) totalsByEpoch[twoYears] = big.NewInt(7_223_364) // 3 years - threeYears := abi.ChainEpoch(3 * 365 * builtin0.EpochsInDay) + threeYears := abi.ChainEpoch(3 * 365 * builtin2.EpochsInDay) totalsByEpoch[threeYears] = big.NewInt(87_637_883) // 6 years - sixYears := abi.ChainEpoch(6 * 365 * builtin0.EpochsInDay) + sixYears := abi.ChainEpoch(6 * 365 * builtin2.EpochsInDay) totalsByEpoch[sixYears] = big.NewInt(100_000_000) totalsByEpoch[sixYears] = big.Add(totalsByEpoch[sixYears], big.NewInt(300_000_000)) @@ -1129,24 +1128,24 @@ func (sm *StateManager) setupPostIgnitionGenesisActors(ctx context.Context) erro totalsByEpoch := make(map[abi.ChainEpoch]abi.TokenAmount) // 6 months - sixMonths := abi.ChainEpoch(183 * builtin0.EpochsInDay) + sixMonths := abi.ChainEpoch(183 * builtin2.EpochsInDay) totalsByEpoch[sixMonths] = big.NewInt(49_929_341) totalsByEpoch[sixMonths] = big.Add(totalsByEpoch[sixMonths], big.NewInt(32_787_700)) // 1 year - oneYear := abi.ChainEpoch(365 * builtin0.EpochsInDay) + oneYear := abi.ChainEpoch(365 * builtin2.EpochsInDay) totalsByEpoch[oneYear] = big.NewInt(22_421_712) // 2 years - twoYears := abi.ChainEpoch(2 * 365 * builtin0.EpochsInDay) + twoYears := abi.ChainEpoch(2 * 365 * builtin2.EpochsInDay) totalsByEpoch[twoYears] = big.NewInt(7_223_364) // 3 years - threeYears := abi.ChainEpoch(3 * 365 * builtin0.EpochsInDay) + threeYears := abi.ChainEpoch(3 * 365 * builtin2.EpochsInDay) totalsByEpoch[threeYears] = big.NewInt(87_637_883) // 6 years - sixYears := abi.ChainEpoch(6 * 365 * builtin0.EpochsInDay) + sixYears := abi.ChainEpoch(6 * 365 * builtin2.EpochsInDay) totalsByEpoch[sixYears] = big.NewInt(100_000_000) totalsByEpoch[sixYears] = big.Add(totalsByEpoch[sixYears], big.NewInt(300_000_000)) @@ -1280,7 +1279,7 @@ func (sm *StateManager) GetFilLocked(ctx context.Context, st *state.StateTree) ( } func GetFilBurnt(ctx context.Context, st *state.StateTree) (abi.TokenAmount, error) { - burnt, err := st.GetActor(builtin0.BurntFundsActorAddr) + burnt, err := st.GetActor(builtin2.BurntFundsActorAddr) if err != nil { return big.Zero(), xerrors.Errorf("failed to load burnt actor: %w", err) } diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index de4f947df..2f5acf0db 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -12,6 +12,7 @@ import ( "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/network" + "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/actors/policy" cid "github.com/ipfs/go-cid" @@ -26,7 +27,6 @@ import ( builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" exported0 "github.com/filecoin-project/specs-actors/actors/builtin/exported" - proof0 "github.com/filecoin-project/specs-actors/actors/runtime/proof" exported2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/exported" "github.com/filecoin-project/lotus/api" @@ -159,7 +159,7 @@ func GetMinerSectorSet(ctx context.Context, sm *StateManager, ts *types.TipSet, return mas.LoadSectors(snos) } -func GetSectorsForWinningPoSt(ctx context.Context, pv ffiwrapper.Verifier, sm *StateManager, st cid.Cid, maddr address.Address, rand abi.PoStRandomness) ([]proof0.SectorInfo, error) { +func GetSectorsForWinningPoSt(ctx context.Context, pv ffiwrapper.Verifier, sm *StateManager, st cid.Cid, maddr address.Address, rand abi.PoStRandomness) ([]builtin.SectorInfo, error) { act, err := sm.LoadActorRaw(ctx, maddr, st) if err != nil { return nil, xerrors.Errorf("failed to load miner actor: %w", err) @@ -244,9 +244,9 @@ func GetSectorsForWinningPoSt(ctx context.Context, pv ffiwrapper.Verifier, sm *S return nil, xerrors.Errorf("loading proving sectors: %w", err) } - out := make([]proof0.SectorInfo, len(sectors)) + out := make([]builtin.SectorInfo, len(sectors)) for i, sinfo := range sectors { - out[i] = proof0.SectorInfo{ + out[i] = builtin.SectorInfo{ SealProof: spt, SectorNumber: sinfo.SectorNumber, SealedCID: sinfo.SealedCID, diff --git a/chain/store/store.go b/chain/store/store.go index c6fc0cbef..092e2d308 100644 --- a/chain/store/store.go +++ b/chain/store/store.go @@ -19,12 +19,12 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/specs-actors/actors/builtin" - adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" + blockadt "github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/journal" bstore "github.com/filecoin-project/lotus/lib/blockstore" @@ -815,7 +815,7 @@ func (cs *ChainStore) GetSignedMessage(c cid.Cid) (*types.SignedMessage, error) func (cs *ChainStore) readAMTCids(root cid.Cid) ([]cid.Cid, error) { ctx := context.TODO() // block headers use adt0, for now. - a, err := adt0.AsArray(cs.Store(ctx), root) + a, err := blockadt.AsArray(cs.Store(ctx), root) if err != nil { return nil, xerrors.Errorf("amt load: %w", err) } @@ -1009,7 +1009,7 @@ func (cs *ChainStore) MessagesForBlock(b *types.BlockHeader) ([]*types.Message, func (cs *ChainStore) GetParentReceipt(b *types.BlockHeader, i int) (*types.MessageReceipt, error) { ctx := context.TODO() // block headers use adt0, for now. - a, err := adt0.AsArray(cs.Store(ctx), b.ParentMessageReceipts) + a, err := blockadt.AsArray(cs.Store(ctx), b.ParentMessageReceipts) if err != nil { return nil, xerrors.Errorf("amt load: %w", err) } diff --git a/chain/sub/incoming.go b/chain/sub/incoming.go index 99ca2fc65..625c8d1e2 100644 --- a/chain/sub/incoming.go +++ b/chain/sub/incoming.go @@ -23,7 +23,7 @@ import ( "go.opencensus.io/stats" "go.opencensus.io/tag" - adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" + blockadt "github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain" @@ -391,9 +391,9 @@ func (bv *BlockValidator) isChainNearSynced() bool { func (bv *BlockValidator) validateMsgMeta(ctx context.Context, msg *types.BlockMsg) error { // TODO there has to be a simpler way to do this without the blockstore dance // block headers use adt0 - store := adt0.WrapStore(ctx, cbor.NewCborStore(blockstore.NewTemporary())) - bmArr := adt0.MakeEmptyArray(store) - smArr := adt0.MakeEmptyArray(store) + store := blockadt.WrapStore(ctx, cbor.NewCborStore(blockstore.NewTemporary())) + bmArr := blockadt.MakeEmptyArray(store) + smArr := blockadt.MakeEmptyArray(store) for i, m := range msg.BlsMessages { c := cbg.CborCid(m) diff --git a/chain/sync.go b/chain/sync.go index 2c7408113..dda6f88d8 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -15,8 +15,6 @@ import ( "github.com/filecoin-project/lotus/node/modules/dtypes" - "github.com/filecoin-project/specs-actors/actors/runtime/proof" - "github.com/Gurpartap/async" "github.com/hashicorp/go-multierror" blocks "github.com/ipfs/go-block-format" @@ -37,7 +35,11 @@ import ( "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" blst "github.com/supranational/blst/bindings/go" - adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" + // named msgarray here to make it clear that these are the types used by + // messages, regardless of specs-actors version. + blockadt "github.com/filecoin-project/specs-actors/actors/util/adt" + + proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" @@ -463,9 +465,9 @@ func zipTipSetAndMessages(bs cbor.IpldStore, ts *types.TipSet, allbmsgs []*types // of both types (BLS and Secpk). func computeMsgMeta(bs cbor.IpldStore, bmsgCids, smsgCids []cid.Cid) (cid.Cid, error) { // block headers use adt0 - store := adt0.WrapStore(context.TODO(), bs) - bmArr := adt0.MakeEmptyArray(store) - smArr := adt0.MakeEmptyArray(store) + store := blockadt.WrapStore(context.TODO(), bs) + bmArr := blockadt.MakeEmptyArray(store) + smArr := blockadt.MakeEmptyArray(store) for i, m := range bmsgCids { c := cbg.CborCid(m) @@ -1015,7 +1017,7 @@ func (syncer *Syncer) VerifyWinningPoStProof(ctx context.Context, h *types.Block return xerrors.Errorf("getting winning post sector set: %w", err) } - ok, err := ffiwrapper.ProofVerifier.VerifyWinningPoSt(ctx, proof.WinningPoStVerifyInfo{ + ok, err := ffiwrapper.ProofVerifier.VerifyWinningPoSt(ctx, proof2.WinningPoStVerifyInfo{ Randomness: rand, Proofs: h.WinPoStProof, ChallengedSectors: sectors, @@ -1110,9 +1112,9 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock // Validate message arrays in a temporary blockstore. tmpbs := bstore.NewTemporary() - tmpstore := adt0.WrapStore(ctx, cbor.NewCborStore(tmpbs)) + tmpstore := blockadt.WrapStore(ctx, cbor.NewCborStore(tmpbs)) - bmArr := adt0.MakeEmptyArray(tmpstore) + bmArr := blockadt.MakeEmptyArray(tmpstore) for i, m := range b.BlsMessages { if err := checkMsg(m); err != nil { return xerrors.Errorf("block had invalid bls message at index %d: %w", i, err) @@ -1129,7 +1131,7 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock } } - smArr := adt0.MakeEmptyArray(tmpstore) + smArr := blockadt.MakeEmptyArray(tmpstore) for i, m := range b.SecpkMessages { if err := checkMsg(m); err != nil { return xerrors.Errorf("block had invalid secpk message at index %d: %w", i, err) diff --git a/chain/sync_test.go b/chain/sync_test.go index 0a8174c41..559a73bf5 100644 --- a/chain/sync_test.go +++ b/chain/sync_test.go @@ -7,8 +7,6 @@ import ( "testing" "time" - "github.com/filecoin-project/specs-actors/actors/runtime/proof" - "github.com/ipfs/go-cid" ds "github.com/ipfs/go-datastore" @@ -20,6 +18,8 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors/policy" @@ -469,8 +469,8 @@ func (wpp badWpp) GenerateCandidates(context.Context, abi.PoStRandomness, uint64 return []uint64{1}, nil } -func (wpp badWpp) ComputeProof(context.Context, []proof.SectorInfo, abi.PoStRandomness) ([]proof.PoStProof, error) { - return []proof.PoStProof{ +func (wpp badWpp) ComputeProof(context.Context, []proof2.SectorInfo, abi.PoStRandomness) ([]proof2.PoStProof, error) { + return []proof2.PoStProof{ { PoStProof: abi.RegisteredPoStProof_StackedDrgWinning2KiBV1, ProofBytes: []byte("evil"), diff --git a/chain/types/blockheader.go b/chain/types/blockheader.go index 0ec33fe42..4db6788e1 100644 --- a/chain/types/blockheader.go +++ b/chain/types/blockheader.go @@ -4,7 +4,7 @@ import ( "bytes" "math/big" - "github.com/filecoin-project/specs-actors/actors/runtime/proof" + proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" "github.com/minio/blake2b-simd" @@ -55,7 +55,7 @@ type BlockHeader struct { BeaconEntries []BeaconEntry // 3 - WinPoStProof []proof.PoStProof // 4 + WinPoStProof []proof2.PoStProof // 4 Parents []cid.Cid // 5 diff --git a/chain/types/blockheader_test.go b/chain/types/blockheader_test.go index f5faac3b3..6674f1205 100644 --- a/chain/types/blockheader_test.go +++ b/chain/types/blockheader_test.go @@ -7,7 +7,7 @@ import ( "reflect" "testing" - "github.com/filecoin-project/specs-actors/actors/runtime/proof" + proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" cid "github.com/ipfs/go-cid" "github.com/stretchr/testify/require" @@ -82,7 +82,7 @@ func TestInteropBH(t *testing.T) { t.Fatal(err) } - posts := []proof.PoStProof{ + posts := []proof2.PoStProof{ {PoStProof: abi.RegisteredPoStProof_StackedDrgWinning2KiBV1, ProofBytes: []byte{0x07}}, } diff --git a/chain/types/message_test.go b/chain/types/message_test.go index dab8e0939..a5a00f66b 100644 --- a/chain/types/message_test.go +++ b/chain/types/message_test.go @@ -9,13 +9,15 @@ import ( "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/crypto" - "github.com/filecoin-project/specs-actors/actors/builtin" + + // we can't import the actors shims from this package due to cyclic imports. + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" ) func TestEqualCall(t *testing.T) { m1 := &Message{ - To: builtin.StoragePowerActorAddr, - From: builtin.SystemActorAddr, + To: builtin2.StoragePowerActorAddr, + From: builtin2.SystemActorAddr, Nonce: 34, Value: big.Zero(), @@ -28,8 +30,8 @@ func TestEqualCall(t *testing.T) { } m2 := &Message{ - To: builtin.StoragePowerActorAddr, - From: builtin.SystemActorAddr, + To: builtin2.StoragePowerActorAddr, + From: builtin2.SystemActorAddr, Nonce: 34, Value: big.Zero(), @@ -42,8 +44,8 @@ func TestEqualCall(t *testing.T) { } m3 := &Message{ - To: builtin.StoragePowerActorAddr, - From: builtin.SystemActorAddr, + To: builtin2.StoragePowerActorAddr, + From: builtin2.SystemActorAddr, Nonce: 34, Value: big.Zero(), @@ -56,8 +58,8 @@ func TestEqualCall(t *testing.T) { } m4 := &Message{ - To: builtin.StoragePowerActorAddr, - From: builtin.SystemActorAddr, + To: builtin2.StoragePowerActorAddr, + From: builtin2.SystemActorAddr, Nonce: 34, Value: big.Zero(), @@ -76,8 +78,8 @@ func TestEqualCall(t *testing.T) { func TestMessageJson(t *testing.T) { m := &Message{ - To: builtin.StoragePowerActorAddr, - From: builtin.SystemActorAddr, + To: builtin2.StoragePowerActorAddr, + From: builtin2.SystemActorAddr, Nonce: 34, Value: big.Zero(), @@ -105,8 +107,8 @@ func TestMessageJson(t *testing.T) { func TestSignedMessageJson(t *testing.T) { m := Message{ - To: builtin.StoragePowerActorAddr, - From: builtin.SystemActorAddr, + To: builtin2.StoragePowerActorAddr, + From: builtin2.SystemActorAddr, Nonce: 34, Value: big.Zero(), diff --git a/chain/vm/gas.go b/chain/vm/gas.go index 6802013e5..cbe5bab13 100644 --- a/chain/vm/gas.go +++ b/chain/vm/gas.go @@ -3,13 +3,13 @@ package vm import ( "fmt" - "github.com/filecoin-project/specs-actors/actors/runtime/proof" + vmr2 "github.com/filecoin-project/specs-actors/v2/actors/runtime" + proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" "github.com/filecoin-project/go-address" addr "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/crypto" - vmr "github.com/filecoin-project/specs-actors/actors/runtime" "github.com/ipfs/go-cid" ) @@ -78,8 +78,8 @@ type Pricelist interface { OnVerifySignature(sigType crypto.SigType, planTextSize int) (GasCharge, error) OnHashing(dataSize int) GasCharge OnComputeUnsealedSectorCid(proofType abi.RegisteredSealProof, pieces []abi.PieceInfo) GasCharge - OnVerifySeal(info proof.SealVerifyInfo) GasCharge - OnVerifyPost(info proof.WindowPoStVerifyInfo) GasCharge + OnVerifySeal(info proof2.SealVerifyInfo) GasCharge + OnVerifyPost(info proof2.WindowPoStVerifyInfo) GasCharge OnVerifyConsensusFault() GasCharge } @@ -150,7 +150,7 @@ func PricelistByEpoch(epoch abi.ChainEpoch) Pricelist { } type pricedSyscalls struct { - under vmr.Syscalls + under vmr2.Syscalls pl Pricelist chargeGas func(GasCharge) } @@ -184,7 +184,7 @@ func (ps pricedSyscalls) ComputeUnsealedSectorCID(reg abi.RegisteredSealProof, p } // Verifies a sector seal proof. -func (ps pricedSyscalls) VerifySeal(vi proof.SealVerifyInfo) error { +func (ps pricedSyscalls) VerifySeal(vi proof2.SealVerifyInfo) error { ps.chargeGas(ps.pl.OnVerifySeal(vi)) defer ps.chargeGas(gasOnActorExec) @@ -192,7 +192,7 @@ func (ps pricedSyscalls) VerifySeal(vi proof.SealVerifyInfo) error { } // Verifies a proof of spacetime. -func (ps pricedSyscalls) VerifyPoSt(vi proof.WindowPoStVerifyInfo) error { +func (ps pricedSyscalls) VerifyPoSt(vi proof2.WindowPoStVerifyInfo) error { ps.chargeGas(ps.pl.OnVerifyPost(vi)) defer ps.chargeGas(gasOnActorExec) @@ -209,14 +209,14 @@ func (ps pricedSyscalls) VerifyPoSt(vi proof.WindowPoStVerifyInfo) error { // the "parent grinding fault", in which case it must be the sibling of h1 (same parent tipset) and one of the // blocks in the parent of h2 (i.e. h2's grandparent). // Returns nil and an error if the headers don't prove a fault. -func (ps pricedSyscalls) VerifyConsensusFault(h1 []byte, h2 []byte, extra []byte) (*vmr.ConsensusFault, error) { +func (ps pricedSyscalls) VerifyConsensusFault(h1 []byte, h2 []byte, extra []byte) (*vmr2.ConsensusFault, error) { ps.chargeGas(ps.pl.OnVerifyConsensusFault()) defer ps.chargeGas(gasOnActorExec) return ps.under.VerifyConsensusFault(h1, h2, extra) } -func (ps pricedSyscalls) BatchVerifySeals(inp map[address.Address][]proof.SealVerifyInfo) (map[address.Address][]bool, error) { +func (ps pricedSyscalls) BatchVerifySeals(inp map[address.Address][]proof2.SealVerifyInfo) (map[address.Address][]bool, error) { count := int64(0) for _, svis := range inp { count += int64(len(svis)) diff --git a/chain/vm/gas_v0.go b/chain/vm/gas_v0.go index bfb49c345..7e879b8c3 100644 --- a/chain/vm/gas_v0.go +++ b/chain/vm/gas_v0.go @@ -3,12 +3,12 @@ package vm import ( "fmt" - "github.com/filecoin-project/specs-actors/actors/runtime/proof" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/crypto" - builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" ) type scalingCost struct { @@ -112,14 +112,14 @@ func (pl *pricelistV0) OnMethodInvocation(value abi.TokenAmount, methodNum abi.M if big.Cmp(value, abi.NewTokenAmount(0)) != 0 { ret += pl.sendTransferFunds - if methodNum == builtin0.MethodSend { + if methodNum == builtin2.MethodSend { // transfer only ret += pl.sendTransferOnlyPremium } extra += "t" } - if methodNum != builtin0.MethodSend { + if methodNum != builtin2.MethodSend { extra += "i" // running actors is cheaper becase we hand over to actors ret += pl.sendInvokeMethod @@ -175,14 +175,14 @@ func (pl *pricelistV0) OnComputeUnsealedSectorCid(proofType abi.RegisteredSealPr } // OnVerifySeal -func (pl *pricelistV0) OnVerifySeal(info proof.SealVerifyInfo) GasCharge { +func (pl *pricelistV0) OnVerifySeal(info proof2.SealVerifyInfo) GasCharge { // TODO: this needs more cost tunning, check with @lotus // this is not used return newGasCharge("OnVerifySeal", pl.verifySealBase, 0) } // OnVerifyPost -func (pl *pricelistV0) OnVerifyPost(info proof.WindowPoStVerifyInfo) GasCharge { +func (pl *pricelistV0) OnVerifyPost(info proof2.WindowPoStVerifyInfo) GasCharge { sectorSize := "unknown" var proofType abi.RegisteredPoStProof diff --git a/chain/vm/invoker_test.go b/chain/vm/invoker_test.go index 4005dd42f..bce385b02 100644 --- a/chain/vm/invoker_test.go +++ b/chain/vm/invoker_test.go @@ -5,16 +5,17 @@ import ( "io" "testing" - "github.com/filecoin-project/go-state-types/abi" - cbor "github.com/ipfs/go-ipld-cbor" "github.com/stretchr/testify/assert" cbg "github.com/whyrusleeping/cbor-gen" + "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/exitcode" + + runtime2 "github.com/filecoin-project/specs-actors/v2/actors/runtime" + "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/aerrors" - "github.com/filecoin-project/specs-actors/actors/runtime" ) type basicContract struct{} @@ -61,17 +62,17 @@ func (b basicContract) Exports() []interface{} { } } -func (basicContract) InvokeSomething0(rt runtime.Runtime, params *basicParams) *abi.EmptyValue { +func (basicContract) InvokeSomething0(rt runtime2.Runtime, params *basicParams) *abi.EmptyValue { rt.Abortf(exitcode.ExitCode(params.B), "params.B") return nil } -func (basicContract) BadParam(rt runtime.Runtime, params *basicParams) *abi.EmptyValue { +func (basicContract) BadParam(rt runtime2.Runtime, params *basicParams) *abi.EmptyValue { rt.Abortf(255, "bad params") return nil } -func (basicContract) InvokeSomething10(rt runtime.Runtime, params *basicParams) *abi.EmptyValue { +func (basicContract) InvokeSomething10(rt runtime2.Runtime, params *basicParams) *abi.EmptyValue { rt.Abortf(exitcode.ExitCode(params.B+10), "params.B") return nil } diff --git a/chain/vm/mkactor.go b/chain/vm/mkactor.go index 22a2acb8b..56eac1e0c 100644 --- a/chain/vm/mkactor.go +++ b/chain/vm/mkactor.go @@ -15,6 +15,7 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/lotus/chain/actors/aerrors" + "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/types" ) @@ -56,7 +57,7 @@ func TryCreateAccountActor(rt *Runtime, addr address.Address) (*types.Actor, add } // call constructor on account - _, aerr = rt.internalSend(builtin0.SystemActorAddr, addrID, builtin0.MethodsAccount.Constructor, big.Zero(), p) + _, aerr = rt.internalSend(builtin.SystemActorAddr, addrID, builtin2.MethodsAccount.Constructor, big.Zero(), p) if aerr != nil { return nil, address.Undef, aerrors.Wrap(aerr, "failed to invoke account constructor") } diff --git a/chain/vm/runtime.go b/chain/vm/runtime.go index ed5501fe9..6e36e8e87 100644 --- a/chain/vm/runtime.go +++ b/chain/vm/runtime.go @@ -53,8 +53,8 @@ func (m *Message) ValueReceived() abi.TokenAmount { var EnableGasTracing = false type Runtime struct { - rt0.Message - rt0.Syscalls + rt2.Message + rt2.Syscalls ctx context.Context diff --git a/chain/vm/syscalls.go b/chain/vm/syscalls.go index a7f5dab0c..347c3409c 100644 --- a/chain/vm/syscalls.go +++ b/chain/vm/syscalls.go @@ -7,8 +7,6 @@ import ( goruntime "runtime" "sync" - "github.com/filecoin-project/specs-actors/actors/runtime/proof" - "github.com/filecoin-project/go-address" "github.com/ipfs/go-cid" cbor "github.com/ipfs/go-ipld-cbor" @@ -23,7 +21,9 @@ import ( "github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/lib/sigs" - "github.com/filecoin-project/specs-actors/actors/runtime" + + runtime2 "github.com/filecoin-project/specs-actors/v2/actors/runtime" + proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" ) @@ -34,10 +34,10 @@ func init() { // Actual type is defined in chain/types/vmcontext.go because the VMContext interface is there -type SyscallBuilder func(ctx context.Context, cstate *state.StateTree, cst cbor.IpldStore) runtime.Syscalls +type SyscallBuilder func(ctx context.Context, cstate *state.StateTree, cst cbor.IpldStore) runtime2.Syscalls func Syscalls(verifier ffiwrapper.Verifier) SyscallBuilder { - return func(ctx context.Context, cstate *state.StateTree, cst cbor.IpldStore) runtime.Syscalls { + return func(ctx context.Context, cstate *state.StateTree, cst cbor.IpldStore) runtime2.Syscalls { return &syscallShim{ ctx: ctx, @@ -79,7 +79,7 @@ func (ss *syscallShim) HashBlake2b(data []byte) [32]byte { // Checks validity of the submitted consensus fault with the two block headers needed to prove the fault // and an optional extra one to check common ancestry (as needed). // Note that the blocks are ordered: the method requires a.Epoch() <= b.Epoch(). -func (ss *syscallShim) VerifyConsensusFault(a, b, extra []byte) (*runtime.ConsensusFault, error) { +func (ss *syscallShim) VerifyConsensusFault(a, b, extra []byte) (*runtime2.ConsensusFault, error) { // Note that block syntax is not validated. Any validly signed block will be accepted pursuant to the below conditions. // Whether or not it could ever have been accepted in a chain is not checked/does not matter here. // for that reason when checking block parent relationships, rather than instantiating a Tipset to do so @@ -115,14 +115,14 @@ func (ss *syscallShim) VerifyConsensusFault(a, b, extra []byte) (*runtime.Consen } // (2) check for the consensus faults themselves - var consensusFault *runtime.ConsensusFault + var consensusFault *runtime2.ConsensusFault // (a) double-fork mining fault if blockA.Height == blockB.Height { - consensusFault = &runtime.ConsensusFault{ + consensusFault = &runtime2.ConsensusFault{ Target: blockA.Miner, Epoch: blockB.Height, - Type: runtime.ConsensusFaultDoubleForkMining, + Type: runtime2.ConsensusFaultDoubleForkMining, } } @@ -130,10 +130,10 @@ func (ss *syscallShim) VerifyConsensusFault(a, b, extra []byte) (*runtime.Consen // strictly speaking no need to compare heights based on double fork mining check above, // but at same height this would be a different fault. if types.CidArrsEqual(blockA.Parents, blockB.Parents) && blockA.Height != blockB.Height { - consensusFault = &runtime.ConsensusFault{ + consensusFault = &runtime2.ConsensusFault{ Target: blockA.Miner, Epoch: blockB.Height, - Type: runtime.ConsensusFaultTimeOffsetMining, + Type: runtime2.ConsensusFaultTimeOffsetMining, } } @@ -153,10 +153,10 @@ func (ss *syscallShim) VerifyConsensusFault(a, b, extra []byte) (*runtime.Consen if types.CidArrsEqual(blockA.Parents, blockC.Parents) && blockA.Height == blockC.Height && types.CidArrsContains(blockB.Parents, blockC.Cid()) && !types.CidArrsContains(blockB.Parents, blockA.Cid()) { - consensusFault = &runtime.ConsensusFault{ + consensusFault = &runtime2.ConsensusFault{ Target: blockA.Miner, Epoch: blockB.Height, - Type: runtime.ConsensusFaultParentGrinding, + Type: runtime2.ConsensusFaultParentGrinding, } } } @@ -215,7 +215,7 @@ func (ss *syscallShim) VerifyBlockSig(blk *types.BlockHeader) error { return nil } -func (ss *syscallShim) VerifyPoSt(proof proof.WindowPoStVerifyInfo) error { +func (ss *syscallShim) VerifyPoSt(proof proof2.WindowPoStVerifyInfo) error { ok, err := ss.verifier.VerifyWindowPoSt(context.TODO(), proof) if err != nil { return err @@ -226,7 +226,7 @@ func (ss *syscallShim) VerifyPoSt(proof proof.WindowPoStVerifyInfo) error { return nil } -func (ss *syscallShim) VerifySeal(info proof.SealVerifyInfo) error { +func (ss *syscallShim) VerifySeal(info proof2.SealVerifyInfo) error { //_, span := trace.StartSpan(ctx, "ValidatePoRep") //defer span.End() @@ -266,7 +266,7 @@ func (ss *syscallShim) VerifySignature(sig crypto.Signature, addr address.Addres var BatchSealVerifyParallelism = goruntime.NumCPU() -func (ss *syscallShim) BatchVerifySeals(inp map[address.Address][]proof.SealVerifyInfo) (map[address.Address][]bool, error) { +func (ss *syscallShim) BatchVerifySeals(inp map[address.Address][]proof2.SealVerifyInfo) (map[address.Address][]bool, error) { out := make(map[address.Address][]bool) sema := make(chan struct{}, BatchSealVerifyParallelism) @@ -278,7 +278,7 @@ func (ss *syscallShim) BatchVerifySeals(inp map[address.Address][]proof.SealVeri for i, s := range seals { wg.Add(1) - go func(ma address.Address, ix int, svi proof.SealVerifyInfo, res []bool) { + go func(ma address.Address, ix int, svi proof2.SealVerifyInfo, res []bool) { defer wg.Done() sema <- struct{}{} diff --git a/cli/client.go b/cli/client.go index 01de8801c..83c452555 100644 --- a/cli/client.go +++ b/cli/client.go @@ -24,7 +24,6 @@ import ( "github.com/fatih/color" datatransfer "github.com/filecoin-project/go-data-transfer" "github.com/filecoin-project/go-fil-markets/retrievalmarket" - "github.com/filecoin-project/specs-actors/actors/builtin" "github.com/ipfs/go-cid" "github.com/ipfs/go-cidutil/cidenc" "github.com/libp2p/go-libp2p-core/peer" @@ -41,6 +40,7 @@ import ( "github.com/filecoin-project/lotus/api" lapi "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/actors/builtin/market" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/lib/tablewriter" diff --git a/cli/multisig.go b/cli/multisig.go index 7cf7ed750..ebdc8ef7d 100644 --- a/cli/multisig.go +++ b/cli/multisig.go @@ -28,8 +28,8 @@ import ( "github.com/urfave/cli/v2" "golang.org/x/xerrors" - init0 "github.com/filecoin-project/specs-actors/actors/builtin/init" - msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig" + init2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/init" + msig2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/multisig" "github.com/filecoin-project/lotus/api/apibstore" "github.com/filecoin-project/lotus/build" @@ -167,7 +167,7 @@ var msigCreateCmd = &cli.Command{ // get address of newly created miner - var execreturn init0.ExecReturn + var execreturn init2.ExecReturn if err := execreturn.UnmarshalCBOR(bytes.NewReader(wait.Receipt.Return)); err != nil { return err } @@ -427,7 +427,7 @@ var msigProposeCmd = &cli.Command{ return fmt.Errorf("proposal returned exit %d", wait.Receipt.ExitCode) } - var retval msig0.ProposeReturn + var retval msig2.ProposeReturn if err := retval.UnmarshalCBOR(bytes.NewReader(wait.Receipt.Return)); err != nil { return fmt.Errorf("failed to unmarshal propose return value: %w", err) } @@ -1160,7 +1160,7 @@ var msigLockProposeCmd = &cli.Command{ from = defaddr } - params, actErr := actors.SerializeParams(&msig0.LockBalanceParams{ + params, actErr := actors.SerializeParams(&msig2.LockBalanceParams{ StartEpoch: abi.ChainEpoch(start), UnlockDuration: abi.ChainEpoch(duration), Amount: abi.NewTokenAmount(amount.Int64()), @@ -1257,7 +1257,7 @@ var msigLockApproveCmd = &cli.Command{ from = defaddr } - params, actErr := actors.SerializeParams(&msig0.LockBalanceParams{ + params, actErr := actors.SerializeParams(&msig2.LockBalanceParams{ StartEpoch: abi.ChainEpoch(start), UnlockDuration: abi.ChainEpoch(duration), Amount: abi.NewTokenAmount(amount.Int64()), @@ -1349,7 +1349,7 @@ var msigLockCancelCmd = &cli.Command{ from = defaddr } - params, actErr := actors.SerializeParams(&msig0.LockBalanceParams{ + params, actErr := actors.SerializeParams(&msig2.LockBalanceParams{ StartEpoch: abi.ChainEpoch(start), UnlockDuration: abi.ChainEpoch(duration), Amount: abi.NewTokenAmount(amount.Int64()), @@ -1488,7 +1488,7 @@ var msigProposeThresholdCmd = &cli.Command{ from = defaddr } - params, actErr := actors.SerializeParams(&msig0.ChangeNumApprovalsThresholdParams{ + params, actErr := actors.SerializeParams(&msig2.ChangeNumApprovalsThresholdParams{ NewThreshold: newM, }) diff --git a/cmd/lotus-bench/caching_verifier.go b/cmd/lotus-bench/caching_verifier.go index 51ab696f7..5b434c762 100644 --- a/cmd/lotus-bench/caching_verifier.go +++ b/cmd/lotus-bench/caching_verifier.go @@ -7,7 +7,7 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" - "github.com/filecoin-project/specs-actors/actors/runtime/proof" + proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" "github.com/ipfs/go-datastore" "github.com/minio/blake2b-simd" cbg "github.com/whyrusleeping/cbor-gen" @@ -78,15 +78,16 @@ func (cv cachingVerifier) withCache(execute func() (bool, error), param cbg.CBOR } } -func (cv *cachingVerifier) VerifySeal(svi proof.SealVerifyInfo) (bool, error) { +func (cv *cachingVerifier) VerifySeal(svi proof2.SealVerifyInfo) (bool, error) { return cv.withCache(func() (bool, error) { return cv.backend.VerifySeal(svi) }, &svi) } -func (cv *cachingVerifier) VerifyWinningPoSt(ctx context.Context, info proof.WinningPoStVerifyInfo) (bool, error) { + +func (cv *cachingVerifier) VerifyWinningPoSt(ctx context.Context, info proof2.WinningPoStVerifyInfo) (bool, error) { return cv.backend.VerifyWinningPoSt(ctx, info) } -func (cv *cachingVerifier) VerifyWindowPoSt(ctx context.Context, info proof.WindowPoStVerifyInfo) (bool, error) { +func (cv *cachingVerifier) VerifyWindowPoSt(ctx context.Context, info proof2.WindowPoStVerifyInfo) (bool, error) { return cv.withCache(func() (bool, error) { return cv.backend.VerifyWindowPoSt(ctx, info) }, &info) diff --git a/cmd/lotus-bench/main.go b/cmd/lotus-bench/main.go index e409dfe5a..ac39a9714 100644 --- a/cmd/lotus-bench/main.go +++ b/cmd/lotus-bench/main.go @@ -11,7 +11,7 @@ import ( "path/filepath" "time" - saproof "github.com/filecoin-project/specs-actors/actors/runtime/proof" + saproof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" "github.com/docker/go-units" logging "github.com/ipfs/go-log/v2" @@ -237,7 +237,7 @@ var sealBenchCmd = &cli.Command{ } var sealTimings []SealingResult - var sealedSectors []saproof.SectorInfo + var sealedSectors []saproof2.SectorInfo if robench == "" { var err error @@ -280,7 +280,7 @@ var sealBenchCmd = &cli.Command{ } for _, s := range genm.Sectors { - sealedSectors = append(sealedSectors, saproof.SectorInfo{ + sealedSectors = append(sealedSectors, saproof2.SectorInfo{ SealedCID: s.CommR, SectorNumber: s.SectorID, SealProof: s.ProofType, @@ -305,7 +305,7 @@ var sealBenchCmd = &cli.Command{ return err } - candidates := make([]saproof.SectorInfo, len(fcandidates)) + candidates := make([]saproof2.SectorInfo, len(fcandidates)) for i, fcandidate := range fcandidates { candidates[i] = sealedSectors[fcandidate] } @@ -328,7 +328,7 @@ var sealBenchCmd = &cli.Command{ winnningpost2 := time.Now() - pvi1 := saproof.WinningPoStVerifyInfo{ + pvi1 := saproof2.WinningPoStVerifyInfo{ Randomness: abi.PoStRandomness(challenge[:]), Proofs: proof1, ChallengedSectors: candidates, @@ -344,7 +344,7 @@ var sealBenchCmd = &cli.Command{ verifyWinningPost1 := time.Now() - pvi2 := saproof.WinningPoStVerifyInfo{ + pvi2 := saproof2.WinningPoStVerifyInfo{ Randomness: abi.PoStRandomness(challenge[:]), Proofs: proof2, ChallengedSectors: candidates, @@ -376,7 +376,7 @@ var sealBenchCmd = &cli.Command{ windowpost2 := time.Now() - wpvi1 := saproof.WindowPoStVerifyInfo{ + wpvi1 := saproof2.WindowPoStVerifyInfo{ Randomness: challenge[:], Proofs: wproof1, ChallengedSectors: sealedSectors, @@ -392,7 +392,7 @@ var sealBenchCmd = &cli.Command{ verifyWindowpost1 := time.Now() - wpvi2 := saproof.WindowPoStVerifyInfo{ + wpvi2 := saproof2.WindowPoStVerifyInfo{ Randomness: challenge[:], Proofs: wproof2, ChallengedSectors: sealedSectors, @@ -464,10 +464,10 @@ type ParCfg struct { Commit int } -func runSeals(sb *ffiwrapper.Sealer, sbfs *basicfs.Provider, numSectors int, par ParCfg, mid abi.ActorID, sectorSize abi.SectorSize, ticketPreimage []byte, saveC2inp string, skipc2, skipunseal bool) ([]SealingResult, []saproof.SectorInfo, error) { +func runSeals(sb *ffiwrapper.Sealer, sbfs *basicfs.Provider, numSectors int, par ParCfg, mid abi.ActorID, sectorSize abi.SectorSize, ticketPreimage []byte, saveC2inp string, skipc2, skipunseal bool) ([]SealingResult, []saproof2.SectorInfo, error) { var pieces []abi.PieceInfo sealTimings := make([]SealingResult, numSectors) - sealedSectors := make([]saproof.SectorInfo, numSectors) + sealedSectors := make([]saproof2.SectorInfo, numSectors) preCommit2Sema := make(chan struct{}, par.PreCommit2) commitSema := make(chan struct{}, par.Commit) @@ -537,7 +537,7 @@ func runSeals(sb *ffiwrapper.Sealer, sbfs *basicfs.Provider, numSectors int, par precommit2 := time.Now() <-preCommit2Sema - sealedSectors[ix] = saproof.SectorInfo{ + sealedSectors[ix] = saproof2.SectorInfo{ SealProof: sb.SealProofType(), SectorNumber: i, SealedCID: cids.Sealed, @@ -589,7 +589,7 @@ func runSeals(sb *ffiwrapper.Sealer, sbfs *basicfs.Provider, numSectors int, par <-commitSema if !skipc2 { - svi := saproof.SealVerifyInfo{ + svi := saproof2.SealVerifyInfo{ SectorID: abi.SectorID{Miner: mid, Number: i}, SealedCID: cids.Sealed, SealProof: sb.SealProofType(), diff --git a/cmd/lotus-chainwatch/processor/processor.go b/cmd/lotus-chainwatch/processor/processor.go index bce2b9fb7..1f8b246ed 100644 --- a/cmd/lotus-chainwatch/processor/processor.go +++ b/cmd/lotus-chainwatch/processor/processor.go @@ -15,7 +15,7 @@ import ( logging "github.com/ipfs/go-log/v2" "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/specs-actors/actors/builtin" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/types" @@ -134,10 +134,10 @@ func (p *Processor) Start(ctx context.Context) { log.Fatalw("Failed to collect actor changes", "error", err) } log.Infow("Collected Actor Changes", - "MarketChanges", len(actorChanges[builtin.StorageMarketActorCodeID]), - "MinerChanges", len(actorChanges[builtin.StorageMinerActorCodeID]), - "RewardChanges", len(actorChanges[builtin.RewardActorCodeID]), - "AccountChanges", len(actorChanges[builtin.AccountActorCodeID]), + "MarketChanges", len(actorChanges[builtin2.StorageMarketActorCodeID]), + "MinerChanges", len(actorChanges[builtin2.StorageMinerActorCodeID]), + "RewardChanges", len(actorChanges[builtin2.RewardActorCodeID]), + "AccountChanges", len(actorChanges[builtin2.AccountActorCodeID]), "nullRounds", len(nullRounds)) grp := sync.WaitGroup{} @@ -145,7 +145,7 @@ func (p *Processor) Start(ctx context.Context) { grp.Add(1) go func() { defer grp.Done() - if err := p.HandleMarketChanges(ctx, actorChanges[builtin.StorageMarketActorCodeID]); err != nil { + if err := p.HandleMarketChanges(ctx, actorChanges[builtin2.StorageMarketActorCodeID]); err != nil { log.Errorf("Failed to handle market changes: %w", err) return } @@ -154,7 +154,7 @@ func (p *Processor) Start(ctx context.Context) { grp.Add(1) go func() { defer grp.Done() - if err := p.HandleMinerChanges(ctx, actorChanges[builtin.StorageMinerActorCodeID]); err != nil { + if err := p.HandleMinerChanges(ctx, actorChanges[builtin2.StorageMinerActorCodeID]); err != nil { log.Errorf("Failed to handle miner changes: %w", err) return } @@ -163,7 +163,7 @@ func (p *Processor) Start(ctx context.Context) { grp.Add(1) go func() { defer grp.Done() - if err := p.HandleRewardChanges(ctx, actorChanges[builtin.RewardActorCodeID], nullRounds); err != nil { + if err := p.HandleRewardChanges(ctx, actorChanges[builtin2.RewardActorCodeID], nullRounds); err != nil { log.Errorf("Failed to handle reward changes: %w", err) return } @@ -172,7 +172,7 @@ func (p *Processor) Start(ctx context.Context) { grp.Add(1) go func() { defer grp.Done() - if err := p.HandlePowerChanges(ctx, actorChanges[builtin.StoragePowerActorCodeID]); err != nil { + if err := p.HandlePowerChanges(ctx, actorChanges[builtin2.StoragePowerActorCodeID]); err != nil { log.Errorf("Failed to handle power actor changes: %w", err) return } diff --git a/cmd/lotus-gateway/endtoend_test.go b/cmd/lotus-gateway/endtoend_test.go index 379c96053..b043ce28c 100644 --- a/cmd/lotus-gateway/endtoend_test.go +++ b/cmd/lotus-gateway/endtoend_test.go @@ -12,8 +12,8 @@ import ( "github.com/filecoin-project/lotus/cli" clitest "github.com/filecoin-project/lotus/cli/test" - init0 "github.com/filecoin-project/specs-actors/actors/builtin/init" - "github.com/filecoin-project/specs-actors/actors/builtin/multisig" + init2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/init" + multisig2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/multisig" "github.com/stretchr/testify/require" "golang.org/x/xerrors" @@ -101,7 +101,7 @@ func TestEndToEndWalletMsig(t *testing.T) { require.NoError(t, err) require.EqualValues(t, 0, res.Receipt.ExitCode) - var execReturn init0.ExecReturn + var execReturn init2.ExecReturn err = execReturn.UnmarshalCBOR(bytes.NewReader(res.Receipt.Return)) require.NoError(t, err) @@ -121,7 +121,7 @@ func TestEndToEndWalletMsig(t *testing.T) { require.NoError(t, err) require.EqualValues(t, 0, res.Receipt.ExitCode) - var proposeReturn multisig.ProposeReturn + var proposeReturn multisig2.ProposeReturn err = proposeReturn.UnmarshalCBOR(bytes.NewReader(res.Receipt.Return)) require.NoError(t, err) @@ -135,7 +135,7 @@ func TestEndToEndWalletMsig(t *testing.T) { require.NoError(t, err) require.EqualValues(t, 0, res.Receipt.ExitCode) - var approveReturn multisig.ApproveReturn + var approveReturn multisig2.ApproveReturn err = approveReturn.UnmarshalCBOR(bytes.NewReader(res.Receipt.Return)) require.NoError(t, err) require.True(t, approveReturn.Applied) diff --git a/cmd/lotus-pcr/main.go b/cmd/lotus-pcr/main.go index f88a0a9dc..02df4a192 100644 --- a/cmd/lotus-pcr/main.go +++ b/cmd/lotus-pcr/main.go @@ -16,9 +16,8 @@ import ( "github.com/filecoin-project/lotus/chain/actors/builtin" - builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" - - miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" "github.com/filecoin-project/go-state-types/network" @@ -871,7 +870,7 @@ func (r *refunder) processTipsetStorageMarketActor(ctx context.Context, tipset * var messageMethod string switch m.Method { - case builtin0.MethodsMarket.PublishStorageDeals: + case builtin2.MethodsMarket.PublishStorageDeals: if !r.publishStorageDealsEnabled { return false, messageMethod, types.NewInt(0), nil } @@ -898,7 +897,7 @@ func (r *refunder) processTipsetStorageMinerActor(ctx context.Context, tipset *t var messageMethod string switch m.Method { - case builtin0.MethodsMiner.SubmitWindowedPoSt: + case builtin2.MethodsMiner.SubmitWindowedPoSt: if !r.windowedPoStEnabled { return false, messageMethod, types.NewInt(0), nil } @@ -911,7 +910,7 @@ func (r *refunder) processTipsetStorageMinerActor(ctx context.Context, tipset *t } refundValue = types.BigMul(types.NewInt(uint64(recp.GasUsed)), tipset.Blocks()[0].ParentBaseFee) - case builtin0.MethodsMiner.ProveCommitSector: + case builtin2.MethodsMiner.ProveCommitSector: if !r.proveCommitEnabled { return false, messageMethod, types.NewInt(0), nil } @@ -930,7 +929,7 @@ func (r *refunder) processTipsetStorageMinerActor(ctx context.Context, tipset *t var sn abi.SectorNumber - var proveCommitSector miner0.ProveCommitSectorParams + var proveCommitSector miner2.ProveCommitSectorParams if err := proveCommitSector.UnmarshalCBOR(bytes.NewBuffer(m.Params)); err != nil { log.Warnw("failed to decode provecommit params", "err", err, "method", messageMethod, "cid", msg.Cid, "miner", m.To) return false, messageMethod, types.NewInt(0), nil @@ -967,7 +966,7 @@ func (r *refunder) processTipsetStorageMinerActor(ctx context.Context, tipset *t if r.refundPercent > 0 { refundValue = types.BigMul(types.BigDiv(refundValue, types.NewInt(100)), types.NewInt(uint64(r.refundPercent))) } - case builtin0.MethodsMiner.PreCommitSector: + case builtin2.MethodsMiner.PreCommitSector: if !r.preCommitEnabled { return false, messageMethod, types.NewInt(0), nil } diff --git a/cmd/lotus-seed/seed/seed.go b/cmd/lotus-seed/seed/seed.go index cd0c4e7ab..49c259084 100644 --- a/cmd/lotus-seed/seed/seed.go +++ b/cmd/lotus-seed/seed/seed.go @@ -22,7 +22,8 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/lotus/extern/sector-storage/zerocomm" - "github.com/filecoin-project/specs-actors/actors/builtin/market" + + market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/wallet" @@ -252,7 +253,7 @@ func WriteGenesisMiner(maddr address.Address, sbroot string, gm *genesis.Miner, func createDeals(m *genesis.Miner, k *wallet.Key, maddr address.Address, ssize abi.SectorSize) error { for i, sector := range m.Sectors { - proposal := &market.DealProposal{ + proposal := &market2.DealProposal{ PieceCID: sector.CommD, PieceSize: abi.PaddedPieceSize(ssize), Client: k.Address, diff --git a/cmd/lotus-shed/mempool-stats.go b/cmd/lotus-shed/mempool-stats.go index d70cd4b71..408e06f71 100644 --- a/cmd/lotus-shed/mempool-stats.go +++ b/cmd/lotus-shed/mempool-stats.go @@ -14,7 +14,7 @@ import ( "go.opencensus.io/stats/view" "go.opencensus.io/tag" - builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" "github.com/filecoin-project/go-address" lapi "github.com/filecoin-project/lotus/api" @@ -145,7 +145,7 @@ var mpoolStatsCmd = &cli.Command{ seen: time.Now(), } - if u.Message.Message.Method == builtin0.MethodsMiner.SubmitWindowedPoSt { + if u.Message.Message.Method == builtin2.MethodsMiner.SubmitWindowedPoSt { miner, err := isMiner(u.Message.Message.To) if err != nil { diff --git a/cmd/lotus-shed/proofs.go b/cmd/lotus-shed/proofs.go index 2379d8599..e75aeed14 100644 --- a/cmd/lotus-shed/proofs.go +++ b/cmd/lotus-shed/proofs.go @@ -4,7 +4,7 @@ import ( "encoding/hex" "fmt" - saproof "github.com/filecoin-project/specs-actors/actors/runtime/proof" + proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" "github.com/urfave/cli/v2" @@ -84,7 +84,7 @@ var verifySealProofCmd = &cli.Command{ snum := abi.SectorNumber(cctx.Uint64("sector-id")) - ok, err := ffi.VerifySeal(saproof.SealVerifyInfo{ + ok, err := ffi.VerifySeal(proof2.SealVerifyInfo{ SectorID: abi.SectorID{ Miner: abi.ActorID(mid), Number: snum, diff --git a/cmd/lotus-shed/sectors.go b/cmd/lotus-shed/sectors.go index 11e678642..cf0d5fcdb 100644 --- a/cmd/lotus-shed/sectors.go +++ b/cmd/lotus-shed/sectors.go @@ -12,7 +12,7 @@ import ( "github.com/filecoin-project/lotus/chain/types" lcli "github.com/filecoin-project/lotus/cli" - "github.com/filecoin-project/specs-actors/actors/builtin" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" miner0 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" "github.com/urfave/cli/v2" ) @@ -106,7 +106,7 @@ var terminateSectorCmd = &cli.Command{ smsg, err := nodeApi.MpoolPushMessage(ctx, &types.Message{ From: mi.Owner, To: maddr, - Method: builtin.MethodsMiner.TerminateSectors, + Method: builtin2.MethodsMiner.TerminateSectors, Value: big.Zero(), Params: sp, diff --git a/cmd/lotus-shed/verifreg.go b/cmd/lotus-shed/verifreg.go index 860498302..c4eada68c 100644 --- a/cmd/lotus-shed/verifreg.go +++ b/cmd/lotus-shed/verifreg.go @@ -11,8 +11,8 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" - verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + verifreg2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/verifreg" "github.com/filecoin-project/lotus/api/apibstore" "github.com/filecoin-project/lotus/build" @@ -63,7 +63,7 @@ var verifRegAddVerifierCmd = &cli.Command{ } // TODO: ActorUpgrade: Abstract - params, err := actors.SerializeParams(&verifreg0.AddVerifierParams{Address: verifier, Allowance: allowance}) + params, err := actors.SerializeParams(&verifreg2.AddVerifierParams{Address: verifier, Allowance: allowance}) if err != nil { return err } @@ -80,7 +80,7 @@ var verifRegAddVerifierCmd = &cli.Command{ return err } - smsg, err := api.MsigPropose(ctx, vrk, verifreg.Address, big.Zero(), sender, uint64(builtin0.MethodsVerifiedRegistry.AddVerifier), params) + smsg, err := api.MsigPropose(ctx, vrk, verifreg.Address, big.Zero(), sender, uint64(builtin2.MethodsVerifiedRegistry.AddVerifier), params) if err != nil { return err } @@ -136,7 +136,7 @@ var verifRegVerifyClientCmd = &cli.Command{ return err } - params, err := actors.SerializeParams(&verifreg0.AddVerifiedClientParams{Address: target, Allowance: allowance}) + params, err := actors.SerializeParams(&verifreg2.AddVerifiedClientParams{Address: target, Allowance: allowance}) if err != nil { return err } @@ -151,7 +151,7 @@ var verifRegVerifyClientCmd = &cli.Command{ msg := &types.Message{ To: verifreg.Address, From: fromk, - Method: builtin0.MethodsVerifiedRegistry.AddVerifiedClient, + Method: builtin2.MethodsVerifiedRegistry.AddVerifiedClient, Params: params, } diff --git a/cmd/lotus-storage-miner/actor.go b/cmd/lotus-storage-miner/actor.go index 35e2a268e..ad2232e1c 100644 --- a/cmd/lotus-storage-miner/actor.go +++ b/cmd/lotus-storage-miner/actor.go @@ -11,7 +11,6 @@ import ( cbor "github.com/ipfs/go-ipld-cbor" "github.com/filecoin-project/lotus/build" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" "github.com/fatih/color" "github.com/libp2p/go-libp2p-core/peer" @@ -23,8 +22,8 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" - "github.com/filecoin-project/specs-actors/actors/builtin" - miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/types" @@ -98,7 +97,7 @@ var actorSetAddrsCmd = &cli.Command{ return err } - params, err := actors.SerializeParams(&miner0.ChangeMultiaddrsParams{NewMultiaddrs: addrs}) + params, err := actors.SerializeParams(&miner2.ChangeMultiaddrsParams{NewMultiaddrs: addrs}) if err != nil { return err } @@ -110,7 +109,7 @@ var actorSetAddrsCmd = &cli.Command{ From: minfo.Worker, Value: types.NewInt(0), GasLimit: gasLimit, - Method: builtin.MethodsMiner.ChangeMultiaddrs, + Method: builtin2.MethodsMiner.ChangeMultiaddrs, Params: params, }, nil) if err != nil { @@ -163,7 +162,7 @@ var actorSetPeeridCmd = &cli.Command{ return err } - params, err := actors.SerializeParams(&miner0.ChangePeerIDParams{NewID: abi.PeerID(pid)}) + params, err := actors.SerializeParams(&miner2.ChangePeerIDParams{NewID: abi.PeerID(pid)}) if err != nil { return err } @@ -175,7 +174,7 @@ var actorSetPeeridCmd = &cli.Command{ From: minfo.Worker, Value: types.NewInt(0), GasLimit: gasLimit, - Method: builtin.MethodsMiner.ChangePeerID, + Method: builtin2.MethodsMiner.ChangePeerID, Params: params, }, nil) if err != nil { @@ -236,7 +235,7 @@ var actorWithdrawCmd = &cli.Command{ } } - params, err := actors.SerializeParams(&miner0.WithdrawBalanceParams{ + params, err := actors.SerializeParams(&miner2.WithdrawBalanceParams{ AmountRequested: amount, // Default to attempting to withdraw all the extra funds in the miner actor }) if err != nil { @@ -247,7 +246,7 @@ var actorWithdrawCmd = &cli.Command{ To: maddr, From: mi.Owner, Value: types.NewInt(0), - Method: builtin.MethodsMiner.WithdrawBalance, + Method: builtin2.MethodsMiner.WithdrawBalance, Params: params, }, nil) if err != nil { @@ -560,7 +559,7 @@ var actorControlSet = &cli.Command{ return nil } - cwp := &miner0.ChangeWorkerAddressParams{ + cwp := &miner2.ChangeWorkerAddressParams{ NewWorker: mi.Worker, NewControlAddrs: toSet, } @@ -573,7 +572,7 @@ var actorControlSet = &cli.Command{ smsg, err := api.MpoolPushMessage(ctx, &types.Message{ From: mi.Owner, To: maddr, - Method: builtin.MethodsMiner.ChangeWorkerAddress, + Method: builtin2.MethodsMiner.ChangeWorkerAddress, Value: big.Zero(), Params: sp, diff --git a/cmd/lotus-storage-miner/init.go b/cmd/lotus-storage-miner/init.go index 326a39e5e..b39ede752 100644 --- a/cmd/lotus-storage-miner/init.go +++ b/cmd/lotus-storage-miner/init.go @@ -31,14 +31,16 @@ import ( "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" "github.com/filecoin-project/lotus/extern/sector-storage/stores" - builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" - market0 "github.com/filecoin-project/specs-actors/actors/builtin/market" - miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" - power0 "github.com/filecoin-project/specs-actors/actors/builtin/power" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market" + miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" + power2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/power" lapi "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/actors/builtin/power" + "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/gen/slashfilter" "github.com/filecoin-project/lotus/chain/types" lcli "github.com/filecoin-project/lotus/cli" @@ -82,7 +84,7 @@ var initCmd = &cli.Command{ &cli.StringFlag{ Name: "sector-size", Usage: "specify sector size to use", - Value: units.BytesSize(float64(build.DefaultSectorSize())), + Value: units.BytesSize(float64(policy.GetDefaultSectorSize())), }, &cli.StringSliceFlag{ Name: "pre-sealed-sectors", @@ -375,7 +377,7 @@ func migratePreSealMeta(ctx context.Context, api lapi.FullNode, metadata string, return mds.Put(datastore.NewKey(modules.StorageCounterDSPrefix), buf[:size]) } -func findMarketDealID(ctx context.Context, api lapi.FullNode, deal market0.DealProposal) (abi.DealID, error) { +func findMarketDealID(ctx context.Context, api lapi.FullNode, deal market2.DealProposal) (abi.DealID, error) { // TODO: find a better way // (this is only used by genesis miners) @@ -568,7 +570,7 @@ func configureStorageMiner(ctx context.Context, api lapi.FullNode, addr address. return xerrors.Errorf("getWorkerAddr returned bad address: %w", err) } - enc, err := actors.SerializeParams(&miner0.ChangePeerIDParams{NewID: abi.PeerID(peerid)}) + enc, err := actors.SerializeParams(&miner2.ChangePeerIDParams{NewID: abi.PeerID(peerid)}) if err != nil { return err } @@ -576,7 +578,7 @@ func configureStorageMiner(ctx context.Context, api lapi.FullNode, addr address. msg := &types.Message{ To: addr, From: mi.Worker, - Method: builtin0.MethodsMiner.ChangePeerID, + Method: builtin2.MethodsMiner.ChangePeerID, Params: enc, Value: types.NewInt(0), GasPremium: gasPrice, @@ -635,7 +637,7 @@ func createStorageMiner(ctx context.Context, api lapi.FullNode, peerid peer.ID, return address.Undef, err } - params, err := actors.SerializeParams(&power0.CreateMinerParams{ + params, err := actors.SerializeParams(&power2.CreateMinerParams{ Owner: owner, Worker: worker, SealProofType: spt, @@ -655,11 +657,11 @@ func createStorageMiner(ctx context.Context, api lapi.FullNode, peerid peer.ID, } createStorageMinerMsg := &types.Message{ - To: builtin0.StoragePowerActorAddr, + To: power.Address, From: sender, Value: big.Zero(), - Method: builtin0.MethodsPower.CreateMiner, + Method: builtin2.MethodsPower.CreateMiner, Params: params, GasLimit: 0, @@ -683,7 +685,7 @@ func createStorageMiner(ctx context.Context, api lapi.FullNode, peerid peer.ID, return address.Undef, xerrors.Errorf("create miner failed: exit code %d", mw.Receipt.ExitCode) } - var retval power0.CreateMinerReturn + var retval power2.CreateMinerReturn if err := retval.UnmarshalCBOR(bytes.NewReader(mw.Receipt.Return)); err != nil { return address.Undef, err } diff --git a/cmd/lotus-storage-miner/sectors.go b/cmd/lotus-storage-miner/sectors.go index b50f4a86d..0c3ef58d6 100644 --- a/cmd/lotus-storage-miner/sectors.go +++ b/cmd/lotus-storage-miner/sectors.go @@ -15,10 +15,9 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" - miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" + "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/lib/tablewriter" @@ -463,7 +462,7 @@ var sectorsCapacityCollateralCmd = &cli.Command{ Expiration: abi.ChainEpoch(cctx.Uint64("expiration")), } if pci.Expiration == 0 { - pci.Expiration = miner0.MaxSectorExpirationExtension + pci.Expiration = policy.GetMaxSectorExpirationExtension() } pc, err := nApi.StateMinerInitialPledgeCollateral(ctx, maddr, pci, types.EmptyTSK) if err != nil { diff --git a/cmd/tvx/extract.go b/cmd/tvx/extract.go index 4a8dd162c..276c38cd4 100644 --- a/cmd/tvx/extract.go +++ b/cmd/tvx/extract.go @@ -14,6 +14,7 @@ import ( "github.com/fatih/color" "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/actors/builtin" init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init" "github.com/filecoin-project/lotus/chain/actors/builtin/reward" "github.com/filecoin-project/lotus/chain/types" @@ -21,8 +22,6 @@ import ( lcli "github.com/filecoin-project/lotus/cli" "github.com/filecoin-project/lotus/conformance" - "github.com/filecoin-project/specs-actors/actors/builtin" - "github.com/filecoin-project/test-vectors/schema" "github.com/ipfs/go-cid" diff --git a/conformance/chaos/actor.go b/conformance/chaos/actor.go index d5e0b4352..3c280e27e 100644 --- a/conformance/chaos/actor.go +++ b/conformance/chaos/actor.go @@ -6,9 +6,10 @@ import ( "github.com/filecoin-project/go-state-types/cbor" "github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/go-state-types/rt" - "github.com/filecoin-project/specs-actors/actors/builtin" - "github.com/filecoin-project/specs-actors/actors/runtime" "github.com/ipfs/go-cid" + + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + runtime2 "github.com/filecoin-project/specs-actors/v2/actors/runtime" ) //go:generate go run ./gen @@ -55,7 +56,7 @@ const ( const ( _ = 0 // skip zero iota value; first usage of iota gets 1. - MethodCallerValidation = builtin.MethodConstructor + iota + MethodCallerValidation = builtin2.MethodConstructor + iota MethodCreateActor MethodResolveAddress // MethodDeleteActor is the identifier for the method that deletes this actor. @@ -76,15 +77,15 @@ const ( // Exports defines the methods this actor exposes publicly. func (a Actor) Exports() []interface{} { return []interface{}{ - builtin.MethodConstructor: a.Constructor, - MethodCallerValidation: a.CallerValidation, - MethodCreateActor: a.CreateActor, - MethodResolveAddress: a.ResolveAddress, - MethodDeleteActor: a.DeleteActor, - MethodSend: a.Send, - MethodMutateState: a.MutateState, - MethodAbortWith: a.AbortWith, - MethodInspectRuntime: a.InspectRuntime, + builtin2.MethodConstructor: a.Constructor, + MethodCallerValidation: a.CallerValidation, + MethodCreateActor: a.CreateActor, + MethodResolveAddress: a.ResolveAddress, + MethodDeleteActor: a.DeleteActor, + MethodSend: a.Send, + MethodMutateState: a.MutateState, + MethodAbortWith: a.AbortWith, + MethodInspectRuntime: a.InspectRuntime, } } @@ -104,19 +105,19 @@ type SendArgs struct { // SendReturn is the return values for the Send method. type SendReturn struct { - Return runtime.CBORBytes + Return builtin2.CBORBytes Code exitcode.ExitCode } // Send requests for this actor to send a message to an actor with the // passed parameters. -func (a Actor) Send(rt runtime.Runtime, args *SendArgs) *SendReturn { +func (a Actor) Send(rt runtime2.Runtime, args *SendArgs) *SendReturn { rt.ValidateImmediateCallerAcceptAny() - var out runtime.CBORBytes + var out builtin2.CBORBytes code := rt.Send( args.To, args.Method, - runtime.CBORBytes(args.Params), + builtin2.CBORBytes(args.Params), args.Value, &out, ) @@ -127,7 +128,7 @@ func (a Actor) Send(rt runtime.Runtime, args *SendArgs) *SendReturn { } // Constructor will panic because the Chaos actor is a singleton. -func (a Actor) Constructor(_ runtime.Runtime, _ *abi.EmptyValue) *abi.EmptyValue { +func (a Actor) Constructor(_ runtime2.Runtime, _ *abi.EmptyValue) *abi.EmptyValue { panic("constructor should not be called; the Chaos actor is a singleton actor") } @@ -144,7 +145,7 @@ type CallerValidationArgs struct { // CallerValidationBranchTwice validates twice. // CallerValidationBranchIsAddress validates caller against CallerValidationArgs.Addrs. // CallerValidationBranchIsType validates caller against CallerValidationArgs.Types. -func (a Actor) CallerValidation(rt runtime.Runtime, args *CallerValidationArgs) *abi.EmptyValue { +func (a Actor) CallerValidation(rt runtime2.Runtime, args *CallerValidationArgs) *abi.EmptyValue { switch args.Branch { case CallerValidationBranchNone: case CallerValidationBranchTwice: @@ -174,7 +175,7 @@ type CreateActorArgs struct { } // CreateActor creates an actor with the supplied CID and Address. -func (a Actor) CreateActor(rt runtime.Runtime, args *CreateActorArgs) *abi.EmptyValue { +func (a Actor) CreateActor(rt runtime2.Runtime, args *CreateActorArgs) *abi.EmptyValue { rt.ValidateImmediateCallerAcceptAny() var ( @@ -199,7 +200,7 @@ type ResolveAddressResponse struct { Success bool } -func (a Actor) ResolveAddress(rt runtime.Runtime, args *address.Address) *ResolveAddressResponse { +func (a Actor) ResolveAddress(rt runtime2.Runtime, args *address.Address) *ResolveAddressResponse { rt.ValidateImmediateCallerAcceptAny() resolvedAddr, ok := rt.ResolveAddress(*args) @@ -212,7 +213,7 @@ func (a Actor) ResolveAddress(rt runtime.Runtime, args *address.Address) *Resolv // DeleteActor deletes the executing actor from the state tree, transferring any // balance to beneficiary. -func (a Actor) DeleteActor(rt runtime.Runtime, beneficiary *address.Address) *abi.EmptyValue { +func (a Actor) DeleteActor(rt runtime2.Runtime, beneficiary *address.Address) *abi.EmptyValue { rt.ValidateImmediateCallerAcceptAny() rt.DeleteActor(*beneficiary) return nil @@ -226,7 +227,7 @@ type MutateStateArgs struct { } // MutateState attempts to mutate a state value in the actor. -func (a Actor) MutateState(rt runtime.Runtime, args *MutateStateArgs) *abi.EmptyValue { +func (a Actor) MutateState(rt runtime2.Runtime, args *MutateStateArgs) *abi.EmptyValue { rt.ValidateImmediateCallerAcceptAny() var st State switch args.Branch { @@ -257,7 +258,7 @@ type AbortWithArgs struct { } // AbortWith simply causes a panic with the passed exit code. -func (a Actor) AbortWith(rt runtime.Runtime, args *AbortWithArgs) *abi.EmptyValue { +func (a Actor) AbortWith(rt runtime2.Runtime, args *AbortWithArgs) *abi.EmptyValue { if args.Uncontrolled { // uncontrolled abort: directly panic panic(args.Message) } else { @@ -277,7 +278,7 @@ type InspectRuntimeReturn struct { } // InspectRuntime returns a copy of the serializable values available in the Runtime. -func (a Actor) InspectRuntime(rt runtime.Runtime, _ *abi.EmptyValue) *InspectRuntimeReturn { +func (a Actor) InspectRuntime(rt runtime2.Runtime, _ *abi.EmptyValue) *InspectRuntimeReturn { rt.ValidateImmediateCallerAcceptAny() var st State rt.StateReadonly(&st) diff --git a/conformance/chaos/actor_test.go b/conformance/chaos/actor_test.go index 2061efb82..dbce4f4c5 100644 --- a/conformance/chaos/actor_test.go +++ b/conformance/chaos/actor_test.go @@ -7,15 +7,16 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/exitcode" - "github.com/filecoin-project/specs-actors/actors/builtin" - "github.com/filecoin-project/specs-actors/support/mock" - atesting "github.com/filecoin-project/specs-actors/support/testing" "github.com/ipfs/go-cid" + + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + mock2 "github.com/filecoin-project/specs-actors/v2/support/mock" + atesting2 "github.com/filecoin-project/specs-actors/v2/support/testing" ) func TestSingleton(t *testing.T) { - receiver := atesting.NewIDAddr(t, 100) - builder := mock.NewBuilder(context.Background(), receiver) + receiver := atesting2.NewIDAddr(t, 100) + builder := mock2.NewBuilder(context.Background(), receiver) rt := builder.Build(t) var a Actor @@ -28,8 +29,8 @@ func TestSingleton(t *testing.T) { } func TestCallerValidationNone(t *testing.T) { - receiver := atesting.NewIDAddr(t, 100) - builder := mock.NewBuilder(context.Background(), receiver) + receiver := atesting2.NewIDAddr(t, 100) + builder := mock2.NewBuilder(context.Background(), receiver) rt := builder.Build(t) var a Actor @@ -39,19 +40,19 @@ func TestCallerValidationNone(t *testing.T) { } func TestCallerValidationIs(t *testing.T) { - caller := atesting.NewIDAddr(t, 100) - receiver := atesting.NewIDAddr(t, 101) - builder := mock.NewBuilder(context.Background(), receiver) + caller := atesting2.NewIDAddr(t, 100) + receiver := atesting2.NewIDAddr(t, 101) + builder := mock2.NewBuilder(context.Background(), receiver) rt := builder.Build(t) - rt.SetCaller(caller, builtin.AccountActorCodeID) + rt.SetCaller(caller, builtin2.AccountActorCodeID) var a Actor - caddrs := []address.Address{atesting.NewIDAddr(t, 101)} + caddrs := []address.Address{atesting2.NewIDAddr(t, 101)} rt.ExpectValidateCallerAddr(caddrs...) - // FIXME: https://github.com/filecoin-project/specs-actors/pull/1155 - rt.ExpectAbort(exitcode.ErrForbidden, func() { + // fixed in: https://github.com/filecoin-project/specs-actors/pull/1155 + rt.ExpectAbort(exitcode.SysErrForbidden, func() { rt.Call(a.CallerValidation, &CallerValidationArgs{ Branch: CallerValidationBranchIsAddress, Addrs: caddrs, @@ -68,35 +69,34 @@ func TestCallerValidationIs(t *testing.T) { } func TestCallerValidationType(t *testing.T) { - caller := atesting.NewIDAddr(t, 100) - receiver := atesting.NewIDAddr(t, 101) - builder := mock.NewBuilder(context.Background(), receiver) + caller := atesting2.NewIDAddr(t, 100) + receiver := atesting2.NewIDAddr(t, 101) + builder := mock2.NewBuilder(context.Background(), receiver) rt := builder.Build(t) - rt.SetCaller(caller, builtin.AccountActorCodeID) + rt.SetCaller(caller, builtin2.AccountActorCodeID) var a Actor - rt.ExpectValidateCallerType(builtin.CronActorCodeID) - // FIXME: https://github.com/filecoin-project/specs-actors/pull/1155 - rt.ExpectAbort(exitcode.ErrForbidden, func() { + rt.ExpectValidateCallerType(builtin2.CronActorCodeID) + rt.ExpectAbort(exitcode.SysErrForbidden, func() { rt.Call(a.CallerValidation, &CallerValidationArgs{ Branch: CallerValidationBranchIsType, - Types: []cid.Cid{builtin.CronActorCodeID}, + Types: []cid.Cid{builtin2.CronActorCodeID}, }) }) rt.Verify() - rt.ExpectValidateCallerType(builtin.AccountActorCodeID) + rt.ExpectValidateCallerType(builtin2.AccountActorCodeID) rt.Call(a.CallerValidation, &CallerValidationArgs{ Branch: CallerValidationBranchIsType, - Types: []cid.Cid{builtin.AccountActorCodeID}, + Types: []cid.Cid{builtin2.AccountActorCodeID}, }) rt.Verify() } func TestCallerValidationInvalidBranch(t *testing.T) { - receiver := atesting.NewIDAddr(t, 100) - builder := mock.NewBuilder(context.Background(), receiver) + receiver := atesting2.NewIDAddr(t, 100) + builder := mock2.NewBuilder(context.Background(), receiver) rt := builder.Build(t) var a Actor @@ -108,9 +108,9 @@ func TestCallerValidationInvalidBranch(t *testing.T) { } func TestDeleteActor(t *testing.T) { - receiver := atesting.NewIDAddr(t, 100) - beneficiary := atesting.NewIDAddr(t, 101) - builder := mock.NewBuilder(context.Background(), receiver) + receiver := atesting2.NewIDAddr(t, 100) + beneficiary := atesting2.NewIDAddr(t, 101) + builder := mock2.NewBuilder(context.Background(), receiver) rt := builder.Build(t) var a Actor @@ -122,8 +122,8 @@ func TestDeleteActor(t *testing.T) { } func TestMutateStateInTransaction(t *testing.T) { - receiver := atesting.NewIDAddr(t, 100) - builder := mock.NewBuilder(context.Background(), receiver) + receiver := atesting2.NewIDAddr(t, 100) + builder := mock2.NewBuilder(context.Background(), receiver) rt := builder.Build(t) var a Actor @@ -148,8 +148,8 @@ func TestMutateStateInTransaction(t *testing.T) { } func TestMutateStateAfterTransaction(t *testing.T) { - receiver := atesting.NewIDAddr(t, 100) - builder := mock.NewBuilder(context.Background(), receiver) + receiver := atesting2.NewIDAddr(t, 100) + builder := mock2.NewBuilder(context.Background(), receiver) rt := builder.Build(t) var a Actor @@ -175,8 +175,8 @@ func TestMutateStateAfterTransaction(t *testing.T) { } func TestMutateStateReadonly(t *testing.T) { - receiver := atesting.NewIDAddr(t, 100) - builder := mock.NewBuilder(context.Background(), receiver) + receiver := atesting2.NewIDAddr(t, 100) + builder := mock2.NewBuilder(context.Background(), receiver) rt := builder.Build(t) var a Actor @@ -201,8 +201,8 @@ func TestMutateStateReadonly(t *testing.T) { } func TestMutateStateInvalidBranch(t *testing.T) { - receiver := atesting.NewIDAddr(t, 100) - builder := mock.NewBuilder(context.Background(), receiver) + receiver := atesting2.NewIDAddr(t, 100) + builder := mock2.NewBuilder(context.Background(), receiver) rt := builder.Build(t) var a Actor @@ -215,8 +215,8 @@ func TestMutateStateInvalidBranch(t *testing.T) { } func TestAbortWith(t *testing.T) { - receiver := atesting.NewIDAddr(t, 100) - builder := mock.NewBuilder(context.Background(), receiver) + receiver := atesting2.NewIDAddr(t, 100) + builder := mock2.NewBuilder(context.Background(), receiver) rt := builder.Build(t) var a Actor @@ -233,8 +233,8 @@ func TestAbortWith(t *testing.T) { } func TestAbortWithUncontrolled(t *testing.T) { - receiver := atesting.NewIDAddr(t, 100) - builder := mock.NewBuilder(context.Background(), receiver) + receiver := atesting2.NewIDAddr(t, 100) + builder := mock2.NewBuilder(context.Background(), receiver) rt := builder.Build(t) var a Actor @@ -250,12 +250,12 @@ func TestAbortWithUncontrolled(t *testing.T) { } func TestInspectRuntime(t *testing.T) { - caller := atesting.NewIDAddr(t, 100) - receiver := atesting.NewIDAddr(t, 101) - builder := mock.NewBuilder(context.Background(), receiver) + caller := atesting2.NewIDAddr(t, 100) + receiver := atesting2.NewIDAddr(t, 101) + builder := mock2.NewBuilder(context.Background(), receiver) rt := builder.Build(t) - rt.SetCaller(caller, builtin.AccountActorCodeID) + rt.SetCaller(caller, builtin2.AccountActorCodeID) rt.StateCreate(&State{}) var a Actor diff --git a/conformance/chaos/cbor_gen.go b/conformance/chaos/cbor_gen.go index 882af7026..876d6a893 100644 --- a/conformance/chaos/cbor_gen.go +++ b/conformance/chaos/cbor_gen.go @@ -587,7 +587,7 @@ func (t *SendReturn) MarshalCBOR(w io.Writer) error { scratch := make([]byte, 9) - // t.Return (runtime.CBORBytes) (slice) + // t.Return (builtin.CBORBytes) (slice) if len(t.Return) > cbg.ByteArrayMaxLen { return xerrors.Errorf("Byte array in field t.Return was too long") } @@ -631,7 +631,7 @@ func (t *SendReturn) UnmarshalCBOR(r io.Reader) error { return fmt.Errorf("cbor input had wrong number of fields") } - // t.Return (runtime.CBORBytes) (slice) + // t.Return (builtin.CBORBytes) (slice) maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) if err != nil { diff --git a/extern/sector-storage/ffiwrapper/sealer_test.go b/extern/sector-storage/ffiwrapper/sealer_test.go index bb26adb77..15a98667f 100644 --- a/extern/sector-storage/ffiwrapper/sealer_test.go +++ b/extern/sector-storage/ffiwrapper/sealer_test.go @@ -15,7 +15,7 @@ import ( "testing" "time" - saproof "github.com/filecoin-project/specs-actors/actors/runtime/proof" + proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" "github.com/ipfs/go-cid" @@ -93,7 +93,7 @@ func (s *seal) commit(t *testing.T, sb *Sealer, done func()) { t.Fatalf("%+v", err) } - ok, err := ProofVerifier.VerifySeal(saproof.SealVerifyInfo{ + ok, err := ProofVerifier.VerifySeal(proof2.SealVerifyInfo{ SectorID: s.id, SealedCID: s.cids.Sealed, SealProof: sealProofType, @@ -171,9 +171,9 @@ func (s *seal) unseal(t *testing.T, sb *Sealer, sp *basicfs.Provider, si abi.Sec func post(t *testing.T, sealer *Sealer, skipped []abi.SectorID, seals ...seal) { randomness := abi.PoStRandomness{0, 9, 2, 7, 6, 5, 4, 3, 2, 1, 0, 9, 8, 7, 6, 45, 3, 2, 1, 0, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 9, 7} - sis := make([]saproof.SectorInfo, len(seals)) + sis := make([]proof2.SectorInfo, len(seals)) for i, s := range seals { - sis[i] = saproof.SectorInfo{ + sis[i] = proof2.SectorInfo{ SealProof: sealProofType, SectorNumber: s.id.Number, SealedCID: s.cids.Sealed, @@ -191,7 +191,7 @@ func post(t *testing.T, sealer *Sealer, skipped []abi.SectorID, seals ...seal) { t.Fatalf("%+v", err) } - ok, err := ProofVerifier.VerifyWindowPoSt(context.TODO(), saproof.WindowPoStVerifyInfo{ + ok, err := ProofVerifier.VerifyWindowPoSt(context.TODO(), proof2.WindowPoStVerifyInfo{ Randomness: randomness, Proofs: proofs, ChallengedSectors: sis, diff --git a/extern/sector-storage/ffiwrapper/types.go b/extern/sector-storage/ffiwrapper/types.go index 318dbd2b0..c8f263b29 100644 --- a/extern/sector-storage/ffiwrapper/types.go +++ b/extern/sector-storage/ffiwrapper/types.go @@ -4,7 +4,7 @@ import ( "context" "io" - "github.com/filecoin-project/specs-actors/actors/runtime/proof" + proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" "github.com/ipfs/go-cid" @@ -35,9 +35,9 @@ type Storage interface { } type Verifier interface { - VerifySeal(proof.SealVerifyInfo) (bool, error) - VerifyWinningPoSt(ctx context.Context, info proof.WinningPoStVerifyInfo) (bool, error) - VerifyWindowPoSt(ctx context.Context, info proof.WindowPoStVerifyInfo) (bool, error) + VerifySeal(proof2.SealVerifyInfo) (bool, error) + VerifyWinningPoSt(ctx context.Context, info proof2.WinningPoStVerifyInfo) (bool, error) + VerifyWindowPoSt(ctx context.Context, info proof2.WindowPoStVerifyInfo) (bool, error) GenerateWinningPoStSectorChallenge(context.Context, abi.RegisteredPoStProof, abi.ActorID, abi.PoStRandomness, uint64) ([]uint64, error) } diff --git a/extern/sector-storage/ffiwrapper/verifier_cgo.go b/extern/sector-storage/ffiwrapper/verifier_cgo.go index d6c0ae35f..bfa77345a 100644 --- a/extern/sector-storage/ffiwrapper/verifier_cgo.go +++ b/extern/sector-storage/ffiwrapper/verifier_cgo.go @@ -5,7 +5,7 @@ package ffiwrapper import ( "context" - "github.com/filecoin-project/specs-actors/actors/runtime/proof" + proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" "golang.org/x/xerrors" @@ -18,7 +18,7 @@ import ( "go.opencensus.io/trace" ) -func (sb *Sealer) GenerateWinningPoSt(ctx context.Context, minerID abi.ActorID, sectorInfo []proof.SectorInfo, randomness abi.PoStRandomness) ([]proof.PoStProof, error) { +func (sb *Sealer) GenerateWinningPoSt(ctx context.Context, minerID abi.ActorID, sectorInfo []proof2.SectorInfo, randomness abi.PoStRandomness) ([]proof2.PoStProof, error) { randomness[31] &= 0x3f privsectors, skipped, done, err := sb.pubSectorToPriv(ctx, minerID, sectorInfo, nil, abi.RegisteredSealProof.RegisteredWinningPoStProof) // TODO: FAULTS? if err != nil { @@ -32,7 +32,7 @@ func (sb *Sealer) GenerateWinningPoSt(ctx context.Context, minerID abi.ActorID, return ffi.GenerateWinningPoSt(minerID, privsectors, randomness) } -func (sb *Sealer) GenerateWindowPoSt(ctx context.Context, minerID abi.ActorID, sectorInfo []proof.SectorInfo, randomness abi.PoStRandomness) ([]proof.PoStProof, []abi.SectorID, error) { +func (sb *Sealer) GenerateWindowPoSt(ctx context.Context, minerID abi.ActorID, sectorInfo []proof2.SectorInfo, randomness abi.PoStRandomness) ([]proof2.PoStProof, []abi.SectorID, error) { randomness[31] &= 0x3f privsectors, skipped, done, err := sb.pubSectorToPriv(ctx, minerID, sectorInfo, nil, abi.RegisteredSealProof.RegisteredWindowPoStProof) if err != nil { @@ -57,7 +57,7 @@ func (sb *Sealer) GenerateWindowPoSt(ctx context.Context, minerID abi.ActorID, s return proof, faultyIDs, err } -func (sb *Sealer) pubSectorToPriv(ctx context.Context, mid abi.ActorID, sectorInfo []proof.SectorInfo, faults []abi.SectorNumber, rpt func(abi.RegisteredSealProof) (abi.RegisteredPoStProof, error)) (ffi.SortedPrivateSectorInfo, []abi.SectorID, func(), error) { +func (sb *Sealer) pubSectorToPriv(ctx context.Context, mid abi.ActorID, sectorInfo []proof2.SectorInfo, faults []abi.SectorNumber, rpt func(abi.RegisteredSealProof) (abi.RegisteredPoStProof, error)) (ffi.SortedPrivateSectorInfo, []abi.SectorID, func(), error) { fmap := map[abi.SectorNumber]struct{}{} for _, fault := range faults { fmap[fault] = struct{}{} @@ -110,11 +110,11 @@ type proofVerifier struct{} var ProofVerifier = proofVerifier{} -func (proofVerifier) VerifySeal(info proof.SealVerifyInfo) (bool, error) { +func (proofVerifier) VerifySeal(info proof2.SealVerifyInfo) (bool, error) { return ffi.VerifySeal(info) } -func (proofVerifier) VerifyWinningPoSt(ctx context.Context, info proof.WinningPoStVerifyInfo) (bool, error) { +func (proofVerifier) VerifyWinningPoSt(ctx context.Context, info proof2.WinningPoStVerifyInfo) (bool, error) { info.Randomness[31] &= 0x3f _, span := trace.StartSpan(ctx, "VerifyWinningPoSt") defer span.End() @@ -122,7 +122,7 @@ func (proofVerifier) VerifyWinningPoSt(ctx context.Context, info proof.WinningPo return ffi.VerifyWinningPoSt(info) } -func (proofVerifier) VerifyWindowPoSt(ctx context.Context, info proof.WindowPoStVerifyInfo) (bool, error) { +func (proofVerifier) VerifyWindowPoSt(ctx context.Context, info proof2.WindowPoStVerifyInfo) (bool, error) { info.Randomness[31] &= 0x3f _, span := trace.StartSpan(ctx, "VerifyWindowPoSt") defer span.End() diff --git a/extern/sector-storage/mock/mock.go b/extern/sector-storage/mock/mock.go index 001c7159c..aa3f1cc55 100644 --- a/extern/sector-storage/mock/mock.go +++ b/extern/sector-storage/mock/mock.go @@ -9,7 +9,7 @@ import ( "math/rand" "sync" - "github.com/filecoin-project/specs-actors/actors/runtime/proof" + proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" commcid "github.com/filecoin-project/go-fil-commcid" "github.com/filecoin-project/go-state-types/abi" @@ -280,12 +280,12 @@ func AddOpFinish(ctx context.Context) (context.Context, func()) { } } -func (mgr *SectorMgr) GenerateWinningPoSt(ctx context.Context, minerID abi.ActorID, sectorInfo []proof.SectorInfo, randomness abi.PoStRandomness) ([]proof.PoStProof, error) { +func (mgr *SectorMgr) GenerateWinningPoSt(ctx context.Context, minerID abi.ActorID, sectorInfo []proof2.SectorInfo, randomness abi.PoStRandomness) ([]proof2.PoStProof, error) { return generateFakePoSt(sectorInfo, abi.RegisteredSealProof.RegisteredWinningPoStProof, randomness), nil } -func (mgr *SectorMgr) GenerateWindowPoSt(ctx context.Context, minerID abi.ActorID, sectorInfo []proof.SectorInfo, randomness abi.PoStRandomness) ([]proof.PoStProof, []abi.SectorID, error) { - si := make([]proof.SectorInfo, 0, len(sectorInfo)) +func (mgr *SectorMgr) GenerateWindowPoSt(ctx context.Context, minerID abi.ActorID, sectorInfo []proof2.SectorInfo, randomness abi.PoStRandomness) ([]proof2.PoStProof, []abi.SectorID, error) { + si := make([]proof2.SectorInfo, 0, len(sectorInfo)) var skipped []abi.SectorID var err error @@ -313,7 +313,7 @@ func (mgr *SectorMgr) GenerateWindowPoSt(ctx context.Context, minerID abi.ActorI return generateFakePoSt(si, abi.RegisteredSealProof.RegisteredWindowPoStProof, randomness), skipped, nil } -func generateFakePoStProof(sectorInfo []proof.SectorInfo, randomness abi.PoStRandomness) []byte { +func generateFakePoStProof(sectorInfo []proof2.SectorInfo, randomness abi.PoStRandomness) []byte { hasher := sha256.New() _, _ = hasher.Write(randomness) for _, info := range sectorInfo { @@ -326,13 +326,13 @@ func generateFakePoStProof(sectorInfo []proof.SectorInfo, randomness abi.PoStRan } -func generateFakePoSt(sectorInfo []proof.SectorInfo, rpt func(abi.RegisteredSealProof) (abi.RegisteredPoStProof, error), randomness abi.PoStRandomness) []proof.PoStProof { +func generateFakePoSt(sectorInfo []proof2.SectorInfo, rpt func(abi.RegisteredSealProof) (abi.RegisteredPoStProof, error), randomness abi.PoStRandomness) []proof2.PoStProof { wp, err := rpt(sectorInfo[0].SealProof) if err != nil { panic(err) } - return []proof.PoStProof{ + return []proof2.PoStProof{ { PoStProof: wp, ProofBytes: generateFakePoStProof(sectorInfo, randomness), @@ -406,7 +406,7 @@ func (mgr *SectorMgr) CheckProvable(ctx context.Context, spt abi.RegisteredSealP return bad, nil } -func (m mockVerif) VerifySeal(svi proof.SealVerifyInfo) (bool, error) { +func (m mockVerif) VerifySeal(svi proof2.SealVerifyInfo) (bool, error) { if len(svi.Proof) != 1920 { return false, nil } @@ -421,11 +421,11 @@ func (m mockVerif) VerifySeal(svi proof.SealVerifyInfo) (bool, error) { return true, nil } -func (m mockVerif) VerifyWinningPoSt(ctx context.Context, info proof.WinningPoStVerifyInfo) (bool, error) { +func (m mockVerif) VerifyWinningPoSt(ctx context.Context, info proof2.WinningPoStVerifyInfo) (bool, error) { return true, nil } -func (m mockVerif) VerifyWindowPoSt(ctx context.Context, info proof.WindowPoStVerifyInfo) (bool, error) { +func (m mockVerif) VerifyWindowPoSt(ctx context.Context, info proof2.WindowPoStVerifyInfo) (bool, error) { if len(info.Proofs) != 1 { return false, xerrors.Errorf("expected 1 proof entry") } diff --git a/extern/storage-sealing/checks.go b/extern/storage-sealing/checks.go index 1010d31b2..ed7a691ef 100644 --- a/extern/storage-sealing/checks.go +++ b/extern/storage-sealing/checks.go @@ -7,7 +7,7 @@ import ( "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/policy" - proof0 "github.com/filecoin-project/specs-actors/actors/runtime/proof" + proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" "golang.org/x/xerrors" @@ -179,7 +179,7 @@ func (m *Sealing) checkCommit(ctx context.Context, si SectorInfo, proof []byte, log.Warn("on-chain sealed CID doesn't match!") } - ok, err := m.verif.VerifySeal(proof0.SealVerifyInfo{ + ok, err := m.verif.VerifySeal(proof2.SealVerifyInfo{ SectorID: m.minerSector(si.SectorNumber), SealedCID: pci.Info.SealedCID, SealProof: spt, diff --git a/extern/storage-sealing/states_sealing.go b/extern/storage-sealing/states_sealing.go index 96589bcd2..1e67a0a03 100644 --- a/extern/storage-sealing/states_sealing.go +++ b/extern/storage-sealing/states_sealing.go @@ -15,8 +15,9 @@ import ( "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/go-statemachine" - "github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-storage/storage" + + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" ) var DealSectorPriority = 1024 @@ -220,7 +221,7 @@ func (m *Sealing) handlePreCommitting(ctx statemachine.Context, sector SectorInf deposit := big.Max(depositMinimum, collateral) log.Infof("submitting precommit for sector %d (deposit: %s): ", sector.SectorNumber, deposit) - mcid, err := m.api.SendMsg(ctx.Context(), waddr, m.maddr, builtin.MethodsMiner.PreCommitSector, deposit, m.feeCfg.MaxPreCommitGasFee, enc.Bytes()) + mcid, err := m.api.SendMsg(ctx.Context(), waddr, m.maddr, builtin2.MethodsMiner.PreCommitSector, deposit, m.feeCfg.MaxPreCommitGasFee, enc.Bytes()) if err != nil { if params.ReplaceCapacity { m.remarkForUpgrade(params.ReplaceSectorNumber) @@ -401,7 +402,7 @@ func (m *Sealing) handleSubmitCommit(ctx statemachine.Context, sector SectorInfo } // TODO: check seed / ticket / deals are up to date - mcid, err := m.api.SendMsg(ctx.Context(), waddr, m.maddr, builtin.MethodsMiner.ProveCommitSector, collateral, m.feeCfg.MaxCommitGasFee, enc.Bytes()) + mcid, err := m.api.SendMsg(ctx.Context(), waddr, m.maddr, builtin2.MethodsMiner.ProveCommitSector, collateral, m.feeCfg.MaxCommitGasFee, enc.Bytes()) if err != nil { return ctx.Send(SectorCommitFailed{xerrors.Errorf("pushing message to mpool: %w", err)}) } diff --git a/extern/storage-sealing/types.go b/extern/storage-sealing/types.go index 046271a7f..8f3e82a0b 100644 --- a/extern/storage-sealing/types.go +++ b/extern/storage-sealing/types.go @@ -9,9 +9,9 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/exitcode" - miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" "github.com/filecoin-project/specs-storage/storage" + "github.com/filecoin-project/lotus/chain/actors/builtin/miner" sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage" "github.com/filecoin-project/lotus/extern/storage-sealing/sealiface" ) @@ -82,7 +82,7 @@ type SectorInfo struct { CommR *cid.Cid Proof []byte - PreCommitInfo *miner0.SectorPreCommitInfo + PreCommitInfo *miner.SectorPreCommitInfo PreCommitDeposit big.Int PreCommitMessage *cid.Cid PreCommitTipSet TipSetToken diff --git a/extern/storage-sealing/types_test.go b/extern/storage-sealing/types_test.go index fc56620dc..0b3c97032 100644 --- a/extern/storage-sealing/types_test.go +++ b/extern/storage-sealing/types_test.go @@ -8,7 +8,7 @@ import ( cborutil "github.com/filecoin-project/go-cbor-util" "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/specs-actors/actors/builtin" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" ) func TestSectorInfoSelialization(t *testing.T) { @@ -22,7 +22,7 @@ func TestSectorInfoSelialization(t *testing.T) { }, } - dummyCid := builtin.AccountActorCodeID + dummyCid := builtin2.AccountActorCodeID si := &SectorInfo{ State: "stateful", diff --git a/genesis/types.go b/genesis/types.go index 79656feac..db8d32a3b 100644 --- a/genesis/types.go +++ b/genesis/types.go @@ -5,9 +5,10 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/specs-actors/actors/builtin/market" "github.com/ipfs/go-cid" "github.com/libp2p/go-libp2p-core/peer" + + market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market" ) type ActorType string @@ -21,7 +22,7 @@ type PreSeal struct { CommR cid.Cid CommD cid.Cid SectorID abi.SectorNumber - Deal market.DealProposal + Deal market2.DealProposal ProofType abi.RegisteredSealProof } diff --git a/markets/storageadapter/client.go b/markets/storageadapter/client.go index 6496fffad..ad2b2df8a 100644 --- a/markets/storageadapter/client.go +++ b/markets/storageadapter/client.go @@ -6,20 +6,20 @@ import ( "bytes" "context" - "golang.org/x/xerrors" - - "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-address" cborutil "github.com/filecoin-project/go-cbor-util" + "github.com/ipfs/go-cid" + "golang.org/x/xerrors" + "github.com/filecoin-project/go-fil-markets/shared" "github.com/filecoin-project/go-fil-markets/storagemarket" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/exitcode" - miner0 "github.com/filecoin-project/specs-actors/actors/builtin" - market0 "github.com/filecoin-project/specs-actors/actors/builtin/market" + + miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" @@ -103,10 +103,10 @@ func (c *ClientNodeAdapter) VerifySignature(ctx context.Context, sig crypto.Sign func (c *ClientNodeAdapter) AddFunds(ctx context.Context, addr address.Address, amount abi.TokenAmount) (cid.Cid, error) { // (Provider Node API) smsg, err := c.MpoolPushMessage(ctx, &types.Message{ - To: miner0.StorageMarketActorAddr, + To: miner2.StorageMarketActorAddr, From: addr, Value: amount, - Method: miner0.MethodsMarket.AddBalance, + Method: miner2.MethodsMarket.AddBalance, }, nil) if err != nil { return cid.Undef, err @@ -157,15 +157,15 @@ func (c *ClientNodeAdapter) ValidatePublishedDeal(ctx context.Context, deal stor return 0, xerrors.Errorf("deal wasn't published by storage provider: from=%s, provider=%s", pubmsg.From, deal.Proposal.Provider) } - if pubmsg.To != miner0.StorageMarketActorAddr { + if pubmsg.To != miner2.StorageMarketActorAddr { return 0, xerrors.Errorf("deal publish message wasn't set to StorageMarket actor (to=%s)", pubmsg.To) } - if pubmsg.Method != miner0.MethodsMarket.PublishStorageDeals { + if pubmsg.Method != miner2.MethodsMarket.PublishStorageDeals { return 0, xerrors.Errorf("deal publish message called incorrect method (method=%s)", pubmsg.Method) } - var params market0.PublishStorageDealsParams + var params market2.PublishStorageDealsParams if err := params.UnmarshalCBOR(bytes.NewReader(pubmsg.Params)); err != nil { return 0, err } @@ -197,7 +197,7 @@ func (c *ClientNodeAdapter) ValidatePublishedDeal(ctx context.Context, deal stor return 0, xerrors.Errorf("deal publish failed: exit=%d", ret.ExitCode) } - var res market0.PublishStorageDealsReturn + var res market2.PublishStorageDealsReturn if err := res.UnmarshalCBOR(bytes.NewReader(ret.Return)); err != nil { return 0, err } @@ -275,7 +275,7 @@ func (c *ClientNodeAdapter) OnDealSectorCommitted(ctx context.Context, provider } switch msg.Method { - case miner0.MethodsMiner.PreCommitSector: + case miner2.MethodsMiner.PreCommitSector: var params miner.SectorPreCommitInfo if err := params.UnmarshalCBOR(bytes.NewReader(msg.Params)); err != nil { return true, false, xerrors.Errorf("unmarshal pre commit: %w", err) @@ -290,7 +290,7 @@ func (c *ClientNodeAdapter) OnDealSectorCommitted(ctx context.Context, provider } return true, false, nil - case miner0.MethodsMiner.ProveCommitSector: + case miner2.MethodsMiner.ProveCommitSector: var params miner.ProveCommitSectorParams if err := params.UnmarshalCBOR(bytes.NewReader(msg.Params)); err != nil { return true, false, xerrors.Errorf("failed to unmarshal prove commit sector params: %w", err) @@ -412,7 +412,7 @@ func (c *ClientNodeAdapter) OnDealExpiredOrSlashed(ctx context.Context, dealID a return nil } -func (c *ClientNodeAdapter) SignProposal(ctx context.Context, signer address.Address, proposal market0.DealProposal) (*market0.ClientDealProposal, error) { +func (c *ClientNodeAdapter) SignProposal(ctx context.Context, signer address.Address, proposal market2.DealProposal) (*market2.ClientDealProposal, error) { // TODO: output spec signed proposal buf, err := cborutil.Dump(&proposal) if err != nil { @@ -431,7 +431,7 @@ func (c *ClientNodeAdapter) SignProposal(ctx context.Context, signer address.Add return nil, err } - return &market0.ClientDealProposal{ + return &market2.ClientDealProposal{ Proposal: proposal, ClientSignature: *sig, }, nil diff --git a/markets/storageadapter/provider.go b/markets/storageadapter/provider.go index b1071adcd..9c088e4de 100644 --- a/markets/storageadapter/provider.go +++ b/markets/storageadapter/provider.go @@ -12,8 +12,8 @@ import ( logging "github.com/ipfs/go-log/v2" "golang.org/x/xerrors" - builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" - market0 "github.com/filecoin-project/specs-actors/actors/builtin/market" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-fil-markets/shared" @@ -79,8 +79,8 @@ func (n *ProviderNodeAdapter) PublishDeals(ctx context.Context, deal storagemark return cid.Undef, err } - params, err := actors.SerializeParams(&market0.PublishStorageDealsParams{ - Deals: []market0.ClientDealProposal{deal.ClientDealProposal}, + params, err := actors.SerializeParams(&market2.PublishStorageDealsParams{ + Deals: []market2.ClientDealProposal{deal.ClientDealProposal}, }) if err != nil { @@ -92,7 +92,7 @@ func (n *ProviderNodeAdapter) PublishDeals(ctx context.Context, deal storagemark To: market.Address, From: mi.Worker, Value: types.NewInt(0), - Method: builtin0.MethodsMarket.PublishStorageDeals, + Method: builtin2.MethodsMarket.PublishStorageDeals, Params: params, }, n.publishSpec) if err != nil { @@ -192,7 +192,7 @@ func (n *ProviderNodeAdapter) AddFunds(ctx context.Context, addr address.Address To: market.Address, From: addr, Value: amount, - Method: builtin0.MethodsMarket.AddBalance, + Method: builtin2.MethodsMarket.AddBalance, }, n.addBalanceSpec) if err != nil { return cid.Undef, err @@ -314,7 +314,7 @@ func (n *ProviderNodeAdapter) OnDealSectorCommitted(ctx context.Context, provide } switch msg.Method { - case builtin0.MethodsMiner.PreCommitSector: + case builtin2.MethodsMiner.PreCommitSector: var params miner.SectorPreCommitInfo if err := params.UnmarshalCBOR(bytes.NewReader(msg.Params)); err != nil { return true, false, xerrors.Errorf("unmarshal pre commit: %w", err) @@ -329,7 +329,7 @@ func (n *ProviderNodeAdapter) OnDealSectorCommitted(ctx context.Context, provide } return true, false, nil - case builtin0.MethodsMiner.ProveCommitSector: + case builtin2.MethodsMiner.ProveCommitSector: var params miner.ProveCommitSectorParams if err := params.UnmarshalCBOR(bytes.NewReader(msg.Params)); err != nil { return true, false, xerrors.Errorf("failed to unmarshal prove commit sector params: %w", err) diff --git a/miner/miner.go b/miner/miner.go index 73985a649..7451d617a 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -9,7 +9,7 @@ import ( "sync" "time" - proof0 "github.com/filecoin-project/specs-actors/actors/runtime/proof" + proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" "github.com/filecoin-project/lotus/chain/gen/slashfilter" @@ -492,7 +492,7 @@ func (m *Miner) computeTicket(ctx context.Context, brand *types.BeaconEntry, bas } func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *types.Ticket, - eproof *types.ElectionProof, bvals []types.BeaconEntry, wpostProof []proof0.PoStProof, msgs []*types.SignedMessage) (*types.BlockMsg, error) { + eproof *types.ElectionProof, bvals []types.BeaconEntry, wpostProof []proof2.PoStProof, msgs []*types.SignedMessage) (*types.BlockMsg, error) { uts := base.TipSet.MinTimestamp() + build.BlockDelaySecs*(uint64(base.NullRounds)+1) nheight := base.TipSet.Height() + base.NullRounds + 1 diff --git a/node/impl/full/gas.go b/node/impl/full/gas.go index 2e5063ccb..4e4fc99d2 100644 --- a/node/impl/full/gas.go +++ b/node/impl/full/gas.go @@ -16,7 +16,7 @@ import ( "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/exitcode" - builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" @@ -259,7 +259,7 @@ func gasEstimateGasLimit( if !builtin.IsPaymentChannelActor(act.Code) { return res.MsgRct.GasUsed, nil } - if msgIn.Method != builtin0.MethodsPaych.Collect { + if msgIn.Method != builtin2.MethodsPaych.Collect { return res.MsgRct.GasUsed, nil } diff --git a/node/impl/full/multisig.go b/node/impl/full/multisig.go index d840620eb..3b13839dd 100644 --- a/node/impl/full/multisig.go +++ b/node/impl/full/multisig.go @@ -12,8 +12,8 @@ import ( "github.com/filecoin-project/lotus/chain/actors/builtin/multisig" "github.com/filecoin-project/lotus/chain/types" - builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" - multisig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + multisig2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/multisig" "github.com/ipfs/go-cid" "go.uber.org/fx" @@ -85,7 +85,7 @@ func (a *MsigAPI) MsigAddPropose(ctx context.Context, msig address.Address, src return cid.Undef, actErr } - return a.MsigPropose(ctx, msig, msig, big.Zero(), src, uint64(builtin0.MethodsMultisig.AddSigner), enc) + return a.MsigPropose(ctx, msig, msig, big.Zero(), src, uint64(builtin2.MethodsMultisig.AddSigner), enc) } func (a *MsigAPI) MsigAddApprove(ctx context.Context, msig address.Address, src address.Address, txID uint64, proposer address.Address, newAdd address.Address, inc bool) (cid.Cid, error) { @@ -94,7 +94,7 @@ func (a *MsigAPI) MsigAddApprove(ctx context.Context, msig address.Address, src return cid.Undef, actErr } - return a.MsigApproveTxnHash(ctx, msig, txID, proposer, msig, big.Zero(), src, uint64(builtin0.MethodsMultisig.AddSigner), enc) + return a.MsigApproveTxnHash(ctx, msig, txID, proposer, msig, big.Zero(), src, uint64(builtin2.MethodsMultisig.AddSigner), enc) } func (a *MsigAPI) MsigAddCancel(ctx context.Context, msig address.Address, src address.Address, txID uint64, newAdd address.Address, inc bool) (cid.Cid, error) { @@ -103,7 +103,7 @@ func (a *MsigAPI) MsigAddCancel(ctx context.Context, msig address.Address, src a return cid.Undef, actErr } - return a.MsigCancel(ctx, msig, txID, msig, big.Zero(), src, uint64(builtin0.MethodsMultisig.AddSigner), enc) + return a.MsigCancel(ctx, msig, txID, msig, big.Zero(), src, uint64(builtin2.MethodsMultisig.AddSigner), enc) } func (a *MsigAPI) MsigSwapPropose(ctx context.Context, msig address.Address, src address.Address, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) { @@ -112,7 +112,7 @@ func (a *MsigAPI) MsigSwapPropose(ctx context.Context, msig address.Address, src return cid.Undef, actErr } - return a.MsigPropose(ctx, msig, msig, big.Zero(), src, uint64(builtin0.MethodsMultisig.SwapSigner), enc) + return a.MsigPropose(ctx, msig, msig, big.Zero(), src, uint64(builtin2.MethodsMultisig.SwapSigner), enc) } func (a *MsigAPI) MsigSwapApprove(ctx context.Context, msig address.Address, src address.Address, txID uint64, proposer address.Address, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) { @@ -121,7 +121,7 @@ func (a *MsigAPI) MsigSwapApprove(ctx context.Context, msig address.Address, src return cid.Undef, actErr } - return a.MsigApproveTxnHash(ctx, msig, txID, proposer, msig, big.Zero(), src, uint64(builtin0.MethodsMultisig.SwapSigner), enc) + return a.MsigApproveTxnHash(ctx, msig, txID, proposer, msig, big.Zero(), src, uint64(builtin2.MethodsMultisig.SwapSigner), enc) } func (a *MsigAPI) MsigSwapCancel(ctx context.Context, msig address.Address, src address.Address, txID uint64, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) { @@ -130,7 +130,7 @@ func (a *MsigAPI) MsigSwapCancel(ctx context.Context, msig address.Address, src return cid.Undef, actErr } - return a.MsigCancel(ctx, msig, txID, msig, big.Zero(), src, uint64(builtin0.MethodsMultisig.SwapSigner), enc) + return a.MsigCancel(ctx, msig, txID, msig, big.Zero(), src, uint64(builtin2.MethodsMultisig.SwapSigner), enc) } func (a *MsigAPI) MsigApprove(ctx context.Context, msig address.Address, txID uint64, src address.Address) (cid.Cid, error) { @@ -151,7 +151,7 @@ func (a *MsigAPI) MsigRemoveSigner(ctx context.Context, msig address.Address, pr return cid.Undef, actErr } - return a.MsigPropose(ctx, msig, msig, types.NewInt(0), proposer, uint64(builtin0.MethodsMultisig.RemoveSigner), enc) + return a.MsigPropose(ctx, msig, msig, types.NewInt(0), proposer, uint64(builtin2.MethodsMultisig.RemoveSigner), enc) } func (a *MsigAPI) msigApproveOrCancelSimple(ctx context.Context, operation api.MsigProposeResponse, msig address.Address, txID uint64, src address.Address) (cid.Cid, error) { @@ -242,7 +242,7 @@ func (a *MsigAPI) msigApproveOrCancelTxnHash(ctx context.Context, operation api. } func serializeAddParams(new address.Address, inc bool) ([]byte, error) { - enc, actErr := actors.SerializeParams(&multisig0.AddSignerParams{ + enc, actErr := actors.SerializeParams(&multisig2.AddSignerParams{ Signer: new, Increase: inc, }) @@ -254,7 +254,7 @@ func serializeAddParams(new address.Address, inc bool) ([]byte, error) { } func serializeSwapParams(old address.Address, new address.Address) ([]byte, error) { - enc, actErr := actors.SerializeParams(&multisig0.SwapSignerParams{ + enc, actErr := actors.SerializeParams(&multisig2.SwapSignerParams{ From: old, To: new, }) @@ -266,7 +266,7 @@ func serializeSwapParams(old address.Address, new address.Address) ([]byte, erro } func serializeRemoveParams(rem address.Address, dec bool) ([]byte, error) { - enc, actErr := actors.SerializeParams(&multisig0.RemoveSignerParams{ + enc, actErr := actors.SerializeParams(&multisig2.RemoveSignerParams{ Signer: rem, Decrease: dec, }) diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 7f510aa70..66b16e9f3 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -44,7 +44,6 @@ import ( paramfetch "github.com/filecoin-project/go-paramfetch" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-storedcounter" - "github.com/filecoin-project/specs-actors/actors/builtin" sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" @@ -56,6 +55,7 @@ import ( lapi "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/gen/slashfilter" "github.com/filecoin-project/lotus/chain/types" diff --git a/node/test/builder.go b/node/test/builder.go index 4aa8a55ea..785e07bbe 100644 --- a/node/test/builder.go +++ b/node/test/builder.go @@ -24,6 +24,7 @@ import ( "github.com/filecoin-project/lotus/api/test" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors" + "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/gen" genesis2 "github.com/filecoin-project/lotus/chain/gen/genesis" "github.com/filecoin-project/lotus/chain/types" @@ -33,14 +34,14 @@ import ( "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" "github.com/filecoin-project/lotus/extern/sector-storage/mock" "github.com/filecoin-project/lotus/genesis" - miner2 "github.com/filecoin-project/lotus/miner" + lotusminer "github.com/filecoin-project/lotus/miner" "github.com/filecoin-project/lotus/node" "github.com/filecoin-project/lotus/node/modules" testing2 "github.com/filecoin-project/lotus/node/modules/testing" "github.com/filecoin-project/lotus/node/repo" "github.com/filecoin-project/lotus/storage/mockstorage" - "github.com/filecoin-project/specs-actors/actors/builtin" - miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" "github.com/ipfs/go-datastore" "github.com/libp2p/go-libp2p-core/crypto" "github.com/libp2p/go-libp2p-core/peer" @@ -86,13 +87,13 @@ func CreateTestStorageNode(ctx context.Context, t *testing.T, waddr address.Addr peerid, err := peer.IDFromPrivateKey(pk) require.NoError(t, err) - enc, err := actors.SerializeParams(&miner0.ChangePeerIDParams{NewID: abi.PeerID(peerid)}) + enc, err := actors.SerializeParams(&miner2.ChangePeerIDParams{NewID: abi.PeerID(peerid)}) require.NoError(t, err) msg := &types.Message{ To: act, From: waddr, - Method: builtin.MethodsMiner.ChangePeerID, + Method: builtin2.MethodsMiner.ChangePeerID, Params: enc, Value: types.NewInt(0), } @@ -103,7 +104,7 @@ func CreateTestStorageNode(ctx context.Context, t *testing.T, waddr address.Addr // start node var minerapi api.StorageMiner - mineBlock := make(chan miner2.MineReq) + mineBlock := make(chan lotusminer.MineReq) stop, err := node.New(ctx, node.StorageMiner(&minerapi), node.Online(), @@ -113,7 +114,7 @@ func CreateTestStorageNode(ctx context.Context, t *testing.T, waddr address.Addr node.MockHost(mn), node.Override(new(api.FullNode), tnd), - node.Override(new(*miner2.Miner), miner2.NewTestMiner(mineBlock, act)), + node.Override(new(*lotusminer.Miner), lotusminer.NewTestMiner(mineBlock, act)), opts, ) @@ -129,7 +130,7 @@ func CreateTestStorageNode(ctx context.Context, t *testing.T, waddr address.Addr err = minerapi.NetConnect(ctx, remoteAddrs) require.NoError(t, err)*/ - mineOne := func(ctx context.Context, req miner2.MineReq) error { + mineOne := func(ctx context.Context, req lotusminer.MineReq) error { select { case mineBlock <- req: return nil @@ -444,7 +445,7 @@ func mockSbBuilderOpts(t *testing.T, fullOpts []test.FullNodeOpts, storage []tes storers[i] = CreateTestStorageNode(ctx, t, genms[i].Worker, maddrs[i], pidKeys[i], f, mn, node.Options( node.Override(new(sectorstorage.SectorManager), func() (sectorstorage.SectorManager, error) { - return mock.NewMockSectorMgr(build.DefaultSectorSize(), sectors), nil + return mock.NewMockSectorMgr(policy.GetDefaultSectorSize(), sectors), nil }), node.Override(new(ffiwrapper.Verifier), mock.MockVerifier), node.Unset(new(*sectorstorage.Manager)), diff --git a/paychmgr/paych_test.go b/paychmgr/paych_test.go index fcd3d50a8..8557dfb63 100644 --- a/paychmgr/paych_test.go +++ b/paychmgr/paych_test.go @@ -14,9 +14,9 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/crypto" - "github.com/filecoin-project/specs-actors/actors/builtin" - tutils "github.com/filecoin-project/specs-actors/support/testing" + "github.com/filecoin-project/specs-actors/v2/actors/builtin" paych2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/paych" + tutils "github.com/filecoin-project/specs-actors/v2/support/testing" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/actors/builtin/paych" @@ -237,7 +237,7 @@ func TestCreateVoucher(t *testing.T) { // Create a voucher in lane 1 voucherLane1Amt := big.NewInt(5) - voucher := paych2.SignedVoucher{ + voucher := paych.SignedVoucher{ Lane: 1, Amount: voucherLane1Amt, } @@ -252,7 +252,7 @@ func TestCreateVoucher(t *testing.T) { // Create a voucher in lane 1 again, with a higher amount voucherLane1Amt = big.NewInt(8) - voucher = paych2.SignedVoucher{ + voucher = paych.SignedVoucher{ Lane: 1, Amount: voucherLane1Amt, } @@ -267,7 +267,7 @@ func TestCreateVoucher(t *testing.T) { // Create a voucher in lane 2 that covers all the remaining funds // in the channel voucherLane2Amt := big.Sub(s.amt, voucherLane1Amt) - voucher = paych2.SignedVoucher{ + voucher = paych.SignedVoucher{ Lane: 2, Amount: voucherLane2Amt, } @@ -281,7 +281,7 @@ func TestCreateVoucher(t *testing.T) { // Create a voucher in lane 2 that exceeds the remaining funds in the // channel voucherLane2Amt = big.Add(voucherLane2Amt, big.NewInt(1)) - voucher = paych2.SignedVoucher{ + voucher = paych.SignedVoucher{ Lane: 2, Amount: voucherLane2Amt, } diff --git a/paychmgr/paychvoucherfunds_test.go b/paychmgr/paychvoucherfunds_test.go index dcbb4acc9..f83a7cd62 100644 --- a/paychmgr/paychvoucherfunds_test.go +++ b/paychmgr/paychvoucherfunds_test.go @@ -4,19 +4,19 @@ import ( "context" "testing" - "github.com/filecoin-project/lotus/chain/actors/builtin/paych" - paychmock "github.com/filecoin-project/lotus/chain/actors/builtin/paych/mock" - - "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" - "github.com/filecoin-project/specs-actors/actors/builtin" - tutils "github.com/filecoin-project/specs-actors/support/testing" "github.com/ipfs/go-cid" ds "github.com/ipfs/go-datastore" ds_sync "github.com/ipfs/go-datastore/sync" "github.com/stretchr/testify/require" + + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + tutils2 "github.com/filecoin-project/specs-actors/v2/support/testing" + + "github.com/filecoin-project/lotus/chain/actors/builtin/paych" + paychmock "github.com/filecoin-project/lotus/chain/actors/builtin/paych/mock" + "github.com/filecoin-project/lotus/chain/types" ) // TestPaychAddVoucherAfterAddFunds tests adding a voucher to a channel with @@ -27,11 +27,11 @@ func TestPaychAddVoucherAfterAddFunds(t *testing.T) { store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore())) fromKeyPrivate, fromKeyPublic := testGenerateKeyPair(t) - ch := tutils.NewIDAddr(t, 100) - from := tutils.NewSECP256K1Addr(t, string(fromKeyPublic)) - to := tutils.NewSECP256K1Addr(t, "secpTo") - fromAcct := tutils.NewActorAddr(t, "fromAct") - toAcct := tutils.NewActorAddr(t, "toAct") + ch := tutils2.NewIDAddr(t, 100) + from := tutils2.NewSECP256K1Addr(t, string(fromKeyPublic)) + to := tutils2.NewSECP256K1Addr(t, "secpTo") + fromAcct := tutils2.NewActorAddr(t, "fromAct") + toAcct := tutils2.NewActorAddr(t, "toAct") mock := newMockManagerAPI() defer mock.close() @@ -55,7 +55,7 @@ func TestPaychAddVoucherAfterAddFunds(t *testing.T) { // Create an actor in state for the channel with the initial channel balance act := &types.Actor{ - Code: builtin.AccountActorCodeID, + Code: builtin2.AccountActorCodeID, Head: cid.Cid{}, Nonce: 0, Balance: createAmt, diff --git a/paychmgr/settler/settler.go b/paychmgr/settler/settler.go index 02fe9256e..8074e8a87 100644 --- a/paychmgr/settler/settler.go +++ b/paychmgr/settler/settler.go @@ -14,7 +14,7 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" @@ -107,7 +107,7 @@ func (pcs *paymentChannelSettler) revertHandler(ctx context.Context, ts *types.T func (pcs *paymentChannelSettler) matcher(msg *types.Message) (matchOnce bool, matched bool, err error) { // Check if this is a settle payment channel message - if msg.Method != builtin0.MethodsPaych.Settle { + if msg.Method != builtin2.MethodsPaych.Settle { return false, false, nil } // Check if this payment channel is of concern to this node (i.e. tracked in payment channel store), diff --git a/storage/adapter_storage_miner.go b/storage/adapter_storage_miner.go index 380fb4471..f645c301a 100644 --- a/storage/adapter_storage_miner.go +++ b/storage/adapter_storage_miner.go @@ -15,8 +15,8 @@ import ( "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/crypto" - builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" - market0 "github.com/filecoin-project/specs-actors/actors/builtin/market" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api/apibstore" @@ -138,7 +138,7 @@ func (s SealingAPIAdapter) StateComputeDataCommitment(ctx context.Context, maddr return cid.Undef, xerrors.Errorf("failed to unmarshal TipSetToken to TipSetKey: %w", err) } - ccparams, err := actors.SerializeParams(&market0.ComputeDataCommitmentParams{ + ccparams, err := actors.SerializeParams(&market2.ComputeDataCommitmentParams{ DealIDs: deals, SectorType: sectorType, }) @@ -150,7 +150,7 @@ func (s SealingAPIAdapter) StateComputeDataCommitment(ctx context.Context, maddr To: market.Address, From: maddr, Value: types.NewInt(0), - Method: builtin0.MethodsMarket.ComputeDataCommitment, + Method: builtin2.MethodsMarket.ComputeDataCommitment, Params: ccparams, } r, err := s.delegate.StateCall(ctx, ccmt, tsk) diff --git a/storage/miner.go b/storage/miner.go index 74a048c8e..b5a2fd6a5 100644 --- a/storage/miner.go +++ b/storage/miner.go @@ -5,9 +5,6 @@ import ( "errors" "time" - miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" - proof0 "github.com/filecoin-project/specs-actors/actors/runtime/proof" - "github.com/filecoin-project/go-state-types/network" "github.com/filecoin-project/go-state-types/dline" @@ -29,7 +26,9 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" + "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/events" "github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/types" @@ -150,7 +149,7 @@ func (m *Miner) Run(ctx context.Context) error { evts := events.NewEvents(ctx, m.api) adaptedAPI := NewSealingAPIAdapter(m.api) // TODO: Maybe we update this policy after actor upgrades? - pcp := sealing.NewBasicPreCommitPolicy(adaptedAPI, miner0.MaxSectorExpirationExtension-(miner0.WPoStProvingPeriod*2), md.PeriodStart%miner0.WPoStProvingPeriod) + pcp := sealing.NewBasicPreCommitPolicy(adaptedAPI, policy.GetMaxSectorExpirationExtension()-(md.WPoStProvingPeriod*2), md.PeriodStart%md.WPoStProvingPeriod) m.sealing = sealing.New(adaptedAPI, fc, NewEventsAdapter(evts), m.maddr, m.ds, m.sealer, m.sc, m.verif, &pcp, sealing.GetSealingConfigFunc(m.getSealConfig), m.handleSealingNotifications) go m.sealing.Run(ctx) //nolint:errcheck // logged intside the function @@ -238,9 +237,9 @@ func (wpp *StorageWpp) GenerateCandidates(ctx context.Context, randomness abi.Po return cds, nil } -func (wpp *StorageWpp) ComputeProof(ctx context.Context, ssi []proof0.SectorInfo, rand abi.PoStRandomness) ([]proof0.PoStProof, error) { +func (wpp *StorageWpp) ComputeProof(ctx context.Context, ssi []builtin.SectorInfo, rand abi.PoStRandomness) ([]builtin.PoStProof, error) { if build.InsecurePoStValidation { - return []proof0.PoStProof{{ProofBytes: []byte("valid proof")}}, nil + return []builtin.PoStProof{{ProofBytes: []byte("valid proof")}}, nil } log.Infof("Computing WinningPoSt ;%+v; %v", ssi, rand) diff --git a/storage/mockstorage/preseal.go b/storage/mockstorage/preseal.go index 090aacc3c..0417405c8 100644 --- a/storage/mockstorage/preseal.go +++ b/storage/mockstorage/preseal.go @@ -9,7 +9,7 @@ import ( "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/lotus/extern/sector-storage/mock" - market0 "github.com/filecoin-project/specs-actors/actors/builtin/market" + market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/wallet" @@ -48,7 +48,7 @@ func PreSeal(ssize abi.SectorSize, maddr address.Address, sectors int) (*genesis r := mock.CommDR(d) preseal.CommR, _ = commcid.ReplicaCommitmentV1ToCID(r[:]) preseal.SectorID = abi.SectorNumber(i + 1) - preseal.Deal = market0.DealProposal{ + preseal.Deal = market2.DealProposal{ PieceCID: preseal.CommD, PieceSize: abi.PaddedPieceSize(ssize), Client: k.Address, diff --git a/storage/wdpost_run.go b/storage/wdpost_run.go index d4ed4d64c..c11e5dca0 100644 --- a/storage/wdpost_run.go +++ b/storage/wdpost_run.go @@ -17,14 +17,14 @@ import ( "go.opencensus.io/trace" "golang.org/x/xerrors" - builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" - miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" - "github.com/filecoin-project/specs-actors/actors/runtime/proof" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" "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/actors/builtin/miner" + "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/types" ) @@ -290,7 +290,7 @@ func (s *WindowPoStScheduler) checkNextRecoveries(ctx context.Context, dlIdx uin msg := &types.Message{ To: s.actor, From: s.worker, - Method: builtin0.MethodsMiner.DeclareFaultsRecovered, + Method: builtin2.MethodsMiner.DeclareFaultsRecovered, Params: enc, Value: types.NewInt(0), } @@ -374,7 +374,7 @@ func (s *WindowPoStScheduler) checkNextFaults(ctx context.Context, dlIdx uint64, msg := &types.Message{ To: s.actor, From: s.worker, - Method: builtin0.MethodsMiner.DeclareFaults, + Method: builtin2.MethodsMiner.DeclareFaults, Params: enc, Value: types.NewInt(0), // TODO: Is there a fee? } @@ -505,12 +505,12 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di dline.Info, ts *ty skipCount := uint64(0) postSkipped := bitfield.New() - var postOut []proof.PoStProof + var postOut []proof2.PoStProof somethingToProve := true for retries := 0; retries < 5; retries++ { var partitions []miner.PoStPartition - var sinfos []proof.SectorInfo + var sinfos []proof2.SectorInfo for partIdx, partition := range batch { // TODO: Can do this in parallel toProve, err := bitfield.SubtractBitField(partition.LiveSectors, partition.FaultySectors) @@ -625,12 +625,6 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di dline.Info, ts *ty } func (s *WindowPoStScheduler) batchPartitions(partitions []api.Partition) ([][]api.Partition, error) { - // Get the number of sectors allowed in a partition, for this proof size - sectorsPerPartition, err := builtin0.PoStProofWindowPoStPartitionSectors(s.proofType) - if err != nil { - return nil, xerrors.Errorf("getting sectors per partition: %w", err) - } - // We don't want to exceed the number of sectors allowed in a message. // So given the number of sectors in a partition, work out the number of // partitions that can be in a message without exceeding sectors per @@ -641,9 +635,10 @@ func (s *WindowPoStScheduler) batchPartitions(partitions []api.Partition) ([][]a // sectors per partition 3: ooo // partitions per message 2: oooOOO // <1><2> (3rd doesn't fit) - // TODO(NETUPGRADE): we're going to need some form of policy abstraction - // where we can get policy from the future. Unfortunately, we can't just get this from the state. - partitionsPerMsg := int(miner0.AddressedSectorsMax / sectorsPerPartition) + partitionsPerMsg, err := policy.GetMaxPoStPartitions(s.proofType) + if err != nil { + return nil, xerrors.Errorf("getting sectors per partition: %w", err) + } // The number of messages will be: // ceiling(number of partitions / partitions per message) @@ -665,7 +660,7 @@ func (s *WindowPoStScheduler) batchPartitions(partitions []api.Partition) ([][]a return batches, nil } -func (s *WindowPoStScheduler) sectorsForProof(ctx context.Context, goodSectors, allSectors bitfield.BitField, ts *types.TipSet) ([]proof.SectorInfo, error) { +func (s *WindowPoStScheduler) sectorsForProof(ctx context.Context, goodSectors, allSectors bitfield.BitField, ts *types.TipSet) ([]proof2.SectorInfo, error) { sset, err := s.api.StateMinerSectors(ctx, s.actor, &goodSectors, ts.Key()) if err != nil { return nil, err @@ -675,22 +670,22 @@ func (s *WindowPoStScheduler) sectorsForProof(ctx context.Context, goodSectors, return nil, nil } - substitute := proof.SectorInfo{ + substitute := proof2.SectorInfo{ SectorNumber: sset[0].SectorNumber, SealedCID: sset[0].SealedCID, SealProof: sset[0].SealProof, } - sectorByID := make(map[uint64]proof.SectorInfo, len(sset)) + sectorByID := make(map[uint64]proof2.SectorInfo, len(sset)) for _, sector := range sset { - sectorByID[uint64(sector.SectorNumber)] = proof.SectorInfo{ + sectorByID[uint64(sector.SectorNumber)] = proof2.SectorInfo{ SectorNumber: sector.SectorNumber, SealedCID: sector.SealedCID, SealProof: sector.SealProof, } } - proofSectors := make([]proof.SectorInfo, 0, len(sset)) + proofSectors := make([]proof2.SectorInfo, 0, len(sset)) if err := allSectors.ForEach(func(sectorNo uint64) error { if info, found := sectorByID[sectorNo]; found { proofSectors = append(proofSectors, info) @@ -719,7 +714,7 @@ func (s *WindowPoStScheduler) submitPost(ctx context.Context, proof *miner.Submi msg := &types.Message{ To: s.actor, From: s.worker, - Method: builtin0.MethodsMiner.SubmitWindowedPoSt, + Method: builtin2.MethodsMiner.SubmitWindowedPoSt, Params: enc, Value: types.NewInt(0), } diff --git a/storage/wdpost_run_test.go b/storage/wdpost_run_test.go index dd7ac4c24..75588d7f8 100644 --- a/storage/wdpost_run_test.go +++ b/storage/wdpost_run_test.go @@ -17,10 +17,10 @@ import ( "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/dline" "github.com/filecoin-project/go-state-types/network" - builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" - miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" - proof0 "github.com/filecoin-project/specs-actors/actors/runtime/proof" - tutils "github.com/filecoin-project/specs-actors/support/testing" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" + proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" + tutils "github.com/filecoin-project/specs-actors/v2/support/testing" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" @@ -98,12 +98,12 @@ func (m *mockStorageMinerAPI) StateWaitMsg(ctx context.Context, cid cid.Cid, con type mockProver struct { } -func (m *mockProver) GenerateWinningPoSt(context.Context, abi.ActorID, []proof0.SectorInfo, abi.PoStRandomness) ([]proof0.PoStProof, error) { +func (m *mockProver) GenerateWinningPoSt(context.Context, abi.ActorID, []proof2.SectorInfo, abi.PoStRandomness) ([]proof2.PoStProof, error) { panic("implement me") } -func (m *mockProver) GenerateWindowPoSt(ctx context.Context, aid abi.ActorID, sis []proof0.SectorInfo, pr abi.PoStRandomness) ([]proof0.PoStProof, []abi.SectorID, error) { - return []proof0.PoStProof{ +func (m *mockProver) GenerateWindowPoSt(ctx context.Context, aid abi.ActorID, sis []proof2.SectorInfo, pr abi.PoStRandomness) ([]proof2.PoStProof, []abi.SectorID, error) { + return []proof2.PoStProof{ { PoStProof: abi.RegisteredPoStProof_StackedDrgWindow2KiBV1, ProofBytes: []byte("post-proof"), @@ -132,13 +132,13 @@ func TestWDPostDoPost(t *testing.T) { mockStgMinerAPI := newMockStorageMinerAPI() // Get the number of sectors allowed in a partition for this proof type - sectorsPerPartition, err := builtin0.PoStProofWindowPoStPartitionSectors(proofType) + sectorsPerPartition, err := builtin2.PoStProofWindowPoStPartitionSectors(proofType) require.NoError(t, err) // Work out the number of partitions that can be included in a message // without exceeding the message sector limit require.NoError(t, err) - partitionsPerMsg := int(miner0.AddressedSectorsMax / sectorsPerPartition) + partitionsPerMsg := int(miner2.AddressedSectorsMax / sectorsPerPartition) // Enough partitions to fill expectedMsgCount-1 messages partitionCount := (expectedMsgCount - 1) * partitionsPerMsg @@ -173,11 +173,11 @@ func TestWDPostDoPost(t *testing.T) { } di := &dline.Info{ - WPoStPeriodDeadlines: miner0.WPoStPeriodDeadlines, - WPoStProvingPeriod: miner0.WPoStProvingPeriod, - WPoStChallengeWindow: miner0.WPoStChallengeWindow, - WPoStChallengeLookback: miner0.WPoStChallengeLookback, - FaultDeclarationCutoff: miner0.FaultDeclarationCutoff, + WPoStPeriodDeadlines: miner2.WPoStPeriodDeadlines, + WPoStProvingPeriod: miner2.WPoStProvingPeriod, + WPoStChallengeWindow: miner2.WPoStChallengeWindow, + WPoStChallengeLookback: miner2.WPoStChallengeLookback, + FaultDeclarationCutoff: miner2.FaultDeclarationCutoff, } ts := mockTipSet(t) @@ -188,7 +188,7 @@ func TestWDPostDoPost(t *testing.T) { // Read the window PoST messages for i := 0; i < expectedMsgCount; i++ { msg := <-mockStgMinerAPI.pushedMessages - require.Equal(t, builtin0.MethodsMiner.SubmitWindowedPoSt, msg.Method) + require.Equal(t, builtin2.MethodsMiner.SubmitWindowedPoSt, msg.Method) var params miner.SubmitWindowedPoStParams err := params.UnmarshalCBOR(bytes.NewReader(msg.Params)) require.NoError(t, err) @@ -254,11 +254,11 @@ func (m *mockStorageMinerAPI) StateMinerProvingDeadline(ctx context.Context, add Close: 0, Challenge: 0, FaultCutoff: 0, - WPoStPeriodDeadlines: miner0.WPoStPeriodDeadlines, - WPoStProvingPeriod: miner0.WPoStProvingPeriod, - WPoStChallengeWindow: miner0.WPoStChallengeWindow, - WPoStChallengeLookback: miner0.WPoStChallengeLookback, - FaultDeclarationCutoff: miner0.FaultDeclarationCutoff, + WPoStPeriodDeadlines: miner2.WPoStPeriodDeadlines, + WPoStProvingPeriod: miner2.WPoStProvingPeriod, + WPoStChallengeWindow: miner2.WPoStChallengeWindow, + WPoStChallengeLookback: miner2.WPoStChallengeLookback, + FaultDeclarationCutoff: miner2.FaultDeclarationCutoff, }, nil } @@ -276,7 +276,7 @@ func (m *mockStorageMinerAPI) StateSearchMsg(ctx context.Context, cid cid.Cid) ( func (m *mockStorageMinerAPI) StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) { return &types.Actor{ - Code: builtin0.StorageMinerActorCodeID, + Code: builtin2.StorageMinerActorCodeID, }, nil } From bcabe7b3b59fed67c823d90fc9ef3b4125ec65aa Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Thu, 8 Oct 2020 13:32:54 -0700 Subject: [PATCH 199/313] migrate methods to abstracted methods Method numbers never change anyways. At worst, we'll deprecate old methods and have to explicitly import them from the correct actors version to use them. --- chain/actors/builtin/account/account.go | 2 ++ chain/actors/builtin/builtin.go | 5 +++ chain/actors/builtin/cron/cron.go | 10 ++++++ chain/actors/builtin/init/init.go | 5 ++- chain/actors/builtin/market/market.go | 5 ++- chain/actors/builtin/miner/miner.go | 2 ++ chain/actors/builtin/multisig/message.go | 3 ++ chain/actors/builtin/paych/message.go | 4 +++ chain/actors/builtin/power/power.go | 5 ++- chain/actors/builtin/reward/reward.go | 5 ++- chain/actors/builtin/verifreg/verifreg.go | 5 ++- chain/market/fundmgr.go | 8 ++--- chain/market/fundmgr_test.go | 4 +-- chain/messagepool/gasguess/guessgas.go | 3 +- chain/stmgr/forks_test.go | 10 +++--- chain/stmgr/stmgr.go | 37 +++++++++++------------ chain/stmgr/utils.go | 14 +++------ chain/vm/gas_v0.go | 7 +++-- chain/vm/mkactor.go | 3 +- cli/multisig.go | 10 +++--- cmd/lotus-pcr/main.go | 9 +++--- cmd/lotus-shed/mempool-stats.go | 5 ++- cmd/lotus-shed/sectors.go | 20 ++++++------ cmd/lotus-shed/verifreg.go | 5 ++- cmd/lotus-storage-miner/actor.go | 24 +++++++-------- cmd/lotus-storage-miner/init.go | 10 +++--- conformance/chaos/actor.go | 21 +++++++------ extern/storage-sealing/states_sealing.go | 6 ++-- markets/storageadapter/provider.go | 9 +++--- node/impl/full/gas.go | 5 ++- node/impl/full/multisig.go | 15 +++++---- node/test/builder.go | 4 +-- paychmgr/settler/settler.go | 4 +-- storage/adapter_storage_miner.go | 3 +- storage/wdpost_run.go | 7 ++--- storage/wdpost_run_test.go | 2 +- 36 files changed, 160 insertions(+), 136 deletions(-) create mode 100644 chain/actors/builtin/cron/cron.go diff --git a/chain/actors/builtin/account/account.go b/chain/actors/builtin/account/account.go index 7b1b2a792..38ed2654b 100644 --- a/chain/actors/builtin/account/account.go +++ b/chain/actors/builtin/account/account.go @@ -24,6 +24,8 @@ func init() { }) } +var Methods = builtin2.MethodsAccount + func Load(store adt.Store, act *types.Actor) (State, error) { switch act.Code { case builtin0.AccountActorCodeID: diff --git a/chain/actors/builtin/builtin.go b/chain/actors/builtin/builtin.go index 52d1375b4..afba8efe8 100644 --- a/chain/actors/builtin/builtin.go +++ b/chain/actors/builtin/builtin.go @@ -37,6 +37,11 @@ const ( SecondsInDay = builtin0.SecondsInDay ) +const ( + MethodSend = builtin2.MethodSend + MethodConstructor = builtin2.MethodConstructor +) + // TODO: Why does actors have 2 different versions of this? type SectorInfo = proof0.SectorInfo type PoStProof = proof0.PoStProof diff --git a/chain/actors/builtin/cron/cron.go b/chain/actors/builtin/cron/cron.go new file mode 100644 index 000000000..65bfd992f --- /dev/null +++ b/chain/actors/builtin/cron/cron.go @@ -0,0 +1,10 @@ +package cron + +import ( + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" +) + +var ( + Address = builtin2.CronActorAddr + Methods = builtin2.MethodsCron +) diff --git a/chain/actors/builtin/init/init.go b/chain/actors/builtin/init/init.go index 5777bb890..60dbdf4fe 100644 --- a/chain/actors/builtin/init/init.go +++ b/chain/actors/builtin/init/init.go @@ -26,7 +26,10 @@ func init() { }) } -var Address = builtin0.InitActorAddr +var ( + Address = builtin2.InitActorAddr + Methods = builtin2.MethodsInit +) func Load(store adt.Store, act *types.Actor) (State, error) { switch act.Code { diff --git a/chain/actors/builtin/market/market.go b/chain/actors/builtin/market/market.go index fd08a0119..195ca40b9 100644 --- a/chain/actors/builtin/market/market.go +++ b/chain/actors/builtin/market/market.go @@ -27,7 +27,10 @@ func init() { }) } -var Address = builtin0.StorageMarketActorAddr +var ( + Address = builtin2.StorageMarketActorAddr + Methods = builtin2.MethodsMarket +) func Load(store adt.Store, act *types.Actor) (st State, err error) { switch act.Code { diff --git a/chain/actors/builtin/miner/miner.go b/chain/actors/builtin/miner/miner.go index 3cca39326..aad41e8a9 100644 --- a/chain/actors/builtin/miner/miner.go +++ b/chain/actors/builtin/miner/miner.go @@ -31,6 +31,8 @@ func init() { }) } +var Methods = builtin2.MethodsMiner + // Unchanged between v0 and v2 actors var WPoStProvingPeriod = miner0.WPoStProvingPeriod var WPoStPeriodDeadlines = miner0.WPoStPeriodDeadlines diff --git a/chain/actors/builtin/multisig/message.go b/chain/actors/builtin/multisig/message.go index 5beb5319d..3d2c66e6b 100644 --- a/chain/actors/builtin/multisig/message.go +++ b/chain/actors/builtin/multisig/message.go @@ -9,12 +9,15 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" multisig2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/multisig" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/types" ) +var Methods = builtin2.MethodsMultisig + func Message(version actors.Version, from address.Address) MessageBuilder { switch version { case actors.Version0: diff --git a/chain/actors/builtin/paych/message.go b/chain/actors/builtin/paych/message.go index 23b360394..5709d4b23 100644 --- a/chain/actors/builtin/paych/message.go +++ b/chain/actors/builtin/paych/message.go @@ -7,8 +7,12 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/types" + + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" ) +var Methods = builtin2.MethodsPaych + func Message(version actors.Version, from address.Address) MessageBuilder { switch version { case actors.Version0: diff --git a/chain/actors/builtin/power/power.go b/chain/actors/builtin/power/power.go index bafb14de0..c9182b7cf 100644 --- a/chain/actors/builtin/power/power.go +++ b/chain/actors/builtin/power/power.go @@ -25,7 +25,10 @@ func init() { }) } -var Address = builtin0.StoragePowerActorAddr +var ( + Address = builtin2.StoragePowerActorAddr + Methods = builtin2.MethodsPower +) func Load(store adt.Store, act *types.Actor) (st State, err error) { switch act.Code { diff --git a/chain/actors/builtin/reward/reward.go b/chain/actors/builtin/reward/reward.go index 065f242e2..952ca270b 100644 --- a/chain/actors/builtin/reward/reward.go +++ b/chain/actors/builtin/reward/reward.go @@ -24,7 +24,10 @@ func init() { }) } -var Address = builtin0.RewardActorAddr +var ( + Address = builtin2.RewardActorAddr + Methods = builtin2.MethodsReward +) func Load(store adt.Store, act *types.Actor) (st State, err error) { switch act.Code { diff --git a/chain/actors/builtin/verifreg/verifreg.go b/chain/actors/builtin/verifreg/verifreg.go index 204cdae95..a4468d8a0 100644 --- a/chain/actors/builtin/verifreg/verifreg.go +++ b/chain/actors/builtin/verifreg/verifreg.go @@ -24,7 +24,10 @@ func init() { }) } -var Address = builtin0.VerifiedRegistryActorAddr +var ( + Address = builtin2.VerifiedRegistryActorAddr + Methods = builtin2.MethodsVerifiedRegistry +) func Load(store adt.Store, act *types.Actor) (State, error) { switch act.Code { diff --git a/chain/market/fundmgr.go b/chain/market/fundmgr.go index c65547285..50467a6e1 100644 --- a/chain/market/fundmgr.go +++ b/chain/market/fundmgr.go @@ -4,15 +4,13 @@ import ( "context" "sync" + "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" - "go.uber.org/fx" - - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" "github.com/ipfs/go-cid" logging "github.com/ipfs/go-log" + "go.uber.org/fx" - "github.com/filecoin-project/go-address" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/builtin/market" @@ -156,7 +154,7 @@ func (fm *FundMgr) EnsureAvailable(ctx context.Context, addr, wallet address.Add To: market.Address, From: wallet, Value: toAdd, - Method: builtin2.MethodsMarket.AddBalance, + Method: market.Methods.AddBalance, Params: params, }, nil) if err != nil { diff --git a/chain/market/fundmgr_test.go b/chain/market/fundmgr_test.go index 7f163201e..88ca2e16f 100644 --- a/chain/market/fundmgr_test.go +++ b/chain/market/fundmgr_test.go @@ -12,7 +12,7 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/crypto" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + tutils "github.com/filecoin-project/specs-actors/v2/support/testing" "github.com/filecoin-project/lotus/api" @@ -51,7 +51,7 @@ func addFundsMsg(toAdd abi.TokenAmount, addr address.Address, wallet address.Add To: market.Address, From: wallet, Value: toAdd, - Method: builtin2.MethodsMarket.AddBalance, + Method: market.Methods.AddBalance, Params: params, } } diff --git a/chain/messagepool/gasguess/guessgas.go b/chain/messagepool/gasguess/guessgas.go index 607c7824a..76ab39078 100644 --- a/chain/messagepool/gasguess/guessgas.go +++ b/chain/messagepool/gasguess/guessgas.go @@ -6,6 +6,7 @@ import ( "github.com/ipfs/go-cid" "golang.org/x/xerrors" + "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/go-address" @@ -68,7 +69,7 @@ func failedGuess(msg *types.SignedMessage) int64 { func GuessGasUsed(ctx context.Context, tsk types.TipSetKey, msg *types.SignedMessage, al ActorLookup) (int64, error) { // MethodSend is the same in all versions. - if msg.Message.Method == builtin0.MethodSend { + if msg.Message.Method == builtin.MethodSend { switch msg.Message.From.Protocol() { case address.BLS: return 1298450, nil diff --git a/chain/stmgr/forks_test.go b/chain/stmgr/forks_test.go index 3e9e9e8c0..89e051088 100644 --- a/chain/stmgr/forks_test.go +++ b/chain/stmgr/forks_test.go @@ -24,7 +24,7 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/aerrors" - lotusinit "github.com/filecoin-project/lotus/chain/actors/builtin/init" + _init "github.com/filecoin-project/lotus/chain/actors/builtin/init" "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/gen" . "github.com/filecoin-project/lotus/chain/stmgr" @@ -183,8 +183,8 @@ func TestForkHeightTriggers(t *testing.T) { m := &types.Message{ From: cg.Banker(), - To: lotusinit.Address, - Method: builtin2.MethodsInit.Exec, + To: _init.Address, + Method: _init.Methods.Exec, Params: enc, GasLimit: types.TestGasLimit, } @@ -281,8 +281,8 @@ func TestForkRefuseCall(t *testing.T) { m := &types.Message{ From: cg.Banker(), - To: lotusinit.Address, - Method: builtin2.MethodsInit.Exec, + To: _init.Address, + Method: _init.Methods.Exec, Params: enc, GasLimit: types.TestGasLimit, Value: types.NewInt(0), diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index 6558b1ea8..4f0c26b7c 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -18,8 +18,6 @@ import ( "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/network" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" - // Used for genesis. msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig" @@ -28,6 +26,7 @@ import ( "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/builtin" + "github.com/filecoin-project/lotus/chain/actors/builtin/cron" _init "github.com/filecoin-project/lotus/chain/actors/builtin/init" "github.com/filecoin-project/lotus/chain/actors/builtin/market" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" @@ -253,14 +252,14 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp runCron := func(epoch abi.ChainEpoch) error { cronMsg := &types.Message{ - To: builtin2.CronActorAddr, - From: builtin2.SystemActorAddr, + To: cron.Address, + From: builtin.SystemActorAddr, Nonce: uint64(epoch), Value: types.NewInt(0), GasFeeCap: types.NewInt(0), GasPremium: types.NewInt(0), GasLimit: build.BlockGasLimit * 10000, // Make super sure this is never too little - Method: builtin2.MethodsCron.EpochTick, + Method: cron.Methods.EpochTick, Params: nil, } ret, err := vmi.ApplyImplicitMessage(ctx, cronMsg) @@ -349,14 +348,14 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp } rwMsg := &types.Message{ - From: builtin2.SystemActorAddr, + From: builtin.SystemActorAddr, To: reward.Address, Nonce: uint64(epoch), Value: types.NewInt(0), GasFeeCap: types.NewInt(0), GasPremium: types.NewInt(0), GasLimit: 1 << 30, - Method: builtin2.MethodsReward.AwardBlockReward, + Method: reward.Methods.AwardBlockReward, Params: params, } ret, actErr := vmi.ApplyImplicitMessage(ctx, rwMsg) @@ -973,7 +972,7 @@ func (sm *StateManager) setupGenesisActors(ctx context.Context) error { } else if builtin.IsAccountActor(act.Code) { // should exclude burnt funds actor and "remainder account actor" // should only ever be "faucet" accounts in testnets - if kaddr == builtin2.BurntFundsActorAddr { + if kaddr == builtin.BurntFundsActorAddr { return nil } @@ -1051,24 +1050,24 @@ func (sm *StateManager) setupPreIgnitionGenesisActorsTestnet(ctx context.Context totalsByEpoch := make(map[abi.ChainEpoch]abi.TokenAmount) // 6 months - sixMonths := abi.ChainEpoch(183 * builtin2.EpochsInDay) + sixMonths := abi.ChainEpoch(183 * builtin.EpochsInDay) totalsByEpoch[sixMonths] = big.NewInt(49_929_341) totalsByEpoch[sixMonths] = big.Add(totalsByEpoch[sixMonths], big.NewInt(32_787_700)) // 1 year - oneYear := abi.ChainEpoch(365 * builtin2.EpochsInDay) + oneYear := abi.ChainEpoch(365 * builtin.EpochsInDay) totalsByEpoch[oneYear] = big.NewInt(22_421_712) // 2 years - twoYears := abi.ChainEpoch(2 * 365 * builtin2.EpochsInDay) + twoYears := abi.ChainEpoch(2 * 365 * builtin.EpochsInDay) totalsByEpoch[twoYears] = big.NewInt(7_223_364) // 3 years - threeYears := abi.ChainEpoch(3 * 365 * builtin2.EpochsInDay) + threeYears := abi.ChainEpoch(3 * 365 * builtin.EpochsInDay) totalsByEpoch[threeYears] = big.NewInt(87_637_883) // 6 years - sixYears := abi.ChainEpoch(6 * 365 * builtin2.EpochsInDay) + sixYears := abi.ChainEpoch(6 * 365 * builtin.EpochsInDay) totalsByEpoch[sixYears] = big.NewInt(100_000_000) totalsByEpoch[sixYears] = big.Add(totalsByEpoch[sixYears], big.NewInt(300_000_000)) @@ -1128,24 +1127,24 @@ func (sm *StateManager) setupPostIgnitionGenesisActors(ctx context.Context) erro totalsByEpoch := make(map[abi.ChainEpoch]abi.TokenAmount) // 6 months - sixMonths := abi.ChainEpoch(183 * builtin2.EpochsInDay) + sixMonths := abi.ChainEpoch(183 * builtin.EpochsInDay) totalsByEpoch[sixMonths] = big.NewInt(49_929_341) totalsByEpoch[sixMonths] = big.Add(totalsByEpoch[sixMonths], big.NewInt(32_787_700)) // 1 year - oneYear := abi.ChainEpoch(365 * builtin2.EpochsInDay) + oneYear := abi.ChainEpoch(365 * builtin.EpochsInDay) totalsByEpoch[oneYear] = big.NewInt(22_421_712) // 2 years - twoYears := abi.ChainEpoch(2 * 365 * builtin2.EpochsInDay) + twoYears := abi.ChainEpoch(2 * 365 * builtin.EpochsInDay) totalsByEpoch[twoYears] = big.NewInt(7_223_364) // 3 years - threeYears := abi.ChainEpoch(3 * 365 * builtin2.EpochsInDay) + threeYears := abi.ChainEpoch(3 * 365 * builtin.EpochsInDay) totalsByEpoch[threeYears] = big.NewInt(87_637_883) // 6 years - sixYears := abi.ChainEpoch(6 * 365 * builtin2.EpochsInDay) + sixYears := abi.ChainEpoch(6 * 365 * builtin.EpochsInDay) totalsByEpoch[sixYears] = big.NewInt(100_000_000) totalsByEpoch[sixYears] = big.Add(totalsByEpoch[sixYears], big.NewInt(300_000_000)) @@ -1279,7 +1278,7 @@ func (sm *StateManager) GetFilLocked(ctx context.Context, st *state.StateTree) ( } func GetFilBurnt(ctx context.Context, st *state.StateTree) (abi.TokenAmount, error) { - burnt, err := st.GetActor(builtin2.BurntFundsActorAddr) + burnt, err := st.GetActor(builtin.BurntFundsActorAddr) if err != nil { return big.Zero(), xerrors.Errorf("failed to load burnt actor: %w", err) } diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index 2f5acf0db..eec7c3a15 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -12,8 +12,6 @@ import ( "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/network" - "github.com/filecoin-project/lotus/chain/actors/builtin" - "github.com/filecoin-project/lotus/chain/actors/policy" cid "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" @@ -25,15 +23,16 @@ import ( "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/rt" - builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" exported0 "github.com/filecoin-project/specs-actors/actors/builtin/exported" exported2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/exported" "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/actors/builtin" init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init" "github.com/filecoin-project/lotus/chain/actors/builtin/market" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/actors/builtin/power" + "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/beacon" "github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/store" @@ -548,8 +547,7 @@ func init() { methods := make(map[abi.MethodNum]MethodMeta, len(exports)) // Explicitly add send, it's special. - // Note that builtin2.MethodSend = builtin0.MethodSend = 0. - methods[builtin0.MethodSend] = MethodMeta{ + methods[builtin.MethodSend] = MethodMeta{ Name: "Send", Params: reflect.TypeOf(new(abi.EmptyValue)), Ret: reflect.TypeOf(new(abi.EmptyValue)), @@ -573,11 +571,9 @@ func init() { fnName = strings.TrimSuffix(fnName[strings.LastIndexByte(fnName, '.')+1:], "-fm") switch abi.MethodNum(number) { - case builtin0.MethodSend: - // Note that builtin2.MethodSend = builtin0.MethodSend = 0. + case builtin.MethodSend: panic("method 0 is reserved for Send") - case builtin0.MethodConstructor: - // Note that builtin2.MethodConstructor = builtin0.MethodConstructor = 1. + case builtin.MethodConstructor: if fnName != "Constructor" { panic("method 1 is reserved for Constructor") } diff --git a/chain/vm/gas_v0.go b/chain/vm/gas_v0.go index 7e879b8c3..7a7fb364d 100644 --- a/chain/vm/gas_v0.go +++ b/chain/vm/gas_v0.go @@ -3,12 +3,13 @@ package vm import ( "fmt" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/crypto" + + "github.com/filecoin-project/lotus/chain/actors/builtin" ) type scalingCost struct { @@ -112,14 +113,14 @@ func (pl *pricelistV0) OnMethodInvocation(value abi.TokenAmount, methodNum abi.M if big.Cmp(value, abi.NewTokenAmount(0)) != 0 { ret += pl.sendTransferFunds - if methodNum == builtin2.MethodSend { + if methodNum == builtin.MethodSend { // transfer only ret += pl.sendTransferOnlyPremium } extra += "t" } - if methodNum != builtin2.MethodSend { + if methodNum != builtin.MethodSend { extra += "i" // running actors is cheaper becase we hand over to actors ret += pl.sendInvokeMethod diff --git a/chain/vm/mkactor.go b/chain/vm/mkactor.go index 56eac1e0c..885d3c0db 100644 --- a/chain/vm/mkactor.go +++ b/chain/vm/mkactor.go @@ -16,6 +16,7 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/lotus/chain/actors/aerrors" "github.com/filecoin-project/lotus/chain/actors/builtin" + "github.com/filecoin-project/lotus/chain/actors/builtin/account" "github.com/filecoin-project/lotus/chain/types" ) @@ -57,7 +58,7 @@ func TryCreateAccountActor(rt *Runtime, addr address.Address) (*types.Actor, add } // call constructor on account - _, aerr = rt.internalSend(builtin.SystemActorAddr, addrID, builtin2.MethodsAccount.Constructor, big.Zero(), p) + _, aerr = rt.internalSend(builtin.SystemActorAddr, addrID, account.Methods.Constructor, big.Zero(), p) if aerr != nil { return nil, address.Undef, aerrors.Wrap(aerr, "failed to invoke account constructor") } diff --git a/cli/multisig.go b/cli/multisig.go index ebdc8ef7d..a50032cda 100644 --- a/cli/multisig.go +++ b/cli/multisig.go @@ -10,8 +10,6 @@ import ( "strconv" "text/tabwriter" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" - "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/actors" @@ -1170,7 +1168,7 @@ var msigLockProposeCmd = &cli.Command{ return actErr } - msgCid, err := api.MsigPropose(ctx, msig, msig, big.Zero(), from, uint64(builtin2.MethodsMultisig.LockBalance), params) + msgCid, err := api.MsigPropose(ctx, msig, msig, big.Zero(), from, uint64(multisig.Methods.LockBalance), params) if err != nil { return err } @@ -1267,7 +1265,7 @@ var msigLockApproveCmd = &cli.Command{ return actErr } - msgCid, err := api.MsigApproveTxnHash(ctx, msig, txid, prop, msig, big.Zero(), from, uint64(builtin2.MethodsMultisig.LockBalance), params) + msgCid, err := api.MsigApproveTxnHash(ctx, msig, txid, prop, msig, big.Zero(), from, uint64(multisig.Methods.LockBalance), params) if err != nil { return err } @@ -1359,7 +1357,7 @@ var msigLockCancelCmd = &cli.Command{ return actErr } - msgCid, err := api.MsigCancel(ctx, msig, txid, msig, big.Zero(), from, uint64(builtin2.MethodsMultisig.LockBalance), params) + msgCid, err := api.MsigCancel(ctx, msig, txid, msig, big.Zero(), from, uint64(multisig.Methods.LockBalance), params) if err != nil { return err } @@ -1496,7 +1494,7 @@ var msigProposeThresholdCmd = &cli.Command{ return actErr } - msgCid, err := api.MsigPropose(ctx, msig, msig, types.NewInt(0), from, uint64(builtin2.MethodsMultisig.ChangeNumApprovalsThreshold), params) + msgCid, err := api.MsigPropose(ctx, msig, msig, types.NewInt(0), from, uint64(multisig.Methods.ChangeNumApprovalsThreshold), params) if err != nil { return fmt.Errorf("failed to propose change of threshold: %w", err) } diff --git a/cmd/lotus-pcr/main.go b/cmd/lotus-pcr/main.go index 02df4a192..1d37a3ce9 100644 --- a/cmd/lotus-pcr/main.go +++ b/cmd/lotus-pcr/main.go @@ -16,7 +16,6 @@ import ( "github.com/filecoin-project/lotus/chain/actors/builtin" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" "github.com/filecoin-project/go-state-types/network" @@ -870,7 +869,7 @@ func (r *refunder) processTipsetStorageMarketActor(ctx context.Context, tipset * var messageMethod string switch m.Method { - case builtin2.MethodsMarket.PublishStorageDeals: + case market.Methods.PublishStorageDeals: if !r.publishStorageDealsEnabled { return false, messageMethod, types.NewInt(0), nil } @@ -897,7 +896,7 @@ func (r *refunder) processTipsetStorageMinerActor(ctx context.Context, tipset *t var messageMethod string switch m.Method { - case builtin2.MethodsMiner.SubmitWindowedPoSt: + case miner.Methods.SubmitWindowedPoSt: if !r.windowedPoStEnabled { return false, messageMethod, types.NewInt(0), nil } @@ -910,7 +909,7 @@ func (r *refunder) processTipsetStorageMinerActor(ctx context.Context, tipset *t } refundValue = types.BigMul(types.NewInt(uint64(recp.GasUsed)), tipset.Blocks()[0].ParentBaseFee) - case builtin2.MethodsMiner.ProveCommitSector: + case miner.Methods.ProveCommitSector: if !r.proveCommitEnabled { return false, messageMethod, types.NewInt(0), nil } @@ -966,7 +965,7 @@ func (r *refunder) processTipsetStorageMinerActor(ctx context.Context, tipset *t if r.refundPercent > 0 { refundValue = types.BigMul(types.BigDiv(refundValue, types.NewInt(100)), types.NewInt(uint64(r.refundPercent))) } - case builtin2.MethodsMiner.PreCommitSector: + case miner.Methods.PreCommitSector: if !r.preCommitEnabled { return false, messageMethod, types.NewInt(0), nil } diff --git a/cmd/lotus-shed/mempool-stats.go b/cmd/lotus-shed/mempool-stats.go index 408e06f71..bc4a801f0 100644 --- a/cmd/lotus-shed/mempool-stats.go +++ b/cmd/lotus-shed/mempool-stats.go @@ -14,11 +14,10 @@ import ( "go.opencensus.io/stats/view" "go.opencensus.io/tag" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" - "github.com/filecoin-project/go-address" lapi "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/actors/builtin" + "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/types" lcli "github.com/filecoin-project/lotus/cli" ) @@ -145,7 +144,7 @@ var mpoolStatsCmd = &cli.Command{ seen: time.Now(), } - if u.Message.Message.Method == builtin2.MethodsMiner.SubmitWindowedPoSt { + if u.Message.Message.Method == miner.Methods.SubmitWindowedPoSt { miner, err := isMiner(u.Message.Message.To) if err != nil { diff --git a/cmd/lotus-shed/sectors.go b/cmd/lotus-shed/sectors.go index cf0d5fcdb..2e78469fa 100644 --- a/cmd/lotus-shed/sectors.go +++ b/cmd/lotus-shed/sectors.go @@ -4,17 +4,19 @@ import ( "fmt" "strconv" + "golang.org/x/xerrors" + "github.com/filecoin-project/go-bitfield" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" - "github.com/filecoin-project/lotus/chain/actors" - "golang.org/x/xerrors" + "github.com/urfave/cli/v2" + miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" + + "github.com/filecoin-project/lotus/chain/actors" + "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/types" lcli "github.com/filecoin-project/lotus/cli" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" - miner0 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" - "github.com/urfave/cli/v2" ) var sectorsCmd = &cli.Command{ @@ -69,7 +71,7 @@ var terminateSectorCmd = &cli.Command{ return err } - terminationDeclarationParams := []miner0.TerminationDeclaration{} + terminationDeclarationParams := []miner2.TerminationDeclaration{} for _, sn := range cctx.Args().Slice() { sectorNum, err := strconv.ParseUint(sn, 10, 64) @@ -85,7 +87,7 @@ var terminateSectorCmd = &cli.Command{ return fmt.Errorf("get state sector partition %s", err) } - para := miner0.TerminationDeclaration{ + para := miner2.TerminationDeclaration{ Deadline: loca.Deadline, Partition: loca.Partition, Sectors: sectorbit, @@ -94,7 +96,7 @@ var terminateSectorCmd = &cli.Command{ terminationDeclarationParams = append(terminationDeclarationParams, para) } - terminateSectorParams := &miner0.TerminateSectorsParams{ + terminateSectorParams := &miner2.TerminateSectorsParams{ Terminations: terminationDeclarationParams, } @@ -106,7 +108,7 @@ var terminateSectorCmd = &cli.Command{ smsg, err := nodeApi.MpoolPushMessage(ctx, &types.Message{ From: mi.Owner, To: maddr, - Method: builtin2.MethodsMiner.TerminateSectors, + Method: miner.Methods.TerminateSectors, Value: big.Zero(), Params: sp, diff --git a/cmd/lotus-shed/verifreg.go b/cmd/lotus-shed/verifreg.go index c4eada68c..df1f0d990 100644 --- a/cmd/lotus-shed/verifreg.go +++ b/cmd/lotus-shed/verifreg.go @@ -11,7 +11,6 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" verifreg2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/verifreg" "github.com/filecoin-project/lotus/api/apibstore" @@ -80,7 +79,7 @@ var verifRegAddVerifierCmd = &cli.Command{ return err } - smsg, err := api.MsigPropose(ctx, vrk, verifreg.Address, big.Zero(), sender, uint64(builtin2.MethodsVerifiedRegistry.AddVerifier), params) + smsg, err := api.MsigPropose(ctx, vrk, verifreg.Address, big.Zero(), sender, uint64(verifreg.Methods.AddVerifier), params) if err != nil { return err } @@ -151,7 +150,7 @@ var verifRegVerifyClientCmd = &cli.Command{ msg := &types.Message{ To: verifreg.Address, From: fromk, - Method: builtin2.MethodsVerifiedRegistry.AddVerifiedClient, + Method: verifreg.Methods.AddVerifiedClient, Params: params, } diff --git a/cmd/lotus-storage-miner/actor.go b/cmd/lotus-storage-miner/actor.go index ad2232e1c..611ea8f19 100644 --- a/cmd/lotus-storage-miner/actor.go +++ b/cmd/lotus-storage-miner/actor.go @@ -5,13 +5,8 @@ import ( "os" "strings" - "github.com/filecoin-project/lotus/api/apibstore" - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/chain/actors/builtin/miner" cbor "github.com/ipfs/go-ipld-cbor" - "github.com/filecoin-project/lotus/build" - "github.com/fatih/color" "github.com/libp2p/go-libp2p-core/peer" ma "github.com/multiformats/go-multiaddr" @@ -22,10 +17,13 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" + "github.com/filecoin-project/lotus/api/apibstore" + "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/types" lcli "github.com/filecoin-project/lotus/cli" "github.com/filecoin-project/lotus/lib/tablewriter" @@ -109,7 +107,7 @@ var actorSetAddrsCmd = &cli.Command{ From: minfo.Worker, Value: types.NewInt(0), GasLimit: gasLimit, - Method: builtin2.MethodsMiner.ChangeMultiaddrs, + Method: miner.Methods.ChangeMultiaddrs, Params: params, }, nil) if err != nil { @@ -174,7 +172,7 @@ var actorSetPeeridCmd = &cli.Command{ From: minfo.Worker, Value: types.NewInt(0), GasLimit: gasLimit, - Method: builtin2.MethodsMiner.ChangePeerID, + Method: miner.Methods.ChangePeerID, Params: params, }, nil) if err != nil { @@ -246,7 +244,7 @@ var actorWithdrawCmd = &cli.Command{ To: maddr, From: mi.Owner, Value: types.NewInt(0), - Method: builtin2.MethodsMiner.WithdrawBalance, + Method: miner.Methods.WithdrawBalance, Params: params, }, nil) if err != nil { @@ -345,7 +343,7 @@ var actorRepayDebtCmd = &cli.Command{ To: maddr, From: fromId, Value: amount, - Method: builtin2.MethodsMiner.RepayDebt, + Method: miner.Methods.RepayDebt, Params: nil, }, nil) if err != nil { @@ -572,7 +570,7 @@ var actorControlSet = &cli.Command{ smsg, err := api.MpoolPushMessage(ctx, &types.Message{ From: mi.Owner, To: maddr, - Method: builtin2.MethodsMiner.ChangeWorkerAddress, + Method: miner.Methods.ChangeWorkerAddress, Value: big.Zero(), Params: sp, @@ -650,7 +648,7 @@ var actorSetOwnerCmd = &cli.Command{ smsg, err := api.MpoolPushMessage(ctx, &types.Message{ From: mi.Owner, To: maddr, - Method: builtin2.MethodsMiner.ChangeOwnerAddress, + Method: miner.Methods.ChangeOwnerAddress, Value: big.Zero(), Params: sp, }, nil) @@ -675,7 +673,7 @@ var actorSetOwnerCmd = &cli.Command{ smsg, err = api.MpoolPushMessage(ctx, &types.Message{ From: newAddr, To: maddr, - Method: builtin2.MethodsMiner.ChangeOwnerAddress, + Method: miner.Methods.ChangeOwnerAddress, Value: big.Zero(), Params: sp, }, nil) diff --git a/cmd/lotus-storage-miner/init.go b/cmd/lotus-storage-miner/init.go index b39ede752..19de95dbf 100644 --- a/cmd/lotus-storage-miner/init.go +++ b/cmd/lotus-storage-miner/init.go @@ -31,7 +31,6 @@ import ( "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" "github.com/filecoin-project/lotus/extern/sector-storage/stores" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market" miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" power2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/power" @@ -39,6 +38,7 @@ import ( lapi "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/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/actors/builtin/power" "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/gen/slashfilter" @@ -47,7 +47,7 @@ import ( sealing "github.com/filecoin-project/lotus/extern/storage-sealing" "github.com/filecoin-project/lotus/genesis" "github.com/filecoin-project/lotus/journal" - "github.com/filecoin-project/lotus/miner" + storageminer "github.com/filecoin-project/lotus/miner" "github.com/filecoin-project/lotus/node/modules" "github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/repo" @@ -470,7 +470,7 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api lapi.FullNode, return fmt.Errorf("failed to open filesystem journal: %w", err) } - m := miner.NewMiner(api, epp, a, slashfilter.New(mds), j) + m := storageminer.NewMiner(api, epp, a, slashfilter.New(mds), j) { if err := m.Start(ctx); err != nil { return xerrors.Errorf("failed to start up genesis miner: %w", err) @@ -578,7 +578,7 @@ func configureStorageMiner(ctx context.Context, api lapi.FullNode, addr address. msg := &types.Message{ To: addr, From: mi.Worker, - Method: builtin2.MethodsMiner.ChangePeerID, + Method: miner.Methods.ChangePeerID, Params: enc, Value: types.NewInt(0), GasPremium: gasPrice, @@ -661,7 +661,7 @@ func createStorageMiner(ctx context.Context, api lapi.FullNode, peerid peer.ID, From: sender, Value: big.Zero(), - Method: builtin2.MethodsPower.CreateMiner, + Method: power.Methods.CreateMiner, Params: params, GasLimit: 0, diff --git a/conformance/chaos/actor.go b/conformance/chaos/actor.go index 3c280e27e..cdda1db83 100644 --- a/conformance/chaos/actor.go +++ b/conformance/chaos/actor.go @@ -6,6 +6,7 @@ import ( "github.com/filecoin-project/go-state-types/cbor" "github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/go-state-types/rt" + "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/ipfs/go-cid" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" @@ -56,7 +57,7 @@ const ( const ( _ = 0 // skip zero iota value; first usage of iota gets 1. - MethodCallerValidation = builtin2.MethodConstructor + iota + MethodCallerValidation = builtin.MethodConstructor + iota MethodCreateActor MethodResolveAddress // MethodDeleteActor is the identifier for the method that deletes this actor. @@ -77,15 +78,15 @@ const ( // Exports defines the methods this actor exposes publicly. func (a Actor) Exports() []interface{} { return []interface{}{ - builtin2.MethodConstructor: a.Constructor, - MethodCallerValidation: a.CallerValidation, - MethodCreateActor: a.CreateActor, - MethodResolveAddress: a.ResolveAddress, - MethodDeleteActor: a.DeleteActor, - MethodSend: a.Send, - MethodMutateState: a.MutateState, - MethodAbortWith: a.AbortWith, - MethodInspectRuntime: a.InspectRuntime, + builtin.MethodConstructor: a.Constructor, + MethodCallerValidation: a.CallerValidation, + MethodCreateActor: a.CreateActor, + MethodResolveAddress: a.ResolveAddress, + MethodDeleteActor: a.DeleteActor, + MethodSend: a.Send, + MethodMutateState: a.MutateState, + MethodAbortWith: a.AbortWith, + MethodInspectRuntime: a.InspectRuntime, } } diff --git a/extern/storage-sealing/states_sealing.go b/extern/storage-sealing/states_sealing.go index 1e67a0a03..7b34751c0 100644 --- a/extern/storage-sealing/states_sealing.go +++ b/extern/storage-sealing/states_sealing.go @@ -16,8 +16,6 @@ import ( "github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/go-statemachine" "github.com/filecoin-project/specs-storage/storage" - - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" ) var DealSectorPriority = 1024 @@ -221,7 +219,7 @@ func (m *Sealing) handlePreCommitting(ctx statemachine.Context, sector SectorInf deposit := big.Max(depositMinimum, collateral) log.Infof("submitting precommit for sector %d (deposit: %s): ", sector.SectorNumber, deposit) - mcid, err := m.api.SendMsg(ctx.Context(), waddr, m.maddr, builtin2.MethodsMiner.PreCommitSector, deposit, m.feeCfg.MaxPreCommitGasFee, enc.Bytes()) + mcid, err := m.api.SendMsg(ctx.Context(), waddr, m.maddr, miner.Methods.PreCommitSector, deposit, m.feeCfg.MaxPreCommitGasFee, enc.Bytes()) if err != nil { if params.ReplaceCapacity { m.remarkForUpgrade(params.ReplaceSectorNumber) @@ -402,7 +400,7 @@ func (m *Sealing) handleSubmitCommit(ctx statemachine.Context, sector SectorInfo } // TODO: check seed / ticket / deals are up to date - mcid, err := m.api.SendMsg(ctx.Context(), waddr, m.maddr, builtin2.MethodsMiner.ProveCommitSector, collateral, m.feeCfg.MaxCommitGasFee, enc.Bytes()) + mcid, err := m.api.SendMsg(ctx.Context(), waddr, m.maddr, miner.Methods.ProveCommitSector, collateral, m.feeCfg.MaxCommitGasFee, enc.Bytes()) if err != nil { return ctx.Send(SectorCommitFailed{xerrors.Errorf("pushing message to mpool: %w", err)}) } diff --git a/markets/storageadapter/provider.go b/markets/storageadapter/provider.go index 9c088e4de..ce7c8e917 100644 --- a/markets/storageadapter/provider.go +++ b/markets/storageadapter/provider.go @@ -12,7 +12,6 @@ import ( logging "github.com/ipfs/go-log/v2" "golang.org/x/xerrors" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market" "github.com/filecoin-project/go-address" @@ -92,7 +91,7 @@ func (n *ProviderNodeAdapter) PublishDeals(ctx context.Context, deal storagemark To: market.Address, From: mi.Worker, Value: types.NewInt(0), - Method: builtin2.MethodsMarket.PublishStorageDeals, + Method: market.Methods.PublishStorageDeals, Params: params, }, n.publishSpec) if err != nil { @@ -192,7 +191,7 @@ func (n *ProviderNodeAdapter) AddFunds(ctx context.Context, addr address.Address To: market.Address, From: addr, Value: amount, - Method: builtin2.MethodsMarket.AddBalance, + Method: market.Methods.AddBalance, }, n.addBalanceSpec) if err != nil { return cid.Undef, err @@ -314,7 +313,7 @@ func (n *ProviderNodeAdapter) OnDealSectorCommitted(ctx context.Context, provide } switch msg.Method { - case builtin2.MethodsMiner.PreCommitSector: + case miner.Methods.PreCommitSector: var params miner.SectorPreCommitInfo if err := params.UnmarshalCBOR(bytes.NewReader(msg.Params)); err != nil { return true, false, xerrors.Errorf("unmarshal pre commit: %w", err) @@ -329,7 +328,7 @@ func (n *ProviderNodeAdapter) OnDealSectorCommitted(ctx context.Context, provide } return true, false, nil - case builtin2.MethodsMiner.ProveCommitSector: + case miner.Methods.ProveCommitSector: var params miner.ProveCommitSectorParams if err := params.UnmarshalCBOR(bytes.NewReader(msg.Params)); err != nil { return true, false, xerrors.Errorf("failed to unmarshal prove commit sector params: %w", err) diff --git a/node/impl/full/gas.go b/node/impl/full/gas.go index 4e4fc99d2..e0cbd2192 100644 --- a/node/impl/full/gas.go +++ b/node/impl/full/gas.go @@ -7,6 +7,7 @@ import ( "sort" "github.com/filecoin-project/lotus/chain/actors/builtin" + "github.com/filecoin-project/lotus/chain/actors/builtin/paych" "go.uber.org/fx" "golang.org/x/xerrors" @@ -16,8 +17,6 @@ import ( "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/exitcode" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/messagepool" @@ -259,7 +258,7 @@ func gasEstimateGasLimit( if !builtin.IsPaymentChannelActor(act.Code) { return res.MsgRct.GasUsed, nil } - if msgIn.Method != builtin2.MethodsPaych.Collect { + if msgIn.Method != paych.Methods.Collect { return res.MsgRct.GasUsed, nil } diff --git a/node/impl/full/multisig.go b/node/impl/full/multisig.go index 3b13839dd..9c5f683c4 100644 --- a/node/impl/full/multisig.go +++ b/node/impl/full/multisig.go @@ -12,7 +12,6 @@ import ( "github.com/filecoin-project/lotus/chain/actors/builtin/multisig" "github.com/filecoin-project/lotus/chain/types" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" multisig2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/multisig" "github.com/ipfs/go-cid" @@ -85,7 +84,7 @@ func (a *MsigAPI) MsigAddPropose(ctx context.Context, msig address.Address, src return cid.Undef, actErr } - return a.MsigPropose(ctx, msig, msig, big.Zero(), src, uint64(builtin2.MethodsMultisig.AddSigner), enc) + return a.MsigPropose(ctx, msig, msig, big.Zero(), src, uint64(multisig.Methods.AddSigner), enc) } func (a *MsigAPI) MsigAddApprove(ctx context.Context, msig address.Address, src address.Address, txID uint64, proposer address.Address, newAdd address.Address, inc bool) (cid.Cid, error) { @@ -94,7 +93,7 @@ func (a *MsigAPI) MsigAddApprove(ctx context.Context, msig address.Address, src return cid.Undef, actErr } - return a.MsigApproveTxnHash(ctx, msig, txID, proposer, msig, big.Zero(), src, uint64(builtin2.MethodsMultisig.AddSigner), enc) + return a.MsigApproveTxnHash(ctx, msig, txID, proposer, msig, big.Zero(), src, uint64(multisig.Methods.AddSigner), enc) } func (a *MsigAPI) MsigAddCancel(ctx context.Context, msig address.Address, src address.Address, txID uint64, newAdd address.Address, inc bool) (cid.Cid, error) { @@ -103,7 +102,7 @@ func (a *MsigAPI) MsigAddCancel(ctx context.Context, msig address.Address, src a return cid.Undef, actErr } - return a.MsigCancel(ctx, msig, txID, msig, big.Zero(), src, uint64(builtin2.MethodsMultisig.AddSigner), enc) + return a.MsigCancel(ctx, msig, txID, msig, big.Zero(), src, uint64(multisig.Methods.AddSigner), enc) } func (a *MsigAPI) MsigSwapPropose(ctx context.Context, msig address.Address, src address.Address, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) { @@ -112,7 +111,7 @@ func (a *MsigAPI) MsigSwapPropose(ctx context.Context, msig address.Address, src return cid.Undef, actErr } - return a.MsigPropose(ctx, msig, msig, big.Zero(), src, uint64(builtin2.MethodsMultisig.SwapSigner), enc) + return a.MsigPropose(ctx, msig, msig, big.Zero(), src, uint64(multisig.Methods.SwapSigner), enc) } func (a *MsigAPI) MsigSwapApprove(ctx context.Context, msig address.Address, src address.Address, txID uint64, proposer address.Address, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) { @@ -121,7 +120,7 @@ func (a *MsigAPI) MsigSwapApprove(ctx context.Context, msig address.Address, src return cid.Undef, actErr } - return a.MsigApproveTxnHash(ctx, msig, txID, proposer, msig, big.Zero(), src, uint64(builtin2.MethodsMultisig.SwapSigner), enc) + return a.MsigApproveTxnHash(ctx, msig, txID, proposer, msig, big.Zero(), src, uint64(multisig.Methods.SwapSigner), enc) } func (a *MsigAPI) MsigSwapCancel(ctx context.Context, msig address.Address, src address.Address, txID uint64, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) { @@ -130,7 +129,7 @@ func (a *MsigAPI) MsigSwapCancel(ctx context.Context, msig address.Address, src return cid.Undef, actErr } - return a.MsigCancel(ctx, msig, txID, msig, big.Zero(), src, uint64(builtin2.MethodsMultisig.SwapSigner), enc) + return a.MsigCancel(ctx, msig, txID, msig, big.Zero(), src, uint64(multisig.Methods.SwapSigner), enc) } func (a *MsigAPI) MsigApprove(ctx context.Context, msig address.Address, txID uint64, src address.Address) (cid.Cid, error) { @@ -151,7 +150,7 @@ func (a *MsigAPI) MsigRemoveSigner(ctx context.Context, msig address.Address, pr return cid.Undef, actErr } - return a.MsigPropose(ctx, msig, msig, types.NewInt(0), proposer, uint64(builtin2.MethodsMultisig.RemoveSigner), enc) + return a.MsigPropose(ctx, msig, msig, types.NewInt(0), proposer, uint64(multisig.Methods.RemoveSigner), enc) } func (a *MsigAPI) msigApproveOrCancelSimple(ctx context.Context, operation api.MsigProposeResponse, msig address.Address, txID uint64, src address.Address) (cid.Cid, error) { diff --git a/node/test/builder.go b/node/test/builder.go index 785e07bbe..ea9a82220 100644 --- a/node/test/builder.go +++ b/node/test/builder.go @@ -24,6 +24,7 @@ import ( "github.com/filecoin-project/lotus/api/test" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors" + "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/gen" genesis2 "github.com/filecoin-project/lotus/chain/gen/genesis" @@ -40,7 +41,6 @@ import ( testing2 "github.com/filecoin-project/lotus/node/modules/testing" "github.com/filecoin-project/lotus/node/repo" "github.com/filecoin-project/lotus/storage/mockstorage" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" "github.com/ipfs/go-datastore" "github.com/libp2p/go-libp2p-core/crypto" @@ -93,7 +93,7 @@ func CreateTestStorageNode(ctx context.Context, t *testing.T, waddr address.Addr msg := &types.Message{ To: act, From: waddr, - Method: builtin2.MethodsMiner.ChangePeerID, + Method: miner.Methods.ChangePeerID, Params: enc, Value: types.NewInt(0), } diff --git a/paychmgr/settler/settler.go b/paychmgr/settler/settler.go index 8074e8a87..d2a0900b5 100644 --- a/paychmgr/settler/settler.go +++ b/paychmgr/settler/settler.go @@ -14,8 +14,6 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors/builtin/paych" @@ -107,7 +105,7 @@ func (pcs *paymentChannelSettler) revertHandler(ctx context.Context, ts *types.T func (pcs *paymentChannelSettler) matcher(msg *types.Message) (matchOnce bool, matched bool, err error) { // Check if this is a settle payment channel message - if msg.Method != builtin2.MethodsPaych.Settle { + if msg.Method != paych.Methods.Settle { return false, false, nil } // Check if this payment channel is of concern to this node (i.e. tracked in payment channel store), diff --git a/storage/adapter_storage_miner.go b/storage/adapter_storage_miner.go index f645c301a..0e4b53752 100644 --- a/storage/adapter_storage_miner.go +++ b/storage/adapter_storage_miner.go @@ -15,7 +15,6 @@ import ( "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/crypto" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market" "github.com/filecoin-project/lotus/api" @@ -150,7 +149,7 @@ func (s SealingAPIAdapter) StateComputeDataCommitment(ctx context.Context, maddr To: market.Address, From: maddr, Value: types.NewInt(0), - Method: builtin2.MethodsMarket.ComputeDataCommitment, + Method: market.Methods.ComputeDataCommitment, Params: ccparams, } r, err := s.delegate.StateCall(ctx, ccmt, tsk) diff --git a/storage/wdpost_run.go b/storage/wdpost_run.go index c11e5dca0..5dbe868d6 100644 --- a/storage/wdpost_run.go +++ b/storage/wdpost_run.go @@ -17,7 +17,6 @@ import ( "go.opencensus.io/trace" "golang.org/x/xerrors" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" "github.com/filecoin-project/lotus/api" @@ -290,7 +289,7 @@ func (s *WindowPoStScheduler) checkNextRecoveries(ctx context.Context, dlIdx uin msg := &types.Message{ To: s.actor, From: s.worker, - Method: builtin2.MethodsMiner.DeclareFaultsRecovered, + Method: miner.Methods.DeclareFaultsRecovered, Params: enc, Value: types.NewInt(0), } @@ -374,7 +373,7 @@ func (s *WindowPoStScheduler) checkNextFaults(ctx context.Context, dlIdx uint64, msg := &types.Message{ To: s.actor, From: s.worker, - Method: builtin2.MethodsMiner.DeclareFaults, + Method: miner.Methods.DeclareFaults, Params: enc, Value: types.NewInt(0), // TODO: Is there a fee? } @@ -714,7 +713,7 @@ func (s *WindowPoStScheduler) submitPost(ctx context.Context, proof *miner.Submi msg := &types.Message{ To: s.actor, From: s.worker, - Method: builtin2.MethodsMiner.SubmitWindowedPoSt, + Method: miner.Methods.SubmitWindowedPoSt, Params: enc, Value: types.NewInt(0), } diff --git a/storage/wdpost_run_test.go b/storage/wdpost_run_test.go index 75588d7f8..ce3d3ad95 100644 --- a/storage/wdpost_run_test.go +++ b/storage/wdpost_run_test.go @@ -188,7 +188,7 @@ func TestWDPostDoPost(t *testing.T) { // Read the window PoST messages for i := 0; i < expectedMsgCount; i++ { msg := <-mockStgMinerAPI.pushedMessages - require.Equal(t, builtin2.MethodsMiner.SubmitWindowedPoSt, msg.Method) + require.Equal(t, miner.Methods.SubmitWindowedPoSt, msg.Method) var params miner.SubmitWindowedPoStParams err := params.UnmarshalCBOR(bytes.NewReader(msg.Params)) require.NoError(t, err) From 710ac9d54421d7c8111673f9003a24fa1507b906 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Thu, 8 Oct 2020 14:23:09 -0700 Subject: [PATCH 200/313] use the correct network version in genesis 1. Version 0 upgrades happen _after_ genesis. 2. Get rid of UseNewestNetwork. It's not useful and quite dangerous. --- build/params_shared_funcs.go | 8 -------- chain/gen/genesis/util.go | 27 +++++++++++++++++++++------ 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/build/params_shared_funcs.go b/build/params_shared_funcs.go index c48b3c507..77fd9256d 100644 --- a/build/params_shared_funcs.go +++ b/build/params_shared_funcs.go @@ -16,14 +16,6 @@ func DhtProtocolName(netName dtypes.NetworkName) protocol.ID { return protocol.ID("/fil/kad/" + string(netName)) } -func UseNewestNetwork() bool { - // TODO: Put these in a container we can iterate over - if UpgradeBreezeHeight <= 0 && UpgradeSmokeHeight <= 0 && UpgradeActorsV2Height <= 0 { - return true - } - return false -} - func SetAddressNetwork(n address.Network) { address.CurrentNetwork = n } diff --git a/chain/gen/genesis/util.go b/chain/gen/genesis/util.go index bcafb007e..54cc30cc1 100644 --- a/chain/gen/genesis/util.go +++ b/chain/gen/genesis/util.go @@ -50,12 +50,27 @@ func doExecValue(ctx context.Context, vm *vm.VM, to, from address.Address, value return ret.Return, nil } -var GenesisNetworkVersion = func() network.Version { // TODO: Get from build/ - if build.UseNewestNetwork() { // TODO: Get from build/ - return build.NewestNetworkVersion // TODO: Get from build/ - } // TODO: Get from build/ - return network.Version1 // TODO: Get from build/ -}() // TODO: Get from build/ +// TODO: Get from build +// TODO: make a list/schedule of these. +var GenesisNetworkVersion = func() network.Version { + // returns the version _before_ the first upgrade. + if build.UpgradeBreezeHeight >= 0 { + return network.Version0 + } + if build.UpgradeSmokeHeight >= 0 { + return network.Version1 + } + if build.UpgradeIgnitionHeight >= 0 { + return network.Version2 + } + if build.UpgradeActorsV2Height >= 0 { + return network.Version3 + } + if build.UpgradeLiftoffHeight >= 0 { + return network.Version3 + } + return build.ActorUpgradeNetworkVersion - 1 // genesis requires actors v0. +}() func genesisNetworkVersion(context.Context, abi.ChainEpoch) network.Version { // TODO: Get from build/ return GenesisNetworkVersion // TODO: Get from build/ From 30bda0b4c4b5a38a77eecb080f72b8187f8c7036 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Thu, 8 Oct 2020 14:57:03 -0700 Subject: [PATCH 201/313] set network name everywhere --- chain/gen/gen.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/chain/gen/gen.go b/chain/gen/gen.go index f2c3832c1..d56f285a0 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -8,12 +8,11 @@ import ( "sync/atomic" "time" - proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" - "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/crypto" + "github.com/google/uuid" block "github.com/ipfs/go-block-format" "github.com/ipfs/go-blockservice" "github.com/ipfs/go-cid" @@ -25,6 +24,8 @@ import ( "go.opencensus.io/trace" "golang.org/x/xerrors" + proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors/policy" @@ -226,7 +227,7 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) { }, VerifregRootKey: DefaultVerifregRootkeyActor, RemainderAccount: DefaultRemainderAccountActor, - NetworkName: "", + NetworkName: uuid.New().String(), Timestamp: uint64(build.Clock.Now().Add(-500 * time.Duration(build.BlockDelaySecs) * time.Second).Unix()), } From 0c2ec04c094f73235e4acf38376431536ad0fb3a Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Thu, 8 Oct 2020 17:36:26 -0700 Subject: [PATCH 202/313] use upgrade schedule from node when getting the network name It doesn't matter now, but may in the future. --- node/modules/chain.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/node/modules/chain.go b/node/modules/chain.go index ce3e9f749..d1414b307 100644 --- a/node/modules/chain.go +++ b/node/modules/chain.go @@ -168,14 +168,19 @@ func SetGenesis(cs *store.ChainStore, g Genesis) (dtypes.AfterGenesisSet, error) return dtypes.AfterGenesisSet{}, cs.SetGenesis(genesis) } -func NetworkName(mctx helpers.MetricsCtx, lc fx.Lifecycle, cs *store.ChainStore, _ dtypes.AfterGenesisSet) (dtypes.NetworkName, error) { +func NetworkName(mctx helpers.MetricsCtx, lc fx.Lifecycle, cs *store.ChainStore, us stmgr.UpgradeSchedule, _ dtypes.AfterGenesisSet) (dtypes.NetworkName, error) { if !build.Devnet { return "testnetnet", nil } ctx := helpers.LifecycleCtx(mctx, lc) - netName, err := stmgr.GetNetworkName(ctx, stmgr.NewStateManager(cs), cs.GetHeaviestTipSet().ParentState()) + sm, err := stmgr.NewStateManagerWithUpgradeSchedule(cs, us) + if err != nil { + return "", err + } + + netName, err := stmgr.GetNetworkName(ctx, sm, cs.GetHeaviestTipSet().ParentState()) return netName, err } From 9d15a08d27a04fe987e9e4e530baa02dd8ab7024 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 13 Oct 2020 22:10:37 -0700 Subject: [PATCH 203/313] correctly mark new actors as "important" --- chain/types/execresult.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/chain/types/execresult.go b/chain/types/execresult.go index 6fc93fac6..917b84a92 100644 --- a/chain/types/execresult.go +++ b/chain/types/execresult.go @@ -3,6 +3,7 @@ package types import ( "encoding/json" "fmt" + "regexp" "runtime" "strings" "time" @@ -68,11 +69,10 @@ func (l Loc) String() string { return fmt.Sprintf("%s@%s:%d", fnpkg, file[len(file)-1], l.Line) } +var importantRegex = regexp.MustCompile(`github.com/filecoin-project/specs-actors/(v\d+/)?actors/builtin`) + func (l Loc) Important() bool { - if strings.HasPrefix(l.Function, "github.com/filecoin-project/specs-actors/actors/builtin") { - return true - } - return false + return importantRegex.MatchString(l.Function) } func (gt *GasTrace) MarshalJSON() ([]byte, error) { From 5e23933757b1c55281869ef9a0d73fe77be33801 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 14 Oct 2020 17:29:25 -0700 Subject: [PATCH 204/313] fix import of v0 for test We're still on actors v0 in this test. --- chain/stmgr/forks_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chain/stmgr/forks_test.go b/chain/stmgr/forks_test.go index 89e051088..a2b7a179f 100644 --- a/chain/stmgr/forks_test.go +++ b/chain/stmgr/forks_test.go @@ -17,7 +17,7 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/cbor" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" init2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/init" rt2 "github.com/filecoin-project/specs-actors/v2/actors/runtime" @@ -46,7 +46,7 @@ type testActor struct { } // must use existing actor that an account is allowed to exec. -func (testActor) Code() cid.Cid { return builtin2.PaymentChannelActorCodeID } +func (testActor) Code() cid.Cid { return builtin0.PaymentChannelActorCodeID } func (testActor) State() cbor.Er { return new(testActorState) } type testActorState struct { From 5c9c08ef8549cb568db5d72040c5cf2fda21972f Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Wed, 21 Oct 2020 22:16:01 +0200 Subject: [PATCH 205/313] heaviestTipSet reurning nil is a ok Signed-off-by: Jakub Sztandera --- chain/sync_manager.go | 1 - 1 file changed, 1 deletion(-) diff --git a/chain/sync_manager.go b/chain/sync_manager.go index 17cec78d7..c7fdea726 100644 --- a/chain/sync_manager.go +++ b/chain/sync_manager.go @@ -257,7 +257,6 @@ func (stb *syncTargetBucket) add(ts *types.TipSet) { func (stb *syncTargetBucket) heaviestTipSet() *types.TipSet { if stb == nil { - log.Warn("sync target bucket was nil when heaviestTipSet got called on it") return nil } From 7bdc7aa5276fc2539f042f79daa6da355a970106 Mon Sep 17 00:00:00 2001 From: Ingar Shu Date: Tue, 20 Oct 2020 17:34:46 -0700 Subject: [PATCH 206/313] Add a market WithdrawBalance CLI --- cli/wallet.go | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/cli/wallet.go b/cli/wallet.go index 3d6abc357..f504e252f 100644 --- a/cli/wallet.go +++ b/cli/wallet.go @@ -13,9 +13,13 @@ import ( "golang.org/x/xerrors" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/crypto" + "github.com/filecoin-project/specs-actors/actors/builtin/market" + "github.com/filecoin-project/specs-actors/v2/actors/builtin" + "github.com/filecoin-project/lotus/chain/actors" types "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/lib/tablewriter" ) @@ -34,6 +38,7 @@ var walletCmd = &cli.Command{ walletSign, walletVerify, walletDelete, + walletWithdrawMarketFunds, }, } @@ -471,3 +476,91 @@ var walletDelete = &cli.Command{ return api.WalletDelete(ctx, addr) }, } + +var walletWithdrawMarketFunds = &cli.Command{ + Name: "withdraw-market-funds", + Usage: "Withdraw funds from the Storage Market Actor", + ArgsUsage: "[amount (FIL) optional, otherwise will withdraw max available]", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "address", + Usage: "Specify address to withdraw funds from, otherwise it will use the default wallet address", + Aliases: []string{"a"}, + }, + }, + Action: func(cctx *cli.Context) error { + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return xerrors.Errorf("getting node API: %w", err) + } + defer closer() + ctx := ReqContext(cctx) + + defAddr, err := api.WalletDefaultAddress(ctx) + if err != nil { + return xerrors.Errorf("getting default wallet address: %w", err) + } + + addr := defAddr + if cctx.String("address") != "" { + addr, err = address.NewFromString(cctx.String("address")) + if err != nil { + return xerrors.Errorf("parsing address: %w", err) + } + } + + ts, err := api.ChainHead(ctx) + if err != nil { + return xerrors.Errorf("getting chain head: %w", err) + } + + bal, err := api.StateMarketBalance(ctx, addr, ts.Key()) + if err != nil { + return xerrors.Errorf("getting market balance for address %s: %w", addr.String(), err) + } + + avail := big.Subtract(bal.Escrow, bal.Locked) + amt := avail + + if cctx.Args().Present() { + f, err := types.ParseFIL(cctx.Args().First()) + if err != nil { + return xerrors.Errorf("parsing 'amount' argument: %w", err) + } + + amt = abi.TokenAmount(f) + } + + if amt.GreaterThan(avail) { + return xerrors.Errorf("can't withdraw more funds than available; requested: %s; available: %s", amt, avail) + } + + if avail.IsZero() { + return xerrors.Errorf("zero unlocked funds available to withdraw") + } + + params, err := actors.SerializeParams(&market.WithdrawBalanceParams{ + ProviderOrClientAddress: addr, + Amount: amt, + }) + if err != nil { + return xerrors.Errorf("serializing params: %w", err) + } + + fmt.Printf("Submitting WithdrawBalance message for amount %s for address %s\n", types.FIL(amt), addr.String()) + smsg, err := api.MpoolPushMessage(ctx, &types.Message{ + To: builtin.StorageMarketActorAddr, + From: defAddr, + Value: types.NewInt(0), + Method: builtin.MethodsMarket.WithdrawBalance, + Params: params, + }, nil) + if err != nil { + return xerrors.Errorf("submitting WithdrawBalance message: %w", err) + } + + fmt.Printf("WithdrawBalance message cid: %s\n", smsg.Cid()) + + return nil + }, +} From 7f98be2920a5a20c2d8ed69d2e14e1212d89103d Mon Sep 17 00:00:00 2001 From: jennijuju Date: Wed, 21 Oct 2020 17:41:45 -0400 Subject: [PATCH 207/313] Delete wallet from local wallet cache --- chain/wallet/wallet.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/chain/wallet/wallet.go b/chain/wallet/wallet.go index 925547ea8..1f3329498 100644 --- a/chain/wallet/wallet.go +++ b/chain/wallet/wallet.go @@ -272,6 +272,7 @@ func (w *LocalWallet) WalletHas(ctx context.Context, addr address.Address) (bool func (w *LocalWallet) WalletDelete(ctx context.Context, addr address.Address) error { k, err := w.findKey(addr) + if err != nil { return xerrors.Errorf("failed to delete key %s : %w", addr, err) } @@ -279,6 +280,9 @@ func (w *LocalWallet) WalletDelete(ctx context.Context, addr address.Address) er return nil // already not there } + w.lk.Lock() + defer w.lk.Unlock() + if err := w.keystore.Put(KTrashPrefix+k.Address.String(), k.KeyInfo); err != nil { return xerrors.Errorf("failed to mark key %s as trashed: %w", addr, err) } @@ -295,6 +299,8 @@ func (w *LocalWallet) WalletDelete(ctx context.Context, addr address.Address) er // TODO: Does this always error in the not-found case? Just ignoring an error return for now. _ = w.keystore.Delete(KNamePrefix + tAddr) + delete(w.keys, addr) + return nil } From 035a762358c1bf860d682238fe6c51e6b6792cc0 Mon Sep 17 00:00:00 2001 From: Will Scott Date: Wed, 21 Oct 2020 16:49:59 -0700 Subject: [PATCH 208/313] update drand to v1.2.1 * stop autowatching * set user-agent --- chain/beacon/drand/drand.go | 7 ++++++- go.mod | 2 +- go.sum | 4 ++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/chain/beacon/drand/drand.go b/chain/beacon/drand/drand.go index 6e8e83a20..4abc12d29 100644 --- a/chain/beacon/drand/drand.go +++ b/chain/beacon/drand/drand.go @@ -65,6 +65,11 @@ type DrandBeacon struct { localCache map[uint64]types.BeaconEntry } +// DrandHTTPClient interface overrides the user agent used by drand +type DrandHTTPClient interface { + SetUserAgent(string) +} + func NewDrandBeacon(genesisTs, interval uint64, ps *pubsub.PubSub, config dtypes.DrandConfig) (*DrandBeacon, error) { if genesisTs == 0 { panic("what are you doing this cant be zero") @@ -84,6 +89,7 @@ func NewDrandBeacon(genesisTs, interval uint64, ps *pubsub.PubSub, config dtypes if err != nil { return nil, xerrors.Errorf("could not create http drand client: %w", err) } + hc.(DrandHTTPClient).SetUserAgent("drand-client-lotus/" + build.BuildVersion) clients = append(clients, hc) } @@ -92,7 +98,6 @@ func NewDrandBeacon(genesisTs, interval uint64, ps *pubsub.PubSub, config dtypes dclient.WithChainInfo(drandChain), dclient.WithCacheSize(1024), dclient.WithLogger(dlogger), - dclient.WithAutoWatch(), } if ps != nil { diff --git a/go.mod b/go.mod index e36f821d3..8132acf24 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/detailyang/go-fallocate v0.0.0-20180908115635-432fa640bd2e github.com/dgraph-io/badger/v2 v2.2007.2 github.com/docker/go-units v0.4.0 - github.com/drand/drand v1.2.0 + github.com/drand/drand v1.2.1 github.com/drand/kyber v1.1.4 github.com/dustin/go-humanize v1.0.0 github.com/elastic/go-sysinfo v1.3.0 diff --git a/go.sum b/go.sum index 6737eff06..b59db3a75 100644 --- a/go.sum +++ b/go.sum @@ -192,8 +192,12 @@ github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/drand/bls12-381 v0.3.2 h1:RImU8Wckmx8XQx1tp1q04OV73J9Tj6mmpQLYDP7V1XE= github.com/drand/bls12-381 v0.3.2/go.mod h1:dtcLgPtYT38L3NO6mPDYH0nbpc5tjPassDqiniuAt4Y= +github.com/drand/drand v1.1.2-0.20201021232824-ead2bc9ad8b5 h1:+zGmXpQ8IKpfQKtF0tKshBBmKxQnZDAZ/lXk1M20EKY= +github.com/drand/drand v1.1.2-0.20201021232824-ead2bc9ad8b5/go.mod h1:j0P7RGmVaY7E/OuO2yQOcQj7OgeZCuhgu2gdv0JAm+g= github.com/drand/drand v1.2.0 h1:EWeIxKFxUR9A+9xZ2oV09sqlxxWhDhgBbgCaCVwnvok= github.com/drand/drand v1.2.0/go.mod h1:j0P7RGmVaY7E/OuO2yQOcQj7OgeZCuhgu2gdv0JAm+g= +github.com/drand/drand v1.2.1 h1:KB7z+69YbnQ5z22AH/LMi0ObDR8DzYmrkS6vZXTR9jI= +github.com/drand/drand v1.2.1/go.mod h1:j0P7RGmVaY7E/OuO2yQOcQj7OgeZCuhgu2gdv0JAm+g= github.com/drand/kyber v1.0.1-0.20200110225416-8de27ed8c0e2/go.mod h1:UpXoA0Upd1N9l4TvRPHr1qAUBBERj6JQ/mnKI3BPEmw= github.com/drand/kyber v1.0.2/go.mod h1:x6KOpK7avKj0GJ4emhXFP5n7M7W7ChAPmnQh/OL6vRw= github.com/drand/kyber v1.1.4 h1:YvKM03QWGvLrdTnYmxxP5iURAX+Gdb6qRDUOgg8i60Q= From 9dc9bf5eb01908343a056757d355b1290c596814 Mon Sep 17 00:00:00 2001 From: Will Scott Date: Wed, 21 Oct 2020 19:49:38 -0700 Subject: [PATCH 209/313] go mod tidy --- go.sum | 4 ---- 1 file changed, 4 deletions(-) diff --git a/go.sum b/go.sum index b59db3a75..825ef5e63 100644 --- a/go.sum +++ b/go.sum @@ -192,10 +192,6 @@ github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/drand/bls12-381 v0.3.2 h1:RImU8Wckmx8XQx1tp1q04OV73J9Tj6mmpQLYDP7V1XE= github.com/drand/bls12-381 v0.3.2/go.mod h1:dtcLgPtYT38L3NO6mPDYH0nbpc5tjPassDqiniuAt4Y= -github.com/drand/drand v1.1.2-0.20201021232824-ead2bc9ad8b5 h1:+zGmXpQ8IKpfQKtF0tKshBBmKxQnZDAZ/lXk1M20EKY= -github.com/drand/drand v1.1.2-0.20201021232824-ead2bc9ad8b5/go.mod h1:j0P7RGmVaY7E/OuO2yQOcQj7OgeZCuhgu2gdv0JAm+g= -github.com/drand/drand v1.2.0 h1:EWeIxKFxUR9A+9xZ2oV09sqlxxWhDhgBbgCaCVwnvok= -github.com/drand/drand v1.2.0/go.mod h1:j0P7RGmVaY7E/OuO2yQOcQj7OgeZCuhgu2gdv0JAm+g= github.com/drand/drand v1.2.1 h1:KB7z+69YbnQ5z22AH/LMi0ObDR8DzYmrkS6vZXTR9jI= github.com/drand/drand v1.2.1/go.mod h1:j0P7RGmVaY7E/OuO2yQOcQj7OgeZCuhgu2gdv0JAm+g= github.com/drand/kyber v1.0.1-0.20200110225416-8de27ed8c0e2/go.mod h1:UpXoA0Upd1N9l4TvRPHr1qAUBBERj6JQ/mnKI3BPEmw= From 9d9da1a3e8a34a13afa26abd5035ca98d8f71b6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 22 Oct 2020 14:15:11 +0200 Subject: [PATCH 210/313] docsgen --- documentation/en/api-methods.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index 2684d0db5..e151ac696 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -196,7 +196,7 @@ * [WalletSignMessage](#WalletSignMessage) * [WalletValidateAddress](#WalletValidateAddress) * [WalletVerify](#WalletVerify) -## +## ### Closing @@ -977,7 +977,7 @@ Response: ClientGetDealStatus returns status given a code -Perms: +Perms: read Inputs: ```json From 90ce1c018e1d849bacc67d840dd4d15b653aaee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 22 Oct 2020 14:46:10 +0200 Subject: [PATCH 211/313] docsgen --- documentation/en/api-methods.md | 51 +++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index e151ac696..c82440375 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -70,6 +70,9 @@ * [MinerCreateBlock](#MinerCreateBlock) * [MinerGetBaseInfo](#MinerGetBaseInfo) * [Mpool](#Mpool) + * [MpoolBatchPush](#MpoolBatchPush) + * [MpoolBatchPushMessage](#MpoolBatchPushMessage) + * [MpoolBatchPushUntrusted](#MpoolBatchPushUntrusted) * [MpoolClear](#MpoolClear) * [MpoolGetConfig](#MpoolGetConfig) * [MpoolGetNonce](#MpoolGetNonce) @@ -1697,6 +1700,54 @@ The Mpool methods are for interacting with the message pool. The message pool manages all incoming and outgoing 'messages' going over the network. +### MpoolBatchPush +MpoolBatchPush batch pushes a signed message to mempool. + + +Perms: write + +Inputs: +```json +[ + null +] +``` + +Response: `null` + +### MpoolBatchPushMessage +MpoolBatchPushMessage batch pushes a unsigned message to mempool. + + +Perms: sign + +Inputs: +```json +[ + null, + { + "MaxFee": "0" + } +] +``` + +Response: `null` + +### MpoolBatchPushUntrusted +MpoolBatchPushUntrusted batch pushes a signed message to mempool from untrusted sources. + + +Perms: write + +Inputs: +```json +[ + null +] +``` + +Response: `null` + ### MpoolClear MpoolClear clears pending messages from the mpool From 00d1e6b54900a4c514b509f9ef6e63b73c04fbd3 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Sat, 10 Oct 2020 11:49:15 -0700 Subject: [PATCH 212/313] add measure datastore wrapper around bench chain datastore --- cmd/lotus-bench/import.go | 9 ++++++++- go.mod | 2 +- go.sum | 2 ++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/cmd/lotus-bench/import.go b/cmd/lotus-bench/import.go index 3f99d0453..00a4d22ef 100644 --- a/cmd/lotus-bench/import.go +++ b/cmd/lotus-bench/import.go @@ -34,6 +34,7 @@ import ( bdg "github.com/dgraph-io/badger/v2" "github.com/ipfs/go-datastore" badger "github.com/ipfs/go-ds-badger2" + measure "github.com/ipfs/go-ds-measure" pebbleds "github.com/ipfs/go-ds-pebble" "github.com/urfave/cli/v2" @@ -89,6 +90,9 @@ var importBenchCmd = &cli.Command{ &cli.BoolFlag{ Name: "only-import", }, + &cli.BoolFlag{ + Name: "use-pebble", + }, }, Action: func(cctx *cli.Context) error { vm.BatchSealVerifyParallelism = cctx.Int("batch-seal-verify-threads") @@ -126,7 +130,7 @@ var importBenchCmd = &cli.Command{ bdgOpt.Options.DetectConflicts = false var bds datastore.Batching - if false { + if cctx.Bool("use-pebble") { cache := 512 bds, err = pebbleds.NewDatastore(tdir, &pebble.Options{ // Pebble has a single combined cache area and the write @@ -155,6 +159,9 @@ var importBenchCmd = &cli.Command{ } defer bds.Close() //nolint:errcheck + under := bds + bds = measure.New("dsbench", bds) + bs := blockstore.NewBlockstore(bds) cacheOpts := blockstore.DefaultCacheOpts() cacheOpts.HasBloomFilterSize = 0 diff --git a/go.mod b/go.mod index 3fde407bb..2564f87a7 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129 github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e - github.com/cockroachdb/pebble v0.0.0-20200916222308-4e219a90ba5b + github.com/cockroachdb/pebble v0.0.0-20201001221639-879f3bfeef07 github.com/coreos/go-systemd/v22 v22.0.0 github.com/detailyang/go-fallocate v0.0.0-20180908115635-432fa640bd2e github.com/dgraph-io/badger/v2 v2.2007.2 diff --git a/go.sum b/go.sum index 9ef3587f4..f72b5998b 100644 --- a/go.sum +++ b/go.sum @@ -136,6 +136,8 @@ github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOi github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= github.com/cockroachdb/pebble v0.0.0-20200916222308-4e219a90ba5b h1:OKALTB609+19AM7wsO0k8yMwAqjEIppcnYvyIhA+ZlQ= github.com/cockroachdb/pebble v0.0.0-20200916222308-4e219a90ba5b/go.mod h1:hU7vhtrqonEphNF+xt8/lHdaBprxmV1h8BOGrd9XwmQ= +github.com/cockroachdb/pebble v0.0.0-20201001221639-879f3bfeef07 h1:Cb2pZUCFXlLA8i7My+wrN51D41GeuhYOKa1dJeZt6NY= +github.com/cockroachdb/pebble v0.0.0-20201001221639-879f3bfeef07/go.mod h1:hU7vhtrqonEphNF+xt8/lHdaBprxmV1h8BOGrd9XwmQ= github.com/cockroachdb/redact v0.0.0-20200622112456-cd282804bbd3 h1:2+dpIJzYMSbLi0587YXpi8tOJT52qCOI/1I0UNThc/I= github.com/cockroachdb/redact v0.0.0-20200622112456-cd282804bbd3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w= From 034194435031d04ac0c8a29f6cfa4ac861f1eb7a Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Sat, 10 Oct 2020 21:57:19 +0200 Subject: [PATCH 213/313] Inject prometheus Signed-off-by: Jakub Sztandera --- cmd/lotus-bench/import.go | 5 ++++- go.mod | 2 ++ go.sum | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/cmd/lotus-bench/import.go b/cmd/lotus-bench/import.go index 00a4d22ef..de3a0ea45 100644 --- a/cmd/lotus-bench/import.go +++ b/cmd/lotus-bench/import.go @@ -26,7 +26,9 @@ import ( "github.com/filecoin-project/lotus/lib/blockstore" _ "github.com/filecoin-project/lotus/lib/sigs/bls" _ "github.com/filecoin-project/lotus/lib/sigs/secp" + metricsprometheus "github.com/ipfs/go-metrics-prometheus" "github.com/ipld/go-car" + "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" @@ -95,6 +97,7 @@ var importBenchCmd = &cli.Command{ }, }, Action: func(cctx *cli.Context) error { + metricsprometheus.Inject() vm.BatchSealVerifyParallelism = cctx.Int("batch-seal-verify-threads") if !cctx.Args().Present() { fmt.Println("must pass car file of chain to benchmark importing") @@ -108,6 +111,7 @@ var importBenchCmd = &cli.Command{ defer cfi.Close() //nolint:errcheck // read only file go func() { + http.Handle("/debug/metrics/prometheus", promhttp.Handler()) http.ListenAndServe("localhost:6060", nil) //nolint:errcheck }() @@ -159,7 +163,6 @@ var importBenchCmd = &cli.Command{ } defer bds.Close() //nolint:errcheck - under := bds bds = measure.New("dsbench", bds) bs := blockstore.NewBlockstore(bds) diff --git a/go.mod b/go.mod index 2564f87a7..b79d18938 100644 --- a/go.mod +++ b/go.mod @@ -81,6 +81,7 @@ require ( github.com/ipfs/go-log v1.0.4 github.com/ipfs/go-log/v2 v2.1.2-0.20200626104915-0016c0b4b3e4 github.com/ipfs/go-merkledag v0.3.2 + github.com/ipfs/go-metrics-prometheus v0.0.2 github.com/ipfs/go-path v0.0.7 github.com/ipfs/go-unixfs v0.2.4 github.com/ipfs/interface-go-ipfs-core v0.2.3 @@ -115,6 +116,7 @@ require ( github.com/multiformats/go-multihash v0.0.14 github.com/opentracing/opentracing-go v1.2.0 github.com/polydawn/refmt v0.0.0-20190809202753-05966cbd336a + github.com/prometheus/client_golang v1.6.0 github.com/raulk/clock v1.1.0 github.com/stretchr/testify v1.6.1 github.com/supranational/blst v0.1.1 diff --git a/go.sum b/go.sum index f72b5998b..be9682c83 100644 --- a/go.sum +++ b/go.sum @@ -632,6 +632,8 @@ github.com/ipfs/go-merkledag v0.3.2 h1:MRqj40QkrWkvPswXs4EfSslhZ4RVPRbxwX11js0t1 github.com/ipfs/go-merkledag v0.3.2/go.mod h1:fvkZNNZixVW6cKSZ/JfLlON5OlgTXNdRLz0p6QG/I2M= github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg= github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY= +github.com/ipfs/go-metrics-prometheus v0.0.2 h1:9i2iljLg12S78OhC6UAiXi176xvQGiZaGVF1CUVdE+s= +github.com/ipfs/go-metrics-prometheus v0.0.2/go.mod h1:ELLU99AQQNi+zX6GCGm2lAgnzdSH3u5UVlCdqSXnEks= github.com/ipfs/go-path v0.0.3/go.mod h1:zIRQUez3LuQIU25zFjC2hpBTHimWx7VK5bjZgRLbbdo= github.com/ipfs/go-path v0.0.7 h1:H06hKMquQ0aYtHiHryOMLpQC1qC3QwXwkahcEVD51Ho= github.com/ipfs/go-path v0.0.7/go.mod h1:6KTKmeRnBXgqrTvzFrPV3CamxcgvXX/4z79tfAd2Sno= From 602d2b8ad50b7bd707c123cd4e01a5c989870191 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Tue, 13 Oct 2020 21:24:56 -0700 Subject: [PATCH 214/313] record datastore metrics after successful run --- cmd/lotus-bench/import.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/cmd/lotus-bench/import.go b/cmd/lotus-bench/import.go index de3a0ea45..681d7ede2 100644 --- a/cmd/lotus-bench/import.go +++ b/cmd/lotus-bench/import.go @@ -320,6 +320,21 @@ var importBenchCmd = &cli.Command{ pprof.StopCPUProfile() + if true { + resp, err := http.Get("http://localhost:6060/debug/metrics/prometheus") + if err != nil { + return err + } + + metricsfi, err := os.Create("import-bench.metrics") + if err != nil { + return err + } + + io.Copy(metricsfi, resp.Body) + metricsfi.Close() + } + return nil }, From 0832d5a7d5e4566785d3d5f3d32113149690ceca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 22 Oct 2020 14:57:55 +0200 Subject: [PATCH 215/313] bench: Fix lint warnings --- cmd/lotus-bench/import.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/lotus-bench/import.go b/cmd/lotus-bench/import.go index 681d7ede2..acbf9ebdc 100644 --- a/cmd/lotus-bench/import.go +++ b/cmd/lotus-bench/import.go @@ -97,7 +97,7 @@ var importBenchCmd = &cli.Command{ }, }, Action: func(cctx *cli.Context) error { - metricsprometheus.Inject() + metricsprometheus.Inject() //nolint:errcheck vm.BatchSealVerifyParallelism = cctx.Int("batch-seal-verify-threads") if !cctx.Args().Present() { fmt.Println("must pass car file of chain to benchmark importing") @@ -331,8 +331,8 @@ var importBenchCmd = &cli.Command{ return err } - io.Copy(metricsfi, resp.Body) - metricsfi.Close() + io.Copy(metricsfi, resp.Body) //nolint:errcheck + metricsfi.Close() //nolint:errcheck } return nil From 6fb3dafa955dee565767c5f2753d1d6dc1d19ed7 Mon Sep 17 00:00:00 2001 From: Travis Person Date: Sun, 11 Oct 2020 19:37:54 +0000 Subject: [PATCH 216/313] lotus-pcr: add blocklist --- cmd/lotus-pcr/main.go | 94 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/cmd/lotus-pcr/main.go b/cmd/lotus-pcr/main.go index 29db4a5fe..a615937f2 100644 --- a/cmd/lotus-pcr/main.go +++ b/cmd/lotus-pcr/main.go @@ -6,12 +6,14 @@ import ( "context" "encoding/csv" "fmt" + "io" "io/ioutil" "net/http" _ "net/http/pprof" "os" "path/filepath" "strconv" + "strings" "time" "github.com/filecoin-project/lotus/chain/actors/builtin" @@ -251,6 +253,15 @@ var recoverMinersCmd = &cli.Command{ } defer closer() + r, err := NewRepo(cctx.String("repo")) + if err != nil { + return err + } + + if err := r.Open(); err != nil { + return err + } + from, err := address.NewFromString(cctx.String("from")) if err != nil { return xerrors.Errorf("parsing source address (provide correct --from flag!): %w", err) @@ -267,6 +278,12 @@ var recoverMinersCmd = &cli.Command{ minerRecoveryCutoff := uint64(cctx.Int("miner-recovery-cutoff")) minerRecoveryBonus := uint64(cctx.Int("miner-recovery-bonus")) + blockmap := make(map[address.Address]struct{}) + + for _, addr := range r.Blocklist() { + blockmap[addr] = struct{}{} + } + rf := &refunder{ api: api, wallet: from, @@ -274,6 +291,7 @@ var recoverMinersCmd = &cli.Command{ minerRecoveryRefundPercent: minerRecoveryRefundPercent, minerRecoveryCutoff: types.FromFil(minerRecoveryCutoff), minerRecoveryBonus: types.FromFil(minerRecoveryBonus), + blockmap: blockmap, } refundTipset, err := api.ChainHead(ctx) @@ -466,6 +484,12 @@ var runCmd = &cli.Command{ return err } + blockmap := make(map[address.Address]struct{}) + + for _, addr := range r.Blocklist() { + blockmap[addr] = struct{}{} + } + rf := &refunder{ api: api, wallet: from, @@ -480,6 +504,7 @@ var runCmd = &cli.Command{ publishStorageDealsEnabled: publishStorageDealsEnabled, preFeeCapMax: types.BigInt(preFeeCapMax), proveFeeCapMax: types.BigInt(proveFeeCapMax), + blockmap: blockmap, } var refunds *MinersRefund = NewMinersRefund() @@ -487,6 +512,10 @@ var runCmd = &cli.Command{ nextMinerRecovery := r.MinerRecoveryHeight() + minerRecoveryPeriod for tipset := range tipsetsCh { + for k, _ := range rf.blockmap { + fmt.Printf("%s\n", k) + } + refunds, err = rf.ProcessTipset(ctx, tipset, refunds) if err != nil { return err @@ -634,6 +663,7 @@ type refunder struct { windowedPoStEnabled bool publishStorageDealsEnabled bool threshold big.Int + blockmap map[address.Address]struct{} preFeeCapMax big.Int proveFeeCapMax big.Int @@ -738,6 +768,11 @@ func (r *refunder) EnsureMinerMinimums(ctx context.Context, tipset *types.TipSet } for _, maddr := range miners { + if _, found := r.blockmap[maddr]; found { + log.Debugw("skipping blocked miner", "height", tipset.Height(), "key", tipset.Key(), "miner", maddr) + continue + } + mact, err := r.api.StateGetActor(ctx, maddr, types.EmptyTSK) if err != nil { log.Errorw("failed", "err", err, "height", tipset.Height(), "key", tipset.Key(), "miner", maddr) @@ -897,6 +932,11 @@ func (r *refunder) processTipsetStorageMinerActor(ctx context.Context, tipset *t refundValue := types.NewInt(0) var messageMethod string + if _, found := r.blockmap[m.To]; found { + log.Debugw("skipping blocked miner", "height", tipset.Height(), "key", tipset.Key(), "miner", m.To) + return false, messageMethod, types.NewInt(0), nil + } + switch m.Method { case builtin0.MethodsMiner.SubmitWindowedPoSt: if !r.windowedPoStEnabled { @@ -1177,6 +1217,7 @@ type Repo struct { lastHeight abi.ChainEpoch lastMinerRecoveryHeight abi.ChainEpoch path string + blocklist []address.Address } func NewRepo(path string) (*Repo, error) { @@ -1232,6 +1273,10 @@ func (r *Repo) Open() error { return err } + if err := r.loadBlockList(); err != nil { + return err + } + return nil } @@ -1257,6 +1302,51 @@ func loadChainEpoch(fn string) (abi.ChainEpoch, error) { return abi.ChainEpoch(height), nil } +func (r *Repo) loadBlockList() error { + var err error + fpath := filepath.Join(r.path, "blocklist") + f, err := os.OpenFile(fpath, os.O_RDWR|os.O_CREATE, 0644) + if err != nil { + return err + } + defer func() { + err = f.Close() + }() + + blocklist := []address.Address{} + input := bufio.NewReader(f) + for { + stra, errR := input.ReadString('\n') + stra = strings.TrimSpace(stra) + + if len(stra) == 0 { + if errR == io.EOF { + break + } + continue + } + + addr, err := address.NewFromString(stra) + if err != nil { + return err + } + + blocklist = append(blocklist, addr) + + if errR != nil && errR != io.EOF { + return err + } + + if errR == io.EOF { + break + } + } + + r.blocklist = blocklist + + return nil +} + func (r *Repo) loadHeight() error { var err error r.lastHeight, err = loadChainEpoch(filepath.Join(r.path, "height")) @@ -1269,6 +1359,10 @@ func (r *Repo) loadMinerRecoveryHeight() error { return err } +func (r *Repo) Blocklist() []address.Address { + return r.blocklist +} + func (r *Repo) Height() abi.ChainEpoch { return r.lastHeight } From ee8d8bf5e5ed6b3b4160fb3cc5f671ce4c63cf06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 22 Oct 2020 15:42:46 +0200 Subject: [PATCH 217/313] pcr: Fix lint --- cmd/lotus-pcr/main.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/lotus-pcr/main.go b/cmd/lotus-pcr/main.go index a615937f2..3c61180d9 100644 --- a/cmd/lotus-pcr/main.go +++ b/cmd/lotus-pcr/main.go @@ -507,12 +507,12 @@ var runCmd = &cli.Command{ blockmap: blockmap, } - var refunds *MinersRefund = NewMinersRefund() - var rounds int = 0 + var refunds = NewMinersRefund() + var rounds = 0 nextMinerRecovery := r.MinerRecoveryHeight() + minerRecoveryPeriod for tipset := range tipsetsCh { - for k, _ := range rf.blockmap { + for k := range rf.blockmap { fmt.Printf("%s\n", k) } From ae04f3029bb0e4ff9c32b2cf14de37ecfb22899b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 22 Oct 2020 15:58:22 +0200 Subject: [PATCH 218/313] chain: Add more robust test for ChainExport --- chain/store/store_test.go | 58 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/chain/store/store_test.go b/chain/store/store_test.go index 326899f90..60167ad86 100644 --- a/chain/store/store_test.go +++ b/chain/store/store_test.go @@ -12,6 +12,7 @@ import ( "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/gen" + "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/lib/blockstore" @@ -107,3 +108,60 @@ func TestChainExportImport(t *testing.T) { t.Fatal("imported chain differed from exported chain") } } + +func TestChainExportImportFull(t *testing.T) { + cg, err := gen.NewGenerator() + if err != nil { + t.Fatal(err) + } + + var last *types.TipSet + for i := 0; i < 100; i++ { + ts, err := cg.NextTipSet() + if err != nil { + t.Fatal(err) + } + + last = ts.TipSet.TipSet() + } + + buf := new(bytes.Buffer) + if err := cg.ChainStore().Export(context.TODO(), last, 100, false, buf); err != nil { + t.Fatal(err) + } + + nbs := blockstore.NewTemporary() + cs := store.NewChainStore(nbs, datastore.NewMapDatastore(), nil, nil) + root, err := cs.Import(buf) + if err != nil { + t.Fatal(err) + } + + err = cs.SetHead(last) + if err != nil { + t.Fatal(err) + } + + if !root.Equals(last) { + t.Fatal("imported chain differed from exported chain") + } + + sm := stmgr.NewStateManager(cs) + for i := 0; i < 100; i++ { + ts, err := cs.GetTipsetByHeight(context.TODO(), abi.ChainEpoch(i), nil, false) + if err != nil { + t.Fatal(err) + } + + st, err := sm.ParentState(ts) + if err != nil { + t.Fatal(err) + } + + // touches a bunch of actors + _, err = sm.GetCirculatingSupply(context.TODO(), abi.ChainEpoch(i), st) + if err != nil { + t.Fatal(err) + } + } +} From f9707ba344d8b90a9e7d4e6ca09e7db4d396fd79 Mon Sep 17 00:00:00 2001 From: ZenGround0 Date: Mon, 12 Oct 2020 13:59:44 -0400 Subject: [PATCH 219/313] add borked inspection command hook up new command Fix head call Debug internal error Debug moa Debug 0 Fix 0 Fix 1 Better print Don't ignore error --- cmd/lotus-shed/borked-miners.go | 85 +++++++++++++++++++++++++++++++++ cmd/lotus-shed/main.go | 1 + 2 files changed, 86 insertions(+) create mode 100644 cmd/lotus-shed/borked-miners.go diff --git a/cmd/lotus-shed/borked-miners.go b/cmd/lotus-shed/borked-miners.go new file mode 100644 index 000000000..ecb3aeae9 --- /dev/null +++ b/cmd/lotus-shed/borked-miners.go @@ -0,0 +1,85 @@ +package main + +import ( + "fmt" + + "github.com/filecoin-project/go-state-types/abi" + lcli "github.com/filecoin-project/lotus/cli" + "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" + "github.com/urfave/cli/v2" + "golang.org/x/xerrors" +) + +var borkedMinersCmd = &cli.Command{ + Name: "borked-miners", + Description: "information about 'borked' miner actors with late or frozen deadline crons", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "tipset", + Usage: "specify tipset state to search on (pass comma separated array of cids)", + }, + &cli.BoolFlag{ + Name: "future", + Usage: "print info of miners with last deadline cron in the future (normal for v0 and early v2 actors)", + }, + }, + Action: func(c *cli.Context) error { + api, acloser, err := lcli.GetFullNodeAPI(c) + if err != nil { + return err + } + defer acloser() + ctx := lcli.ReqContext(c) + + ts, err := lcli.LoadTipSet(ctx, c, api) + if err != nil { + return err + } + if ts == nil { + ts, err = api.ChainHead(ctx) + if err != nil { + return err + } + } + + queryEpoch := ts.Height() + + mAddrs, err := api.StateListMiners(ctx, ts.Key()) + if err != nil { + return err + } + + for _, mAddr := range mAddrs { + st, err := api.StateReadState(ctx, mAddr, ts.Key()) + if err != nil { + return err + } + minerState, ok := st.State.(map[string]interface{}) + if !ok { + return xerrors.Errorf("internal error: failed to cast miner state to expected map type") + } + + ppsIface := minerState["ProvingPeriodStart"] + pps := int64(ppsIface.(float64)) + dlIdxIface := minerState["CurrentDeadline"] + dlIdx := uint64(dlIdxIface.(float64)) + latestDeadline := abi.ChainEpoch(pps) + abi.ChainEpoch(int64(dlIdx))*miner.WPoStChallengeWindow + nextDeadline := latestDeadline + miner.WPoStChallengeWindow + + // Need +1 because last epoch of the deadline queryEpoch = x + 59 cron gets run and + // state is left with latestDeadline = x + 60 + if c.Bool("future") && latestDeadline > queryEpoch+1 { + fmt.Printf("%s -- last deadline start in future epoch %d > query epoch %d + 1\n", mAddr, latestDeadline, queryEpoch) + } + + // Equality is an error because last epoch of the deadline queryEpoch = x + 59. Cron + // should get run and bump latestDeadline = x + 60 so nextDeadline = x + 120 + if queryEpoch >= nextDeadline { + fmt.Printf("%s -- next deadline start in non-future epoch %d <= query epoch %d\n", mAddr, nextDeadline, queryEpoch) + } + + } + + return nil + }, +} diff --git a/cmd/lotus-shed/main.go b/cmd/lotus-shed/main.go index 5acaa3218..c8ce3ae04 100644 --- a/cmd/lotus-shed/main.go +++ b/cmd/lotus-shed/main.go @@ -19,6 +19,7 @@ func main() { base32Cmd, base16Cmd, bitFieldCmd, + borkedMinersCmd, keyinfoCmd, jwtCmd, noncefix, From 9a58763a4e59129fed3a55b854fbe9b647be0ae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 22 Oct 2020 16:07:42 +0200 Subject: [PATCH 220/313] shed: Rename the command to frozen-miners --- cmd/lotus-shed/{borked-miners.go => frozen-miners.go} | 6 +++--- cmd/lotus-shed/main.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename cmd/lotus-shed/{borked-miners.go => frozen-miners.go} (93%) diff --git a/cmd/lotus-shed/borked-miners.go b/cmd/lotus-shed/frozen-miners.go similarity index 93% rename from cmd/lotus-shed/borked-miners.go rename to cmd/lotus-shed/frozen-miners.go index ecb3aeae9..6b843f0d6 100644 --- a/cmd/lotus-shed/borked-miners.go +++ b/cmd/lotus-shed/frozen-miners.go @@ -10,9 +10,9 @@ import ( "golang.org/x/xerrors" ) -var borkedMinersCmd = &cli.Command{ - Name: "borked-miners", - Description: "information about 'borked' miner actors with late or frozen deadline crons", +var frozenMinersCmd = &cli.Command{ + Name: "frozen-miners", + Description: "information about miner actors with late or frozen deadline crons", Flags: []cli.Flag{ &cli.StringFlag{ Name: "tipset", diff --git a/cmd/lotus-shed/main.go b/cmd/lotus-shed/main.go index c8ce3ae04..488e2a6ae 100644 --- a/cmd/lotus-shed/main.go +++ b/cmd/lotus-shed/main.go @@ -19,7 +19,7 @@ func main() { base32Cmd, base16Cmd, bitFieldCmd, - borkedMinersCmd, + frozenMinersCmd, keyinfoCmd, jwtCmd, noncefix, From 70c39fe78c291063d156347ddb7ce81f86ff7bdd Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 21 Oct 2020 16:52:13 -0700 Subject: [PATCH 221/313] Fix global test options Set BELLMAN_NO_GPU on init. Set InsecurePoStValidation once in an obvious place. --- api/test/ccupgrade.go | 3 --- api/test/deals.go | 17 ----------------- api/test/mining.go | 3 --- api/test/paych.go | 3 --- api/test/test.go | 17 +++++++++++++++++ api/test/window_post.go | 8 -------- 6 files changed, 17 insertions(+), 34 deletions(-) diff --git a/api/test/ccupgrade.go b/api/test/ccupgrade.go index 4a860c661..e8010bdd4 100644 --- a/api/test/ccupgrade.go +++ b/api/test/ccupgrade.go @@ -3,7 +3,6 @@ package test import ( "context" "fmt" - "os" "sync/atomic" "testing" "time" @@ -17,8 +16,6 @@ import ( ) func TestCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration) { - _ = os.Setenv("BELLMAN_NO_GPU", "1") - for _, height := range []abi.ChainEpoch{ 1, // before 162, // while sealing diff --git a/api/test/deals.go b/api/test/deals.go index 8b4a7fe8b..ed856445b 100644 --- a/api/test/deals.go +++ b/api/test/deals.go @@ -16,15 +16,12 @@ import ( "github.com/ipfs/go-cid" files "github.com/ipfs/go-ipfs-files" - logging "github.com/ipfs/go-log/v2" "github.com/ipld/go-car" "github.com/filecoin-project/go-fil-markets/storagemarket" - "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" sealing "github.com/filecoin-project/lotus/extern/storage-sealing" - "github.com/filecoin-project/lotus/miner" dag "github.com/ipfs/go-merkledag" dstest "github.com/ipfs/go-merkledag/test" unixfile "github.com/ipfs/go-unixfs/file" @@ -34,18 +31,7 @@ import ( ipld "github.com/ipfs/go-ipld-format" ) -var MineNext = miner.MineReq{ - InjectNulls: 0, - Done: func(bool, abi.ChainEpoch, error) {}, -} - -func init() { - logging.SetAllLoggers(logging.LevelInfo) - build.InsecurePoStValidation = true -} - func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, carExport, fastRet bool) { - _ = os.Setenv("BELLMAN_NO_GPU", "1") ctx := context.Background() n, sn := b(t, OneFull, OneMiner) @@ -82,7 +68,6 @@ func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, carExport } func TestDoubleDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) { - _ = os.Setenv("BELLMAN_NO_GPU", "1") ctx := context.Background() n, sn := b(t, OneFull, OneMiner) @@ -146,7 +131,6 @@ func makeDeal(t *testing.T, ctx context.Context, rseed int, client *impl.FullNod } func TestFastRetrievalDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) { - _ = os.Setenv("BELLMAN_NO_GPU", "1") ctx := context.Background() n, sn := b(t, OneFull, OneMiner) @@ -201,7 +185,6 @@ func TestFastRetrievalDealFlow(t *testing.T, b APIBuilder, blocktime time.Durati } func TestSenondDealRetrieval(t *testing.T, b APIBuilder, blocktime time.Duration) { - _ = os.Setenv("BELLMAN_NO_GPU", "1") ctx := context.Background() n, sn := b(t, OneFull, OneMiner) diff --git a/api/test/mining.go b/api/test/mining.go index 8147c224b..90e8e8a45 100644 --- a/api/test/mining.go +++ b/api/test/mining.go @@ -5,7 +5,6 @@ import ( "context" "fmt" "math/rand" - "os" "sync/atomic" "testing" "time" @@ -88,8 +87,6 @@ func (ts *testSuite) testMiningReal(t *testing.T) { } func TestDealMining(t *testing.T, b APIBuilder, blocktime time.Duration, carExport bool) { - _ = os.Setenv("BELLMAN_NO_GPU", "1") - // test making a deal with a fresh miner, and see if it starts to mine ctx := context.Background() diff --git a/api/test/paych.go b/api/test/paych.go index 69def18bb..2bcea4369 100644 --- a/api/test/paych.go +++ b/api/test/paych.go @@ -3,7 +3,6 @@ package test import ( "context" "fmt" - "os" "sync/atomic" "testing" "time" @@ -28,8 +27,6 @@ import ( ) func TestPaymentChannels(t *testing.T, b APIBuilder, blocktime time.Duration) { - _ = os.Setenv("BELLMAN_NO_GPU", "1") - ctx := context.Background() n, sn := b(t, TwoFull, OneMiner) diff --git a/api/test/test.go b/api/test/test.go index 4074ce4a6..bae3d520e 100644 --- a/api/test/test.go +++ b/api/test/test.go @@ -2,12 +2,15 @@ package test import ( "context" + "fmt" + "os" "testing" "time" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/types" + logging "github.com/ipfs/go-log/v2" "github.com/multiformats/go-multiaddr" "github.com/stretchr/testify/assert" @@ -22,6 +25,15 @@ import ( "github.com/filecoin-project/lotus/node" ) +func init() { + logging.SetAllLoggers(logging.LevelInfo) + err := os.Setenv("BELLMAN_NO_GPU", "1") + if err != nil { + panic(fmt.Sprintf("failed to set BELLMAN_NO_GPU env variable: %s", err)) + } + build.InsecurePoStValidation = true +} + type TestNode struct { api.FullNode // ListenAddr is the address on which an API server is listening, if an @@ -110,6 +122,11 @@ var FullNodeWithUpgradeAt = func(upgradeHeight abi.ChainEpoch) FullNodeOpts { } } +var MineNext = miner.MineReq{ + InjectNulls: 0, + Done: func(bool, abi.ChainEpoch, error) {}, +} + func (ts *testSuite) testVersion(t *testing.T) { build.RunningNodeType = build.NodeFull diff --git a/api/test/window_post.go b/api/test/window_post.go index 28639cda8..55fc4ad70 100644 --- a/api/test/window_post.go +++ b/api/test/window_post.go @@ -5,7 +5,6 @@ import ( "fmt" "sync/atomic" - "os" "strings" "testing" "time" @@ -24,13 +23,6 @@ import ( "github.com/filecoin-project/lotus/node/impl" ) -func init() { - err := os.Setenv("BELLMAN_NO_GPU", "1") - if err != nil { - panic(fmt.Sprintf("failed to set BELLMAN_NO_GPU env variable: %s", err)) - } -} - func TestPledgeSector(t *testing.T, b APIBuilder, blocktime time.Duration, nSectors int) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() From 4a550d12d438f7ad87259235611d01c77044e797 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 21 Oct 2020 17:11:09 -0700 Subject: [PATCH 222/313] Always validate VRFs, even when insecure post validation is enabled We always generate them, we might as well validate them. --- chain/sync.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/chain/sync.go b/chain/sync.go index dda6f88d8..d05a3d8bb 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -1731,9 +1731,6 @@ func (syncer *Syncer) collectChain(ctx context.Context, ts *types.TipSet) error } func VerifyElectionPoStVRF(ctx context.Context, worker address.Address, rand []byte, evrf []byte) error { - if build.InsecurePoStValidation { - return nil - } return gen.VerifyVRF(ctx, worker, rand, evrf) } From defeba5576398b243cd198e000dc3e6a7cc6beee Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 21 Oct 2020 15:47:52 -0700 Subject: [PATCH 223/313] Fix lookback for worker key when computing ticket We need to compute the ticket based on our worker key from the lookback epoch, not the current epoch. --- miner/miner.go | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/miner/miner.go b/miner/miner.go index 7451d617a..7916e0405 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -386,7 +386,7 @@ func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (*types.BlockMsg, rbase = bvals[len(bvals)-1] } - ticket, err := m.computeTicket(ctx, &rbase, base) + ticket, err := m.computeTicket(ctx, &rbase, base, mbi) if err != nil { return nil, xerrors.Errorf("scratching ticket failed: %w", err) } @@ -456,16 +456,7 @@ func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (*types.BlockMsg, return b, nil } -func (m *Miner) computeTicket(ctx context.Context, brand *types.BeaconEntry, base *MiningBase) (*types.Ticket, error) { - mi, err := m.api.StateMinerInfo(ctx, m.address, types.EmptyTSK) - if err != nil { - return nil, err - } - worker, err := m.api.StateAccountKey(ctx, mi.Worker, types.EmptyTSK) - if err != nil { - return nil, err - } - +func (m *Miner) computeTicket(ctx context.Context, brand *types.BeaconEntry, base *MiningBase, mbi *api.MiningBaseInfo) (*types.Ticket, error) { buf := new(bytes.Buffer) if err := m.address.MarshalCBOR(buf); err != nil { return nil, xerrors.Errorf("failed to marshal address to cbor: %w", err) @@ -476,6 +467,11 @@ func (m *Miner) computeTicket(ctx context.Context, brand *types.BeaconEntry, bas buf.Write(base.TipSet.MinTicket().VRFProof) } + worker, err := m.api.StateAccountKey(ctx, mbi.WorkerKey, types.EmptyTSK) + if err != nil { + return nil, err + } + input, err := store.DrawRandomness(brand.Data, crypto.DomainSeparationTag_TicketProduction, round-build.TicketRandomnessLookback, buf.Bytes()) if err != nil { return nil, err From b05613445e709cd89f2f016aeff36fbb0e276a6a Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 21 Oct 2020 16:08:24 -0700 Subject: [PATCH 224/313] Sign blocks with the worker key from the correct lookback epoch --- chain/gen/mining.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/chain/gen/mining.go b/chain/gen/mining.go index 4889c632f..5fc56e8b2 100644 --- a/chain/gen/mining.go +++ b/chain/gen/mining.go @@ -27,7 +27,17 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w api.WalletA return nil, xerrors.Errorf("failed to load tipset state: %w", err) } - worker, err := stmgr.GetMinerWorkerRaw(ctx, sm, st, bt.Miner) + lbts, err := stmgr.GetLookbackTipSetForRound(ctx, sm, pts, bt.Epoch) + if err != nil { + return nil, xerrors.Errorf("getting lookback miner actor state: %w", err) + } + + lbst, _, err := sm.TipSetState(ctx, lbts) + if err != nil { + return nil, err + } + + worker, err := stmgr.GetMinerWorkerRaw(ctx, sm, lbst, bt.Miner) if err != nil { return nil, xerrors.Errorf("failed to get miner worker: %w", err) } From 98297cef4d601319b5c03128f83d03330f25b299 Mon Sep 17 00:00:00 2001 From: hannahhoward Date: Thu, 22 Oct 2020 13:40:26 -0700 Subject: [PATCH 225/313] feat(data-transfer): fill in utils --- api/api_full.go | 2 + api/api_storage.go | 6 ++ api/apistruct/struct.go | 15 ++++ cli/client.go | 76 ++++++++++++++++- cmd/lotus-storage-miner/market.go | 135 +++++++++++++++++++++++++++++- node/impl/client/client.go | 8 ++ node/impl/storminer.go | 17 ++++ 7 files changed, 252 insertions(+), 7 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index e2025f581..c7625e373 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -312,6 +312,8 @@ type FullNode interface { ClientDataTransferUpdates(ctx context.Context) (<-chan DataTransferChannel, error) // ClientRestartDataTransfer attempts to restart a data transfer with the given transfer ID and other peer ClientRestartDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error + // ClientCancelDataTransfer cancels a data transfer with the given transfer ID and other peer + ClientCancelDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error // ClientRetrieveTryRestartInsufficientFunds attempts to restart stalled retrievals on a given payment channel // which are stuck due to insufficient funds ClientRetrieveTryRestartInsufficientFunds(ctx context.Context, paymentChannel address.Address) error diff --git a/api/api_storage.go b/api/api_storage.go index 529224f6e..54f8e8780 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -5,7 +5,9 @@ import ( "context" "time" + datatransfer "github.com/filecoin-project/go-data-transfer" "github.com/ipfs/go-cid" + "github.com/libp2p/go-libp2p-core/peer" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-fil-markets/piecestore" @@ -81,6 +83,10 @@ type StorageMiner interface { MarketGetRetrievalAsk(ctx context.Context) (*retrievalmarket.Ask, error) MarketListDataTransfers(ctx context.Context) ([]DataTransferChannel, error) MarketDataTransferUpdates(ctx context.Context) (<-chan DataTransferChannel, error) + // MinerRestartDataTransfer attempts to restart a data transfer with the given transfer ID and other peer + MarketRestartDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error + // ClientCancelDataTransfer cancels a data transfer with the given transfer ID and other peer + MarketCancelDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error DealsImportData(ctx context.Context, dealPropCid cid.Cid, file string) error DealsList(ctx context.Context) ([]MarketDeal, error) diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index e8e4ee33c..76c5c5369 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -172,6 +172,7 @@ type FullNodeStruct struct { ClientListDataTransfers func(ctx context.Context) ([]api.DataTransferChannel, error) `perm:"write"` ClientDataTransferUpdates func(ctx context.Context) (<-chan api.DataTransferChannel, error) `perm:"write"` ClientRestartDataTransfer func(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error `perm:"write"` + ClientCancelDataTransfer func(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error `perm:"write"` ClientRetrieveTryRestartInsufficientFunds func(ctx context.Context, paymentChannel address.Address) error `perm:"write"` StateNetworkName func(context.Context) (dtypes.NetworkName, error) `perm:"read"` @@ -284,6 +285,8 @@ type StorageMinerStruct struct { MarketGetRetrievalAsk func(ctx context.Context) (*retrievalmarket.Ask, error) `perm:"read"` MarketListDataTransfers func(ctx context.Context) ([]api.DataTransferChannel, error) `perm:"write"` MarketDataTransferUpdates func(ctx context.Context) (<-chan api.DataTransferChannel, error) `perm:"write"` + MarketRestartDataTransfer func(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error `perm:"read"` + MarketCancelDataTransfer func(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error `perm:"read"` PledgeSector func(context.Context) error `perm:"write"` @@ -568,6 +571,10 @@ func (c *FullNodeStruct) ClientRestartDataTransfer(ctx context.Context, transfer return c.Internal.ClientRestartDataTransfer(ctx, transferID, otherPeer, isInitiator) } +func (c *FullNodeStruct) ClientCancelDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error { + return c.Internal.ClientCancelDataTransfer(ctx, transferID, otherPeer, isInitiator) +} + func (c *FullNodeStruct) ClientRetrieveTryRestartInsufficientFunds(ctx context.Context, paymentChannel address.Address) error { return c.Internal.ClientRetrieveTryRestartInsufficientFunds(ctx, paymentChannel) } @@ -1304,6 +1311,14 @@ func (c *StorageMinerStruct) MarketDataTransferUpdates(ctx context.Context) (<-c return c.Internal.MarketDataTransferUpdates(ctx) } +func (c *StorageMinerStruct) MarketRestartDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error { + return c.Internal.MarketRestartDataTransfer(ctx, transferID, otherPeer, isInitiator) +} + +func (c *StorageMinerStruct) MarketCancelDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error { + return c.Internal.MarketCancelDataTransfer(ctx, transferID, otherPeer, isInitiator) +} + func (c *StorageMinerStruct) DealsImportData(ctx context.Context, dealPropCid cid.Cid, file string) error { return c.Internal.DealsImportData(ctx, dealPropCid, file) } diff --git a/cli/client.go b/cli/client.go index 83c452555..433125129 100644 --- a/cli/client.go +++ b/cli/client.go @@ -91,6 +91,7 @@ var clientCmd = &cli.Command{ WithCategory("util", clientInfoCmd), WithCategory("util", clientListTransfers), WithCategory("util", clientRestartTransfer), + WithCategory("util", clientCancelTransfer), }, } @@ -1694,6 +1695,66 @@ var clientRestartTransfer = &cli.Command{ }, } +var clientCancelTransfer = &cli.Command{ + Name: "cancel-transfer", + Usage: "Force cancel a data transfer", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "peerid", + Usage: "narrow to transfer with specific peer", + }, + &cli.BoolFlag{ + Name: "initiator", + Usage: "specify only transfers where peer is/is not initiator", + Value: true, + }, + }, + Action: func(cctx *cli.Context) error { + if !cctx.Args().Present() { + return cli.ShowCommandHelp(cctx, cctx.Command.Name) + } + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + transferUint, err := strconv.ParseUint(cctx.Args().First(), 10, 64) + if err != nil { + return fmt.Errorf("Error reading transfer ID: %w", err) + } + transferID := datatransfer.TransferID(transferUint) + initiator := cctx.Bool("initiator") + var other peer.ID + if pidstr := cctx.String("peerid"); pidstr != "" { + p, err := peer.Decode(pidstr) + if err != nil { + return err + } + other = p + } else { + channels, err := api.ClientListDataTransfers(ctx) + if err != nil { + return err + } + found := false + for _, channel := range channels { + if channel.IsInitiator == initiator && channel.TransferID == transferID { + other = channel.OtherPeer + found = true + break + } + } + if !found { + return errors.New("unable to find matching data transfer") + } + } + + return api.ClientCancelDataTransfer(ctx, transferID, other, initiator) + }, +} + var clientListTransfers = &cli.Command{ Name: "list-transfers", Usage: "List ongoing data transfers for deals", @@ -1711,6 +1772,10 @@ var clientListTransfers = &cli.Command{ Name: "watch", Usage: "watch deal updates in real-time, rather than a one time list", }, + &cli.BoolFlag{ + Name: "show-failed", + Usage: "show failed/cancelled transfers", + }, }, Action: func(cctx *cli.Context) error { api, closer, err := GetFullNodeAPI(cctx) @@ -1728,7 +1793,7 @@ var clientListTransfers = &cli.Command{ completed := cctx.Bool("completed") color := cctx.Bool("color") watch := cctx.Bool("watch") - + showFailed := cctx.Bool("show-failed") if watch { channelUpdates, err := api.ClientDataTransferUpdates(ctx) if err != nil { @@ -1740,7 +1805,7 @@ var clientListTransfers = &cli.Command{ tm.MoveCursor(1, 1) - OutputDataTransferChannels(tm.Screen, channels, completed, color) + OutputDataTransferChannels(tm.Screen, channels, completed, color, showFailed) tm.Flush() @@ -1765,13 +1830,13 @@ var clientListTransfers = &cli.Command{ } } } - OutputDataTransferChannels(os.Stdout, channels, completed, color) + OutputDataTransferChannels(os.Stdout, channels, completed, color, showFailed) return nil }, } // OutputDataTransferChannels generates table output for a list of channels -func OutputDataTransferChannels(out io.Writer, channels []lapi.DataTransferChannel, completed bool, color bool) { +func OutputDataTransferChannels(out io.Writer, channels []lapi.DataTransferChannel, completed bool, color bool, showFailed bool) { sort.Slice(channels, func(i, j int) bool { return channels[i].TransferID < channels[j].TransferID }) @@ -1781,6 +1846,9 @@ func OutputDataTransferChannels(out io.Writer, channels []lapi.DataTransferChann if !completed && channel.Status == datatransfer.Completed { continue } + if !showFailed && (channel.Status == datatransfer.Failed || channel.Status == datatransfer.Cancelled) { + continue + } if channel.IsSender { sendingChannels = append(sendingChannels, channel) } else { diff --git a/cmd/lotus-storage-miner/market.go b/cmd/lotus-storage-miner/market.go index bb1ebd9ec..be4a529e9 100644 --- a/cmd/lotus-storage-miner/market.go +++ b/cmd/lotus-storage-miner/market.go @@ -2,6 +2,7 @@ package main import ( "bufio" + "errors" "fmt" "io" "os" @@ -13,8 +14,10 @@ import ( tm "github.com/buger/goterm" "github.com/docker/go-units" + datatransfer "github.com/filecoin-project/go-data-transfer" "github.com/ipfs/go-cid" "github.com/ipfs/go-cidutil/cidenc" + "github.com/libp2p/go-libp2p-core/peer" "github.com/multiformats/go-multibase" "github.com/urfave/cli/v2" "golang.org/x/xerrors" @@ -569,6 +572,128 @@ var dataTransfersCmd = &cli.Command{ Usage: "Manage data transfers", Subcommands: []*cli.Command{ transfersListCmd, + marketRestartTransfer, + marketCancelTransfer, + }, +} + +var marketRestartTransfer = &cli.Command{ + Name: "restart", + Usage: "Force restart a stalled data transfer", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "peerid", + Usage: "narrow to transfer with specific peer", + }, + &cli.BoolFlag{ + Name: "initiator", + Usage: "specify only transfers where peer is/is not initiator", + Value: false, + }, + }, + Action: func(cctx *cli.Context) error { + if !cctx.Args().Present() { + return cli.ShowCommandHelp(cctx, cctx.Command.Name) + } + nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := lcli.ReqContext(cctx) + + transferUint, err := strconv.ParseUint(cctx.Args().First(), 10, 64) + if err != nil { + return fmt.Errorf("Error reading transfer ID: %w", err) + } + transferID := datatransfer.TransferID(transferUint) + initiator := cctx.Bool("initiator") + var other peer.ID + if pidstr := cctx.String("peerid"); pidstr != "" { + p, err := peer.Decode(pidstr) + if err != nil { + return err + } + other = p + } else { + channels, err := nodeApi.MarketListDataTransfers(ctx) + if err != nil { + return err + } + found := false + for _, channel := range channels { + if channel.IsInitiator == initiator && channel.TransferID == transferID { + other = channel.OtherPeer + found = true + break + } + } + if !found { + return errors.New("unable to find matching data transfer") + } + } + + return nodeApi.MarketRestartDataTransfer(ctx, transferID, other, initiator) + }, +} + +var marketCancelTransfer = &cli.Command{ + Name: "cancel", + Usage: "Force cancel a data transfer", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "peerid", + Usage: "narrow to transfer with specific peer", + }, + &cli.BoolFlag{ + Name: "initiator", + Usage: "specify only transfers where peer is/is not initiator", + Value: false, + }, + }, + Action: func(cctx *cli.Context) error { + if !cctx.Args().Present() { + return cli.ShowCommandHelp(cctx, cctx.Command.Name) + } + nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := lcli.ReqContext(cctx) + + transferUint, err := strconv.ParseUint(cctx.Args().First(), 10, 64) + if err != nil { + return fmt.Errorf("Error reading transfer ID: %w", err) + } + transferID := datatransfer.TransferID(transferUint) + initiator := cctx.Bool("initiator") + var other peer.ID + if pidstr := cctx.String("peerid"); pidstr != "" { + p, err := peer.Decode(pidstr) + if err != nil { + return err + } + other = p + } else { + channels, err := nodeApi.MarketListDataTransfers(ctx) + if err != nil { + return err + } + found := false + for _, channel := range channels { + if channel.IsInitiator == initiator && channel.TransferID == transferID { + other = channel.OtherPeer + found = true + break + } + } + if !found { + return errors.New("unable to find matching data transfer") + } + } + + return nodeApi.MarketCancelDataTransfer(ctx, transferID, other, initiator) }, } @@ -589,6 +714,10 @@ var transfersListCmd = &cli.Command{ Name: "watch", Usage: "watch deal updates in real-time, rather than a one time list", }, + &cli.BoolFlag{ + Name: "show-failed", + Usage: "show failed/cancelled transfers", + }, }, Action: func(cctx *cli.Context) error { api, closer, err := lcli.GetStorageMinerAPI(cctx) @@ -606,7 +735,7 @@ var transfersListCmd = &cli.Command{ completed := cctx.Bool("completed") color := cctx.Bool("color") watch := cctx.Bool("watch") - + showFailed := cctx.Bool("show-failed") if watch { channelUpdates, err := api.MarketDataTransferUpdates(ctx) if err != nil { @@ -618,7 +747,7 @@ var transfersListCmd = &cli.Command{ tm.MoveCursor(1, 1) - lcli.OutputDataTransferChannels(tm.Screen, channels, completed, color) + lcli.OutputDataTransferChannels(tm.Screen, channels, completed, color, showFailed) tm.Flush() @@ -643,7 +772,7 @@ var transfersListCmd = &cli.Command{ } } } - lcli.OutputDataTransferChannels(os.Stdout, channels, completed, color) + lcli.OutputDataTransferChannels(os.Stdout, channels, completed, color, showFailed) return nil }, } diff --git a/node/impl/client/client.go b/node/impl/client/client.go index 0cd164826..c166548e3 100644 --- a/node/impl/client/client.go +++ b/node/impl/client/client.go @@ -858,6 +858,14 @@ func (a *API) ClientRestartDataTransfer(ctx context.Context, transferID datatran return a.DataTransfer.RestartDataTransferChannel(ctx, datatransfer.ChannelID{Initiator: otherPeer, Responder: selfPeer, ID: transferID}) } +func (a *API) ClientCancelDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error { + selfPeer := a.Host.ID() + if isInitiator { + return a.DataTransfer.CloseDataTransferChannel(ctx, datatransfer.ChannelID{Initiator: selfPeer, Responder: otherPeer, ID: transferID}) + } + return a.DataTransfer.CloseDataTransferChannel(ctx, datatransfer.ChannelID{Initiator: otherPeer, Responder: selfPeer, ID: transferID}) +} + func newDealInfo(v storagemarket.ClientDeal) api.DealInfo { return api.DealInfo{ ProposalCid: v.ProposalCid, diff --git a/node/impl/storminer.go b/node/impl/storminer.go index 6090e8a58..74b3f78f3 100644 --- a/node/impl/storminer.go +++ b/node/impl/storminer.go @@ -10,6 +10,7 @@ import ( "github.com/ipfs/go-cid" "github.com/libp2p/go-libp2p-core/host" + "github.com/libp2p/go-libp2p-core/peer" "golang.org/x/xerrors" "github.com/filecoin-project/go-address" @@ -400,6 +401,22 @@ func (sm *StorageMinerAPI) MarketListDataTransfers(ctx context.Context) ([]api.D return apiChannels, nil } +func (sm *StorageMinerAPI) MarketRestartDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error { + selfPeer := sm.Host.ID() + if isInitiator { + return sm.DataTransfer.RestartDataTransferChannel(ctx, datatransfer.ChannelID{Initiator: selfPeer, Responder: otherPeer, ID: transferID}) + } + return sm.DataTransfer.RestartDataTransferChannel(ctx, datatransfer.ChannelID{Initiator: otherPeer, Responder: selfPeer, ID: transferID}) +} + +func (sm *StorageMinerAPI) MarketCancelDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error { + selfPeer := sm.Host.ID() + if isInitiator { + return sm.DataTransfer.CloseDataTransferChannel(ctx, datatransfer.ChannelID{Initiator: selfPeer, Responder: otherPeer, ID: transferID}) + } + return sm.DataTransfer.CloseDataTransferChannel(ctx, datatransfer.ChannelID{Initiator: otherPeer, Responder: selfPeer, ID: transferID}) +} + func (sm *StorageMinerAPI) MarketDataTransferUpdates(ctx context.Context) (<-chan api.DataTransferChannel, error) { channels := make(chan api.DataTransferChannel) From febc28f83f71b46d7d121e22beca1d7d40108af4 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Thu, 22 Oct 2020 04:57:29 +0200 Subject: [PATCH 226/313] Add log and Insert Signed-off-by: Jakub Sztandera --- chain/sync_manager.go | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/chain/sync_manager.go b/chain/sync_manager.go index c7fdea726..53fd07bc9 100644 --- a/chain/sync_manager.go +++ b/chain/sync_manager.go @@ -4,6 +4,7 @@ import ( "context" "sort" "sync" + "time" "github.com/filecoin-project/lotus/chain/types" peer "github.com/libp2p/go-libp2p-core/peer" @@ -224,8 +225,7 @@ func (sbs *syncBucketSet) Empty() bool { } type syncTargetBucket struct { - tips []*types.TipSet - count int + tips []*types.TipSet } func (stb *syncTargetBucket) sameChainAs(ts *types.TipSet) bool { @@ -244,7 +244,6 @@ func (stb *syncTargetBucket) sameChainAs(ts *types.TipSet) bool { } func (stb *syncTargetBucket) add(ts *types.TipSet) { - stb.count++ for _, t := range stb.tips { if t.Equals(ts) { @@ -294,6 +293,7 @@ func (sm *syncManager) selectSyncTarget() (*types.TipSet, error) { } func (sm *syncManager) syncScheduler() { + t := time.NewTicker(10 * time.Second) for { select { @@ -311,6 +311,16 @@ func (sm *syncManager) syncScheduler() { case <-sm.stop: log.Info("sync scheduler shutting down") return + case <-t.C: + activeSyncs := make([]types.TipSetKey, len(sm.activeSyncs), 0) + for tsk := range sm.activeSyncs { + activeSyncs = append(activeSyncs, tsk) + } + sort.Slice(activeSyncs, func(i, j int) bool { + return string(activeSyncs[i].Bytes()) < string(activeSyncs[j].Bytes()) + }) + + log.Infof("activeSyncs: %v, ", activeSyncs) } } } @@ -376,7 +386,9 @@ func (sm *syncManager) scheduleProcessResult(res *syncResult) { sm.nextSyncTarget = relbucket sm.workerChan = sm.syncTargets } else { - sm.syncQueue.buckets = append(sm.syncQueue.buckets, relbucket) + for _, t := range relbucket.tips { + sm.syncQueue.Insert(t) + } } return } From 5edfc527b0b0eeec035d82792e7ab463f10073fe Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Wed, 21 Oct 2020 22:52:35 +0200 Subject: [PATCH 227/313] More than one bucket Signed-off-by: Jakub Sztandera --- chain/sync_manager.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/chain/sync_manager.go b/chain/sync_manager.go index 53fd07bc9..63bc377ec 100644 --- a/chain/sync_manager.go +++ b/chain/sync_manager.go @@ -199,13 +199,18 @@ func (sbs *syncBucketSet) removeBucket(toremove *syncTargetBucket) { } func (sbs *syncBucketSet) PopRelated(ts *types.TipSet) *syncTargetBucket { + var bOut *syncTargetBucket for _, b := range sbs.buckets { if b.sameChainAs(ts) { - sbs.removeBucket(b) - return b + if bOut == nil { + sbs.removeBucket(b) + bOut = b + } else { + log.Errorf("REPORT THIS more that one related bucket for %s", ts) + } } } - return nil + return bOut } func (sbs *syncBucketSet) Heaviest() *types.TipSet { @@ -312,7 +317,7 @@ func (sm *syncManager) syncScheduler() { log.Info("sync scheduler shutting down") return case <-t.C: - activeSyncs := make([]types.TipSetKey, len(sm.activeSyncs), 0) + activeSyncs := make([]types.TipSetKey, 0, len(sm.activeSyncs)) for tsk := range sm.activeSyncs { activeSyncs = append(activeSyncs, tsk) } From 24fc7d4cbdee6871012a1cb0c9f12c52def80307 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Thu, 22 Oct 2020 23:33:05 +0200 Subject: [PATCH 228/313] Add reproduction test and fix the issue Signed-off-by: Jakub Sztandera --- chain/sync_manager.go | 19 ++++++++++-- chain/sync_manager_test.go | 61 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/chain/sync_manager.go b/chain/sync_manager.go index 63bc377ec..1c5951bb5 100644 --- a/chain/sync_manager.go +++ b/chain/sync_manager.go @@ -3,6 +3,7 @@ package chain import ( "context" "sort" + "strings" "sync" "time" @@ -153,6 +154,19 @@ func newSyncTargetBucket(tipsets ...*types.TipSet) *syncTargetBucket { return &stb } +func (sbs *syncBucketSet) String() string { + var bStrings []string + for _, b := range sbs.buckets { + var tsStrings []string + for _, t := range b.tips { + tsStrings = append(tsStrings, t.String()) + } + bStrings = append(bStrings, "["+strings.Join(tsStrings, ",")+"]") + } + + return "{" + strings.Join(bStrings, ";") + "}" +} + func (sbs *syncBucketSet) RelatedToAny(ts *types.TipSet) bool { for _, b := range sbs.buckets { if b.sameChainAs(ts) { @@ -325,7 +339,7 @@ func (sm *syncManager) syncScheduler() { return string(activeSyncs[i].Bytes()) < string(activeSyncs[j].Bytes()) }) - log.Infof("activeSyncs: %v, ", activeSyncs) + log.Infof("activeSyncs: %v, activeSyncTips: %s ", activeSyncs, sm.activeSyncTips.String()) } } } @@ -341,7 +355,8 @@ func (sm *syncManager) scheduleIncoming(ts *types.TipSet) { var relatedToActiveSync bool for _, acts := range sm.activeSyncs { if ts.Equals(acts) { - break + // ignore, we are already syncing it + return } if ts.Parents() == acts.Key() { diff --git a/chain/sync_manager_test.go b/chain/sync_manager_test.go index 269b3a62e..276e4bb36 100644 --- a/chain/sync_manager_test.go +++ b/chain/sync_manager_test.go @@ -67,6 +67,67 @@ func assertGetSyncOp(t *testing.T, c chan *syncOp, ts *types.TipSet) { } } +func TestSyncManagerEdgeCase(t *testing.T) { + ctx := context.Background() + + a := mock.TipSet(mock.MkBlock(genTs, 1, 1)) + t.Logf("a: %s", a) + b1 := mock.TipSet(mock.MkBlock(a, 1, 2)) + t.Logf("b1: %s", b1) + b2 := mock.TipSet(mock.MkBlock(a, 2, 3)) + t.Logf("b2: %s", b2) + c1 := mock.TipSet(mock.MkBlock(b1, 2, 4)) + t.Logf("c1: %s", c1) + c2 := mock.TipSet(mock.MkBlock(b2, 1, 5)) + t.Logf("c2: %s", c2) + + runSyncMgrTest(t, "edgeCase", 1, func(t *testing.T, sm *syncManager, stc chan *syncOp) { + sm.SetPeerHead(ctx, "peer1", a) + assertGetSyncOp(t, stc, a) + time.Sleep(10 * time.Millisecond) + t.Logf("bootstate: %d", sm.bootstrapState) + + sm.SetPeerHead(ctx, "peer1", b1) + sm.SetPeerHead(ctx, "peer1", b2) + // b1 and b2 are being processed + + b1op := <-stc + b2op := <-stc + if !b1op.ts.Equals(b1) { + b1op, b2op = b2op, b1op + } + t.Logf("activeSyncs: %s: activeSyncTips: %s", sm.activeSyncs, sm.activeSyncTips.String()) + + sm.SetPeerHead(ctx, "peer2", c2) // c2 is put into activeSyncTips at index 0 + sm.SetPeerHead(ctx, "peer2", c1) // c1 is put into activeSyncTips at index 1 + sm.SetPeerHead(ctx, "peer3", b2) // b2 is related to c2 and even though it is actively synced it is put into activeSyncTips index 0 + sm.SetPeerHead(ctx, "peer1", a) // a is related to b2 and is put into activeSyncTips index 0 + + b1op.done() // b1 completes first, is related to a, so it pops activeSyncTips index 0 + // even though correct one is index 1 + + time.Sleep(100 * time.Millisecond) + t.Logf("activeSyncs: %s: activeSyncTips: %s", sm.activeSyncs, sm.activeSyncTips.String()) + b2op.done() + // b2 completes and is not related to c1, so it leaves activeSyncTips as it is + for i := 0; i < 10; { + select { + case so := <-stc: + so.done() + default: + i++ + time.Sleep(10 * time.Millisecond) + } + } + + time.Sleep(10 * time.Millisecond) + if len(sm.activeSyncTips.buckets) != 0 { + t.Errorf("activeSyncTips expected empty but got: %s", sm.activeSyncTips.String()) + } + t.Logf("activeSyncs: %s: activeSyncTips: %s", sm.activeSyncs, sm.activeSyncTips.String()) + }) +} + func TestSyncManager(t *testing.T) { ctx := context.Background() From 810feee5a159de58a166071dc3b05bb08004a689 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Fri, 23 Oct 2020 00:33:35 +0200 Subject: [PATCH 229/313] PopRelated should pop all Signed-off-by: Jakub Sztandera --- chain/sync_manager.go | 38 ++++++++++++-------------------------- chain/sync_manager_test.go | 34 ++++++++++++++++++---------------- 2 files changed, 30 insertions(+), 42 deletions(-) diff --git a/chain/sync_manager.go b/chain/sync_manager.go index 1c5951bb5..460405a91 100644 --- a/chain/sync_manager.go +++ b/chain/sync_manager.go @@ -5,7 +5,6 @@ import ( "sort" "strings" "sync" - "time" "github.com/filecoin-project/lotus/chain/types" peer "github.com/libp2p/go-libp2p-core/peer" @@ -212,16 +211,12 @@ func (sbs *syncBucketSet) removeBucket(toremove *syncTargetBucket) { sbs.buckets = nbuckets } -func (sbs *syncBucketSet) PopRelated(ts *types.TipSet) *syncTargetBucket { - var bOut *syncTargetBucket +func (sbs *syncBucketSet) PopRelated(ts *types.TipSet) []*syncTargetBucket { + var bOut []*syncTargetBucket for _, b := range sbs.buckets { if b.sameChainAs(ts) { - if bOut == nil { - sbs.removeBucket(b) - bOut = b - } else { - log.Errorf("REPORT THIS more that one related bucket for %s", ts) - } + sbs.removeBucket(b) + bOut = append(bOut, b) } } return bOut @@ -312,8 +307,6 @@ func (sm *syncManager) selectSyncTarget() (*types.TipSet, error) { } func (sm *syncManager) syncScheduler() { - t := time.NewTicker(10 * time.Second) - for { select { case ts, ok := <-sm.incomingTipSets: @@ -330,16 +323,6 @@ func (sm *syncManager) syncScheduler() { case <-sm.stop: log.Info("sync scheduler shutting down") return - case <-t.C: - activeSyncs := make([]types.TipSetKey, 0, len(sm.activeSyncs)) - for tsk := range sm.activeSyncs { - activeSyncs = append(activeSyncs, tsk) - } - sort.Slice(activeSyncs, func(i, j int) bool { - return string(activeSyncs[i].Bytes()) < string(activeSyncs[j].Bytes()) - }) - - log.Infof("activeSyncs: %v, activeSyncTips: %s ", activeSyncs, sm.activeSyncTips.String()) } } } @@ -399,14 +382,17 @@ func (sm *syncManager) scheduleProcessResult(res *syncResult) { } delete(sm.activeSyncs, res.ts.Key()) - relbucket := sm.activeSyncTips.PopRelated(res.ts) - if relbucket != nil { + relbuckets := sm.activeSyncTips.PopRelated(res.ts) + if len(relbuckets) != 0 { if res.success { if sm.nextSyncTarget == nil { - sm.nextSyncTarget = relbucket + sm.nextSyncTarget = relbuckets[0] sm.workerChan = sm.syncTargets - } else { - for _, t := range relbucket.tips { + relbuckets = relbuckets[1:] + } + + for _, b := range relbuckets { + for _, t := range b.tips { sm.syncQueue.Insert(t) } } diff --git a/chain/sync_manager_test.go b/chain/sync_manager_test.go index 276e4bb36..709e03a41 100644 --- a/chain/sync_manager_test.go +++ b/chain/sync_manager_test.go @@ -80,12 +80,14 @@ func TestSyncManagerEdgeCase(t *testing.T) { t.Logf("c1: %s", c1) c2 := mock.TipSet(mock.MkBlock(b2, 1, 5)) t.Logf("c2: %s", c2) + d1 := mock.TipSet(mock.MkBlock(c1, 1, 6)) + t.Logf("d1: %s", d1) + e1 := mock.TipSet(mock.MkBlock(d1, 1, 7)) + t.Logf("e1: %s", e1) runSyncMgrTest(t, "edgeCase", 1, func(t *testing.T, sm *syncManager, stc chan *syncOp) { sm.SetPeerHead(ctx, "peer1", a) assertGetSyncOp(t, stc, a) - time.Sleep(10 * time.Millisecond) - t.Logf("bootstate: %d", sm.bootstrapState) sm.SetPeerHead(ctx, "peer1", b1) sm.SetPeerHead(ctx, "peer1", b2) @@ -96,7 +98,6 @@ func TestSyncManagerEdgeCase(t *testing.T) { if !b1op.ts.Equals(b1) { b1op, b2op = b2op, b1op } - t.Logf("activeSyncs: %s: activeSyncTips: %s", sm.activeSyncs, sm.activeSyncTips.String()) sm.SetPeerHead(ctx, "peer2", c2) // c2 is put into activeSyncTips at index 0 sm.SetPeerHead(ctx, "peer2", c1) // c1 is put into activeSyncTips at index 1 @@ -106,28 +107,29 @@ func TestSyncManagerEdgeCase(t *testing.T) { b1op.done() // b1 completes first, is related to a, so it pops activeSyncTips index 0 // even though correct one is index 1 - time.Sleep(100 * time.Millisecond) - t.Logf("activeSyncs: %s: activeSyncTips: %s", sm.activeSyncs, sm.activeSyncTips.String()) b2op.done() // b2 completes and is not related to c1, so it leaves activeSyncTips as it is - for i := 0; i < 10; { - select { - case so := <-stc: - so.done() - default: - i++ - time.Sleep(10 * time.Millisecond) - } - } - time.Sleep(10 * time.Millisecond) + waitUntilAllWorkersAreDone(stc) + if len(sm.activeSyncTips.buckets) != 0 { t.Errorf("activeSyncTips expected empty but got: %s", sm.activeSyncTips.String()) } - t.Logf("activeSyncs: %s: activeSyncTips: %s", sm.activeSyncs, sm.activeSyncTips.String()) }) } +func waitUntilAllWorkersAreDone(stc chan *syncOp) { + for i := 0; i < 10; { + select { + case so := <-stc: + so.done() + default: + i++ + time.Sleep(10 * time.Millisecond) + } + } +} + func TestSyncManager(t *testing.T) { ctx := context.Background() From 59cfabf8a4496716c79a3f449c33019964473e13 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Thu, 22 Oct 2020 15:48:09 -0700 Subject: [PATCH 230/313] don't resolve the worker key twice --- miner/miner.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/miner/miner.go b/miner/miner.go index 7916e0405..7de7f5b73 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -467,17 +467,12 @@ func (m *Miner) computeTicket(ctx context.Context, brand *types.BeaconEntry, bas buf.Write(base.TipSet.MinTicket().VRFProof) } - worker, err := m.api.StateAccountKey(ctx, mbi.WorkerKey, types.EmptyTSK) - if err != nil { - return nil, err - } - input, err := store.DrawRandomness(brand.Data, crypto.DomainSeparationTag_TicketProduction, round-build.TicketRandomnessLookback, buf.Bytes()) if err != nil { return nil, err } - vrfOut, err := gen.ComputeVRF(ctx, m.api.WalletSign, worker, input) + vrfOut, err := gen.ComputeVRF(ctx, m.api.WalletSign, mbi.WorkerKey, input) if err != nil { return nil, err } From c8fe21c1ef2f5292dbe5a151a305a1203b959d4d Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Fri, 23 Oct 2020 01:18:13 +0200 Subject: [PATCH 231/313] PopRelated aggretates the bucket Signed-off-by: Jakub Sztandera --- chain/sync_manager.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/chain/sync_manager.go b/chain/sync_manager.go index 460405a91..27643b054 100644 --- a/chain/sync_manager.go +++ b/chain/sync_manager.go @@ -211,12 +211,15 @@ func (sbs *syncBucketSet) removeBucket(toremove *syncTargetBucket) { sbs.buckets = nbuckets } -func (sbs *syncBucketSet) PopRelated(ts *types.TipSet) []*syncTargetBucket { - var bOut []*syncTargetBucket +func (sbs *syncBucketSet) PopRelated(ts *types.TipSet) *syncTargetBucket { + var bOut *syncTargetBucket for _, b := range sbs.buckets { if b.sameChainAs(ts) { sbs.removeBucket(b) - bOut = append(bOut, b) + if bOut == nil { + bOut = &syncTargetBucket{} + } + bOut.tips = append(bOut.tips, b.tips...) } } return bOut @@ -382,17 +385,14 @@ func (sm *syncManager) scheduleProcessResult(res *syncResult) { } delete(sm.activeSyncs, res.ts.Key()) - relbuckets := sm.activeSyncTips.PopRelated(res.ts) - if len(relbuckets) != 0 { + relbucket := sm.activeSyncTips.PopRelated(res.ts) + if relbucket != nil { if res.success { if sm.nextSyncTarget == nil { - sm.nextSyncTarget = relbuckets[0] + sm.nextSyncTarget = relbucket sm.workerChan = sm.syncTargets - relbuckets = relbuckets[1:] - } - - for _, b := range relbuckets { - for _, t := range b.tips { + } else { + for _, t := range relbucket.tips { sm.syncQueue.Insert(t) } } From 580a2f4dc6a8c301346684d6021917eb9f954ec0 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Fri, 23 Oct 2020 01:35:26 +0200 Subject: [PATCH 232/313] Add option to join by common parents Signed-off-by: Jakub Sztandera --- chain/sync_manager.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/chain/sync_manager.go b/chain/sync_manager.go index 27643b054..c25068f60 100644 --- a/chain/sync_manager.go +++ b/chain/sync_manager.go @@ -2,6 +2,7 @@ package chain import ( "context" + "os" "sort" "strings" "sync" @@ -12,6 +13,14 @@ import ( const BootstrapPeerThreshold = 2 +var coalesceForksParents = false + +func init() { + if os.Getenv("LOTUS_SYNC_REL_PARENT") == "yes" { + coalesceForksParents = true + } +} + const ( BSStateInit = 0 BSStateSelected = 1 @@ -256,6 +265,9 @@ func (stb *syncTargetBucket) sameChainAs(ts *types.TipSet) bool { if ts.Parents() == t.Key() { return true } + if coalesceForksParents && ts.Parents() == t.Parents() { + return true + } } return false } From 6842c0339984265f2d9f711d2146a0c552d133a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 23 Oct 2020 11:16:29 +0200 Subject: [PATCH 233/313] wallet cli: rename withdraw-market-funds -> market withdraw --- cli/wallet.go | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/cli/wallet.go b/cli/wallet.go index f504e252f..f231f3454 100644 --- a/cli/wallet.go +++ b/cli/wallet.go @@ -38,7 +38,7 @@ var walletCmd = &cli.Command{ walletSign, walletVerify, walletDelete, - walletWithdrawMarketFunds, + walletMarket, }, } @@ -477,15 +477,23 @@ var walletDelete = &cli.Command{ }, } -var walletWithdrawMarketFunds = &cli.Command{ - Name: "withdraw-market-funds", +var walletMarket = &cli.Command{ + Name: "market", + Usage: "Interact with market balances", + Subcommands: []*cli.Command{ + walletMarketWithdraw, + }, +} + +var walletMarketWithdraw = &cli.Command{ + Name: "withdraw", Usage: "Withdraw funds from the Storage Market Actor", ArgsUsage: "[amount (FIL) optional, otherwise will withdraw max available]", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "address", + Name: "from", Usage: "Specify address to withdraw funds from, otherwise it will use the default wallet address", - Aliases: []string{"a"}, + Aliases: []string{"f"}, }, }, Action: func(cctx *cli.Context) error { @@ -496,25 +504,20 @@ var walletWithdrawMarketFunds = &cli.Command{ defer closer() ctx := ReqContext(cctx) - defAddr, err := api.WalletDefaultAddress(ctx) - if err != nil { - return xerrors.Errorf("getting default wallet address: %w", err) - } - - addr := defAddr - if cctx.String("address") != "" { - addr, err = address.NewFromString(cctx.String("address")) + var addr address.Address + if cctx.String("from") != "" { + addr, err = address.NewFromString(cctx.String("from")) if err != nil { - return xerrors.Errorf("parsing address: %w", err) + return xerrors.Errorf("parsing from address: %w", err) + } + } else { + addr, err = api.WalletDefaultAddress(ctx) + if err != nil { + return xerrors.Errorf("getting default wallet address: %w", err) } } - ts, err := api.ChainHead(ctx) - if err != nil { - return xerrors.Errorf("getting chain head: %w", err) - } - - bal, err := api.StateMarketBalance(ctx, addr, ts.Key()) + bal, err := api.StateMarketBalance(ctx, addr, types.EmptyTSK) if err != nil { return xerrors.Errorf("getting market balance for address %s: %w", addr.String(), err) } @@ -550,7 +553,7 @@ var walletWithdrawMarketFunds = &cli.Command{ fmt.Printf("Submitting WithdrawBalance message for amount %s for address %s\n", types.FIL(amt), addr.String()) smsg, err := api.MpoolPushMessage(ctx, &types.Message{ To: builtin.StorageMarketActorAddr, - From: defAddr, + From: addr, Value: types.NewInt(0), Method: builtin.MethodsMarket.WithdrawBalance, Params: params, From 92395745d3e3b6842c766bc0bb21921c78c4f901 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Wed, 21 Oct 2020 10:58:07 +0100 Subject: [PATCH 234/313] tvx simulate: execute raw message against height. --- cmd/tvx/extract.go | 70 +++++------- cmd/tvx/extract_many.go | 17 +-- cmd/tvx/main.go | 50 ++++++++- cmd/tvx/simulate.go | 231 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 309 insertions(+), 59 deletions(-) create mode 100644 cmd/tvx/simulate.go diff --git a/cmd/tvx/extract.go b/cmd/tvx/extract.go index 276c38cd4..06a7d4cea 100644 --- a/cmd/tvx/extract.go +++ b/cmd/tvx/extract.go @@ -19,7 +19,6 @@ import ( "github.com/filecoin-project/lotus/chain/actors/builtin/reward" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/vm" - lcli "github.com/filecoin-project/lotus/cli" "github.com/filecoin-project/lotus/conformance" "github.com/filecoin-project/test-vectors/schema" @@ -88,10 +87,10 @@ var extractCmd = &cli.Command{ }, &cli.StringFlag{ Name: "precursor-select", - Usage: "precursors to apply; values: 'all', 'sender'; 'all' selects all preceding" + - "messages in the canonicalised tipset, 'sender' selects only preceding messages from the same" + - "sender. Usually, 'sender' is a good tradeoff and gives you sufficient accuracy. If the receipt sanity" + - "check fails due to gas reasons, switch to 'all', as previous messages in the tipset may have" + + Usage: "precursors to apply; values: 'all', 'sender'; 'all' selects all preceding " + + "messages in the canonicalised tipset, 'sender' selects only preceding messages from the same " + + "sender. Usually, 'sender' is a good tradeoff and gives you sufficient accuracy. If the receipt sanity " + + "check fails due to gas reasons, switch to 'all', as previous messages in the tipset may have " + "affected state in a disruptive way", Value: "sender", Destination: &extractFlags.precursor, @@ -100,41 +99,24 @@ var extractCmd = &cli.Command{ } func runExtract(c *cli.Context) error { - // LOTUS_DISABLE_VM_BUF disables what's called "VM state tree buffering", - // which stashes write operations in a BufferedBlockstore - // (https://github.com/filecoin-project/lotus/blob/b7a4dbb07fd8332b4492313a617e3458f8003b2a/lib/bufbstore/buf_bstore.go#L21) - // such that they're not written until the VM is actually flushed. - // - // For some reason, the standard behaviour was not working for me (raulk), - // and disabling it (such that the state transformations are written immediately - // to the blockstore) worked. - _ = os.Setenv("LOTUS_DISABLE_VM_BUF", "iknowitsabadidea") - - ctx := context.Background() - - // Make the API client. - fapi, closer, err := lcli.GetFullNodeAPI(c) - if err != nil { - return err - } - defer closer() - - return doExtract(ctx, fapi, extractFlags) + return doExtract(extractFlags) } -func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error { +func doExtract(opts extractOpts) error { + ctx := context.Background() + mcid, err := cid.Decode(opts.cid) if err != nil { return err } - msg, execTs, incTs, err := resolveFromChain(ctx, fapi, mcid, opts.block) + msg, execTs, incTs, err := resolveFromChain(ctx, FullAPI, mcid, opts.block) if err != nil { return fmt.Errorf("failed to resolve message and tipsets from chain: %w", err) } // get the circulating supply before the message was executed. - circSupplyDetail, err := fapi.StateVMCirculatingSupplyInternal(ctx, incTs.Key()) + circSupplyDetail, err := FullAPI.StateVMCirculatingSupplyInternal(ctx, incTs.Key()) if err != nil { return fmt.Errorf("failed while fetching circulating supply: %w", err) } @@ -147,7 +129,7 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error { log.Printf("finding precursor messages using mode: %s", opts.precursor) // Fetch messages in canonical order from inclusion tipset. - msgs, err := fapi.ChainGetParentMessages(ctx, execTs.Blocks()[0].Cid()) + msgs, err := FullAPI.ChainGetParentMessages(ctx, execTs.Blocks()[0].Cid()) if err != nil { return fmt.Errorf("failed to fetch messages in canonical order from inclusion tipset: %w", err) } @@ -174,8 +156,8 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error { var ( // create a read-through store that uses ChainGetObject to fetch unknown CIDs. - pst = NewProxyingStores(ctx, fapi) - g = NewSurgeon(ctx, fapi, pst) + pst = NewProxyingStores(ctx, FullAPI) + g = NewSurgeon(ctx, FullAPI, pst) ) driver := conformance.NewDriver(ctx, schema.Selector{}, conformance.DriverOpts{ @@ -200,7 +182,7 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error { CircSupply: circSupplyDetail.FilCirculating, BaseFee: basefee, // recorded randomness will be discarded. - Rand: conformance.NewRecordingRand(new(conformance.LogReporter), fapi), + Rand: conformance.NewRecordingRand(new(conformance.LogReporter), FullAPI), }) if err != nil { return fmt.Errorf("failed to execute precursor message: %w", err) @@ -215,7 +197,7 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error { retention = opts.retain // recordingRand will record randomness so we can embed it in the test vector. - recordingRand = conformance.NewRecordingRand(new(conformance.LogReporter), fapi) + recordingRand = conformance.NewRecordingRand(new(conformance.LogReporter), FullAPI) ) log.Printf("using state retention strategy: %s", retention) @@ -248,7 +230,7 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error { case "accessed-actors": log.Printf("calculating accessed actors") // get actors accessed by message. - retain, err := g.GetAccessedActors(ctx, fapi, mcid) + retain, err := g.GetAccessedActors(ctx, FullAPI, mcid) if err != nil { return fmt.Errorf("failed to calculate accessed actors: %w", err) } @@ -286,7 +268,7 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error { // TODO sometimes this returns a nil receipt and no error ¯\_(ツ)_/¯ // ex: https://filfox.info/en/message/bafy2bzacebpxw3yiaxzy2bako62akig46x3imji7fewszen6fryiz6nymu2b2 // This code is lenient and skips receipt comparison in case of a nil receipt. - rec, err := fapi.StateGetReceipt(ctx, mcid, execTs.Key()) + rec, err := FullAPI.StateGetReceipt(ctx, mcid, execTs.Key()) if err != nil { return fmt.Errorf("failed to find receipt on chain: %w", err) } @@ -336,17 +318,17 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error { return err } - version, err := fapi.Version(ctx) + version, err := FullAPI.Version(ctx) if err != nil { return err } - ntwkName, err := fapi.StateNetworkName(ctx) + ntwkName, err := FullAPI.StateNetworkName(ctx) if err != nil { return err } - nv, err := fapi.StateNetworkVersion(ctx, execTs.Key()) + nv, err := FullAPI.StateNetworkVersion(ctx, execTs.Key()) if err != nil { return err } @@ -399,8 +381,12 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error { }, } + return writeVector(vector, opts.file) +} + +func writeVector(vector schema.TestVector, file string) (err error) { output := io.WriteCloser(os.Stdout) - if file := opts.file; file != "" { + if file := file; file != "" { dir := filepath.Dir(file) if err := os.MkdirAll(dir, 0755); err != nil { return fmt.Errorf("unable to create directory %s: %w", dir, err) @@ -415,11 +401,7 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error { enc := json.NewEncoder(output) enc.SetIndent("", " ") - if err := enc.Encode(&vector); err != nil { - return err - } - - return nil + return enc.Encode(&vector) } // resolveFromChain queries the chain for the provided message, using the block CID to diff --git a/cmd/tvx/extract_many.go b/cmd/tvx/extract_many.go index fe0ce6a6c..bf02d0880 100644 --- a/cmd/tvx/extract_many.go +++ b/cmd/tvx/extract_many.go @@ -1,7 +1,6 @@ package main import ( - "context" "encoding/csv" "fmt" "io" @@ -20,7 +19,6 @@ import ( "github.com/urfave/cli/v2" "github.com/filecoin-project/lotus/chain/stmgr" - lcli "github.com/filecoin-project/lotus/cli" ) var extractManyFlags struct { @@ -77,15 +75,6 @@ func runExtractMany(c *cli.Context) error { // to the blockstore) worked. _ = os.Setenv("LOTUS_DISABLE_VM_BUF", "iknowitsabadidea") - ctx := context.Background() - - // Make the API client. - fapi, closer, err := lcli.GetFullNodeAPI(c) - if err != nil { - return err - } - defer closer() - var ( in = extractManyFlags.in outdir = extractManyFlags.outdir @@ -198,8 +187,8 @@ func runExtractMany(c *cli.Context) error { precursor: PrecursorSelectSender, } - if err := doExtract(ctx, fapi, opts); err != nil { - log.Println(color.RedString("failed to extract vector for message %s: %s; queuing for 'canonical' precursor selection", mcid, err)) + if err := doExtract(opts); err != nil { + log.Println(color.RedString("failed to extract vector for message %s: %s; queuing for 'all' precursor selection", mcid, err)) retry = append(retry, opts) continue } @@ -215,7 +204,7 @@ func runExtractMany(c *cli.Context) error { log.Printf("retrying %s: %s", r.cid, r.id) r.precursor = PrecursorSelectAll - if err := doExtract(ctx, fapi, r); err != nil { + if err := doExtract(r); err != nil { merr = multierror.Append(merr, fmt.Errorf("failed to extract vector for message %s: %w", r.cid, err)) continue } diff --git a/cmd/tvx/main.go b/cmd/tvx/main.go index 6c887d163..5937cea8d 100644 --- a/cmd/tvx/main.go +++ b/cmd/tvx/main.go @@ -5,9 +5,21 @@ import ( "os" "sort" + "github.com/filecoin-project/go-jsonrpc" "github.com/urfave/cli/v2" + + "github.com/filecoin-project/lotus/api" + lcli "github.com/filecoin-project/lotus/cli" ) +// FullAPI is a JSON-RPC client targeting a full node. It's initialized in a +// cli.BeforeFunc. +var FullAPI api.FullNode + +// Closer is the closer for the JSON-RPC client, which must be called on +// cli.AfterFunc. +var Closer jsonrpc.ClientCloser + // DefaultLotusRepoPath is where the fallback path where to look for a Lotus // client repo. It is expanded with mitchellh/go-homedir, so it'll work with all // OSes despite the Unix twiddle notation. @@ -23,7 +35,7 @@ var repoFlag = cli.StringFlag{ func main() { app := &cli.App{ Name: "tvx", - Description: `tvx is a tool for extracting and executing test vectors. It has three subcommands. + Description: `tvx is a tool for extracting and executing test vectors. It has four subcommands. tvx extract extracts a test vector from a live network. It requires access to a Filecoin client that exposes the standard JSON-RPC API endpoint. Only @@ -35,6 +47,15 @@ func main() { tvx extract-many performs a batch extraction of many messages, supplied in a CSV file. Refer to the help of that subcommand for more info. + tvx project projects an existing test vector against a different protocol + version, reporting the result, optionally appending a new variant to the + vector in place if deemed equivalent, or producing a new vector if + non-equivalent. + + tvx simulate takes a raw message and simulates it on top of the supplied + epoch, reporting the result on stderr and writing a test vector on stdout + or into the specified file. + SETTING THE JSON-RPC API ENDPOINT You can set the JSON-RPC API endpoint through one of the following methods. @@ -57,7 +78,10 @@ func main() { extractCmd, execCmd, extractManyCmd, + simulateCmd, }, + Before: initialize, + After: destroy, } sort.Sort(cli.CommandsByName(app.Commands)) @@ -69,3 +93,27 @@ func main() { log.Fatal(err) } } + +func initialize(c *cli.Context) error { + // LOTUS_DISABLE_VM_BUF disables what's called "VM state tree buffering", + // which stashes write operations in a BufferedBlockstore + // (https://github.com/filecoin-project/lotus/blob/b7a4dbb07fd8332b4492313a617e3458f8003b2a/lib/bufbstore/buf_bstore.go#L21) + // such that they're not written until the VM is actually flushed. + // + // For some reason, the standard behaviour was not working for me (raulk), + // and disabling it (such that the state transformations are written immediately + // to the blockstore) worked. + _ = os.Setenv("LOTUS_DISABLE_VM_BUF", "iknowitsabadidea") + + // Make the API client. + var err error + FullAPI, Closer, err = lcli.GetFullNodeAPI(c) + return err +} + +func destroy(_ *cli.Context) error { + if Closer != nil { + Closer() + } + return nil +} diff --git a/cmd/tvx/simulate.go b/cmd/tvx/simulate.go new file mode 100644 index 000000000..856193e49 --- /dev/null +++ b/cmd/tvx/simulate.go @@ -0,0 +1,231 @@ +package main + +import ( + "bytes" + "compress/gzip" + "context" + "encoding/base64" + "encoding/json" + "fmt" + "log" + "os/exec" + + "github.com/fatih/color" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/test-vectors/schema" + "github.com/urfave/cli/v2" + + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/conformance" +) + +var simulateFlags struct { + msg string + epoch int64 + out string + statediff bool +} + +var simulateCmd = &cli.Command{ + Name: "simulate", + Description: "simulate a raw message on top of the supplied" + + "epoch, reporting the result on stderr and writing a test vector on stdout" + + "or into the specified file", + Action: runSimulateCmd, + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "msg", + Usage: "base64 cbor-encoded message", + Destination: &simulateFlags.msg, + }, + &cli.Int64Flag{ + Name: "at-epoch", + Usage: "epoch at which to run this message (or HEAD if not provided)", + Destination: &simulateFlags.epoch, + }, + &cli.StringFlag{ + Name: "out", + Usage: "file to write the test vector to; if nil, the vector will be written to stdout", + TakesFile: true, + Destination: &simulateFlags.out, + }, + &cli.BoolFlag{ + Name: "statediff", + Usage: "display a statediff of the precondition and postcondition states", + Destination: &simulateFlags.statediff, + }, + }, +} + +func runSimulateCmd(_ *cli.Context) error { + ctx := context.Background() + r := new(conformance.LogReporter) + + msgb, err := base64.StdEncoding.DecodeString(simulateFlags.msg) + if err != nil { + return fmt.Errorf("failed to base64-decode message: %w", err) + } + + msg, err := types.DecodeMessage(msgb) + if err != nil { + return fmt.Errorf("failed to deserialize message: %w", err) + } + + log.Printf("message to simulate has CID: %s", msg.Cid()) + + msgjson, err := json.Marshal(msg) + if err != nil { + return fmt.Errorf("failed to serialize message to json for printing: %w", err) + } + + log.Printf("message to simulate: %s", string(msgjson)) + + // Resolve the tipset, root, epoch. + var ts *types.TipSet + if epochIn := simulateFlags.epoch; epochIn == 0 { + ts, err = FullAPI.ChainHead(ctx) + } else { + ts, err = FullAPI.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(epochIn), types.EmptyTSK) + } + + if err != nil { + return fmt.Errorf("failed to get tipset: %w", err) + } + + var ( + preroot = ts.ParentState() + epoch = ts.Height() + baseFee = ts.Blocks()[0].ParentBaseFee + circSupply api.CirculatingSupply + ) + + // Get circulating supply. + circSupply, err = FullAPI.StateVMCirculatingSupplyInternal(ctx, ts.Key()) + if err != nil { + return fmt.Errorf("failed to get circulating supply for tipset %s: %w", ts.Key(), err) + } + + // Create the driver. + stores := NewProxyingStores(ctx, FullAPI) + driver := conformance.NewDriver(ctx, schema.Selector{}, conformance.DriverOpts{ + DisableVMFlush: true, + }) + rand := conformance.NewRecordingRand(r, FullAPI) + + tbs, ok := stores.Blockstore.(TracingBlockstore) + if !ok { + return fmt.Errorf("no tracing blockstore available") + } + tbs.StartTracing() + applyret, postroot, err := driver.ExecuteMessage(stores.Blockstore, conformance.ExecuteMessageParams{ + Preroot: preroot, + Epoch: epoch, + Message: msg, + CircSupply: circSupply.FilCirculating, + BaseFee: baseFee, + Rand: rand, + }) + if err != nil { + return fmt.Errorf("failed to apply message: %w", err) + } + + accessed := tbs.FinishTracing() + + var ( + out = new(bytes.Buffer) + gw = gzip.NewWriter(out) + g = NewSurgeon(ctx, FullAPI, stores) + ) + if err := g.WriteCARIncluding(gw, accessed, preroot, postroot); err != nil { + return err + } + if err = gw.Flush(); err != nil { + return err + } + if err = gw.Close(); err != nil { + return err + } + + version, err := FullAPI.Version(ctx) + if err != nil { + log.Printf("failed to get node version: %s; falling back to unknown", err) + version = api.Version{} + } + + nv, err := FullAPI.StateNetworkVersion(ctx, ts.Key()) + if err != nil { + return err + } + + codename := GetProtocolCodename(epoch) + + // Write out the test vector. + vector := schema.TestVector{ + Class: schema.ClassMessage, + Meta: &schema.Metadata{ + ID: fmt.Sprintf("simulated-%s", msg.Cid()), + Gen: []schema.GenerationData{ + {Source: "github.com/filecoin-project/lotus", Version: version.String()}}, + }, + Selector: schema.Selector{ + schema.SelectorMinProtocolVersion: codename, + }, + Randomness: rand.Recorded(), + CAR: out.Bytes(), + Pre: &schema.Preconditions{ + Variants: []schema.Variant{ + {ID: codename, Epoch: int64(epoch), NetworkVersion: uint(nv)}, + }, + CircSupply: circSupply.FilCirculating.Int, + BaseFee: baseFee.Int, + StateTree: &schema.StateTree{ + RootCID: preroot, + }, + }, + ApplyMessages: []schema.Message{{Bytes: msgb}}, + Post: &schema.Postconditions{ + StateTree: &schema.StateTree{ + RootCID: postroot, + }, + Receipts: []*schema.Receipt{ + { + ExitCode: int64(applyret.ExitCode), + ReturnValue: applyret.Return, + GasUsed: applyret.GasUsed, + }, + }, + }, + } + + if err := writeVector(vector, simulateFlags.out); err != nil { + return fmt.Errorf("failed to write vector: %w", err) + } + + log.Printf(color.GreenString("wrote vector at: %s"), simulateFlags.out) + + if !simulateFlags.statediff { + return nil + } + + if simulateFlags.out == "" { + log.Print("omitting statediff in non-file mode") + return nil + } + + // check if statediff is installed; if not, skip. + if err := exec.Command("statediff", "--help").Run(); err != nil { + log.Printf("could not perform statediff on generated vector; command not found (%s)", err) + log.Printf("install statediff with:") + log.Printf("$ GOMODULE111=off go get github.com/filecoin-project/statediff/cmd/statediff") + return err + } + + stdiff, err := exec.Command("statediff", "vector", "--file", simulateFlags.out).CombinedOutput() + if err != nil { + return fmt.Errorf("failed to statediff: %w", err) + } + + log.Print(string(stdiff)) + return nil +} From 5301c416bc1a9476b127f1d692240b25710a8233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Fri, 23 Oct 2020 10:46:56 +0100 Subject: [PATCH 235/313] tvx extract: --ignore-sanity-checks flag. --- cmd/tvx/extract.go | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/cmd/tvx/extract.go b/cmd/tvx/extract.go index 06a7d4cea..92b6d6fe3 100644 --- a/cmd/tvx/extract.go +++ b/cmd/tvx/extract.go @@ -33,13 +33,14 @@ const ( ) type extractOpts struct { - id string - block string - class string - cid string - file string - retain string - precursor string + id string + block string + class string + cid string + file string + retain string + precursor string + ignoreSanityChecks bool } var extractFlags extractOpts @@ -95,10 +96,16 @@ var extractCmd = &cli.Command{ Value: "sender", Destination: &extractFlags.precursor, }, + &cli.BoolFlag{ + Name: "ignore-sanity-checks", + Usage: "generate vector even if sanity checks fail", + Value: false, + Destination: &extractFlags.ignoreSanityChecks, + }, }, } -func runExtract(c *cli.Context) error { +func runExtract(_ *cli.Context) error { return doExtract(extractFlags) } @@ -282,13 +289,20 @@ func doExtract(opts extractOpts) error { ReturnValue: rec.Return, GasUsed: rec.GasUsed, } + reporter := new(conformance.LogReporter) conformance.AssertMsgResult(reporter, receipt, applyret, "as locally executed") if reporter.Failed() { - log.Println(color.RedString("receipt sanity check failed; aborting")) - return fmt.Errorf("vector generation aborted") + if opts.ignoreSanityChecks { + log.Println(color.YellowString("receipt sanity check failed; proceeding anyway")) + } else { + log.Println(color.RedString("receipt sanity check failed; aborting")) + return fmt.Errorf("vector generation aborted") + } + } else { + log.Println(color.GreenString("receipt sanity check succeeded")) } - log.Println(color.GreenString("receipt sanity check succeeded")) + } else { receipt = &schema.Receipt{ ExitCode: int64(applyret.ExitCode), From 39d915017586702ed49efdc356354310756e3937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Fri, 23 Oct 2020 13:30:04 +0100 Subject: [PATCH 236/313] fix tvx init. --- cmd/tvx/extract.go | 2 ++ cmd/tvx/extract_many.go | 2 ++ cmd/tvx/main.go | 12 ++++-------- cmd/tvx/simulate.go | 8 ++++++-- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/cmd/tvx/extract.go b/cmd/tvx/extract.go index 92b6d6fe3..3dfec37d8 100644 --- a/cmd/tvx/extract.go +++ b/cmd/tvx/extract.go @@ -49,6 +49,8 @@ var extractCmd = &cli.Command{ Name: "extract", Description: "generate a test vector by extracting it from a live chain", Action: runExtract, + Before: initialize, + After: destroy, Flags: []cli.Flag{ &repoFlag, &cli.StringFlag{ diff --git a/cmd/tvx/extract_many.go b/cmd/tvx/extract_many.go index bf02d0880..048271456 100644 --- a/cmd/tvx/extract_many.go +++ b/cmd/tvx/extract_many.go @@ -43,6 +43,8 @@ var extractManyCmd = &cli.Command{ after these compulsory seven. `, Action: runExtractMany, + Before: initialize, + After: destroy, Flags: []cli.Flag{ &repoFlag, &cli.StringFlag{ diff --git a/cmd/tvx/main.go b/cmd/tvx/main.go index 5937cea8d..8de851ed5 100644 --- a/cmd/tvx/main.go +++ b/cmd/tvx/main.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "log" "os" "sort" @@ -47,11 +48,6 @@ func main() { tvx extract-many performs a batch extraction of many messages, supplied in a CSV file. Refer to the help of that subcommand for more info. - tvx project projects an existing test vector against a different protocol - version, reporting the result, optionally appending a new variant to the - vector in place if deemed equivalent, or producing a new vector if - non-equivalent. - tvx simulate takes a raw message and simulates it on top of the supplied epoch, reporting the result on stderr and writing a test vector on stdout or into the specified file. @@ -80,8 +76,6 @@ func main() { extractManyCmd, simulateCmd, }, - Before: initialize, - After: destroy, } sort.Sort(cli.CommandsByName(app.Commands)) @@ -107,7 +101,9 @@ func initialize(c *cli.Context) error { // Make the API client. var err error - FullAPI, Closer, err = lcli.GetFullNodeAPI(c) + if FullAPI, Closer, err = lcli.GetFullNodeAPI(c); err != nil { + err = fmt.Errorf("failed to locate Lotus node; ") + } return err } diff --git a/cmd/tvx/simulate.go b/cmd/tvx/simulate.go index 856193e49..82b2bc118 100644 --- a/cmd/tvx/simulate.go +++ b/cmd/tvx/simulate.go @@ -29,15 +29,19 @@ var simulateFlags struct { var simulateCmd = &cli.Command{ Name: "simulate", - Description: "simulate a raw message on top of the supplied" + - "epoch, reporting the result on stderr and writing a test vector on stdout" + + Description: "simulate a raw message on top of the supplied epoch (or HEAD), " + + "reporting the result on stderr and writing a test vector on stdout " + "or into the specified file", Action: runSimulateCmd, + Before: initialize, + After: destroy, Flags: []cli.Flag{ + &repoFlag, &cli.StringFlag{ Name: "msg", Usage: "base64 cbor-encoded message", Destination: &simulateFlags.msg, + Required: true, }, &cli.Int64Flag{ Name: "at-epoch", From 9caa6ae69c18c7fecdcf3cb283b0c52f5b09cd83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 23 Oct 2020 14:42:19 +0200 Subject: [PATCH 237/313] wallet list: Add market balance and ID address flags --- cli/wallet.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/cli/wallet.go b/cli/wallet.go index f231f3454..ec343114d 100644 --- a/cli/wallet.go +++ b/cli/wallet.go @@ -79,6 +79,16 @@ var walletList = &cli.Command{ Usage: "Only print addresses", Aliases: []string{"a"}, }, + &cli.BoolFlag{ + Name: "id", + Usage: "Output ID addresses", + Aliases: []string{"i"}, + }, + &cli.BoolFlag{ + Name: "market", + Usage: "Output market balances", + Aliases: []string{"m"}, + }, }, Action: func(cctx *cli.Context) error { api, closer, err := GetFullNodeAPI(cctx) @@ -98,7 +108,10 @@ var walletList = &cli.Command{ tw := tablewriter.New( tablewriter.Col("Address"), + tablewriter.Col("ID"), tablewriter.Col("Balance"), + tablewriter.Col("Market(Avail)"), + tablewriter.Col("Market(Locked)"), tablewriter.Col("Nonce"), tablewriter.Col("Default"), tablewriter.NewLineCol("Error")) @@ -131,6 +144,23 @@ var walletList = &cli.Command{ row["Default"] = "X" } + if cctx.Bool("id") { + id, err := api.StateLookupID(ctx, addr, types.EmptyTSK) + if err != nil { + row["ID"] = "n/a" + } else { + row["ID"] = id + } + } + + if cctx.Bool("market") { + mbal, err := api.StateMarketBalance(ctx, addr, types.EmptyTSK) + if err == nil { + row["Market(Avail)"] = types.FIL(types.BigSub(mbal.Escrow, mbal.Locked)) + row["Market(Locked)"] = types.FIL(mbal.Locked) + } + } + tw.Write(row) } } From 92942d44d122af3d25f14130d0671db3f6d17e8b Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Fri, 9 Oct 2020 13:41:09 +0200 Subject: [PATCH 238/313] feat: lite-mode - market storage and retrieval clients --- api/api_gateway.go | 12 ++++ api/apistruct/struct.go | 85 ++++++++++++++++++----- api/test/ccupgrade.go | 2 +- api/test/deals.go | 29 +++++--- chain/stmgr/stmgr.go | 2 + chain/stmgr/utils.go | 19 ----- cmd/lotus-gateway/api.go | 107 ++++++++++++++++++++++------- cmd/lotus-gateway/api_test.go | 39 +++++++++-- cmd/lotus-gateway/endtoend_test.go | 86 +++++++++++++++++++---- markets/storageadapter/client.go | 24 +++---- node/builder.go | 1 - node/impl/full/chain.go | 17 +++-- node/impl/full/state.go | 82 +++++++++++++--------- node/impl/paych/paych.go | 5 -- node/modules/rpcstatemanager.go | 31 ++++++++- paychmgr/manager.go | 11 +-- 16 files changed, 394 insertions(+), 158 deletions(-) diff --git a/api/api_gateway.go b/api/api_gateway.go index c99ff8408..2b7b52b43 100644 --- a/api/api_gateway.go +++ b/api/api_gateway.go @@ -5,6 +5,8 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/network" + "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/types" "github.com/ipfs/go-cid" ) @@ -12,15 +14,25 @@ import ( type GatewayAPI interface { ChainHasObj(context.Context, cid.Cid) (bool, error) ChainHead(ctx context.Context) (*types.TipSet, error) + ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error) + ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) + ChainNotify(context.Context) (<-chan []*HeadChange, error) ChainReadObj(context.Context, cid.Cid) ([]byte, error) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) + StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (DealCollateralBounds, error) StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) + StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error) + StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) + StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (MarketBalance, error) + StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*MarketDeal, error) + StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) + StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*MsgLookup, error) } diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index e8e4ee33c..6811eff98 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -374,20 +374,29 @@ type WorkerStruct struct { type GatewayStruct struct { Internal struct { - // TODO: does the gateway need perms? - ChainHasObj func(context.Context, cid.Cid) (bool, error) - ChainGetTipSet func(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) - ChainGetTipSetByHeight func(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) - ChainHead func(ctx context.Context) (*types.TipSet, error) - ChainReadObj func(context.Context, cid.Cid) ([]byte, error) - GasEstimateMessageGas func(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) - MpoolPush func(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) - MsigGetAvailableBalance func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) - MsigGetVested func(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) - StateAccountKey func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) - StateGetActor func(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) - StateLookupID func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) - StateWaitMsg func(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) + ChainGetBlockMessages func(ctx context.Context, c cid.Cid) (*api.BlockMessages, error) + ChainGetMessage func(ctx context.Context, mc cid.Cid) (*types.Message, error) + ChainGetTipSet func(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) + ChainGetTipSetByHeight func(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) + ChainHasObj func(context.Context, cid.Cid) (bool, error) + ChainHead func(ctx context.Context) (*types.TipSet, error) + ChainNotify func(ctx context.Context) (<-chan []*api.HeadChange, error) + ChainReadObj func(context.Context, cid.Cid) ([]byte, error) + GasEstimateMessageGas func(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) + MpoolPush func(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) + MsigGetAvailableBalance func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) + MsigGetVested func(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) + StateAccountKey func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) + StateDealProviderCollateralBounds func(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) + StateGetActor func(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) + StateGetReceipt func(ctx context.Context, c cid.Cid, tsk types.TipSetKey) (*types.MessageReceipt, error) + StateLookupID func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) + StateListMiners func(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) + StateMinerInfo func(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) + StateMarketBalance func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) + StateMarketStorageDeal func(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) + StateNetworkVersion func(ctx context.Context, tsk types.TipSetKey) (stnetwork.Version, error) + StateWaitMsg func(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) } } @@ -1450,12 +1459,12 @@ func (w *WorkerStruct) Closing(ctx context.Context) (<-chan struct{}, error) { return w.Internal.Closing(ctx) } -func (g GatewayStruct) ChainHasObj(ctx context.Context, c cid.Cid) (bool, error) { - return g.Internal.ChainHasObj(ctx, c) +func (g GatewayStruct) ChainGetBlockMessages(ctx context.Context, c cid.Cid) (*api.BlockMessages, error) { + return g.Internal.ChainGetBlockMessages(ctx, c) } -func (g GatewayStruct) ChainHead(ctx context.Context) (*types.TipSet, error) { - return g.Internal.ChainHead(ctx) +func (g GatewayStruct) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) { + return g.Internal.ChainGetMessage(ctx, mc) } func (g GatewayStruct) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) { @@ -1466,6 +1475,18 @@ func (g GatewayStruct) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEp return g.Internal.ChainGetTipSetByHeight(ctx, h, tsk) } +func (g GatewayStruct) ChainHasObj(ctx context.Context, c cid.Cid) (bool, error) { + return g.Internal.ChainHasObj(ctx, c) +} + +func (g GatewayStruct) ChainHead(ctx context.Context) (*types.TipSet, error) { + return g.Internal.ChainHead(ctx) +} + +func (g GatewayStruct) ChainNotify(ctx context.Context) (<-chan []*api.HeadChange, error) { + return g.Internal.ChainNotify(ctx) +} + func (g GatewayStruct) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) { return g.Internal.ChainReadObj(ctx, c) } @@ -1490,14 +1511,42 @@ func (g GatewayStruct) StateAccountKey(ctx context.Context, addr address.Address return g.Internal.StateAccountKey(ctx, addr, tsk) } +func (g GatewayStruct) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) { + return g.Internal.StateDealProviderCollateralBounds(ctx, size, verified, tsk) +} + func (g GatewayStruct) StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) { return g.Internal.StateGetActor(ctx, actor, ts) } +func (g GatewayStruct) StateGetReceipt(ctx context.Context, c cid.Cid, tsk types.TipSetKey) (*types.MessageReceipt, error) { + return g.Internal.StateGetReceipt(ctx, c, tsk) +} + func (g GatewayStruct) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) { return g.Internal.StateLookupID(ctx, addr, tsk) } +func (g GatewayStruct) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) { + return g.Internal.StateListMiners(ctx, tsk) +} + +func (g GatewayStruct) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) { + return g.Internal.StateMarketBalance(ctx, addr, tsk) +} + +func (g GatewayStruct) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) { + return g.Internal.StateMarketStorageDeal(ctx, dealId, tsk) +} + +func (g GatewayStruct) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) { + return g.Internal.StateMinerInfo(ctx, actor, tsk) +} + +func (g GatewayStruct) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (stnetwork.Version, error) { + return g.Internal.StateNetworkVersion(ctx, tsk) +} + func (g GatewayStruct) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) { return g.Internal.StateWaitMsg(ctx, msg, confidence) } diff --git a/api/test/ccupgrade.go b/api/test/ccupgrade.go index e8010bdd4..75f72d861 100644 --- a/api/test/ccupgrade.go +++ b/api/test/ccupgrade.go @@ -89,7 +89,7 @@ func testCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration, upgradeH t.Fatal(err) } - makeDeal(t, ctx, 6, client, miner, false, false) + MakeDeal(t, ctx, 6, client, miner, false, false) // Validate upgrade diff --git a/api/test/deals.go b/api/test/deals.go index ed856445b..2317131f8 100644 --- a/api/test/deals.go +++ b/api/test/deals.go @@ -60,7 +60,7 @@ func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, carExport } }() - makeDeal(t, ctx, 6, client, miner, carExport, fastRet) + MakeDeal(t, ctx, 6, client, miner, carExport, fastRet) atomic.AddInt64(&mine, -1) fmt.Println("shutting down mining") @@ -97,24 +97,35 @@ func TestDoubleDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) { } }() - makeDeal(t, ctx, 6, client, miner, false, false) - makeDeal(t, ctx, 7, client, miner, false, false) + MakeDeal(t, ctx, 6, client, miner, false, false) + MakeDeal(t, ctx, 7, client, miner, false, false) atomic.AddInt64(&mine, -1) fmt.Println("shutting down mining") <-done } -func makeDeal(t *testing.T, ctx context.Context, rseed int, client *impl.FullNodeAPI, miner TestStorageNode, carExport, fastRet bool) { +func MakeDeal(t *testing.T, ctx context.Context, rseed int, client api.FullNode, miner TestStorageNode, carExport, fastRet bool) { data := make([]byte, 1600) rand.New(rand.NewSource(int64(rseed))).Read(data) - r := bytes.NewReader(data) - fcid, err := client.ClientImportLocal(ctx, r) + dir, err := ioutil.TempDir(os.TempDir(), "test-make-deal-") if err != nil { t.Fatal(err) } + path := filepath.Join(dir, "sourcefile.dat") + err = ioutil.WriteFile(path, data, 0644) + if err != nil { + t.Fatal(err) + } + + res, err := client.ClientImport(ctx, api.FileRef{Path: path}) + if err != nil { + t.Fatal(err) + } + + fcid := res.Root fmt.Println("FILE CID: ", fcid) deal := startDeal(t, ctx, miner, client, fcid, fastRet) @@ -259,7 +270,7 @@ func TestSenondDealRetrieval(t *testing.T, b APIBuilder, blocktime time.Duration <-done } -func startDeal(t *testing.T, ctx context.Context, miner TestStorageNode, client *impl.FullNodeAPI, fcid cid.Cid, fastRet bool) *cid.Cid { +func startDeal(t *testing.T, ctx context.Context, miner TestStorageNode, client api.FullNode, fcid cid.Cid, fastRet bool) *cid.Cid { maddr, err := miner.ActorAddress(ctx) if err != nil { t.Fatal(err) @@ -286,7 +297,7 @@ func startDeal(t *testing.T, ctx context.Context, miner TestStorageNode, client return deal } -func waitDealSealed(t *testing.T, ctx context.Context, miner TestStorageNode, client *impl.FullNodeAPI, deal *cid.Cid, noseal bool) { +func waitDealSealed(t *testing.T, ctx context.Context, miner TestStorageNode, client api.FullNode, deal *cid.Cid, noseal bool) { loop: for { di, err := client.ClientGetDealInfo(ctx, *deal) @@ -359,7 +370,7 @@ func startSealingWaiting(t *testing.T, ctx context.Context, miner TestStorageNod } } -func testRetrieval(t *testing.T, ctx context.Context, client *impl.FullNodeAPI, fcid cid.Cid, piece *cid.Cid, carExport bool, data []byte) { +func testRetrieval(t *testing.T, ctx context.Context, client api.FullNode, fcid cid.Cid, piece *cid.Cid, carExport bool, data []byte) { offers, err := client.ClientFindData(ctx, fcid, piece) if err != nil { t.Fatal(err) diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index 4f0c26b7c..2822344b0 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -46,6 +46,8 @@ const LookbackNoLimit = abi.ChainEpoch(-1) var log = logging.Logger("statemgr") type StateManagerAPI interface { + Call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*api.InvocResult, error) + GetPaychState(ctx context.Context, addr address.Address, ts *types.TipSet) (*types.Actor, paych.State, error) LoadActorTsk(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*types.Actor, error) LookupID(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) ResolveToKeyAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index 7c744f60f..54f75c138 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -255,25 +255,6 @@ func GetSectorsForWinningPoSt(ctx context.Context, pv ffiwrapper.Verifier, sm *S return out, nil } -func StateMinerInfo(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (*miner.MinerInfo, error) { - act, err := sm.LoadActor(ctx, maddr, ts) - if err != nil { - return nil, xerrors.Errorf("failed to load miner actor: %w", err) - } - - mas, err := miner.Load(sm.cs.Store(ctx), act) - if err != nil { - return nil, xerrors.Errorf("failed to load miner actor state: %w", err) - } - - mi, err := mas.Info() - if err != nil { - return nil, err - } - - return &mi, err -} - func GetMinerSlashed(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (bool, error) { act, err := sm.LoadActor(ctx, power.Address, ts) if err != nil { diff --git a/cmd/lotus-gateway/api.go b/cmd/lotus-gateway/api.go index 7fc004327..0ebb99298 100644 --- a/cmd/lotus-gateway/api.go +++ b/cmd/lotus-gateway/api.go @@ -24,7 +24,7 @@ import ( const ( LookbackCap = time.Hour * 24 - stateWaitLookbackLimit = abi.ChainEpoch(20) + StateWaitLookbackLimit = abi.ChainEpoch(20) ) var ( @@ -35,20 +35,28 @@ var ( // (to make it easy to mock for tests) type gatewayDepsAPI interface { Version(context.Context) (api.Version, error) - - ChainHasObj(context.Context, cid.Cid) (bool, error) - ChainHead(ctx context.Context) (*types.TipSet, error) + ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error) + ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) + ChainGetNode(ctx context.Context, p string) (*api.IpldObject, error) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) + ChainHasObj(context.Context, cid.Cid) (bool, error) + ChainHead(ctx context.Context) (*types.TipSet, error) + ChainNotify(context.Context) (<-chan []*api.HeadChange, error) ChainReadObj(context.Context, cid.Cid) ([]byte, error) - ChainGetNode(ctx context.Context, p string) (*api.IpldObject, error) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) MpoolPushUntrusted(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) + StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) + StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) + StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) + StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) + StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) + StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error) StateWaitMsgLimited(ctx context.Context, msg cid.Cid, confidence uint64, h abi.ChainEpoch) (*api.MsgLookup, error) StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error) StateMinerPower(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error) @@ -60,22 +68,22 @@ type gatewayDepsAPI interface { StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*dline.Info, error) StateCirculatingSupply(context.Context, types.TipSetKey) (abi.TokenAmount, error) StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (api.CirculatingSupply, error) - StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error) } type GatewayAPI struct { - api gatewayDepsAPI - lookbackCap time.Duration + api gatewayDepsAPI + lookbackCap time.Duration + stateWaitLookbackLimit abi.ChainEpoch } // NewGatewayAPI creates a new GatewayAPI with the default lookback cap func NewGatewayAPI(api gatewayDepsAPI) *GatewayAPI { - return newGatewayAPI(api, LookbackCap) + return newGatewayAPI(api, LookbackCap, StateWaitLookbackLimit) } // used by the tests -func newGatewayAPI(api gatewayDepsAPI, lookbackCap time.Duration) *GatewayAPI { - return &GatewayAPI{api: api, lookbackCap: lookbackCap} +func newGatewayAPI(api gatewayDepsAPI, lookbackCap time.Duration, stateWaitLookbackLimit abi.ChainEpoch) *GatewayAPI { + return &GatewayAPI{api: api, lookbackCap: lookbackCap, stateWaitLookbackLimit: stateWaitLookbackLimit} } func (a *GatewayAPI) checkTipsetKey(ctx context.Context, tsk types.TipSetKey) error { @@ -122,6 +130,10 @@ func (a *GatewayAPI) Version(ctx context.Context) (api.Version, error) { return a.api.Version(ctx) } +func (a *GatewayAPI) ChainGetBlockMessages(ctx context.Context, c cid.Cid) (*api.BlockMessages, error) { + return a.api.ChainGetBlockMessages(ctx, c) +} + func (a *GatewayAPI) ChainHasObj(ctx context.Context, c cid.Cid) (bool, error) { return a.api.ChainHasObj(ctx, c) } @@ -132,6 +144,10 @@ func (a *GatewayAPI) ChainHead(ctx context.Context) (*types.TipSet, error) { return a.api.ChainHead(ctx) } +func (a *GatewayAPI) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) { + return a.api.ChainGetMessage(ctx, mc) +} + func (a *GatewayAPI) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) { return a.api.ChainGetTipSet(ctx, tsk) } @@ -165,14 +181,18 @@ func (a *GatewayAPI) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoc return a.api.ChainGetTipSetByHeight(ctx, h, tsk) } -func (a *GatewayAPI) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) { - return a.api.ChainReadObj(ctx, c) -} - func (a *GatewayAPI) ChainGetNode(ctx context.Context, p string) (*api.IpldObject, error) { return a.api.ChainGetNode(ctx, p) } +func (a *GatewayAPI) ChainNotify(ctx context.Context) (<-chan []*api.HeadChange, error) { + return a.api.ChainNotify(ctx) +} + +func (a *GatewayAPI) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) { + return a.api.ChainReadObj(ctx, c) +} + func (a *GatewayAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) { if err := a.checkTipsetKey(ctx, tsk); err != nil { return nil, err @@ -213,6 +233,14 @@ func (a *GatewayAPI) StateAccountKey(ctx context.Context, addr address.Address, return a.api.StateAccountKey(ctx, addr, tsk) } +func (a *GatewayAPI) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) { + if err := a.checkTipsetKey(ctx, tsk); err != nil { + return api.DealCollateralBounds{}, err + } + + return a.api.StateDealProviderCollateralBounds(ctx, size, verified, tsk) +} + func (a *GatewayAPI) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) { if err := a.checkTipsetKey(ctx, tsk); err != nil { return nil, err @@ -221,6 +249,22 @@ func (a *GatewayAPI) StateGetActor(ctx context.Context, actor address.Address, t return a.api.StateGetActor(ctx, actor, tsk) } +func (a *GatewayAPI) StateGetReceipt(ctx context.Context, c cid.Cid, tsk types.TipSetKey) (*types.MessageReceipt, error) { + if err := a.checkTipsetKey(ctx, tsk); err != nil { + return nil, err + } + + return a.api.StateGetReceipt(ctx, c, tsk) +} + +func (a *GatewayAPI) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) { + if err := a.checkTipsetKey(ctx, tsk); err != nil { + return nil, err + } + + return a.api.StateListMiners(ctx, tsk) +} + func (a *GatewayAPI) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) { if err := a.checkTipsetKey(ctx, tsk); err != nil { return address.Undef, err @@ -229,8 +273,32 @@ func (a *GatewayAPI) StateLookupID(ctx context.Context, addr address.Address, ts return a.api.StateLookupID(ctx, addr, tsk) } +func (a *GatewayAPI) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) { + if err := a.checkTipsetKey(ctx, tsk); err != nil { + return api.MarketBalance{}, err + } + + return a.api.StateMarketBalance(ctx, addr, tsk) +} + +func (a *GatewayAPI) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) { + if err := a.checkTipsetKey(ctx, tsk); err != nil { + return nil, err + } + + return a.api.StateMarketStorageDeal(ctx, dealId, tsk) +} + +func (a *GatewayAPI) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (network.Version, error) { + if err := a.checkTipsetKey(ctx, tsk); err != nil { + return network.VersionMax, err + } + + return a.api.StateNetworkVersion(ctx, tsk) +} + func (a *GatewayAPI) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) { - return a.api.StateWaitMsgLimited(ctx, msg, confidence, stateWaitLookbackLimit) + return a.api.StateWaitMsgLimited(ctx, msg, confidence, a.stateWaitLookbackLimit) } func (a *GatewayAPI) StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error) { @@ -303,13 +371,6 @@ func (a *GatewayAPI) StateVMCirculatingSupplyInternal(ctx context.Context, tsk t return a.api.StateVMCirculatingSupplyInternal(ctx, tsk) } -func (a *GatewayAPI) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (network.Version, error) { - if err := a.checkTipsetKey(ctx, tsk); err != nil { - return 0, err - } - return a.api.StateNetworkVersion(ctx, tsk) -} - func (a *GatewayAPI) WalletVerify(ctx context.Context, k address.Address, msg []byte, sig *crypto.Signature) (bool, error) { return sigs.Verify(sig, k, msg) == nil, nil } diff --git a/cmd/lotus-gateway/api_test.go b/cmd/lotus-gateway/api_test.go index ae161945b..23d2cbf3a 100644 --- a/cmd/lotus-gateway/api_test.go +++ b/cmd/lotus-gateway/api_test.go @@ -6,6 +6,9 @@ import ( "testing" "time" + "github.com/filecoin-project/go-state-types/network" + "github.com/filecoin-project/lotus/chain/actors/builtin/miner" + "github.com/filecoin-project/lotus/build" "github.com/stretchr/testify/require" @@ -116,6 +119,38 @@ func (m *mockGatewayDepsAPI) ChainHasObj(context.Context, cid.Cid) (bool, error) panic("implement me") } +func (m *mockGatewayDepsAPI) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) { + panic("implement me") +} + +func (m *mockGatewayDepsAPI) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) { + panic("implement me") +} + +func (m *mockGatewayDepsAPI) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) { + panic("implement me") +} + +func (m *mockGatewayDepsAPI) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) { + panic("implement me") +} + +func (m *mockGatewayDepsAPI) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) { + panic("implement me") +} + +func (m *mockGatewayDepsAPI) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) { + panic("implement me") +} + +func (m *mockGatewayDepsAPI) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) { + panic("implement me") +} + +func (m *mockGatewayDepsAPI) StateNetworkVersion(ctx context.Context, key types.TipSetKey) (network.Version, error) { + panic("implement me") +} + func (m *mockGatewayDepsAPI) ChainHead(ctx context.Context) (*types.TipSet, error) { m.lk.RLock() defer m.lk.RUnlock() @@ -165,10 +200,6 @@ func (m *mockGatewayDepsAPI) ChainGetTipSetByHeight(ctx context.Context, h abi.C return m.tipsets[h], nil } -func (m *mockGatewayDepsAPI) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) { - panic("implement me") -} - func (m *mockGatewayDepsAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) { panic("implement me") } diff --git a/cmd/lotus-gateway/endtoend_test.go b/cmd/lotus-gateway/endtoend_test.go index b043ce28c..c5b513f44 100644 --- a/cmd/lotus-gateway/endtoend_test.go +++ b/cmd/lotus-gateway/endtoend_test.go @@ -11,6 +11,7 @@ import ( "github.com/filecoin-project/lotus/cli" clitest "github.com/filecoin-project/lotus/cli/test" + logging "github.com/ipfs/go-log/v2" init2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/init" multisig2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/multisig" @@ -25,12 +26,14 @@ import ( "github.com/filecoin-project/lotus/api/client" "github.com/filecoin-project/lotus/api/test" "github.com/filecoin-project/lotus/chain/actors/policy" + "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/node" builder "github.com/filecoin-project/lotus/node/test" ) const maxLookbackCap = time.Duration(math.MaxInt64) +const maxStateWaitLookbackLimit = stmgr.LookbackNoLimit func init() { policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1) @@ -38,15 +41,18 @@ func init() { policy.SetMinVerifiedDealSize(abi.NewStoragePower(256)) } -// TestEndToEndWalletMsig tests that wallet and msig API calls can be made -// on a lite node that is connected through a gateway to a full API node -func TestEndToEndWalletMsig(t *testing.T) { +// TestWalletMsig tests that API calls to wallet and msig can be made on a lite +// node that is connected through a gateway to a full API node +func TestWalletMsig(t *testing.T) { _ = os.Setenv("BELLMAN_NO_GPU", "1") blocktime := 5 * time.Millisecond ctx := context.Background() - full, lite, closer := startNodes(ctx, t, blocktime, maxLookbackCap) - defer closer() + nodes := startNodes(ctx, t, blocktime, maxLookbackCap, maxStateWaitLookbackLimit) + defer nodes.closer() + + lite := nodes.lite + full := nodes.full // The full node starts with a wallet fullWalletAddr, err := full.WalletDefaultAddress(ctx) @@ -141,16 +147,19 @@ func TestEndToEndWalletMsig(t *testing.T) { require.True(t, approveReturn.Applied) } -// TestEndToEndMsigCLI tests that msig CLI calls can be made +// TestMsigCLI tests that msig CLI calls can be made // on a lite node that is connected through a gateway to a full API node -func TestEndToEndMsigCLI(t *testing.T) { +func TestMsigCLI(t *testing.T) { _ = os.Setenv("BELLMAN_NO_GPU", "1") clitest.QuietMiningLogs() blocktime := 5 * time.Millisecond ctx := context.Background() - full, lite, closer := startNodes(ctx, t, blocktime, maxLookbackCap) - defer closer() + nodes := startNodes(ctx, t, blocktime, maxLookbackCap, maxStateWaitLookbackLimit) + defer nodes.closer() + + lite := nodes.lite + full := nodes.full // The full node starts with a wallet fullWalletAddr, err := full.WalletDefaultAddress(ctx) @@ -190,7 +199,52 @@ func sendFunds(ctx context.Context, fromNode test.TestNode, fromAddr address.Add return nil } -func startNodes(ctx context.Context, t *testing.T, blocktime time.Duration, lookbackCap time.Duration) (test.TestNode, test.TestNode, jsonrpc.ClientCloser) { +func TestDealFlow(t *testing.T) { + _ = os.Setenv("BELLMAN_NO_GPU", "1") + + logging.SetLogLevel("miner", "ERROR") + logging.SetLogLevel("chainstore", "ERROR") + logging.SetLogLevel("chain", "ERROR") + logging.SetLogLevel("sub", "ERROR") + logging.SetLogLevel("storageminer", "ERROR") + + blocktime := 5 * time.Millisecond + ctx := context.Background() + nodes := startNodes(ctx, t, blocktime, maxLookbackCap, maxStateWaitLookbackLimit) + defer nodes.closer() + + full := nodes.full + lite := nodes.lite + + // The full node starts with a wallet + fullWalletAddr, err := full.WalletDefaultAddress(ctx) + require.NoError(t, err) + + // Create a wallet on the lite node + liteWalletAddr, err := lite.WalletNew(ctx, types.KTSecp256k1) + require.NoError(t, err) + + // Send some funds from the full node to the lite node + err = sendFunds(ctx, full, fullWalletAddr, liteWalletAddr, types.NewInt(1e18)) + require.NoError(t, err) + + test.MakeDeal(t, ctx, 6, lite, nodes.miner, false, false) +} + +type testNodes struct { + lite test.TestNode + full test.TestNode + miner test.TestStorageNode + closer jsonrpc.ClientCloser +} + +func startNodes( + ctx context.Context, + t *testing.T, + blocktime time.Duration, + lookbackCap time.Duration, + stateWaitLookbackLimit abi.ChainEpoch, +) *testNodes { var closer jsonrpc.ClientCloser // Create one miner and two full nodes. @@ -207,7 +261,8 @@ func startNodes(ctx context.Context, t *testing.T, blocktime time.Duration, look fullNode := nodes[0] // Create a gateway server in front of the full node - _, addr, err := builder.CreateRPCServer(newGatewayAPI(fullNode, lookbackCap)) + gapiImpl := newGatewayAPI(fullNode, lookbackCap, stateWaitLookbackLimit) + _, addr, err := builder.CreateRPCServer(gapiImpl) require.NoError(t, err) // Create a gateway client API that connects to the gateway server @@ -234,9 +289,16 @@ func startNodes(ctx context.Context, t *testing.T, blocktime time.Duration, look err = miner.NetConnect(ctx, fullAddr) require.NoError(t, err) + // Connect the miner and the lite node (so that the lite node can send + // data to the miner) + liteAddr, err := lite.NetAddrsListen(ctx) + require.NoError(t, err) + err = miner.NetConnect(ctx, liteAddr) + require.NoError(t, err) + // Start mining blocks bm := test.NewBlockMiner(ctx, t, miner, blocktime) bm.MineBlocks() - return full, lite, closer + return &testNodes{lite: lite, full: full, miner: miner, closer: closer} } diff --git a/markets/storageadapter/client.go b/markets/storageadapter/client.go index ad2b2df8a..f299dd4d5 100644 --- a/markets/storageadapter/client.go +++ b/markets/storageadapter/client.go @@ -27,8 +27,6 @@ import ( "github.com/filecoin-project/lotus/chain/events" "github.com/filecoin-project/lotus/chain/events/state" "github.com/filecoin-project/lotus/chain/market" - "github.com/filecoin-project/lotus/chain/stmgr" - "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/lib/sigs" "github.com/filecoin-project/lotus/markets/utils" @@ -40,8 +38,6 @@ type ClientNodeAdapter struct { full.ChainAPI full.MpoolAPI - sm *stmgr.StateManager - cs *store.ChainStore fm *market.FundMgr ev *events.Events } @@ -51,14 +47,12 @@ type clientApi struct { full.StateAPI } -func NewClientNodeAdapter(state full.StateAPI, chain full.ChainAPI, mpool full.MpoolAPI, sm *stmgr.StateManager, cs *store.ChainStore, fm *market.FundMgr) storagemarket.StorageClientNode { +func NewClientNodeAdapter(state full.StateAPI, chain full.ChainAPI, mpool full.MpoolAPI, fm *market.FundMgr) storagemarket.StorageClientNode { return &ClientNodeAdapter{ StateAPI: state, ChainAPI: chain, MpoolAPI: mpool, - sm: sm, - cs: cs, fm: fm, ev: events.NewEvents(context.TODO(), &clientApi{chain, state}), } @@ -138,12 +132,12 @@ func (c *ClientNodeAdapter) GetBalance(ctx context.Context, addr address.Address func (c *ClientNodeAdapter) ValidatePublishedDeal(ctx context.Context, deal storagemarket.ClientDeal) (abi.DealID, error) { log.Infow("DEAL ACCEPTED!") - pubmsg, err := c.cs.GetMessage(*deal.PublishMessage) + pubmsg, err := c.ChainGetMessage(ctx, *deal.PublishMessage) if err != nil { return 0, xerrors.Errorf("getting deal publish message: %w", err) } - mi, err := stmgr.StateMinerInfo(ctx, c.sm, c.cs.GetHeaviestTipSet(), deal.Proposal.Provider) + mi, err := c.StateMinerInfo(ctx, deal.Proposal.Provider, types.EmptyTSK) if err != nil { return 0, xerrors.Errorf("getting miner worker failed: %w", err) } @@ -189,16 +183,16 @@ func (c *ClientNodeAdapter) ValidatePublishedDeal(ctx context.Context, deal stor } // TODO: timeout - _, ret, _, err := c.sm.WaitForMessage(ctx, *deal.PublishMessage, build.MessageConfidence, stmgr.LookbackNoLimit) + ret, err := c.StateWaitMsg(ctx, *deal.PublishMessage, build.MessageConfidence) if err != nil { return 0, xerrors.Errorf("waiting for deal publish message: %w", err) } - if ret.ExitCode != 0 { - return 0, xerrors.Errorf("deal publish failed: exit=%d", ret.ExitCode) + if ret.Receipt.ExitCode != 0 { + return 0, xerrors.Errorf("deal publish failed: exit=%d", ret.Receipt.ExitCode) } var res market2.PublishStorageDealsReturn - if err := res.UnmarshalCBOR(bytes.NewReader(ret.Return)); err != nil { + if err := res.UnmarshalCBOR(bytes.NewReader(ret.Receipt.Return)); err != nil { return 0, err } @@ -218,7 +212,7 @@ func (c *ClientNodeAdapter) DealProviderCollateralBounds(ctx context.Context, si func (c *ClientNodeAdapter) OnDealSectorCommitted(ctx context.Context, provider address.Address, dealId abi.DealID, cb storagemarket.DealSectorCommittedCallback) error { checkFunc := func(ts *types.TipSet) (done bool, more bool, err error) { - sd, err := stmgr.GetStorageDeal(ctx, c.StateManager, dealId, ts) + sd, err := c.StateMarketStorageDeal(ctx, dealId, ts.Key()) if err != nil { // TODO: This may be fine for some errors @@ -245,7 +239,7 @@ func (c *ClientNodeAdapter) OnDealSectorCommitted(ctx context.Context, provider return false, nil } - sd, err := stmgr.GetStorageDeal(ctx, c.StateManager, dealId, ts) + sd, err := c.StateMarketStorageDeal(ctx, dealId, ts.Key()) if err != nil { return false, xerrors.Errorf("failed to look up deal on chain: %w", err) } diff --git a/node/builder.go b/node/builder.go index 1dc12e80a..1d632c35c 100644 --- a/node/builder.go +++ b/node/builder.go @@ -250,7 +250,6 @@ func Online() Option { Override(new(*store.ChainStore), modules.ChainStore), Override(new(stmgr.UpgradeSchedule), stmgr.DefaultUpgradeSchedule()), Override(new(*stmgr.StateManager), stmgr.NewStateManagerWithUpgradeSchedule), - Override(new(stmgr.StateManagerAPI), From(new(*stmgr.StateManager))), Override(new(*wallet.LocalWallet), wallet.NewWallet), Override(new(wallet.Default), From(new(*wallet.LocalWallet))), Override(new(api.WalletAPI), From(new(wallet.MultiWallet))), diff --git a/node/impl/full/chain.go b/node/impl/full/chain.go index 095b51ed8..a3410b8db 100644 --- a/node/impl/full/chain.go +++ b/node/impl/full/chain.go @@ -40,8 +40,11 @@ import ( var log = logging.Logger("fullnode") type ChainModuleAPI interface { + ChainNotify(context.Context) (<-chan []*api.HeadChange, error) + ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error) ChainHasObj(context.Context, cid.Cid) (bool, error) ChainHead(context.Context) (*types.TipSet, error) + ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) ChainReadObj(context.Context, cid.Cid) ([]byte, error) @@ -67,8 +70,8 @@ type ChainAPI struct { Chain *store.ChainStore } -func (a *ChainAPI) ChainNotify(ctx context.Context) (<-chan []*api.HeadChange, error) { - return a.Chain.SubHeadChanges(ctx), nil +func (m *ChainModule) ChainNotify(ctx context.Context) (<-chan []*api.HeadChange, error) { + return m.Chain.SubHeadChanges(ctx), nil } func (m *ChainModule) ChainHead(context.Context) (*types.TipSet, error) { @@ -101,13 +104,13 @@ func (m *ChainModule) ChainGetTipSet(ctx context.Context, key types.TipSetKey) ( return m.Chain.LoadTipSet(key) } -func (a *ChainAPI) ChainGetBlockMessages(ctx context.Context, msg cid.Cid) (*api.BlockMessages, error) { - b, err := a.Chain.GetBlock(msg) +func (m *ChainModule) ChainGetBlockMessages(ctx context.Context, msg cid.Cid) (*api.BlockMessages, error) { + b, err := m.Chain.GetBlock(msg) if err != nil { return nil, err } - bmsgs, smsgs, err := a.Chain.MessagesForBlock(b) + bmsgs, smsgs, err := m.Chain.MessagesForBlock(b) if err != nil { return nil, err } @@ -532,8 +535,8 @@ func (a *ChainAPI) ChainGetNode(ctx context.Context, p string) (*api.IpldObject, }, nil } -func (a *ChainAPI) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) { - cm, err := a.Chain.GetCMessage(mc) +func (m *ChainModule) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) { + cm, err := m.Chain.GetCMessage(mc) if err != nil { return nil, err } diff --git a/node/impl/full/state.go b/node/impl/full/state.go index a6564296b..75ad03e7b 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -40,12 +40,19 @@ import ( ) type StateModuleAPI interface { - StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) - StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) - StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) - StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) + StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) + StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) + StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) + StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error) + StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) + StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) + StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) + StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) + StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) + StateNetworkVersion(ctx context.Context, key types.TipSetKey) (network.Version, error) + StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) } // StateModule provides a default implementation of StateModuleAPI. @@ -112,13 +119,13 @@ func (a *StateAPI) StateMinerActiveSectors(ctx context.Context, maddr address.Ad return stmgr.GetMinerSectorSet(ctx, a.StateManager, ts, maddr, &activeSectors) } -func (a *StateAPI) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) { - act, err := a.StateManager.LoadActorTsk(ctx, actor, tsk) +func (m *StateModule) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) { + act, err := m.StateManager.LoadActorTsk(ctx, actor, tsk) if err != nil { return miner.MinerInfo{}, xerrors.Errorf("failed to load miner actor: %w", err) } - mas, err := miner.Load(a.StateManager.ChainStore().Store(ctx), act) + mas, err := miner.Load(m.StateManager.ChainStore().Store(ctx), act) if err != nil { return miner.MinerInfo{}, xerrors.Errorf("failed to load miner actor state: %w", err) } @@ -563,20 +570,20 @@ func (a *StateAPI) StateSearchMsg(ctx context.Context, msg cid.Cid) (*api.MsgLoo return nil, nil } -func (a *StateAPI) StateGetReceipt(ctx context.Context, msg cid.Cid, tsk types.TipSetKey) (*types.MessageReceipt, error) { - ts, err := a.Chain.GetTipSetFromKey(tsk) +func (m *StateModule) StateGetReceipt(ctx context.Context, msg cid.Cid, tsk types.TipSetKey) (*types.MessageReceipt, error) { + ts, err := m.Chain.GetTipSetFromKey(tsk) if err != nil { return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) } - return a.StateManager.GetReceipt(ctx, msg, ts) + return m.StateManager.GetReceipt(ctx, msg, ts) } -func (a *StateAPI) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) { - ts, err := a.Chain.GetTipSetFromKey(tsk) +func (m *StateModule) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) { + ts, err := m.Chain.GetTipSetFromKey(tsk) if err != nil { return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) } - return stmgr.ListMinerActors(ctx, a.StateManager, ts) + return stmgr.ListMinerActors(ctx, m.StateManager, ts) } func (a *StateAPI) StateListActors(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) { @@ -587,12 +594,12 @@ func (a *StateAPI) StateListActors(ctx context.Context, tsk types.TipSetKey) ([] return a.StateManager.ListAllActors(ctx, ts) } -func (a *StateAPI) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) { - ts, err := a.Chain.GetTipSetFromKey(tsk) +func (m *StateModule) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) { + ts, err := m.Chain.GetTipSetFromKey(tsk) if err != nil { return api.MarketBalance{}, xerrors.Errorf("loading tipset %s: %w", tsk, err) } - return a.StateManager.MarketBalance(ctx, addr, ts) + return m.StateManager.MarketBalance(ctx, addr, ts) } func (a *StateAPI) StateMarketParticipants(ctx context.Context, tsk types.TipSetKey) (map[string]api.MarketBalance, error) { @@ -676,12 +683,12 @@ func (a *StateAPI) StateMarketDeals(ctx context.Context, tsk types.TipSetKey) (m return out, nil } -func (a *StateAPI) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) { - ts, err := a.Chain.GetTipSetFromKey(tsk) +func (m *StateModule) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) { + ts, err := m.Chain.GetTipSetFromKey(tsk) if err != nil { return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) } - return stmgr.GetStorageDeal(ctx, a.StateManager, dealId, ts) + return stmgr.GetStorageDeal(ctx, m.StateManager, dealId, ts) } func (a *StateAPI) StateChangedActors(ctx context.Context, old cid.Cid, new cid.Cid) (map[string]types.Actor, error) { @@ -1205,33 +1212,33 @@ var dealProviderCollateralDen = types.NewInt(100) // StateDealProviderCollateralBounds returns the min and max collateral a storage provider // can issue. It takes the deal size and verified status as parameters. -func (a *StateAPI) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) { - ts, err := a.Chain.GetTipSetFromKey(tsk) +func (m *StateModule) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) { + ts, err := m.Chain.GetTipSetFromKey(tsk) if err != nil { return api.DealCollateralBounds{}, xerrors.Errorf("loading tipset %s: %w", tsk, err) } - pact, err := a.StateGetActor(ctx, power.Address, tsk) + pact, err := m.StateGetActor(ctx, power.Address, tsk) if err != nil { return api.DealCollateralBounds{}, xerrors.Errorf("failed to load power actor: %w", err) } - ract, err := a.StateGetActor(ctx, reward.Address, tsk) + ract, err := m.StateGetActor(ctx, reward.Address, tsk) if err != nil { return api.DealCollateralBounds{}, xerrors.Errorf("failed to load reward actor: %w", err) } - pst, err := power.Load(a.StateManager.ChainStore().Store(ctx), pact) + pst, err := power.Load(m.StateManager.ChainStore().Store(ctx), pact) if err != nil { return api.DealCollateralBounds{}, xerrors.Errorf("failed to load power actor state: %w", err) } - rst, err := reward.Load(a.StateManager.ChainStore().Store(ctx), ract) + rst, err := reward.Load(m.StateManager.ChainStore().Store(ctx), ract) if err != nil { return api.DealCollateralBounds{}, xerrors.Errorf("failed to load reward actor state: %w", err) } - circ, err := a.StateVMCirculatingSupplyInternal(ctx, ts.Key()) + circ, err := stateVMCirculatingSupplyInternal(ctx, ts.Key(), m.Chain, m.StateManager) if err != nil { return api.DealCollateralBounds{}, xerrors.Errorf("getting total circulating supply: %w", err) } @@ -1252,7 +1259,7 @@ func (a *StateAPI) StateDealProviderCollateralBounds(ctx context.Context, size a powClaim.QualityAdjPower, rewPow, circ.FilCirculating, - a.StateManager.GetNtwkVersion(ctx, ts.Height())) + m.StateManager.GetNtwkVersion(ctx, ts.Height())) return api.DealCollateralBounds{ Min: types.BigDiv(types.BigMul(min, dealProviderCollateralNum), dealProviderCollateralDen), Max: max, @@ -1273,23 +1280,32 @@ func (a *StateAPI) StateCirculatingSupply(ctx context.Context, tsk types.TipSetK } func (a *StateAPI) StateVMCirculatingSupplyInternal(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) { - ts, err := a.Chain.GetTipSetFromKey(tsk) + return stateVMCirculatingSupplyInternal(ctx, tsk, a.Chain, a.StateManager) +} +func stateVMCirculatingSupplyInternal( + ctx context.Context, + tsk types.TipSetKey, + cstore *store.ChainStore, + smgr *stmgr.StateManager, +) (api.CirculatingSupply, error) { + ts, err := cstore.GetTipSetFromKey(tsk) if err != nil { return api.CirculatingSupply{}, xerrors.Errorf("loading tipset %s: %w", tsk, err) } - sTree, err := a.stateForTs(ctx, ts) + sTree, err := stateForTs(ctx, ts, cstore, smgr) if err != nil { return api.CirculatingSupply{}, err } - return a.StateManager.GetVMCirculatingSupplyDetailed(ctx, ts.Height(), sTree) + + return smgr.GetVMCirculatingSupplyDetailed(ctx, ts.Height(), sTree) } -func (a *StateAPI) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (network.Version, error) { - ts, err := a.Chain.GetTipSetFromKey(tsk) +func (m *StateModule) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (network.Version, error) { + ts, err := m.Chain.GetTipSetFromKey(tsk) if err != nil { return network.VersionMax, xerrors.Errorf("loading tipset %s: %w", tsk, err) } - return a.StateManager.GetNtwkVersion(ctx, ts.Height()), nil + return m.StateManager.GetNtwkVersion(ctx, ts.Height()), nil } diff --git a/node/impl/paych/paych.go b/node/impl/paych/paych.go index af0a1db15..773a5efab 100644 --- a/node/impl/paych/paych.go +++ b/node/impl/paych/paych.go @@ -13,17 +13,12 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/actors/builtin/paych" "github.com/filecoin-project/lotus/chain/types" - full "github.com/filecoin-project/lotus/node/impl/full" "github.com/filecoin-project/lotus/paychmgr" ) type PaychAPI struct { fx.In - full.MpoolAPI - full.WalletAPI - full.ChainAPI - PaychMgr *paychmgr.Manager } diff --git a/node/modules/rpcstatemanager.go b/node/modules/rpcstatemanager.go index 0ed054d45..7d7b92437 100644 --- a/node/modules/rpcstatemanager.go +++ b/node/modules/rpcstatemanager.go @@ -3,19 +3,40 @@ package modules import ( "context" - "github.com/filecoin-project/lotus/api" + "golang.org/x/xerrors" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/api/apibstore" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin/paych" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/types" + cbor "github.com/ipfs/go-ipld-cbor" ) type RPCStateManager struct { - gapi api.GatewayAPI + gapi api.GatewayAPI + cstore *cbor.BasicIpldStore } func NewRPCStateManager(api api.GatewayAPI) *RPCStateManager { - return &RPCStateManager{gapi: api} + cstore := cbor.NewCborStore(apibstore.NewAPIBlockstore(api)) + return &RPCStateManager{gapi: api, cstore: cstore} +} + +func (s *RPCStateManager) GetPaychState(ctx context.Context, addr address.Address, ts *types.TipSet) (*types.Actor, paych.State, error) { + act, err := s.gapi.StateGetActor(ctx, addr, ts.Key()) + if err != nil { + return nil, nil, err + } + + actState, err := paych.Load(adt.WrapStore(ctx, s.cstore), act) + if err != nil { + return nil, nil, err + } + return act, actState, nil + } func (s *RPCStateManager) LoadActorTsk(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*types.Actor, error) { @@ -30,4 +51,8 @@ func (s *RPCStateManager) ResolveToKeyAddress(ctx context.Context, addr address. return s.gapi.StateAccountKey(ctx, addr, ts.Key()) } +func (s *RPCStateManager) Call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*api.InvocResult, error) { + return nil, xerrors.Errorf("RPCStateManager does not implement StateManager.Call") +} + var _ stmgr.StateManagerAPI = (*RPCStateManager)(nil) diff --git a/paychmgr/manager.go b/paychmgr/manager.go index f2fc190c7..5e0aa88ce 100644 --- a/paychmgr/manager.go +++ b/paychmgr/manager.go @@ -16,7 +16,6 @@ import ( "github.com/filecoin-project/go-state-types/network" "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/builtin/paych" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/types" @@ -61,14 +60,10 @@ type managerAPI interface { // managerAPIImpl is used to create a composite that implements managerAPI type managerAPIImpl struct { - *stmgr.StateManager + stmgr.StateManagerAPI paychAPI } -func (m *managerAPIImpl) AdtStore(ctx context.Context) adt.Store { - return m.ChainStore().Store(ctx) -} - type Manager struct { // The Manager context is used to terminate wait operations on shutdown ctx context.Context @@ -82,11 +77,11 @@ type Manager struct { channels map[string]*channelAccessor } -func NewManager(mctx helpers.MetricsCtx, lc fx.Lifecycle, sm *stmgr.StateManager, pchstore *Store, api PaychAPI) *Manager { +func NewManager(mctx helpers.MetricsCtx, lc fx.Lifecycle, sm stmgr.StateManagerAPI, pchstore *Store, api PaychAPI) *Manager { ctx := helpers.LifecycleCtx(mctx, lc) ctx, shutdown := context.WithCancel(ctx) - impl := &managerAPIImpl{StateManager: sm, paychAPI: &api} + impl := &managerAPIImpl{StateManagerAPI: sm, paychAPI: &api} return &Manager{ ctx: ctx, shutdown: shutdown, From 906286fdbe245a286cb4e0340d0dafeee1a01bc9 Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Tue, 20 Oct 2020 17:08:25 +0200 Subject: [PATCH 239/313] feat: lite-mode - CLI tests for `lotus client` commands --- api/api_gateway.go | 1 + api/apistruct/struct.go | 5 ++ api/test/deals.go | 38 +++++---- cli/client.go | 74 +++++++++--------- cli/client_test.go | 22 ++++++ cli/helper.go | 43 +++++++++-- cli/multisig_test.go | 37 +-------- cli/test/client.go | 115 +++++++++++++++++++++++++++ cli/test/mockcli.go | 9 +++ cli/test/multisig.go | 9 --- cli/test/net.go | 41 ++++++++++ cli/test/util.go | 12 +++ cmd/lotus-gateway/api.go | 8 ++ cmd/lotus-gateway/endtoend_test.go | 120 +++++++++++++++-------------- node/impl/full/state.go | 9 ++- 15 files changed, 381 insertions(+), 162 deletions(-) create mode 100644 cli/client_test.go create mode 100644 cli/test/client.go create mode 100644 cli/test/net.go create mode 100644 cli/test/util.go diff --git a/api/api_gateway.go b/api/api_gateway.go index 2b7b52b43..5f31b8d31 100644 --- a/api/api_gateway.go +++ b/api/api_gateway.go @@ -34,5 +34,6 @@ type GatewayAPI interface { StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*MarketDeal, error) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error) + StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*MsgLookup, error) } diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 6811eff98..6c6c19f23 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -396,6 +396,7 @@ type GatewayStruct struct { StateMarketBalance func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) StateMarketStorageDeal func(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) StateNetworkVersion func(ctx context.Context, tsk types.TipSetKey) (stnetwork.Version, error) + StateVerifiedClientStatus func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) StateWaitMsg func(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) } } @@ -1547,6 +1548,10 @@ func (g GatewayStruct) StateNetworkVersion(ctx context.Context, tsk types.TipSet return g.Internal.StateNetworkVersion(ctx, tsk) } +func (g GatewayStruct) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) { + return g.Internal.StateVerifiedClientStatus(ctx, addr, tsk) +} + func (g GatewayStruct) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) { return g.Internal.StateWaitMsg(ctx, msg, confidence) } diff --git a/api/test/deals.go b/api/test/deals.go index 2317131f8..b81099d90 100644 --- a/api/test/deals.go +++ b/api/test/deals.go @@ -106,21 +106,7 @@ func TestDoubleDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) { } func MakeDeal(t *testing.T, ctx context.Context, rseed int, client api.FullNode, miner TestStorageNode, carExport, fastRet bool) { - data := make([]byte, 1600) - rand.New(rand.NewSource(int64(rseed))).Read(data) - - dir, err := ioutil.TempDir(os.TempDir(), "test-make-deal-") - if err != nil { - t.Fatal(err) - } - - path := filepath.Join(dir, "sourcefile.dat") - err = ioutil.WriteFile(path, data, 0644) - if err != nil { - t.Fatal(err) - } - - res, err := client.ClientImport(ctx, api.FileRef{Path: path}) + res, data, err := CreateClientFile(ctx, client, rseed) if err != nil { t.Fatal(err) } @@ -141,6 +127,28 @@ func MakeDeal(t *testing.T, ctx context.Context, rseed int, client api.FullNode, testRetrieval(t, ctx, client, fcid, &info.PieceCID, carExport, data) } +func CreateClientFile(ctx context.Context, client api.FullNode, rseed int) (*api.ImportRes, []byte, error) { + data := make([]byte, 1600) + rand.New(rand.NewSource(int64(rseed))).Read(data) + + dir, err := ioutil.TempDir(os.TempDir(), "test-make-deal-") + if err != nil { + return nil, nil, err + } + + path := filepath.Join(dir, "sourcefile.dat") + err = ioutil.WriteFile(path, data, 0644) + if err != nil { + return nil, nil, err + } + + res, err := client.ClientImport(ctx, api.FileRef{Path: path}) + if err != nil { + return nil, nil, err + } + return res, data, nil +} + func TestFastRetrievalDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) { ctx := context.Background() diff --git a/cli/client.go b/cli/client.go index 83c452555..c3479a725 100644 --- a/cli/client.go +++ b/cli/client.go @@ -343,6 +343,7 @@ var clientDealCmd = &cli.Command{ } defer closer() ctx := ReqContext(cctx) + afmt := NewAppFmt(cctx.App) if cctx.NArg() != 4 { return xerrors.New("expected 4 args: dataCid, miner, price, duration") @@ -462,7 +463,7 @@ var clientDealCmd = &cli.Command{ return err } - fmt.Println(encoder.Encode(*proposal)) + afmt.Println(encoder.Encode(*proposal)) return nil }, @@ -477,6 +478,7 @@ func interactiveDeal(cctx *cli.Context) error { ctx := ReqContext(cctx) ctx, cancel := context.WithCancel(ctx) defer cancel() + afmt := NewAppFmt(cctx.App) state := "import" gib := types.NewInt(1 << 30) @@ -517,10 +519,10 @@ func interactiveDeal(cctx *cli.Context) error { } printErr := func(err error) { - fmt.Printf("%s %s\n", color.RedString("Error:"), err.Error()) + afmt.Printf("%s %s\n", color.RedString("Error:"), err.Error()) } - cs := readline.NewCancelableStdin(os.Stdin) + cs := readline.NewCancelableStdin(afmt.Stdin) go func() { <-ctx.Done() cs.Close() // nolint:errcheck @@ -537,7 +539,7 @@ uiLoop: switch state { case "import": - fmt.Print("Data CID (from " + color.YellowString("lotus client import") + "): ") + afmt.Print("Data CID (from " + color.YellowString("lotus client import") + "): ") _cidStr, _, err := rl.ReadLine() cidStr := string(_cidStr) @@ -560,7 +562,7 @@ uiLoop: state = "duration" case "duration": - fmt.Print("Deal duration (days): ") + afmt.Print("Deal duration (days): ") _daystr, _, err := rl.ReadLine() daystr := string(_daystr) @@ -605,7 +607,7 @@ uiLoop: continue } - fmt.Print("\nMake this a verified deal? (yes/no): ") + afmt.Print("\nMake this a verified deal? (yes/no): ") _yn, _, err := rl.ReadLine() yn := string(_yn) @@ -619,13 +621,13 @@ uiLoop: case "no": verified = false default: - fmt.Println("Type in full 'yes' or 'no'") + afmt.Println("Type in full 'yes' or 'no'") continue } state = "miner" case "miner": - fmt.Print("Miner Addresses (f0.. f0..), none to find: ") + afmt.Print("Miner Addresses (f0.. f0..), none to find: ") _maddrsStr, _, err := rl.ReadLine() maddrsStr := string(_maddrsStr) @@ -664,11 +666,11 @@ uiLoop: candidateAsks = append(candidateAsks, ask) } - fmt.Printf("Found %d candidate asks\n", len(candidateAsks)) + afmt.Printf("Found %d candidate asks\n", len(candidateAsks)) state = "find-budget" case "find-budget": - fmt.Printf("Proposing from %s, Current Balance: %s\n", a, types.FIL(fromBal)) - fmt.Print("Maximum budget (FIL): ") // TODO: Propose some default somehow? + afmt.Printf("Proposing from %s, Current Balance: %s\n", a, types.FIL(fromBal)) + afmt.Print("Maximum budget (FIL): ") // TODO: Propose some default somehow? _budgetStr, _, err := rl.ReadLine() budgetStr := string(_budgetStr) @@ -698,10 +700,10 @@ uiLoop: } } candidateAsks = goodAsks - fmt.Printf("%d asks within budget\n", len(candidateAsks)) + afmt.Printf("%d asks within budget\n", len(candidateAsks)) state = "find-count" case "find-count": - fmt.Print("Deals to make (1): ") + afmt.Print("Deals to make (1): ") dealcStr, _, err := rl.ReadLine() if err != nil { printErr(xerrors.Errorf("reading deal count: %w", err)) @@ -780,12 +782,12 @@ uiLoop: case "confirm": // TODO: do some more or epochs math (round to miner PP, deal start buffer) - fmt.Printf("-----\n") - fmt.Printf("Proposing from %s\n", a) - fmt.Printf("\tBalance: %s\n", types.FIL(fromBal)) - fmt.Printf("\n") - fmt.Printf("Piece size: %s (Payload size: %s)\n", units.BytesSize(float64(ds.PieceSize)), units.BytesSize(float64(ds.PayloadSize))) - fmt.Printf("Duration: %s\n", dur) + afmt.Printf("-----\n") + afmt.Printf("Proposing from %s\n", a) + afmt.Printf("\tBalance: %s\n", types.FIL(fromBal)) + afmt.Printf("\n") + afmt.Printf("Piece size: %s (Payload size: %s)\n", units.BytesSize(float64(ds.PieceSize)), units.BytesSize(float64(ds.PayloadSize))) + afmt.Printf("Duration: %s\n", dur) pricePerGib := big.Zero() for _, a := range ask { @@ -804,7 +806,7 @@ uiLoop: if len(ask) > 1 { totalPrice := types.BigMul(epochPrice, types.NewInt(uint64(epochs))) - fmt.Printf("Miner %s (Power:%s) price: ~%s (%s per epoch)\n", color.YellowString(a.Miner.String()), color.GreenString(types.SizeStr(mpow.MinerPower.QualityAdjPower)), color.BlueString(types.FIL(totalPrice).String()), types.FIL(epochPrice)) + afmt.Printf("Miner %s (Power:%s) price: ~%s (%s per epoch)\n", color.YellowString(a.Miner.String()), color.GreenString(types.SizeStr(mpow.MinerPower.QualityAdjPower)), color.BlueString(types.FIL(totalPrice).String()), types.FIL(epochPrice)) } } @@ -812,12 +814,12 @@ uiLoop: epochPrice := types.BigDiv(types.BigMul(pricePerGib, types.NewInt(uint64(ds.PieceSize))), gib) totalPrice := types.BigMul(epochPrice, types.NewInt(uint64(epochs))) - fmt.Printf("Total price: ~%s (%s per epoch)\n", color.CyanString(types.FIL(totalPrice).String()), types.FIL(epochPrice)) - fmt.Printf("Verified: %v\n", verified) + afmt.Printf("Total price: ~%s (%s per epoch)\n", color.CyanString(types.FIL(totalPrice).String()), types.FIL(epochPrice)) + afmt.Printf("Verified: %v\n", verified) state = "accept" case "accept": - fmt.Print("\nAccept (yes/no): ") + afmt.Print("\nAccept (yes/no): ") _yn, _, err := rl.ReadLine() yn := string(_yn) @@ -830,7 +832,7 @@ uiLoop: } if yn != "yes" { - fmt.Println("Type in full 'yes' or 'no'") + afmt.Println("Type in full 'yes' or 'no'") continue } @@ -861,7 +863,7 @@ uiLoop: return err } - fmt.Printf("Deal (%s) CID: %s\n", maddr, color.GreenString(encoder.Encode(*proposal))) + afmt.Printf("Deal (%s) CID: %s\n", maddr, color.GreenString(encoder.Encode(*proposal))) } return nil @@ -975,6 +977,7 @@ var clientRetrieveCmd = &cli.Command{ } defer closer() ctx := ReqContext(cctx) + afmt := NewAppFmt(cctx.App) var payer address.Address if cctx.String("from") != "" { @@ -1083,14 +1086,14 @@ var clientRetrieveCmd = &cli.Command{ select { case evt, ok := <-updates: if ok { - fmt.Printf("> Recv: %s, Paid %s, %s (%s)\n", + afmt.Printf("> Recv: %s, Paid %s, %s (%s)\n", types.SizeStr(types.NewInt(evt.BytesReceived)), types.FIL(evt.FundsSpent), retrievalmarket.ClientEvents[evt.Event], retrievalmarket.DealStatuses[evt.Status], ) } else { - fmt.Println("Success") + afmt.Println("Success") return nil } @@ -1269,8 +1272,9 @@ var clientQueryAskCmd = &cli.Command{ }, }, Action: func(cctx *cli.Context) error { + afmt := NewAppFmt(cctx.App) if cctx.NArg() != 1 { - fmt.Println("Usage: query-ask [minerAddress]") + afmt.Println("Usage: query-ask [minerAddress]") return nil } @@ -1311,23 +1315,23 @@ var clientQueryAskCmd = &cli.Command{ return err } - fmt.Printf("Ask: %s\n", maddr) - fmt.Printf("Price per GiB: %s\n", types.FIL(ask.Price)) - fmt.Printf("Verified Price per GiB: %s\n", types.FIL(ask.VerifiedPrice)) - fmt.Printf("Max Piece size: %s\n", types.SizeStr(types.NewInt(uint64(ask.MaxPieceSize)))) + afmt.Printf("Ask: %s\n", maddr) + afmt.Printf("Price per GiB: %s\n", types.FIL(ask.Price)) + afmt.Printf("Verified Price per GiB: %s\n", types.FIL(ask.VerifiedPrice)) + afmt.Printf("Max Piece size: %s\n", types.SizeStr(types.NewInt(uint64(ask.MaxPieceSize)))) size := cctx.Int64("size") if size == 0 { return nil } perEpoch := types.BigDiv(types.BigMul(ask.Price, types.NewInt(uint64(size))), types.NewInt(1<<30)) - fmt.Printf("Price per Block: %s\n", types.FIL(perEpoch)) + afmt.Printf("Price per Block: %s\n", types.FIL(perEpoch)) duration := cctx.Int64("duration") if duration == 0 { return nil } - fmt.Printf("Total Price: %s\n", types.FIL(types.BigMul(perEpoch, types.NewInt(uint64(duration))))) + afmt.Printf("Total Price: %s\n", types.FIL(types.BigMul(perEpoch, types.NewInt(uint64(duration))))) return nil }, @@ -1410,7 +1414,7 @@ var clientListDeals = &cli.Command{ } } - return outputStorageDeals(ctx, os.Stdout, api, localDeals, cctx.Bool("verbose"), cctx.Bool("color"), showFailed) + return outputStorageDeals(ctx, cctx.App.Writer, api, localDeals, cctx.Bool("verbose"), cctx.Bool("color"), showFailed) }, } diff --git a/cli/client_test.go b/cli/client_test.go new file mode 100644 index 000000000..f0e8efda8 --- /dev/null +++ b/cli/client_test.go @@ -0,0 +1,22 @@ +package cli + +import ( + "context" + "os" + "testing" + "time" + + clitest "github.com/filecoin-project/lotus/cli/test" +) + +// TestClient does a basic test to exercise the client CLI +// commands +func TestClient(t *testing.T) { + _ = os.Setenv("BELLMAN_NO_GPU", "1") + clitest.QuietMiningLogs() + + blocktime := 5 * time.Millisecond + ctx := context.Background() + clientNode, _ := clitest.StartOneNodeOneMiner(ctx, t, blocktime) + clitest.RunClientTest(t, Commands, clientNode) +} diff --git a/cli/helper.go b/cli/helper.go index 9398ead71..da236bcae 100644 --- a/cli/helper.go +++ b/cli/helper.go @@ -2,15 +2,16 @@ package cli import ( "fmt" + "io" "os" - "github.com/urfave/cli/v2" + ufcli "github.com/urfave/cli/v2" "golang.org/x/xerrors" ) type PrintHelpErr struct { Err error - Ctx *cli.Context + Ctx *ufcli.Context } func (e *PrintHelpErr) Error() string { @@ -26,11 +27,11 @@ func (e *PrintHelpErr) Is(o error) bool { return ok } -func ShowHelp(cctx *cli.Context, err error) error { +func ShowHelp(cctx *ufcli.Context, err error) error { return &PrintHelpErr{Err: err, Ctx: cctx} } -func RunApp(app *cli.App) { +func RunApp(app *ufcli.App) { if err := app.Run(os.Args); err != nil { if os.Getenv("LOTUS_DEV") != "" { log.Warnf("%+v", err) @@ -39,8 +40,40 @@ func RunApp(app *cli.App) { } var phe *PrintHelpErr if xerrors.As(err, &phe) { - _ = cli.ShowCommandHelp(phe.Ctx, phe.Ctx.Command.Name) + _ = ufcli.ShowCommandHelp(phe.Ctx, phe.Ctx.Command.Name) } os.Exit(1) } } + +type AppFmt struct { + app *ufcli.App + Stdin io.Reader +} + +func NewAppFmt(a *ufcli.App) *AppFmt { + var stdin io.Reader + istdin, ok := a.Metadata["stdin"] + if ok { + stdin = istdin.(io.Reader) + } else { + stdin = os.Stdin + } + return &AppFmt{app: a, Stdin: stdin} +} + +func (a *AppFmt) Print(args ...interface{}) { + fmt.Fprint(a.app.Writer, args...) +} + +func (a *AppFmt) Println(args ...interface{}) { + fmt.Fprintln(a.app.Writer, args...) +} + +func (a *AppFmt) Printf(fmtstr string, args ...interface{}) { + fmt.Fprintf(a.app.Writer, fmtstr, args...) +} + +func (a *AppFmt) Scan(args ...interface{}) (int, error) { + return fmt.Fscan(a.Stdin, args...) +} diff --git a/cli/multisig_test.go b/cli/multisig_test.go index 09cdbe056..82472cd62 100644 --- a/cli/multisig_test.go +++ b/cli/multisig_test.go @@ -6,50 +6,17 @@ import ( "testing" "time" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/lotus/api/test" clitest "github.com/filecoin-project/lotus/cli/test" - builder "github.com/filecoin-project/lotus/node/test" ) // TestMultisig does a basic test to exercise the multisig CLI // commands func TestMultisig(t *testing.T) { _ = os.Setenv("BELLMAN_NO_GPU", "1") + clitest.QuietMiningLogs() blocktime := 5 * time.Millisecond ctx := context.Background() - nodes, _ := startNodes(ctx, t, blocktime) - clientNode := nodes[0] + clientNode, _ := clitest.StartOneNodeOneMiner(ctx, t, blocktime) clitest.RunMultisigTest(t, Commands, clientNode) } - -func startNodes(ctx context.Context, t *testing.T, blocktime time.Duration) ([]test.TestNode, []address.Address) { - n, sn := builder.RPCMockSbBuilder(t, test.OneFull, test.OneMiner) - - full := n[0] - miner := sn[0] - - // Get everyone connected - addrs, err := full.NetAddrsListen(ctx) - if err != nil { - t.Fatal(err) - } - - if err := miner.NetConnect(ctx, addrs); err != nil { - t.Fatal(err) - } - - // Start mining blocks - bm := test.NewBlockMiner(ctx, t, miner, blocktime) - bm.MineBlocks() - - // Get the creator's address - creatorAddr, err := full.WalletDefaultAddress(ctx) - if err != nil { - t.Fatal(err) - } - - // Create mock CLI - return n, []address.Address{creatorAddr} -} diff --git a/cli/test/client.go b/cli/test/client.go new file mode 100644 index 000000000..3a5146219 --- /dev/null +++ b/cli/test/client.go @@ -0,0 +1,115 @@ +package test + +import ( + "context" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "regexp" + "strings" + "testing" + "time" + + "github.com/filecoin-project/lotus/api/test" + "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/specs-actors/v2/actors/builtin" + "github.com/stretchr/testify/require" + lcli "github.com/urfave/cli/v2" +) + +// RunClientTest exercises some of the client CLI commands +func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) { + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + // Create mock CLI + mockCLI := newMockCLI(t, cmds) + clientCLI := mockCLI.client(clientNode.ListenAddr) + + // Get the miner address + addrs, err := clientNode.StateListMiners(ctx, types.EmptyTSK) + require.NoError(t, err) + require.Len(t, addrs, 1) + + minerAddr := addrs[0] + fmt.Println("Miner:", minerAddr) + + // client query-ask + cmd := []string{ + "client", "query-ask", minerAddr.String(), + } + out := clientCLI.runCmd(cmd) + require.Regexp(t, regexp.MustCompile("Ask:"), out) + + // Create a deal (non-interactive) + // client deal 1000000attofil + res, _, err := test.CreateClientFile(ctx, clientNode, 1) + require.NoError(t, err) + dataCid := res.Root + price := "1000000attofil" + duration := fmt.Sprintf("%d", build.MinDealDuration) + cmd = []string{ + "client", "deal", dataCid.String(), minerAddr.String(), price, duration, + } + out = clientCLI.runCmd(cmd) + fmt.Println("client deal", out) + + // Create a deal (interactive) + // client deal + // + // (in days) + // + // "no" (verified client) + // "yes" (confirm deal) + res, _, err = test.CreateClientFile(ctx, clientNode, 2) + require.NoError(t, err) + dataCid2 := res.Root + duration = fmt.Sprintf("%d", build.MinDealDuration/builtin.EpochsInDay) + cmd = []string{ + "client", "deal", + } + interactiveCmds := []string{ + dataCid2.String(), + duration, + minerAddr.String(), + "no", + "yes", + } + out = clientCLI.runInteractiveCmd(cmd, interactiveCmds) + fmt.Println("client deal:\n", out) + + // Wait for provider to start sealing deal + dealStatus := "" + for dealStatus != "StorageDealSealing" { + // client list-deals + cmd = []string{"client", "list-deals"} + out = clientCLI.runCmd(cmd) + fmt.Println("list-deals:\n", out) + + lines := strings.Split(out, "\n") + require.Len(t, lines, 2) + re := regexp.MustCompile(`\s+`) + parts := re.Split(lines[1], -1) + if len(parts) < 4 { + require.Fail(t, "bad list-deals output format") + } + dealStatus = parts[3] + fmt.Println(" Deal status:", dealStatus) + + time.Sleep(time.Second) + } + + // Retrieve the first file from the miner + // client retrieve + tmpdir, err := ioutil.TempDir(os.TempDir(), "test-cli-client") + require.NoError(t, err) + path := filepath.Join(tmpdir, "outfile.dat") + cmd = []string{ + "client", "retrieve", dataCid.String(), path, + } + out = clientCLI.runCmd(cmd) + fmt.Println("retrieve:\n", out) + require.Regexp(t, regexp.MustCompile("Success"), out) +} diff --git a/cli/test/mockcli.go b/cli/test/mockcli.go index f5d5cfcba..c7eb70092 100644 --- a/cli/test/mockcli.go +++ b/cli/test/mockcli.go @@ -122,3 +122,12 @@ func (c *mockCLIClient) flagSet(cmd *lcli.Command) *flag.FlagSet { } return fs } + +func (c *mockCLIClient) runInteractiveCmd(cmd []string, interactive []string) string { + c.toStdin(strings.Join(interactive, "\n") + "\n") + return c.runCmd(cmd) +} + +func (c *mockCLIClient) toStdin(s string) { + c.cctx.App.Metadata["stdin"] = bytes.NewBufferString(s) +} diff --git a/cli/test/multisig.go b/cli/test/multisig.go index e77879346..d2c0238d2 100644 --- a/cli/test/multisig.go +++ b/cli/test/multisig.go @@ -10,19 +10,10 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/lotus/api/test" "github.com/filecoin-project/lotus/chain/types" - logging "github.com/ipfs/go-log/v2" "github.com/stretchr/testify/require" lcli "github.com/urfave/cli/v2" ) -func QuietMiningLogs() { - logging.SetLogLevel("miner", "ERROR") - logging.SetLogLevel("chainstore", "ERROR") - logging.SetLogLevel("chain", "ERROR") - logging.SetLogLevel("sub", "ERROR") - logging.SetLogLevel("storageminer", "ERROR") -} - func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) { ctx := context.Background() diff --git a/cli/test/net.go b/cli/test/net.go new file mode 100644 index 000000000..d13993d16 --- /dev/null +++ b/cli/test/net.go @@ -0,0 +1,41 @@ +package test + +import ( + "context" + "testing" + "time" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/lotus/api/test" + test2 "github.com/filecoin-project/lotus/node/test" +) + +func StartOneNodeOneMiner(ctx context.Context, t *testing.T, blocktime time.Duration) (test.TestNode, address.Address) { + n, sn := test2.RPCMockSbBuilder(t, test.OneFull, test.OneMiner) + + full := n[0] + miner := sn[0] + + // Get everyone connected + addrs, err := full.NetAddrsListen(ctx) + if err != nil { + t.Fatal(err) + } + + if err := miner.NetConnect(ctx, addrs); err != nil { + t.Fatal(err) + } + + // Start mining blocks + bm := test.NewBlockMiner(ctx, t, miner, blocktime) + bm.MineBlocks() + + // Get the full node's wallet address + fullAddr, err := full.WalletDefaultAddress(ctx) + if err != nil { + t.Fatal(err) + } + + // Create mock CLI + return full, fullAddr +} diff --git a/cli/test/util.go b/cli/test/util.go new file mode 100644 index 000000000..e3930dc83 --- /dev/null +++ b/cli/test/util.go @@ -0,0 +1,12 @@ +package test + +import "github.com/ipfs/go-log/v2" + +func QuietMiningLogs() { + _ = log.SetLogLevel("miner", "ERROR") + _ = log.SetLogLevel("chainstore", "ERROR") + _ = log.SetLogLevel("chain", "ERROR") + _ = log.SetLogLevel("sub", "ERROR") + _ = log.SetLogLevel("storageminer", "ERROR") + _ = log.SetLogLevel("pubsub", "ERROR") +} diff --git a/cmd/lotus-gateway/api.go b/cmd/lotus-gateway/api.go index 0ebb99298..875eaac7d 100644 --- a/cmd/lotus-gateway/api.go +++ b/cmd/lotus-gateway/api.go @@ -67,6 +67,7 @@ type gatewayDepsAPI interface { StateMinerAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*dline.Info, error) StateCirculatingSupply(context.Context, types.TipSetKey) (abi.TokenAmount, error) + StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (api.CirculatingSupply, error) } @@ -364,6 +365,13 @@ func (a *GatewayAPI) StateCirculatingSupply(ctx context.Context, tsk types.TipSe } +func (a *GatewayAPI) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) { + if err := a.checkTipsetKey(ctx, tsk); err != nil { + return nil, err + } + return a.api.StateVerifiedClientStatus(ctx, addr, tsk) +} + func (a *GatewayAPI) StateVMCirculatingSupplyInternal(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) { if err := a.checkTipsetKey(ctx, tsk); err != nil { return api.CirculatingSupply{}, err diff --git a/cmd/lotus-gateway/endtoend_test.go b/cmd/lotus-gateway/endtoend_test.go index c5b513f44..1e1e5e229 100644 --- a/cmd/lotus-gateway/endtoend_test.go +++ b/cmd/lotus-gateway/endtoend_test.go @@ -11,7 +11,6 @@ import ( "github.com/filecoin-project/lotus/cli" clitest "github.com/filecoin-project/lotus/cli/test" - logging "github.com/ipfs/go-log/v2" init2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/init" multisig2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/multisig" @@ -45,6 +44,7 @@ func init() { // node that is connected through a gateway to a full API node func TestWalletMsig(t *testing.T) { _ = os.Setenv("BELLMAN_NO_GPU", "1") + clitest.QuietMiningLogs() blocktime := 5 * time.Millisecond ctx := context.Background() @@ -155,80 +155,35 @@ func TestMsigCLI(t *testing.T) { blocktime := 5 * time.Millisecond ctx := context.Background() - nodes := startNodes(ctx, t, blocktime, maxLookbackCap, maxStateWaitLookbackLimit) + nodes := startNodesWithFunds(ctx, t, blocktime, maxLookbackCap, maxStateWaitLookbackLimit) defer nodes.closer() lite := nodes.lite - full := nodes.full - - // The full node starts with a wallet - fullWalletAddr, err := full.WalletDefaultAddress(ctx) - require.NoError(t, err) - - // Create a wallet on the lite node - liteWalletAddr, err := lite.WalletNew(ctx, types.KTSecp256k1) - require.NoError(t, err) - - // Send some funds from the full node to the lite node - err = sendFunds(ctx, full, fullWalletAddr, liteWalletAddr, types.NewInt(1e18)) - require.NoError(t, err) - clitest.RunMultisigTest(t, cli.Commands, lite) } -func sendFunds(ctx context.Context, fromNode test.TestNode, fromAddr address.Address, toAddr address.Address, amt types.BigInt) error { - msg := &types.Message{ - From: fromAddr, - To: toAddr, - Value: amt, - } - - sm, err := fromNode.MpoolPushMessage(ctx, msg, nil) - if err != nil { - return err - } - - res, err := fromNode.StateWaitMsg(ctx, sm.Cid(), 1) - if err != nil { - return err - } - if res.Receipt.ExitCode != 0 { - return xerrors.Errorf("send funds failed with exit code %d", res.Receipt.ExitCode) - } - - return nil -} - func TestDealFlow(t *testing.T) { _ = os.Setenv("BELLMAN_NO_GPU", "1") - - logging.SetLogLevel("miner", "ERROR") - logging.SetLogLevel("chainstore", "ERROR") - logging.SetLogLevel("chain", "ERROR") - logging.SetLogLevel("sub", "ERROR") - logging.SetLogLevel("storageminer", "ERROR") + clitest.QuietMiningLogs() blocktime := 5 * time.Millisecond ctx := context.Background() - nodes := startNodes(ctx, t, blocktime, maxLookbackCap, maxStateWaitLookbackLimit) + nodes := startNodesWithFunds(ctx, t, blocktime, maxLookbackCap, maxStateWaitLookbackLimit) defer nodes.closer() - full := nodes.full - lite := nodes.lite + test.MakeDeal(t, ctx, 6, nodes.lite, nodes.miner, false, false) +} - // The full node starts with a wallet - fullWalletAddr, err := full.WalletDefaultAddress(ctx) - require.NoError(t, err) +func TestCLIDealFlow(t *testing.T) { + _ = os.Setenv("BELLMAN_NO_GPU", "1") + clitest.QuietMiningLogs() - // Create a wallet on the lite node - liteWalletAddr, err := lite.WalletNew(ctx, types.KTSecp256k1) - require.NoError(t, err) + blocktime := 5 * time.Millisecond + ctx := context.Background() + nodes := startNodesWithFunds(ctx, t, blocktime, maxLookbackCap, maxStateWaitLookbackLimit) + defer nodes.closer() - // Send some funds from the full node to the lite node - err = sendFunds(ctx, full, fullWalletAddr, liteWalletAddr, types.NewInt(1e18)) - require.NoError(t, err) - - test.MakeDeal(t, ctx, 6, lite, nodes.miner, false, false) + clitest.RunClientTest(t, cli.Commands, nodes.lite) } type testNodes struct { @@ -238,6 +193,30 @@ type testNodes struct { closer jsonrpc.ClientCloser } +func startNodesWithFunds( + ctx context.Context, + t *testing.T, + blocktime time.Duration, + lookbackCap time.Duration, + stateWaitLookbackLimit abi.ChainEpoch, +) *testNodes { + nodes := startNodes(ctx, t, blocktime, lookbackCap, stateWaitLookbackLimit) + + // The full node starts with a wallet + fullWalletAddr, err := nodes.full.WalletDefaultAddress(ctx) + require.NoError(t, err) + + // Create a wallet on the lite node + liteWalletAddr, err := nodes.lite.WalletNew(ctx, types.KTSecp256k1) + require.NoError(t, err) + + // Send some funds from the full node to the lite node + err = sendFunds(ctx, nodes.full, fullWalletAddr, liteWalletAddr, types.NewInt(1e18)) + require.NoError(t, err) + + return nodes +} + func startNodes( ctx context.Context, t *testing.T, @@ -302,3 +281,26 @@ func startNodes( return &testNodes{lite: lite, full: full, miner: miner, closer: closer} } + +func sendFunds(ctx context.Context, fromNode test.TestNode, fromAddr address.Address, toAddr address.Address, amt types.BigInt) error { + msg := &types.Message{ + From: fromAddr, + To: toAddr, + Value: amt, + } + + sm, err := fromNode.MpoolPushMessage(ctx, msg, nil) + if err != nil { + return err + } + + res, err := fromNode.StateWaitMsg(ctx, sm.Cid(), 1) + if err != nil { + return err + } + if res.Receipt.ExitCode != 0 { + return xerrors.Errorf("send funds failed with exit code %d", res.Receipt.ExitCode) + } + + return nil +} diff --git a/node/impl/full/state.go b/node/impl/full/state.go index 75ad03e7b..d0e813758 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -52,6 +52,7 @@ type StateModuleAPI interface { StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) StateNetworkVersion(ctx context.Context, key types.TipSetKey) (network.Version, error) + StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) } @@ -1165,19 +1166,19 @@ func (a *StateAPI) StateVerifierStatus(ctx context.Context, addr address.Address // StateVerifiedClientStatus returns the data cap for the given address. // Returns zero if there is no entry in the data cap table for the // address. -func (a *StateAPI) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) { - act, err := a.StateGetActor(ctx, verifreg.Address, tsk) +func (m *StateModule) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) { + act, err := m.StateGetActor(ctx, verifreg.Address, tsk) if err != nil { return nil, err } - aid, err := a.StateLookupID(ctx, addr, tsk) + aid, err := m.StateLookupID(ctx, addr, tsk) if err != nil { log.Warnf("lookup failure %v", err) return nil, err } - vrs, err := verifreg.Load(a.StateManager.ChainStore().Store(ctx), act) + vrs, err := verifreg.Load(m.StateManager.ChainStore().Store(ctx), act) if err != nil { return nil, xerrors.Errorf("failed to load verified registry state: %w", err) } From 36816fb4f3281ad23c72a66b00b90eb73063036f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 23 Oct 2020 16:51:27 +0200 Subject: [PATCH 240/313] Fix list-asks, deals with non-genesis miners in lite-mode --- api/api_gateway.go | 7 ++++++- api/apistruct/struct.go | 10 ++++++++++ node/impl/client/client.go | 4 ++-- node/impl/full/state.go | 18 ++++++++++-------- 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/api/api_gateway.go b/api/api_gateway.go index 5f31b8d31..07fb5deb3 100644 --- a/api/api_gateway.go +++ b/api/api_gateway.go @@ -3,12 +3,15 @@ package api import ( "context" + "github.com/ipfs/go-cid" + "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/dline" "github.com/filecoin-project/go-state-types/network" + "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/types" - "github.com/ipfs/go-cid" ) type GatewayAPI interface { @@ -33,6 +36,8 @@ type GatewayAPI interface { StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (MarketBalance, error) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*MarketDeal, error) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) + StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error) + StateMinerPower(context.Context, address.Address, types.TipSetKey) (*MinerPower, error) StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*MsgLookup, error) diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 6c6c19f23..883eeda46 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -393,6 +393,8 @@ type GatewayStruct struct { StateLookupID func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) StateListMiners func(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) StateMinerInfo func(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) + StateMinerProvingDeadline func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error) + StateMinerPower func(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error) StateMarketBalance func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) StateMarketStorageDeal func(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) StateNetworkVersion func(ctx context.Context, tsk types.TipSetKey) (stnetwork.Version, error) @@ -1544,6 +1546,14 @@ func (g GatewayStruct) StateMinerInfo(ctx context.Context, actor address.Address return g.Internal.StateMinerInfo(ctx, actor, tsk) } +func (g GatewayStruct) StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error) { + return g.Internal.StateMinerProvingDeadline(ctx, addr, tsk) +} + +func (g GatewayStruct) StateMinerPower(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*api.MinerPower, error) { + return g.Internal.StateMinerPower(ctx, addr, tsk) +} + func (g GatewayStruct) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (stnetwork.Version, error) { return g.Internal.StateNetworkVersion(ctx, tsk) } diff --git a/node/impl/client/client.go b/node/impl/client/client.go index 0cd164826..37a24998e 100644 --- a/node/impl/client/client.go +++ b/node/impl/client/client.go @@ -65,9 +65,9 @@ type API struct { fx.In full.ChainAPI - full.StateAPI full.WalletAPI paych.PaychAPI + full.StateAPI SMDealClient storagemarket.StorageClient RetDiscovery discovery.PeerResolver @@ -117,7 +117,7 @@ func (a *API) ClientStartDeal(ctx context.Context, params *api.StartDealParams) } } - walletKey, err := a.StateAPI.StateManager.ResolveToKeyAddress(ctx, params.Wallet, nil) + walletKey, err := a.StateAccountKey(ctx, params.Wallet, types.EmptyTSK) if err != nil { return nil, xerrors.Errorf("failed resolving params.Wallet addr: %w", params.Wallet) } diff --git a/node/impl/full/state.go b/node/impl/full/state.go index d0e813758..882b3e93c 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -51,6 +51,8 @@ type StateModuleAPI interface { StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) + StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error) + StateMinerPower(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error) StateNetworkVersion(ctx context.Context, key types.TipSetKey) (network.Version, error) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) @@ -223,18 +225,18 @@ func (a *StateAPI) StateMinerPartitions(ctx context.Context, m address.Address, return out, err } -func (a *StateAPI) StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error) { - ts, err := a.StateManager.ChainStore().GetTipSetFromKey(tsk) +func (m *StateModule) StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error) { + ts, err := m.Chain.GetTipSetFromKey(tsk) if err != nil { return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) } - act, err := a.StateManager.LoadActor(ctx, addr, ts) + act, err := m.StateManager.LoadActor(ctx, addr, ts) if err != nil { return nil, xerrors.Errorf("failed to load miner actor: %w", err) } - mas, err := miner.Load(a.StateManager.ChainStore().Store(ctx), act) + mas, err := miner.Load(m.StateManager.ChainStore().Store(ctx), act) if err != nil { return nil, xerrors.Errorf("failed to load miner actor state: %w", err) } @@ -318,19 +320,19 @@ func (a *StateAPI) StateMinerRecoveries(ctx context.Context, addr address.Addres return miner.AllPartSectors(mas, miner.Partition.RecoveringSectors) } -func (a *StateAPI) StateMinerPower(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*api.MinerPower, error) { - ts, err := a.Chain.GetTipSetFromKey(tsk) +func (m *StateModule) StateMinerPower(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*api.MinerPower, error) { + ts, err := m.Chain.GetTipSetFromKey(tsk) if err != nil { return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) } - m, net, hmp, err := stmgr.GetPower(ctx, a.StateManager, ts, addr) + mp, net, hmp, err := stmgr.GetPower(ctx, m.StateManager, ts, addr) if err != nil { return nil, err } return &api.MinerPower{ - MinerPower: m, + MinerPower: mp, TotalPower: net, HasMinPower: hmp, }, nil From 16a911bc39085c545f0c67f26a13dc9555d8f9be Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Fri, 23 Oct 2020 19:30:42 +0200 Subject: [PATCH 241/313] Fix random test failures If block 1 was a null block then blockSet would include genesis which would lead to us trying to load parent of a genesis block. Signed-off-by: Jakub Sztandera --- chain/sync.go | 5 +++++ miner/miner.go | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/chain/sync.go b/chain/sync.go index d05a3d8bb..8da093cb6 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -1396,6 +1396,11 @@ loop: } base := blockSet[len(blockSet)-1] + if base.Equals(known) { + blockSet = blockSet[:len(blockSet)-1] + base = blockSet[len(blockSet)-1] + } + if base.IsChildOf(known) { // common case: receiving blocks that are building on top of our best tipset return blockSet, nil diff --git a/miner/miner.go b/miner/miner.go index 7de7f5b73..f2468a911 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -280,7 +280,7 @@ minerLoop: m.minedBlockHeights.Add(blkKey, true) if err := m.api.SyncSubmitBlock(ctx, b); err != nil { - log.Errorf("failed to submit newly mined block: %s", err) + log.Errorf("failed to submit newly mined block: %+v", err) } } else { base.NullRounds++ From ea69386519519b3c3b309467b96d2e6dd9bd2e76 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Fri, 23 Oct 2020 20:46:06 +0200 Subject: [PATCH 242/313] Fix flaky TestTimedBSSimple Signed-off-by: Jakub Sztandera --- lib/timedbs/timedbs.go | 14 ++++++++++---- lib/timedbs/timedbs_test.go | 23 +++++++++++++++-------- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/lib/timedbs/timedbs.go b/lib/timedbs/timedbs.go index bb03a59e9..c5c1a8fe0 100644 --- a/lib/timedbs/timedbs.go +++ b/lib/timedbs/timedbs.go @@ -8,6 +8,7 @@ import ( blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + "github.com/raulk/clock" "go.uber.org/multierr" "github.com/filecoin-project/lotus/build" @@ -24,9 +25,10 @@ import ( type TimedCacheBS struct { mu sync.RWMutex active, inactive blockstore.MemStore - - interval time.Duration - closeCh chan struct{} + clock clock.Clock + interval time.Duration + closeCh chan struct{} + doneRotatingCh chan struct{} } func NewTimedCacheBS(cacheTime time.Duration) *TimedCacheBS { @@ -34,6 +36,7 @@ func NewTimedCacheBS(cacheTime time.Duration) *TimedCacheBS { active: blockstore.NewTemporary(), inactive: blockstore.NewTemporary(), interval: cacheTime, + clock: build.Clock, } } @@ -45,12 +48,15 @@ func (t *TimedCacheBS) Start(ctx context.Context) error { } t.closeCh = make(chan struct{}) go func() { - ticker := build.Clock.Ticker(t.interval) + ticker := t.clock.Ticker(t.interval) defer ticker.Stop() for { select { case <-ticker.C: t.rotate() + if t.doneRotatingCh != nil { + t.doneRotatingCh <- struct{}{} + } case <-t.closeCh: return } diff --git a/lib/timedbs/timedbs_test.go b/lib/timedbs/timedbs_test.go index 2126b9287..db21a5d79 100644 --- a/lib/timedbs/timedbs_test.go +++ b/lib/timedbs/timedbs_test.go @@ -1,21 +1,27 @@ -package timedbs_test +package timedbs import ( "context" "testing" "time" + "github.com/raulk/clock" "github.com/stretchr/testify/require" blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - - "github.com/filecoin-project/lotus/lib/timedbs" ) func TestTimedBSSimple(t *testing.T) { - tc := timedbs.NewTimedCacheBS(10 * time.Millisecond) - _ = tc.Start(context.Background()) + tc := NewTimedCacheBS(10 * time.Millisecond) + mClock := clock.NewMock() + mClock.Set(time.Now()) + tc.clock = mClock + tc.doneRotatingCh = make(chan struct{}) + + tc.Start(context.Background()) + mClock.Add(1) // IDK why it is needed but it makes it work + defer func() { _ = tc.Stop(context.Background()) }() @@ -36,7 +42,8 @@ func TestTimedBSSimple(t *testing.T) { require.NoError(t, err) require.True(t, has) - time.Sleep(15 * time.Millisecond) + mClock.Add(10 * time.Millisecond) + <-tc.doneRotatingCh // We should still have everything. has, err = tc.Has(b1.Cid()) @@ -60,8 +67,8 @@ func TestTimedBSSimple(t *testing.T) { require.NoError(t, err) require.ElementsMatch(t, ks, []cid.Cid{b1.Cid(), b2.Cid(), b3.Cid()}) - time.Sleep(10 * time.Millisecond) - + mClock.Add(10 * time.Millisecond) + <-tc.doneRotatingCh // should still have b2, and b3, but not b1 has, err = tc.Has(b1.Cid()) From 9fbd2a50ffb9c93a56647ee59bcab2b446bc5099 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Fri, 23 Oct 2020 20:50:17 +0200 Subject: [PATCH 243/313] Fix lint Signed-off-by: Jakub Sztandera --- lib/timedbs/timedbs_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/timedbs/timedbs_test.go b/lib/timedbs/timedbs_test.go index db21a5d79..e01215bbd 100644 --- a/lib/timedbs/timedbs_test.go +++ b/lib/timedbs/timedbs_test.go @@ -19,7 +19,7 @@ func TestTimedBSSimple(t *testing.T) { tc.clock = mClock tc.doneRotatingCh = make(chan struct{}) - tc.Start(context.Background()) + _ = tc.Start(context.Background()) mClock.Add(1) // IDK why it is needed but it makes it work defer func() { From c7e6c8eacc3b7b399a535a635c69e3e5712d6ac0 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Fri, 23 Oct 2020 21:45:08 +0200 Subject: [PATCH 244/313] Fix flaky TestChainExportImportFull Signed-off-by: Jakub Sztandera --- chain/store/store_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chain/store/store_test.go b/chain/store/store_test.go index 60167ad86..160527104 100644 --- a/chain/store/store_test.go +++ b/chain/store/store_test.go @@ -126,7 +126,7 @@ func TestChainExportImportFull(t *testing.T) { } buf := new(bytes.Buffer) - if err := cg.ChainStore().Export(context.TODO(), last, 100, false, buf); err != nil { + if err := cg.ChainStore().Export(context.TODO(), last, last.Height(), false, buf); err != nil { t.Fatal(err) } From 109b326ae2733725f172604503483890b8459a57 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 23 Oct 2020 12:32:07 -0700 Subject: [PATCH 245/313] Use older randomness for the PoSt commit on specs-actors version 2 After the upgrade, we're allowed to use randomness up to the challenge epoch. This safe-guards us against very large reorgs where a miner computes a PoSt very quickly. --- storage/wdpost_run.go | 9 +++++++++ storage/wdpost_run_test.go | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/storage/wdpost_run.go b/storage/wdpost_run.go index 54d3d3dcc..fd3053a34 100644 --- a/storage/wdpost_run.go +++ b/storage/wdpost_run.go @@ -12,6 +12,7 @@ import ( "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/dline" + "github.com/filecoin-project/go-state-types/network" "github.com/ipfs/go-cid" "go.opencensus.io/trace" @@ -151,7 +152,15 @@ func (s *WindowPoStScheduler) runSubmitPoST( defer span.End() // Get randomness from tickets + // use the challenge epoch if we've upgraded to network version 4 + // (actors version 2). We want to go back as far as possible to be safe. commEpoch := deadline.Open + if ver, err := s.api.StateNetworkVersion(ctx, types.EmptyTSK); err != nil { + log.Errorw("failed to get network version to determine PoSt epoch randomness lookback", "error", err) + } else if ver >= network.Version4 { + commEpoch = deadline.Challenge + } + commRand, err := s.api.ChainGetRandomnessFromTickets(ctx, ts.Key(), crypto.DomainSeparationTag_PoStChainCommit, commEpoch, nil) if err != nil { err = xerrors.Errorf("failed to get chain randomness from tickets for windowPost (ts=%d; deadline=%d): %w", ts.Height(), commEpoch, err) diff --git a/storage/wdpost_run_test.go b/storage/wdpost_run_test.go index bac86f022..4145a6e70 100644 --- a/storage/wdpost_run_test.go +++ b/storage/wdpost_run_test.go @@ -23,6 +23,7 @@ import ( tutils "github.com/filecoin-project/specs-actors/v2/support/testing" "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/journal" @@ -47,7 +48,7 @@ func (m *mockStorageMinerAPI) StateMinerInfo(ctx context.Context, a address.Addr } func (m *mockStorageMinerAPI) StateNetworkVersion(ctx context.Context, key types.TipSetKey) (network.Version, error) { - panic("implement me") + return build.NewestNetworkVersion, nil } func (m *mockStorageMinerAPI) ChainGetRandomnessFromTickets(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) { From b7b6ab779ae5607a0a9b398b82652510b7ff0e99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 23 Oct 2020 14:54:52 +0200 Subject: [PATCH 246/313] Make wallet market withdraw usable with miner addresses --- cli/wallet.go | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/cli/wallet.go b/cli/wallet.go index f231f3454..2501618f8 100644 --- a/cli/wallet.go +++ b/cli/wallet.go @@ -495,6 +495,11 @@ var walletMarketWithdraw = &cli.Command{ Usage: "Specify address to withdraw funds from, otherwise it will use the default wallet address", Aliases: []string{"f"}, }, + &cli.StringFlag{ + Name: "address", + Usage: "Market address to withdraw from (account or miner actor address, defaults to --from address)", + Aliases: []string{"a"}, + }, }, Action: func(cctx *cli.Context) error { api, closer, err := GetFullNodeAPI(cctx) @@ -504,19 +509,27 @@ var walletMarketWithdraw = &cli.Command{ defer closer() ctx := ReqContext(cctx) - var addr address.Address + var from address.Address if cctx.String("from") != "" { - addr, err = address.NewFromString(cctx.String("from")) + from, err = address.NewFromString(cctx.String("from")) if err != nil { return xerrors.Errorf("parsing from address: %w", err) } } else { - addr, err = api.WalletDefaultAddress(ctx) + from, err = api.WalletDefaultAddress(ctx) if err != nil { return xerrors.Errorf("getting default wallet address: %w", err) } } + addr := from + if cctx.String("address") != "" { + addr, err = address.NewFromString(cctx.String("address")) + if err != nil { + return xerrors.Errorf("parsing market address: %w", err) + } + } + bal, err := api.StateMarketBalance(ctx, addr, types.EmptyTSK) if err != nil { return xerrors.Errorf("getting market balance for address %s: %w", addr.String(), err) @@ -535,7 +548,7 @@ var walletMarketWithdraw = &cli.Command{ } if amt.GreaterThan(avail) { - return xerrors.Errorf("can't withdraw more funds than available; requested: %s; available: %s", amt, avail) + return xerrors.Errorf("can't withdraw more funds than available; requested: %s; available: %s", types.FIL(amt), types.FIL(avail)) } if avail.IsZero() { @@ -550,10 +563,10 @@ var walletMarketWithdraw = &cli.Command{ return xerrors.Errorf("serializing params: %w", err) } - fmt.Printf("Submitting WithdrawBalance message for amount %s for address %s\n", types.FIL(amt), addr.String()) + fmt.Printf("Submitting WithdrawBalance message for amount %s for address %s\n", types.FIL(amt), from.String()) smsg, err := api.MpoolPushMessage(ctx, &types.Message{ To: builtin.StorageMarketActorAddr, - From: addr, + From: from, Value: types.NewInt(0), Method: builtin.MethodsMarket.WithdrawBalance, Params: params, From 067de4508bdd4776aa1efb61540a5ffbbea654bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 23 Oct 2020 21:51:10 +0200 Subject: [PATCH 247/313] shed: Commad to decode messages --- cli/chain.go | 2 +- cli/state.go | 4 +- cmd/lotus-shed/main.go | 1 + cmd/lotus-shed/msg.go | 280 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 284 insertions(+), 3 deletions(-) create mode 100644 cmd/lotus-shed/msg.go diff --git a/cli/chain.go b/cli/chain.go index b1351549f..e2d0ebb4a 100644 --- a/cli/chain.go +++ b/cli/chain.go @@ -1291,7 +1291,7 @@ var chainDecodeParamsCmd = &cli.Command{ return xerrors.Errorf("getting actor: %w", err) } - pstr, err := jsonParams(act.Code, abi.MethodNum(method), params) + pstr, err := JsonParams(act.Code, abi.MethodNum(method), params) if err != nil { return err } diff --git a/cli/state.go b/cli/state.go index d0fcc4f95..13aa5c39b 100644 --- a/cli/state.go +++ b/cli/state.go @@ -1211,7 +1211,7 @@ func ComputeStateHTMLTempl(w io.Writer, ts *types.TipSet, o *api.ComputeStateOut "GetCode": getCode, "GetMethod": getMethod, "ToFil": toFil, - "JsonParams": jsonParams, + "JsonParams": JsonParams, "JsonReturn": jsonReturn, "IsSlow": isSlow, "IsVerySlow": isVerySlow, @@ -1298,7 +1298,7 @@ func sumGas(changes []*types.GasTrace) types.GasTrace { return out } -func jsonParams(code cid.Cid, method abi.MethodNum, params []byte) (string, error) { +func JsonParams(code cid.Cid, method abi.MethodNum, params []byte) (string, error) { methodMeta, found := stmgr.MethodsMap[code][method] if !found { return "", fmt.Errorf("method %d not found on actor %s", method, code) diff --git a/cmd/lotus-shed/main.go b/cmd/lotus-shed/main.go index 488e2a6ae..8201ec111 100644 --- a/cmd/lotus-shed/main.go +++ b/cmd/lotus-shed/main.go @@ -45,6 +45,7 @@ func main() { datastoreCmd, ledgerCmd, sectorsCmd, + msgCmd, } app := &cli.App{ diff --git a/cmd/lotus-shed/msg.go b/cmd/lotus-shed/msg.go new file mode 100644 index 000000000..63cfc86b9 --- /dev/null +++ b/cmd/lotus-shed/msg.go @@ -0,0 +1,280 @@ +package main + +import ( + "bytes" + "encoding/base64" + "encoding/hex" + "encoding/json" + "fmt" + + "github.com/fatih/color" + + "github.com/ipfs/go-cid" + "github.com/urfave/cli/v2" + "golang.org/x/xerrors" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/big" + + "github.com/filecoin-project/lotus/chain/stmgr" + "github.com/filecoin-project/lotus/chain/types" + lcli "github.com/filecoin-project/lotus/cli" + "github.com/filecoin-project/specs-actors/v2/actors/builtin/multisig" +) + +var msgCmd = &cli.Command{ + Name: "msg", + Usage: "Translate message between various formats", + ArgsUsage: "Message in any form", + Action: func(cctx *cli.Context) error { + if cctx.Args().Len() != 1 { + return xerrors.Errorf("expected 1 argument") + } + + msg, err := messageFromString(cctx, cctx.Args().First()) + if err != nil { + return err + } + + switch msg := msg.(type) { + case *types.SignedMessage: + return printSignedMessage(cctx, msg) + case *types.Message: + return printMessage(cctx, msg) + default: + return xerrors.Errorf("this error message can't be printed") + } + }, +} + +func printSignedMessage(cctx *cli.Context, smsg *types.SignedMessage) error { + color.Green("Signed:") + color.Blue("CID: %s\n", smsg.Cid()) + + b, err := smsg.Serialize() + if err != nil { + return err + } + color.Magenta("HEX: %x\n", b) + color.Blue("B64: %s\n", base64.StdEncoding.EncodeToString(b)) + jm, err := json.MarshalIndent(smsg, "", " ") + if err != nil { + return xerrors.Errorf("marshaling as json: %w", err) + } + + color.Magenta("JSON: %s\n", string(jm)) + fmt.Println() + fmt.Println("---") + color.Green("Signed Message Details:") + fmt.Printf("Signature(hex): %x\n", smsg.Signature.Data) + fmt.Printf("Signature(b64): %s\n", base64.StdEncoding.EncodeToString(smsg.Signature.Data)) + + sigtype, err := smsg.Signature.Type.Name() + if err != nil { + sigtype = err.Error() + } + fmt.Printf("Signature type: %d (%s)\n", smsg.Signature.Type, sigtype) + + fmt.Println("-------") + return printMessage(cctx, &smsg.Message) +} + +func printMessage(cctx *cli.Context, msg *types.Message) error { + if msg.Version != 0x6d736967 { + color.Green("Unsigned:") + color.Yellow("CID: %s\n", msg.Cid()) + + b, err := msg.Serialize() + if err != nil { + return err + } + color.Cyan("HEX: %x\n", b) + color.Yellow("B64: %s\n", base64.StdEncoding.EncodeToString(b)) + + jm, err := json.MarshalIndent(msg, "", " ") + if err != nil { + return xerrors.Errorf("marshaling as json: %w", err) + } + + color.Cyan("JSON: %s\n", string(jm)) + fmt.Println() + } else { + color.Green("Msig Propose:") + pp := &multisig.ProposeParams{ + To: msg.To, + Value: msg.Value, + Method: msg.Method, + Params: msg.Params, + } + var b bytes.Buffer + if err := pp.MarshalCBOR(&b); err != nil { + return err + } + + color.Cyan("HEX: %x\n", b.Bytes()) + color.Yellow("B64: %s\n", base64.StdEncoding.EncodeToString(b.Bytes())) + jm, err := json.MarshalIndent(pp, "", " ") + if err != nil { + return xerrors.Errorf("marshaling as json: %w", err) + } + + color.Cyan("JSON: %s\n", string(jm)) + fmt.Println() + } + + fmt.Println("---") + color.Green("Message Details:") + fmt.Println("Value:", types.FIL(msg.Value)) + fmt.Println("Max Fees:", types.FIL(msg.RequiredFunds())) + fmt.Println("Max Total Cost:", types.FIL(big.Add(msg.RequiredFunds(), msg.Value))) + + api, closer, err := lcli.GetFullNodeAPI(cctx) + if err != nil { + return err + } + + defer closer() + ctx := lcli.ReqContext(cctx) + + toact, err := api.StateGetActor(ctx, msg.To, types.EmptyTSK) + if err != nil { + return nil + } + + fmt.Println("Method:", stmgr.MethodsMap[toact.Code][msg.Method].Name) + p, err := lcli.JsonParams(toact.Code, msg.Method, msg.Params) + if err != nil { + return err + } + + fmt.Println("Params:", p) + + return nil +} + +func messageFromString(cctx *cli.Context, smsg string) (types.ChainMsg, error) { + // a CID is least likely to just decode + if c, err := cid.Parse(smsg); err == nil { + return messageFromCID(cctx, c) + } + + // try baseX serializations next + { + // hex first, some hay strings may be decodable as b64 + if b, err := hex.DecodeString(smsg); err == nil { + return messageFromBytes(cctx, b) + } + + // b64 next + if b, err := base64.StdEncoding.DecodeString(smsg); err == nil { + return messageFromBytes(cctx, b) + } + + // b64u?? + if b, err := base64.URLEncoding.DecodeString(smsg); err == nil { + return messageFromBytes(cctx, b) + } + } + + // maybe it's json? + if _, err := messageFromJson(cctx, []byte(smsg)); err == nil { + return nil, err + } + + // declare defeat + return nil, xerrors.Errorf("couldn't decode the message") +} + +func messageFromJson(cctx *cli.Context, msgb []byte) (types.ChainMsg, error) { + // Unsigned + { + var msg types.Message + if err := json.Unmarshal(msgb, &msg); err == nil { + if msg.To != address.Undef { + return &msg, nil + } + } + } + + // Signed + { + var msg types.SignedMessage + if err := json.Unmarshal(msgb, &msg); err == nil { + if msg.Message.To != address.Undef { + return &msg, nil + } + } + } + + return nil, xerrors.New("probably not a json-serialized message") +} + +func messageFromBytes(cctx *cli.Context, msgb []byte) (types.ChainMsg, error) { + // Signed + { + var msg types.SignedMessage + if err := msg.UnmarshalCBOR(bytes.NewReader(msgb)); err == nil { + return &msg, nil + } + } + + // Unsigned + { + var msg types.Message + if err := msg.UnmarshalCBOR(bytes.NewReader(msgb)); err == nil { + return &msg, nil + } + } + + // Multisig propose? + { + var pp multisig.ProposeParams + if err := pp.UnmarshalCBOR(bytes.NewReader(msgb)); err == nil { + i, err := address.NewIDAddress(0) + if err != nil { + return nil, err + } + + return &types.Message{ + // Hack(-ish) + Version: 0x6d736967, + From: i, + + To: pp.To, + Value: pp.Value, + + Method: pp.Method, + Params: pp.Params, + + GasFeeCap: big.Zero(), + GasPremium: big.Zero(), + }, nil + } + } + + // Encoded json??? + { + if msg, err := messageFromJson(cctx, msgb); err == nil { + return msg, nil + } + } + + return nil, xerrors.New("probably not a cbor-serialized message") +} + +func messageFromCID(cctx *cli.Context, c cid.Cid) (types.ChainMsg, error) { + api, closer, err := lcli.GetFullNodeAPI(cctx) + if err != nil { + return nil, err + } + + defer closer() + ctx := lcli.ReqContext(cctx) + + msgb, err := api.ChainReadObj(ctx, c) + if err != nil { + return nil, err + } + + return messageFromBytes(cctx, msgb) +} From de2cbfa8a9bbd13a7c39c994c2b0e4244bbc736d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 22 Oct 2020 13:59:08 +0200 Subject: [PATCH 248/313] client deal: Cache CommD when creating multiple deals --- api/api_full.go | 8 +++ api/apistruct/struct.go | 6 ++ cli/client.go | 7 +- documentation/en/api-methods.md | 27 ++++++++ node/impl/client/client.go | 119 ++++++++++++++++++++++++++++++++ node/impl/client/client_test.go | 88 +++++++++++++++++++++++ 6 files changed, 253 insertions(+), 2 deletions(-) create mode 100644 node/impl/client/client_test.go diff --git a/api/api_full.go b/api/api_full.go index 57ca5bcfd..f2e7ecf6b 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -290,6 +290,8 @@ type FullNode interface { ClientRetrieveWithEvents(ctx context.Context, order RetrievalOrder, ref *FileRef) (<-chan marketevents.RetrievalEvent, error) // ClientQueryAsk returns a signed StorageAsk from the specified miner. ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.StorageAsk, error) + // ClientCalcCommP calculates the CommP and data size of the specified CID + ClientDealPieceCID(ctx context.Context, root cid.Cid) (DataCIDSize, error) // ClientCalcCommP calculates the CommP for a specified file ClientCalcCommP(ctx context.Context, inpath string) (*CommPRet, error) // ClientGenCar generates a CAR file for the specified file. @@ -876,6 +878,12 @@ type DataSize struct { PieceSize abi.PaddedPieceSize } +type DataCIDSize struct { + PayloadSize int64 + PieceSize abi.PaddedPieceSize + PieceCID cid.Cid +} + type CommPRet struct { Root cid.Cid Size abi.UnpaddedPieceSize diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index e302aa8dc..36c7124d1 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -161,6 +161,7 @@ type FullNodeStruct struct { ClientRetrieve func(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) error `perm:"admin"` ClientRetrieveWithEvents func(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) (<-chan marketevents.RetrievalEvent, error) `perm:"admin"` ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.StorageAsk, error) `perm:"read"` + ClientDealPieceCID func(ctx context.Context, root cid.Cid) (api.DataCIDSize, error) `perm:"read"` ClientCalcCommP func(ctx context.Context, inpath string) (*api.CommPRet, error) `perm:"read"` ClientGenCar func(ctx context.Context, ref api.FileRef, outpath string) error `perm:"write"` ClientDealSize func(ctx context.Context, root cid.Cid) (api.DataSize, error) `perm:"read"` @@ -535,6 +536,11 @@ func (c *FullNodeStruct) ClientRetrieveWithEvents(ctx context.Context, order api func (c *FullNodeStruct) ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.StorageAsk, error) { return c.Internal.ClientQueryAsk(ctx, p, miner) } + +func (c *FullNodeStruct) ClientDealPieceCID(ctx context.Context, root cid.Cid) (api.DataCIDSize, error) { + return c.Internal.ClientDealPieceCID(ctx, root) +} + func (c *FullNodeStruct) ClientCalcCommP(ctx context.Context, inpath string) (*api.CommPRet, error) { return c.Internal.ClientCalcCommP(ctx, inpath) } diff --git a/cli/client.go b/cli/client.go index 01de8801c..4df17dce3 100644 --- a/cli/client.go +++ b/cli/client.go @@ -489,7 +489,7 @@ func interactiveDeal(cctx *cli.Context) error { var dur time.Duration var epochs abi.ChainEpoch var verified bool - var ds lapi.DataSize + var ds lapi.DataCIDSize // find var candidateAsks []*storagemarket.StorageAsk @@ -553,7 +553,7 @@ uiLoop: } color.Blue(".. calculating data size\n") - ds, err = api.ClientDealSize(ctx, data) + ds, err = api.ClientDealPieceCID(ctx, data) if err != nil { return err } @@ -843,6 +843,9 @@ uiLoop: Data: &storagemarket.DataRef{ TransferType: storagemarket.TTGraphsync, Root: data, + + PieceCid: &ds.PieceCID, + PieceSize: ds.PieceSize.Unpadded(), }, Wallet: a, Miner: maddr, diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index 3aeb6c096..cb51792c1 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -33,6 +33,7 @@ * [Client](#Client) * [ClientCalcCommP](#ClientCalcCommP) * [ClientDataTransferUpdates](#ClientDataTransferUpdates) + * [ClientDealPieceCID](#ClientDealPieceCID) * [ClientDealSize](#ClientDealSize) * [ClientFindData](#ClientFindData) * [ClientGenCar](#ClientGenCar) @@ -868,6 +869,32 @@ Response: } ``` +### ClientDealPieceCID +ClientCalcCommP calculates the CommP and data size of the specified CID + + +Perms: read + +Inputs: +```json +[ + { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + } +] +``` + +Response: +```json +{ + "PayloadSize": 9, + "PieceSize": 1032, + "PieceCID": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + } +} +``` + ### ClientDealSize ClientDealSize calculates real deal data size diff --git a/node/impl/client/client.go b/node/impl/client/client.go index f04d310ce..63158e581 100644 --- a/node/impl/client/client.go +++ b/node/impl/client/client.go @@ -1,9 +1,12 @@ package client import ( + "bufio" + "bytes" "context" "fmt" "io" + "math/bits" "os" "github.com/filecoin-project/go-state-types/dline" @@ -31,6 +34,7 @@ import ( mh "github.com/multiformats/go-multihash" "go.uber.org/fx" + ffi "github.com/filecoin-project/filecoin-ffi" "github.com/filecoin-project/go-address" datatransfer "github.com/filecoin-project/go-data-transfer" "github.com/filecoin-project/go-fil-markets/discovery" @@ -44,6 +48,7 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" + "github.com/filecoin-project/lotus/extern/sector-storage/zerocomm" marketevents "github.com/filecoin-project/lotus/markets/loggers" "github.com/filecoin-project/lotus/api" @@ -709,6 +714,120 @@ func (a *API) ClientDealSize(ctx context.Context, root cid.Cid) (api.DataSize, e }, nil } +const commPBufPad = abi.PaddedPieceSize(8 << 20) +const commPBuf = abi.UnpaddedPieceSize(commPBufPad - (commPBufPad / 128)) // can't use .Unpadded() for const + +type commPWriter struct { + len int64 + buf [commPBuf]byte + leaves []cid.Cid +} + +func (w *commPWriter) Write(p []byte) (int, error) { + n := len(p) + for len(p) > 0 { + buffered := int(w.len % int64(len(w.buf))) + toBuffer := len(w.buf) - buffered + if toBuffer > len(p) { + toBuffer = len(p) + } + + copied := copy(w.buf[buffered:], p[:toBuffer]) + p = p[copied:] + w.len += int64(copied) + + if copied > 0 && w.len%int64(len(w.buf)) == 0 { + leaf, err := ffiwrapper.GeneratePieceCIDFromFile(abi.RegisteredSealProof_StackedDrg32GiBV1, bytes.NewReader(w.buf[:]), commPBuf) + if err != nil { + return 0, err + } + w.leaves = append(w.leaves, leaf) + } + } + return n, nil +} + +func (w *commPWriter) Sum() (api.DataCIDSize, error) { + // process last non-zero leaf if exists + lastLen := w.len % int64(len(w.buf)) + rawLen := w.len + + // process remaining bit of data + if lastLen != 0 { + if len(w.leaves) != 0 { + copy(w.buf[lastLen:], make([]byte, int(int64(commPBuf)-lastLen))) + lastLen = int64(commPBuf) + } + + r, sz := padreader.New(bytes.NewReader(w.buf[:lastLen]), uint64(lastLen)) + p, err := ffiwrapper.GeneratePieceCIDFromFile(abi.RegisteredSealProof_StackedDrg32GiBV1, r, sz) + if err != nil { + return api.DataCIDSize{}, err + } + + if sz < commPBuf { // special case for pieces smaller than 16MiB + return api.DataCIDSize{ + PayloadSize: w.len, + PieceSize: sz.Padded(), + PieceCID: p, + }, nil + } + + w.leaves = append(w.leaves, p) + } + + // pad with zero pieces to power-of-two size + fillerLeaves := (1 << (bits.Len(uint(len(w.leaves) - 1)))) - len(w.leaves) + for i := 0; i < fillerLeaves; i++ { + w.leaves = append(w.leaves, zerocomm.ZeroPieceCommitment(commPBuf)) + } + + if len(w.leaves) == 1 { + return api.DataCIDSize{ + PayloadSize: rawLen, + PieceSize: abi.PaddedPieceSize(len(w.leaves)) * commPBufPad, + PieceCID: w.leaves[0], + }, nil + } + + pieces := make([]abi.PieceInfo, len(w.leaves)) + for i, leaf := range w.leaves { + pieces[i] = abi.PieceInfo{ + Size: commPBufPad, + PieceCID: leaf, + } + } + + p, err := ffi.GenerateUnsealedCID(abi.RegisteredSealProof_StackedDrg32GiBV1, pieces) + if err != nil { + return api.DataCIDSize{}, xerrors.Errorf("generating unsealed CID: %w", err) + } + + return api.DataCIDSize{ + PayloadSize: rawLen, + PieceSize: abi.PaddedPieceSize(len(w.leaves)) * commPBufPad, + PieceCID: p, + }, nil +} + +func (a *API) ClientDealPieceCID(ctx context.Context, root cid.Cid) (api.DataCIDSize, error) { + dag := merkledag.NewDAGService(blockservice.New(a.CombinedBstore, offline.Exchange(a.CombinedBstore))) + + w := &commPWriter{} + bw := bufio.NewWriterSize(w, int(commPBuf)) + + err := car.WriteCar(ctx, dag, []cid.Cid{root}, w) + if err != nil { + return api.DataCIDSize{}, err + } + + if err := bw.Flush(); err != nil { + return api.DataCIDSize{}, err + } + + return w.Sum() +} + func (a *API) ClientGenCar(ctx context.Context, ref api.FileRef, outputPath string) error { id, st, err := a.imgr().NewStore() if err != nil { diff --git a/node/impl/client/client_test.go b/node/impl/client/client_test.go new file mode 100644 index 000000000..00e7b828c --- /dev/null +++ b/node/impl/client/client_test.go @@ -0,0 +1,88 @@ +package client + +import ( + "bytes" + "crypto/rand" + "fmt" + "io" + "io/ioutil" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/filecoin-project/go-padreader" + "github.com/filecoin-project/go-state-types/abi" + + "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" + "github.com/filecoin-project/lotus/extern/sector-storage/zerocomm" +) + +func TestClientDealPieceCIDZero(t *testing.T) { + for i, s := range []struct { + writes []int + expect abi.PaddedPieceSize + }{ + {writes: []int{200}, expect: 256}, + {writes: []int{200, 200}, expect: 512}, + + {writes: []int{int(commPBuf)}, expect: commPBufPad}, + {writes: []int{int(commPBuf) * 2}, expect: 2 * commPBufPad}, + {writes: []int{int(commPBuf), int(commPBuf), int(commPBuf)}, expect: 4 * commPBufPad}, + {writes: []int{int(commPBuf), int(commPBuf), int(commPBuf), int(commPBuf), int(commPBuf), int(commPBuf), int(commPBuf), int(commPBuf), int(commPBuf)}, expect: 16 * commPBufPad}, + + {writes: []int{200, int(commPBuf)}, expect: 2 * commPBufPad}, + } { + s := s + t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { + w := &commPWriter{} + var rawSum int64 + for _, write := range s.writes { + rawSum += int64(write) + _, err := w.Write(make([]byte, write)) + require.NoError(t, err) + } + + p, err := w.Sum() + require.NoError(t, err) + require.Equal(t, rawSum, p.PayloadSize) + require.Equal(t, s.expect, p.PieceSize) + require.Equal(t, zerocomm.ZeroPieceCommitment(s.expect.Unpadded()).String(), p.PieceCID.String()) + }) + } +} + +func TestClientDealPieceCIDData(t *testing.T) { + dataLen := float64(commPBuf) * 6.78 + data, _ := ioutil.ReadAll(io.LimitReader(rand.Reader, int64(dataLen))) + + pr, sz := padreader.New(bytes.NewReader(data), uint64(dataLen)) + exp, err := ffiwrapper.GeneratePieceCIDFromFile(abi.RegisteredSealProof_StackedDrg32GiBV1, pr, sz) + require.NoError(t, err) + + w := &commPWriter{} + _, err = io.Copy(w, bytes.NewReader(data)) + require.NoError(t, err) + + res, err := w.Sum() + require.NoError(t, err) + + require.Equal(t, exp.String(), res.PieceCID.String()) +} + +func BenchmarkClientDealPieceCIDZero(b *testing.B) { + buf := make([]byte, int(commPBuf)*b.N) + b.SetBytes(int64(commPBuf)) + b.ResetTimer() + + w := &commPWriter{} + + _, err := w.Write(buf) + require.NoError(b, err) + o, err := w.Sum() + + b.StopTimer() + + require.NoError(b, err) + require.Equal(b, zerocomm.ZeroPieceCommitment(o.PieceSize.Unpadded()).String(), o.PieceCID.String()) + require.Equal(b, int64(commPBuf)*int64(b.N), o.PayloadSize) +} From 4d874730538ae7b4845976b7a4c415bd58739942 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 23 Oct 2020 23:31:18 +0200 Subject: [PATCH 249/313] Fix lint --- storage/wdpost_run_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/storage/wdpost_run_test.go b/storage/wdpost_run_test.go index b987b604c..3a0a36ad7 100644 --- a/storage/wdpost_run_test.go +++ b/storage/wdpost_run_test.go @@ -22,7 +22,6 @@ import ( tutils "github.com/filecoin-project/specs-actors/v2/support/testing" "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/journal" From f05b03f02c86affd736421ec0d8232bca9906906 Mon Sep 17 00:00:00 2001 From: jennijuju Date: Thu, 22 Oct 2020 03:58:21 -0400 Subject: [PATCH 250/313] Updated msig inspect: - Show account address of signer if the id address is corresponding to an account address. - When a message receiver is a new account, do not lookup method name. --- cli/multisig.go | 53 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/cli/multisig.go b/cli/multisig.go index 7cf7ed750..31cd961b1 100644 --- a/cli/multisig.go +++ b/cli/multisig.go @@ -266,8 +266,19 @@ var msigInspectCmd = &cli.Command{ } fmt.Fprintf(cctx.App.Writer, "Threshold: %d / %d\n", threshold, len(signers)) fmt.Fprintln(cctx.App.Writer, "Signers:") + + signerTable := tabwriter.NewWriter(cctx.App.Writer, 8, 4, 2, ' ', 0) + fmt.Fprintf(signerTable, "ID\tAddress\n") for _, s := range signers { - fmt.Fprintf(cctx.App.Writer, "\t%s\n", s) + signerActor, err := api.StateAccountKey(ctx, s, types.EmptyTSK) + if err != nil { + fmt.Fprintf(signerTable, "%s\t%s\n", s, "N/A") + } else { + fmt.Fprintf(signerTable, "%s\t%s\n", s, signerActor) + } + } + if err := signerTable.Flush(); err != nil { + return xerrors.Errorf("flushing output: %+v", err) } pending := make(map[int64]multisig.Transaction) @@ -298,27 +309,33 @@ var msigInspectCmd = &cli.Command{ target += " (self)" } targAct, err := api.StateGetActor(ctx, tx.To, types.EmptyTSK) - if err != nil { - return xerrors.Errorf("failed to resolve 'To' address of multisig transaction %d: %w", txid, err) - } - method := stmgr.MethodsMap[targAct.Code][tx.Method] - paramStr := fmt.Sprintf("%x", tx.Params) - if decParams && tx.Method != 0 { - ptyp := reflect.New(method.Params.Elem()).Interface().(cbg.CBORUnmarshaler) - if err := ptyp.UnmarshalCBOR(bytes.NewReader(tx.Params)); err != nil { - return xerrors.Errorf("failed to decode parameters of transaction %d: %w", txid, err) + + if err != nil { + if tx.Method == 0 { + fmt.Fprintf(w, "%d\t%s\t%d\t%s\t%s\t%s(%d)\t%s\n", txid, "pending", len(tx.Approved), target, types.FIL(tx.Value), "Send", tx.Method, paramStr) + } else { + fmt.Fprintf(w, "%d\t%s\t%d\t%s\t%s\t%s(%d)\t%s\n", txid, "pending", len(tx.Approved), target, types.FIL(tx.Value), "new account, unknown method", tx.Method, paramStr) + } + } else { + method := stmgr.MethodsMap[targAct.Code][tx.Method] + + if decParams && tx.Method != 0 { + ptyp := reflect.New(method.Params.Elem()).Interface().(cbg.CBORUnmarshaler) + if err := ptyp.UnmarshalCBOR(bytes.NewReader(tx.Params)); err != nil { + return xerrors.Errorf("failed to decode parameters of transaction %d: %w", txid, err) + } + + b, err := json.Marshal(ptyp) + if err != nil { + return xerrors.Errorf("could not json marshal parameter type: %w", err) + } + + paramStr = string(b) } - b, err := json.Marshal(ptyp) - if err != nil { - return xerrors.Errorf("could not json marshal parameter type: %w", err) - } - - paramStr = string(b) + fmt.Fprintf(w, "%d\t%s\t%d\t%s\t%s\t%s(%d)\t%s\n", txid, "pending", len(tx.Approved), target, types.FIL(tx.Value), method.Name, tx.Method, paramStr) } - - fmt.Fprintf(w, "%d\t%s\t%d\t%s\t%s\t%s(%d)\t%s\n", txid, "pending", len(tx.Approved), target, types.FIL(tx.Value), method.Name, tx.Method, paramStr) } if err := w.Flush(); err != nil { return xerrors.Errorf("flushing output: %+v", err) From b98b2d4310d8b9e4403b4068a0573c66665aadc4 Mon Sep 17 00:00:00 2001 From: hannahhoward Date: Fri, 23 Oct 2020 18:35:01 -0700 Subject: [PATCH 251/313] docs(docsgen): update api docs --- documentation/en/api-methods.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index c82440375..df06a6024 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -32,6 +32,7 @@ * [ChainTipSetWeight](#ChainTipSetWeight) * [Client](#Client) * [ClientCalcCommP](#ClientCalcCommP) + * [ClientCancelDataTransfer](#ClientCancelDataTransfer) * [ClientDataTransferUpdates](#ClientDataTransferUpdates) * [ClientDealSize](#ClientDealSize) * [ClientFindData](#ClientFindData) @@ -848,6 +849,23 @@ Response: } ``` +### ClientCancelDataTransfer +ClientCancelDataTransfer cancels a data transfer with the given transfer ID and other peer + + +Perms: write + +Inputs: +```json +[ + 3, + "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf", + true +] +``` + +Response: `{}` + ### ClientDataTransferUpdates There are not yet any comments for this method. From 8bb69f1e9cfe070d1334eb04ce99db713105d994 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 23 Oct 2020 14:52:26 -0700 Subject: [PATCH 252/313] Use pre-computed parent state root for lookback info There's no need to call TipSetState and recompute it. --- chain/gen/mining.go | 7 +------ chain/stmgr/utils.go | 37 ++++++++++++++++++++++++------------- chain/sub/incoming.go | 2 +- chain/sync.go | 7 +------ 4 files changed, 27 insertions(+), 26 deletions(-) diff --git a/chain/gen/mining.go b/chain/gen/mining.go index 5fc56e8b2..cca4b6169 100644 --- a/chain/gen/mining.go +++ b/chain/gen/mining.go @@ -27,16 +27,11 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w api.WalletA return nil, xerrors.Errorf("failed to load tipset state: %w", err) } - lbts, err := stmgr.GetLookbackTipSetForRound(ctx, sm, pts, bt.Epoch) + _, lbst, err := stmgr.GetLookbackTipSetForRound(ctx, sm, pts, bt.Epoch) if err != nil { return nil, xerrors.Errorf("getting lookback miner actor state: %w", err) } - lbst, _, err := sm.TipSetState(ctx, lbts) - if err != nil { - return nil, err - } - worker, err := stmgr.GetMinerWorkerRaw(ctx, sm, lbst, bt.Miner) if err != nil { return nil, xerrors.Errorf("failed to get miner worker: %w", err) diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index 54f75c138..486805786 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -391,7 +391,7 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch, return root, trace, nil } -func GetLookbackTipSetForRound(ctx context.Context, sm *StateManager, ts *types.TipSet, round abi.ChainEpoch) (*types.TipSet, error) { +func GetLookbackTipSetForRound(ctx context.Context, sm *StateManager, ts *types.TipSet, round abi.ChainEpoch) (*types.TipSet, cid.Cid, error) { var lbr abi.ChainEpoch lb := policy.GetWinningPoStSectorSetLookback(sm.GetNtwkVersion(ctx, round)) if round > lb { @@ -399,16 +399,33 @@ func GetLookbackTipSetForRound(ctx context.Context, sm *StateManager, ts *types. } // more null blocks than our lookback - if lbr > ts.Height() { - return ts, nil + if lbr >= ts.Height() { + // This should never happen at this point, but may happen before + // network version 3 (where the lookback was only 10 blocks). + st, _, err := sm.TipSetState(ctx, ts) + if err != nil { + return nil, cid.Undef, err + } + return ts, st, nil } - lbts, err := sm.ChainStore().GetTipsetByHeight(ctx, lbr, ts, true) + // Get the tipset after the lookback tipset, or the next non-null one. + nextTs, err := sm.ChainStore().GetTipsetByHeight(ctx, lbr+1, ts, false) if err != nil { - return nil, xerrors.Errorf("failed to get lookback tipset: %w", err) + return nil, cid.Undef, xerrors.Errorf("failed to get lookback tipset+1: %w", err) } - return lbts, nil + if lbr > nextTs.Height() { + return nil, cid.Undef, xerrors.Errorf("failed to find non-null tipset %s (%d) which is known to exist, found %s (%d)", ts.Key(), ts.Height(), nextTs.Key(), nextTs.Height()) + + } + + lbts, err := sm.ChainStore().GetTipSetFromKey(nextTs.Parents()) + if err != nil { + return nil, cid.Undef, xerrors.Errorf("failed to resolve lookback tipset: %w", err) + } + + return lbts, nextTs.ParentState(), nil } func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcs beacon.Schedule, tsk types.TipSetKey, round abi.ChainEpoch, maddr address.Address, pv ffiwrapper.Verifier) (*api.MiningBaseInfo, error) { @@ -436,17 +453,11 @@ func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcs beacon.Schedule rbase = entries[len(entries)-1] } - lbts, err := GetLookbackTipSetForRound(ctx, sm, ts, round) + lbts, lbst, err := GetLookbackTipSetForRound(ctx, sm, ts, round) if err != nil { return nil, xerrors.Errorf("getting lookback miner actor state: %w", err) } - // TODO: load the state instead of computing it? - lbst, _, err := sm.TipSetState(ctx, lbts) - if err != nil { - return nil, err - } - act, err := sm.LoadActorRaw(ctx, maddr, lbst) if xerrors.Is(err, types.ErrActorNotFound) { _, err := sm.LoadActor(ctx, maddr, ts) diff --git a/chain/sub/incoming.go b/chain/sub/incoming.go index 625c8d1e2..be103876d 100644 --- a/chain/sub/incoming.go +++ b/chain/sub/incoming.go @@ -484,7 +484,7 @@ func (bv *BlockValidator) checkPowerAndGetWorkerKey(ctx context.Context, bh *typ // we check that the miner met the minimum power at the lookback tipset baseTs := bv.chain.GetHeaviestTipSet() - lbts, err := stmgr.GetLookbackTipSetForRound(ctx, bv.stmgr, baseTs, bh.Height) + lbts, _, err := stmgr.GetLookbackTipSetForRound(ctx, bv.stmgr, baseTs, bh.Height) if err != nil { log.Warnf("failed to load lookback tipset for incoming block: %s", err) return address.Undef, ErrSoftFailure diff --git a/chain/sync.go b/chain/sync.go index 8da093cb6..1410dd2a7 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -730,16 +730,11 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock, use return xerrors.Errorf("load parent tipset failed (%s): %w", h.Parents, err) } - lbts, err := stmgr.GetLookbackTipSetForRound(ctx, syncer.sm, baseTs, h.Height) + lbts, lbst, err := stmgr.GetLookbackTipSetForRound(ctx, syncer.sm, baseTs, h.Height) if err != nil { return xerrors.Errorf("failed to get lookback tipset for block: %w", err) } - lbst, _, err := syncer.sm.TipSetState(ctx, lbts) - if err != nil { - return xerrors.Errorf("failed to compute lookback tipset state (epoch %d): %w", lbts.Height(), err) - } - prevBeacon, err := syncer.store.GetLatestBeaconEntry(baseTs) if err != nil { return xerrors.Errorf("failed to get latest beacon entry: %w", err) From 06af2fb52be05a20351d4a1e22edf6a2ba214d73 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 23 Oct 2020 14:57:21 -0700 Subject: [PATCH 253/313] Remove the worker key cache and use the correct worker key We need to use the worker key from the lookback tipset state. We can't reasonably maintain this cache, unfortunately (unless we kept some form of "per-height" cache). --- chain/sub/incoming.go | 65 ++++++++----------------------------------- 1 file changed, 11 insertions(+), 54 deletions(-) diff --git a/chain/sub/incoming.go b/chain/sub/incoming.go index be103876d..1701866eb 100644 --- a/chain/sub/incoming.go +++ b/chain/sub/incoming.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "sync" "time" "golang.org/x/xerrors" @@ -27,14 +26,11 @@ import ( "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain" - "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/messagepool" - "github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/lib/blockstore" - "github.com/filecoin-project/lotus/lib/bufbstore" "github.com/filecoin-project/lotus/lib/sigs" "github.com/filecoin-project/lotus/metrics" "github.com/filecoin-project/lotus/node/impl/client" @@ -227,9 +223,6 @@ type BlockValidator struct { // necessary for block validation chain *store.ChainStore stmgr *stmgr.StateManager - - mx sync.Mutex - keycache map[string]address.Address } func NewBlockValidator(self peer.ID, chain *store.ChainStore, stmgr *stmgr.StateManager, blacklist func(peer.ID)) *BlockValidator { @@ -242,7 +235,6 @@ func NewBlockValidator(self peer.ID, chain *store.ChainStore, stmgr *stmgr.State recvBlocks: newBlockReceiptCache(), chain: chain, stmgr: stmgr, - keycache: make(map[string]address.Address), } } @@ -436,60 +428,25 @@ func (bv *BlockValidator) validateMsgMeta(ctx context.Context, msg *types.BlockM } func (bv *BlockValidator) checkPowerAndGetWorkerKey(ctx context.Context, bh *types.BlockHeader) (address.Address, error) { - addr := bh.Miner - - bv.mx.Lock() - key, ok := bv.keycache[addr.String()] - bv.mx.Unlock() - if !ok { - // TODO I have a feeling all this can be simplified by cleverer DI to use the API - ts := bv.chain.GetHeaviestTipSet() - st, _, err := bv.stmgr.TipSetState(ctx, ts) - if err != nil { - return address.Undef, err - } - - buf := bufbstore.NewBufferedBstore(bv.chain.Blockstore()) - cst := cbor.NewCborStore(buf) - state, err := state.LoadStateTree(cst, st) - if err != nil { - return address.Undef, err - } - act, err := state.GetActor(addr) - if err != nil { - return address.Undef, err - } - - mst, err := miner.Load(bv.chain.Store(ctx), act) - if err != nil { - return address.Undef, err - } - - info, err := mst.Info() - if err != nil { - return address.Undef, err - } - - worker := info.Worker - key, err = bv.stmgr.ResolveToKeyAddress(ctx, worker, ts) - if err != nil { - return address.Undef, err - } - - bv.mx.Lock() - bv.keycache[addr.String()] = key - bv.mx.Unlock() - } - // we check that the miner met the minimum power at the lookback tipset baseTs := bv.chain.GetHeaviestTipSet() - lbts, _, err := stmgr.GetLookbackTipSetForRound(ctx, bv.stmgr, baseTs, bh.Height) + lbts, lbst, err := stmgr.GetLookbackTipSetForRound(ctx, bv.stmgr, baseTs, bh.Height) if err != nil { log.Warnf("failed to load lookback tipset for incoming block: %s", err) return address.Undef, ErrSoftFailure } + key, err := stmgr.GetMinerWorkerRaw(ctx, bv.stmgr, lbst, bh.Miner) + if err != nil { + log.Warnf("failed to resolve worker key for miner %s: %s", bh.Miner, err) + return address.Undef, ErrSoftFailure + } + + // NOTE: we check to see if the miner was eligible in the lookback + // tipset - 1 for historical reasons. DO NOT use the lookback state + // returned by GetLookbackTipSetForRound. + eligible, err := stmgr.MinerEligibleToMine(ctx, bv.stmgr, bh.Miner, baseTs, lbts) if err != nil { log.Warnf("failed to determine if incoming block's miner has minimum power: %s", err) From 8b8d81e767064c1eb46d8e49a75d56655804479a Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Sat, 24 Oct 2020 00:16:45 -0400 Subject: [PATCH 254/313] Lotus version 1.1.1 --- CHANGELOG.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ build/version.go | 2 +- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c21ffb685..070d2414c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,50 @@ # Lotus changelog +# 1.1.1 / 2020-10-24 + +This is a patch release of Lotus that addresses some issues caused by when miners change their worker keys. Miners and node operators should update to this release as soon as possible, especially any miner who has changed their worker key recently. + +## Changes + +- Miner finder for interactive client deal CLI (https://github.com/filecoin-project/lotus/pull/4504) +- Disable blockstore bloom filter (https://github.com/filecoin-project/lotus/pull/4512) +- Add api for getting status given a code (https://github.com/filecoin-project/lotus/pull/4210) +- add batch api for push messages (https://github.com/filecoin-project/lotus/pull/4236) +- add measure datastore wrapper around bench chain datastore (https://github.com/filecoin-project/lotus/pull/4302) +- Look at block base fee for PCR (https://github.com/filecoin-project/lotus/pull/4313) +- Add a shed util to determine % of power that has won a block (https://github.com/filecoin-project/lotus/pull/4318) +- Shed/borked cmd (https://github.com/filecoin-project/lotus/pull/4339) +- optimize mining code (https://github.com/filecoin-project/lotus/pull/4379) +- heaviestTipSet reurning nil is a ok (https://github.com/filecoin-project/lotus/pull/4523) +- Remove most v0 actor imports (https://github.com/filecoin-project/lotus/pull/4383) +- Small chain export optimization (https://github.com/filecoin-project/lotus/pull/4536) +- Add block list to pcr (https://github.com/filecoin-project/lotus/pull/4314) +- Fix circ supply default in conformance (https://github.com/filecoin-project/lotus/pull/4449) +- miner: fix init --create-worker-key (https://github.com/filecoin-project/lotus/pull/4475) +- make push and addLocal atomic (https://github.com/filecoin-project/lotus/pull/4500) +- add some methods that oni needs (https://github.com/filecoin-project/lotus/pull/4501) +- MinerGetBaseInfo: if miner is not found in lookback, check current (https://github.com/filecoin-project/lotus/pull/4508) +- Delete wallet from local wallet cache (https://github.com/filecoin-project/lotus/pull/4526) +- Fix lotus-shed ledger list (https://github.com/filecoin-project/lotus/pull/4521) +- Manage sectors by size instead of proof type (https://github.com/filecoin-project/lotus/pull/4511) +- Feat/api request metrics wrapper (https://github.com/filecoin-project/lotus/pull/4516) +- Fix chain sync stopping to sync (https://github.com/filecoin-project/lotus/pull/4541) +- Use the correct lookback for the worker key when creating blocks (https://github.com/filecoin-project/lotus/pull/4539) +- Cleanup test initialization and always validate VRFs in tests (https://github.com/filecoin-project/lotus/pull/4538) +- Add a market WithdrawBalance CLI (https://github.com/filecoin-project/lotus/pull/4524) +- wallet list: Add market balance and ID address flags (https://github.com/filecoin-project/lotus/pull/4555) +- tvx simulate command; tvx extract --ignore-sanity-checks (https://github.com/filecoin-project/lotus/pull/4554) +- lotus-lite: CLI tests for `lotus client` commands (https://github.com/filecoin-project/lotus/pull/4497) +- lite-mode - market storage and retrieval clients (https://github.com/filecoin-project/lotus/pull/4263) +- Chore: update drand to v1.2.0 (https://github.com/filecoin-project/lotus/pull/4420) +- Fix random test failures (https://github.com/filecoin-project/lotus/pull/4559) +- Fix flaky TestTimedBSSimple (https://github.com/filecoin-project/lotus/pull/4561) +- Make wallet market withdraw usable with miner addresses (https://github.com/filecoin-project/lotus/pull/4556) +- Fix flaky TestChainExportImportFull (https://github.com/filecoin-project/lotus/pull/4564) +- Use older randomness for the PoSt commit on specs-actors version 2 (https://github.com/filecoin-project/lotus/pull/4563) +- shed: Commad to decode messages (https://github.com/filecoin-project/lotus/pull/4565) +- Fetch worker key from correct block on sync (https://github.com/filecoin-project/lotus/pull/4573) + # 1.1.0 / 2020-10-20 This is a mandatory release that introduces the first post-liftoff upgrade to the Filecoin network. The changes that break consensus are an upgrade to specs-actors v2.2.0 at epoch 170000. diff --git a/build/version.go b/build/version.go index b8941cb7a..701e47d4a 100644 --- a/build/version.go +++ b/build/version.go @@ -29,7 +29,7 @@ func buildType() string { } // BuildVersion is the local build version, set by build system -const BuildVersion = "1.1.0" +const BuildVersion = "1.1.1" func UserVersion() string { return BuildVersion + buildType() + CurrentCommit From f23034305fc4cc9129dd29384e135506ac936ae2 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Sat, 24 Oct 2020 02:57:17 -0700 Subject: [PATCH 255/313] Handle worker key changes correctly in runtime --- chain/gen/genesis/miners.go | 4 +-- chain/stmgr/call.go | 2 ++ chain/stmgr/stmgr.go | 1 + chain/stmgr/utils.go | 11 +++++++ chain/vm/syscalls.go | 59 ++++++++++++++++++++++--------------- chain/vm/vm.go | 15 ++++++---- 6 files changed, 61 insertions(+), 31 deletions(-) diff --git a/chain/gen/genesis/miners.go b/chain/gen/genesis/miners.go index 49e09d792..be83a8711 100644 --- a/chain/gen/genesis/miners.go +++ b/chain/gen/genesis/miners.go @@ -56,9 +56,9 @@ func (fss *fakedSigSyscalls) VerifySignature(signature crypto.Signature, signer } func mkFakedSigSyscalls(base vm.SyscallBuilder) vm.SyscallBuilder { - return func(ctx context.Context, cstate *state.StateTree, cst cbor.IpldStore) runtime2.Syscalls { + return func(ctx context.Context, rt *vm.Runtime) runtime2.Syscalls { return &fakedSigSyscalls{ - base(ctx, cstate, cst), + base(ctx, rt), } } } diff --git a/chain/stmgr/call.go b/chain/stmgr/call.go index 3d7d284bc..bb0f0e5ec 100644 --- a/chain/stmgr/call.go +++ b/chain/stmgr/call.go @@ -64,6 +64,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types. CircSupplyCalc: sm.GetVMCirculatingSupply, NtwkVersion: sm.GetNtwkVersion, BaseFee: types.NewInt(0), + LookbackState: LookbackStateGetterForTipset(sm, ts), } vmi, err := sm.newVM(ctx, vmopt) @@ -178,6 +179,7 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri CircSupplyCalc: sm.GetVMCirculatingSupply, NtwkVersion: sm.GetNtwkVersion, BaseFee: ts.Blocks()[0].ParentBaseFee, + LookbackState: LookbackStateGetterForTipset(sm, ts), } vmi, err := sm.newVM(ctx, vmopt) if err != nil { diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index 2822344b0..7e5809a84 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -241,6 +241,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp CircSupplyCalc: sm.GetVMCirculatingSupply, NtwkVersion: sm.GetNtwkVersion, BaseFee: baseFee, + LookbackState: LookbackStateGetterForTipset(sm, ts), } return sm.newVM(ctx, vmopt) diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index 486805786..5b144281d 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -366,6 +366,7 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch, CircSupplyCalc: sm.GetVMCirculatingSupply, NtwkVersion: sm.GetNtwkVersion, BaseFee: ts.Blocks()[0].ParentBaseFee, + LookbackState: LookbackStateGetterForTipset(sm, ts), } vmi, err := sm.newVM(ctx, vmopt) if err != nil { @@ -391,6 +392,16 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch, return root, trace, nil } +func LookbackStateGetterForTipset(sm *StateManager, ts *types.TipSet) vm.LookbackStateGetter { + return func(ctx context.Context, round abi.ChainEpoch) (*state.StateTree, error) { + _, st, err := GetLookbackTipSetForRound(ctx, sm, ts, round) + if err != nil { + return nil, err + } + return sm.StateTree(st) + } +} + func GetLookbackTipSetForRound(ctx context.Context, sm *StateManager, ts *types.TipSet, round abi.ChainEpoch) (*types.TipSet, cid.Cid, error) { var lbr abi.ChainEpoch lb := policy.GetWinningPoStSectorSetLookback(sm.GetNtwkVersion(ctx, round)) diff --git a/chain/vm/syscalls.go b/chain/vm/syscalls.go index 347c3409c..d2f1f77d3 100644 --- a/chain/vm/syscalls.go +++ b/chain/vm/syscalls.go @@ -34,15 +34,18 @@ func init() { // Actual type is defined in chain/types/vmcontext.go because the VMContext interface is there -type SyscallBuilder func(ctx context.Context, cstate *state.StateTree, cst cbor.IpldStore) runtime2.Syscalls +type SyscallBuilder func(ctx context.Context, rt *Runtime) runtime2.Syscalls func Syscalls(verifier ffiwrapper.Verifier) SyscallBuilder { - return func(ctx context.Context, cstate *state.StateTree, cst cbor.IpldStore) runtime2.Syscalls { + return func(ctx context.Context, rt *Runtime) runtime2.Syscalls { + return &syscallShim{ ctx: ctx, - cstate: cstate, - cst: cst, + actor: rt.Receiver(), + cstate: rt.state, + cst: rt.cst, + lbState: rt.vm.lbStateGet, verifier: verifier, } @@ -52,6 +55,8 @@ func Syscalls(verifier ffiwrapper.Verifier) SyscallBuilder { type syscallShim struct { ctx context.Context + lbState LookbackStateGetter + actor address.Address cstate *state.StateTree cst cbor.IpldStore verifier ffiwrapper.Verifier @@ -184,26 +189,7 @@ func (ss *syscallShim) VerifyConsensusFault(a, b, extra []byte) (*runtime2.Conse } func (ss *syscallShim) VerifyBlockSig(blk *types.BlockHeader) error { - - // get appropriate miner actor - act, err := ss.cstate.GetActor(blk.Miner) - if err != nil { - return err - } - - // use that to get the miner state - mas, err := miner.Load(adt.WrapStore(ss.ctx, ss.cst), act) - if err != nil { - return err - } - - info, err := mas.Info() - if err != nil { - return err - } - - // and use to get resolved workerKey - waddr, err := ResolveToKeyAddr(ss.cstate, ss.cst, info.Worker) + waddr, err := ss.workerKeyAtLookback(blk.Height) if err != nil { return err } @@ -215,6 +201,31 @@ func (ss *syscallShim) VerifyBlockSig(blk *types.BlockHeader) error { return nil } +func (ss *syscallShim) workerKeyAtLookback(height abi.ChainEpoch) (address.Address, error) { + lbState, err := ss.lbState(ss.ctx, height) + if err != nil { + return address.Undef, err + } + // get appropriate miner actor + act, err := lbState.GetActor(ss.actor) + if err != nil { + return address.Undef, err + } + + // use that to get the miner state + mas, err := miner.Load(adt.WrapStore(ss.ctx, ss.cst), act) + if err != nil { + return address.Undef, err + } + + info, err := mas.Info() + if err != nil { + return address.Undef, err + } + + return ResolveToKeyAddr(ss.cstate, ss.cst, info.Worker) +} + func (ss *syscallShim) VerifyPoSt(proof proof2.WindowPoStVerifyInfo) error { ok, err := ss.verifier.VerifyWindowPoSt(context.TODO(), proof) if err != nil { diff --git a/chain/vm/vm.go b/chain/vm/vm.go index a7aa05719..8b7f78074 100644 --- a/chain/vm/vm.go +++ b/chain/vm/vm.go @@ -134,11 +134,6 @@ func (vm *VM) makeRuntime(ctx context.Context, msg *types.Message, parent *Runti Blocks: &gasChargingBlocks{rt.chargeGasFunc(2), rt.pricelist, vm.cst.Blocks}, Atlas: vm.cst.Atlas, } - rt.Syscalls = pricedSyscalls{ - under: vm.Syscalls(ctx, vm.cstate, rt.cst), - chargeGas: rt.chargeGasFunc(1), - pl: rt.pricelist, - } vmm := *msg resF, ok := rt.ResolveAddress(msg.From) @@ -156,6 +151,12 @@ func (vm *VM) makeRuntime(ctx context.Context, msg *types.Message, parent *Runti rt.Message = &Message{msg: vmm} } + rt.Syscalls = pricedSyscalls{ + under: vm.Syscalls(ctx, rt), + chargeGas: rt.chargeGasFunc(1), + pl: rt.pricelist, + } + return rt } @@ -169,6 +170,7 @@ func (vm *UnsafeVM) MakeRuntime(ctx context.Context, msg *types.Message) *Runtim type CircSupplyCalculator func(context.Context, abi.ChainEpoch, *state.StateTree) (abi.TokenAmount, error) type NtwkVersionGetter func(context.Context, abi.ChainEpoch) network.Version +type LookbackStateGetter func(context.Context, abi.ChainEpoch) (*state.StateTree, error) type VM struct { cstate *state.StateTree @@ -181,6 +183,7 @@ type VM struct { circSupplyCalc CircSupplyCalculator ntwkVersion NtwkVersionGetter baseFee abi.TokenAmount + lbStateGet LookbackStateGetter Syscalls SyscallBuilder } @@ -194,6 +197,7 @@ type VMOpts struct { CircSupplyCalc CircSupplyCalculator NtwkVersion NtwkVersionGetter // TODO: stebalien: In what cases do we actually need this? It seems like even when creating new networks we want to use the 'global'/build-default version getter BaseFee abi.TokenAmount + LookbackState LookbackStateGetter } func NewVM(ctx context.Context, opts *VMOpts) (*VM, error) { @@ -216,6 +220,7 @@ func NewVM(ctx context.Context, opts *VMOpts) (*VM, error) { ntwkVersion: opts.NtwkVersion, Syscalls: opts.Syscalls, baseFee: opts.BaseFee, + lbStateGet: opts.LookbackState, }, nil } From 7b3f1c2b85a0eff2d7f8677aaf79da6dfac07bd9 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Sat, 24 Oct 2020 06:33:31 -0400 Subject: [PATCH 256/313] Lotus version 1.1.2 --- CHANGELOG.md | 8 ++++++++ build/version.go | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 070d2414c..88a30c91d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Lotus changelog +# 1.1.2 / 2020-10-24 + +This is a patch release of Lotus that builds on the fixes involving worker keys that was introduced in v1.1.1. Miners and node operators should update to this release as soon as possible in order to ensure their blocks are propagated and validated. + +## Changes + +- Handle worker key changes correctly in runtime (https://github.com/filecoin-project/lotus/pull/4579) + # 1.1.1 / 2020-10-24 This is a patch release of Lotus that addresses some issues caused by when miners change their worker keys. Miners and node operators should update to this release as soon as possible, especially any miner who has changed their worker key recently. diff --git a/build/version.go b/build/version.go index 701e47d4a..a8487f98b 100644 --- a/build/version.go +++ b/build/version.go @@ -29,7 +29,7 @@ func buildType() string { } // BuildVersion is the local build version, set by build system -const BuildVersion = "1.1.1" +const BuildVersion = "1.1.2" func UserVersion() string { return BuildVersion + buildType() + CurrentCommit From 6b76371d64c0027cb0aca627868bf75090db97b5 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Sat, 24 Oct 2020 17:15:44 -0300 Subject: [PATCH 257/313] update filecoin-ffi Signed-off-by: Ignacio Hagopian --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 98925e736..723640930 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/dustin/go-humanize v1.0.0 github.com/elastic/go-sysinfo v1.3.0 github.com/fatih/color v1.9.0 - github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200716204036-cddc56607e1d + github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200910194244-f640612a1a1f github.com/filecoin-project/go-address v0.0.4 github.com/filecoin-project/go-amt-ipld/v2 v2.1.1-0.20201006184820-924ee87a1349 // indirect github.com/filecoin-project/go-bitfield v0.2.1 From bfbf6a27114d8811fc581de5ba45bfae2b33f7a9 Mon Sep 17 00:00:00 2001 From: Jinsub Moon Date: Sun, 25 Oct 2020 06:03:39 +0000 Subject: [PATCH 258/313] Do not fail wallet delete because of pre-existing trashed key --- chain/wallet/wallet.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/chain/wallet/wallet.go b/chain/wallet/wallet.go index 1f3329498..33fa3135e 100644 --- a/chain/wallet/wallet.go +++ b/chain/wallet/wallet.go @@ -283,6 +283,10 @@ func (w *LocalWallet) WalletDelete(ctx context.Context, addr address.Address) er w.lk.Lock() defer w.lk.Unlock() + if err := w.keystore.Delete(KTrashPrefix + k.Address.String()); err != nil && !xerrors.Is(err, types.ErrKeyInfoNotFound) { + return xerrors.Errorf("failed to purge trashed key %s: %w", addr, err) + } + if err := w.keystore.Put(KTrashPrefix+k.Address.String(), k.KeyInfo); err != nil { return xerrors.Errorf("failed to mark key %s as trashed: %w", addr, err) } From e65aa4cf17dac869440cb908df9c28e61ba8a044 Mon Sep 17 00:00:00 2001 From: wangchao Date: Mon, 26 Oct 2020 14:52:42 +0800 Subject: [PATCH 259/313] worker key should change when set sender found key not equal with the value on chain --- storage/wdpost_run.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/storage/wdpost_run.go b/storage/wdpost_run.go index fd3053a34..f456ff68d 100644 --- a/storage/wdpost_run.go +++ b/storage/wdpost_run.go @@ -759,6 +759,18 @@ func (s *WindowPoStScheduler) setSender(ctx context.Context, msg *types.Message, msg.From = s.worker return } + worker, err := s.api.StateAccountKey(ctx, mi.Worker, types.EmptyTSK) + if err != nil { + log.Errorw("error getting account key", "error", err) + + msg.From = s.worker + return + } + // worker should keep sync with state on chain, if not, will met error when estimate msg gas. + if s.worker != worker { + s.worker = worker + msg.From = s.worker + } gm, err := s.api.GasEstimateMessageGas(ctx, msg, spec, types.EmptyTSK) if err != nil { From 5ed57d34f0184635c83f8415d54191e9f0514806 Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Mon, 26 Oct 2020 11:09:56 +0100 Subject: [PATCH 260/313] fix: race in paych manager add funds --- paychmgr/paychget_test.go | 5 ++++- paychmgr/simple.go | 7 +++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/paychmgr/paychget_test.go b/paychmgr/paychget_test.go index 9f19dd13d..e6b94db57 100644 --- a/paychmgr/paychget_test.go +++ b/paychmgr/paychget_test.go @@ -663,6 +663,7 @@ func TestPaychGetMergeAddFunds(t *testing.T) { defer addFundsSent.Done() // Request add funds - should block until create channel has completed + var err error addFundsCh1, addFundsMcid1, err = mgr.GetPaych(ctx, from, to, addFundsAmt1) require.NoError(t, err) }() @@ -671,6 +672,7 @@ func TestPaychGetMergeAddFunds(t *testing.T) { defer addFundsSent.Done() // Request add funds again - should merge with waiting add funds request + var err error addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2) require.NoError(t, err) }() @@ -766,6 +768,7 @@ func TestPaychGetMergeAddFundsCtxCancelOne(t *testing.T) { defer addFundsSent.Done() // Request add funds again - should merge with waiting add funds request + var err error addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2) require.NoError(t, err) }() @@ -861,7 +864,6 @@ func TestPaychGetMergeAddFundsCtxCancelAll(t *testing.T) { // Request add funds again - should merge with waiting add funds request _, _, addFundsErr2 = mgr.GetPaych(addFundsCtx2, from, to, big.NewInt(3)) - require.NoError(t, err) }() // Wait for add funds requests to be queued up waitForQueueSize(t, mgr, from, to, 2) @@ -950,6 +952,7 @@ func TestPaychAvailableFunds(t *testing.T) { defer addFundsSent.Done() // Request add funds - should block until create channel has completed + var err error _, addFundsMcid, err = mgr.GetPaych(ctx, from, to, addFundsAmt) require.NoError(t, err) }() diff --git a/paychmgr/simple.go b/paychmgr/simple.go index 253075604..afa1ae1f7 100644 --- a/paychmgr/simple.go +++ b/paychmgr/simple.go @@ -101,10 +101,13 @@ type mergedFundsReq struct { func newMergedFundsReq(reqs []*fundsReq) *mergedFundsReq { ctx, cancel := context.WithCancel(context.Background()) + + rqs := make([]*fundsReq, len(reqs)) + copy(rqs, reqs) m := &mergedFundsReq{ ctx: ctx, cancel: cancel, - reqs: reqs, + reqs: rqs, } for _, r := range m.reqs { @@ -201,7 +204,7 @@ func (ca *channelAccessor) processQueue(channelID string) (*api.ChannelAvailable // Merge all pending requests into one. // For example if there are pending requests for 3, 2, 4 then // amt = 3 + 2 + 4 = 9 - merged := newMergedFundsReq(ca.fundsReqQueue[:]) + merged := newMergedFundsReq(ca.fundsReqQueue) amt := merged.sum() if amt.IsZero() { // Note: The amount can be zero if requests are cancelled as we're From b097a5fb0c8c36cf2ea913c5a7e28fd5e0351d89 Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Mon, 26 Oct 2020 12:01:33 +0100 Subject: [PATCH 261/313] refactor: share code between CLI tests --- cli/paych_test.go | 295 ++++++++++++------------------------------- cli/test/client.go | 14 +- cli/test/mockcli.go | 70 ++++++---- cli/test/multisig.go | 12 +- cli/test/net.go | 46 +++++++ 5 files changed, 188 insertions(+), 249 deletions(-) diff --git a/cli/paych_test.go b/cli/paych_test.go index 77a6e61eb..777574105 100644 --- a/cli/paych_test.go +++ b/cli/paych_test.go @@ -1,9 +1,7 @@ package cli import ( - "bytes" "context" - "flag" "fmt" "os" "regexp" @@ -12,24 +10,21 @@ import ( "testing" "time" - "github.com/stretchr/testify/require" - "github.com/urfave/cli/v2" + clitest "github.com/filecoin-project/lotus/cli/test" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - cbor "github.com/ipfs/go-ipld-cbor" - "github.com/multiformats/go-multiaddr" - "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/builtin/paych" "github.com/filecoin-project/lotus/chain/actors/policy" + cbor "github.com/ipfs/go-ipld-cbor" + "github.com/stretchr/testify/require" "github.com/filecoin-project/lotus/api/apibstore" "github.com/filecoin-project/lotus/api/test" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/events" "github.com/filecoin-project/lotus/chain/types" - builder "github.com/filecoin-project/lotus/node/test" ) func init() { @@ -45,21 +40,21 @@ func TestPaymentChannels(t *testing.T) { blocktime := 5 * time.Millisecond ctx := context.Background() - nodes, addrs := startTwoNodesOneMiner(ctx, t, blocktime) + nodes, addrs := clitest.StartTwoNodesOneMiner(ctx, t, blocktime) paymentCreator := nodes[0] paymentReceiver := nodes[1] creatorAddr := addrs[0] receiverAddr := addrs[1] // Create mock CLI - mockCLI := newMockCLI(t) - creatorCLI := mockCLI.client(paymentCreator.ListenAddr) - receiverCLI := mockCLI.client(paymentReceiver.ListenAddr) + mockCLI := clitest.NewMockCLI(t, Commands) + creatorCLI := mockCLI.Client(paymentCreator.ListenAddr) + receiverCLI := mockCLI.Client(paymentReceiver.ListenAddr) // creator: paych add-funds channelAmt := "100000" - cmd := []string{creatorAddr.String(), receiverAddr.String(), channelAmt} - chstr := creatorCLI.runCmd(paychAddFundsCmd, cmd) + cmd := []string{"paych", "add-funds", creatorAddr.String(), receiverAddr.String(), channelAmt} + chstr := creatorCLI.RunCmd(cmd) chAddr, err := address.NewFromString(chstr) require.NoError(t, err) @@ -67,16 +62,16 @@ func TestPaymentChannels(t *testing.T) { // creator: paych voucher create voucherAmt := 100 vamt := strconv.Itoa(voucherAmt) - cmd = []string{chAddr.String(), vamt} - voucher := creatorCLI.runCmd(paychVoucherCreateCmd, cmd) + cmd = []string{"paych", "voucher", "create", chAddr.String(), vamt} + voucher := creatorCLI.RunCmd(cmd) // receiver: paych voucher add - cmd = []string{chAddr.String(), voucher} - receiverCLI.runCmd(paychVoucherAddCmd, cmd) + cmd = []string{"paych", "voucher", "add", chAddr.String(), voucher} + receiverCLI.RunCmd(cmd) // creator: paych settle - cmd = []string{chAddr.String()} - creatorCLI.runCmd(paychSettleCmd, cmd) + cmd = []string{"paych", "settle", chAddr.String()} + creatorCLI.RunCmd(cmd) // Wait for the chain to reach the settle height chState := getPaychState(ctx, t, paymentReceiver, chAddr) @@ -85,8 +80,8 @@ func TestPaymentChannels(t *testing.T) { waitForHeight(ctx, t, paymentReceiver, sa) // receiver: paych collect - cmd = []string{chAddr.String()} - receiverCLI.runCmd(paychCloseCmd, cmd) + cmd = []string{"paych", "collect", chAddr.String()} + receiverCLI.RunCmd(cmd) } type voucherSpec struct { @@ -101,17 +96,18 @@ func TestPaymentChannelStatus(t *testing.T) { blocktime := 5 * time.Millisecond ctx := context.Background() - nodes, addrs := startTwoNodesOneMiner(ctx, t, blocktime) + nodes, addrs := clitest.StartTwoNodesOneMiner(ctx, t, blocktime) paymentCreator := nodes[0] creatorAddr := addrs[0] receiverAddr := addrs[1] // Create mock CLI - mockCLI := newMockCLI(t) - creatorCLI := mockCLI.client(paymentCreator.ListenAddr) + mockCLI := clitest.NewMockCLI(t, Commands) + creatorCLI := mockCLI.Client(paymentCreator.ListenAddr) - cmd := []string{creatorAddr.String(), receiverAddr.String()} - out := creatorCLI.runCmd(paychStatusByFromToCmd, cmd) + // creator: paych status-by-from-to + cmd := []string{"paych", "status-by-from-to", creatorAddr.String(), receiverAddr.String()} + out := creatorCLI.RunCmd(cmd) fmt.Println(out) noChannelState := "Channel does not exist" require.Regexp(t, regexp.MustCompile(noChannelState), out) @@ -120,14 +116,14 @@ func TestPaymentChannelStatus(t *testing.T) { create := make(chan string) go func() { // creator: paych add-funds - cmd := []string{creatorAddr.String(), receiverAddr.String(), fmt.Sprintf("%d", channelAmt)} - create <- creatorCLI.runCmd(paychAddFundsCmd, cmd) + cmd := []string{"paych", "add-funds", creatorAddr.String(), receiverAddr.String(), fmt.Sprintf("%d", channelAmt)} + create <- creatorCLI.RunCmd(cmd) }() // Wait for the output to stop being "Channel does not exist" for regexp.MustCompile(noChannelState).MatchString(out) { - cmd := []string{creatorAddr.String(), receiverAddr.String()} - out = creatorCLI.runCmd(paychStatusByFromToCmd, cmd) + cmd := []string{"paych", "status-by-from-to", creatorAddr.String(), receiverAddr.String()} + out = creatorCLI.RunCmd(cmd) } fmt.Println(out) @@ -147,8 +143,8 @@ func TestPaymentChannelStatus(t *testing.T) { // Wait for create channel to complete chstr := <-create - cmd = []string{chstr} - out = creatorCLI.runCmd(paychStatusCmd, cmd) + cmd = []string{"paych", "status", chstr} + out = creatorCLI.RunCmd(cmd) fmt.Println(out) // Output should have the channel address require.Regexp(t, regexp.MustCompile("Channel.*"+chstr), out) @@ -160,11 +156,11 @@ func TestPaymentChannelStatus(t *testing.T) { // creator: paych voucher create voucherAmt := uint64(10) - cmd = []string{chAddr.String(), fmt.Sprintf("%d", voucherAmt)} - creatorCLI.runCmd(paychVoucherCreateCmd, cmd) + cmd = []string{"paych", "voucher", "create", chAddr.String(), fmt.Sprintf("%d", voucherAmt)} + creatorCLI.RunCmd(cmd) - cmd = []string{chstr} - out = creatorCLI.runCmd(paychStatusCmd, cmd) + cmd = []string{"paych", "status", chstr} + out = creatorCLI.RunCmd(cmd) fmt.Println(out) voucherAmtAtto := types.BigMul(types.NewInt(voucherAmt), types.NewInt(build.FilecoinPrecision)) voucherAmtStr := fmt.Sprintf("%d", voucherAmtAtto) @@ -179,21 +175,21 @@ func TestPaymentChannelVouchers(t *testing.T) { blocktime := 5 * time.Millisecond ctx := context.Background() - nodes, addrs := startTwoNodesOneMiner(ctx, t, blocktime) + nodes, addrs := clitest.StartTwoNodesOneMiner(ctx, t, blocktime) paymentCreator := nodes[0] paymentReceiver := nodes[1] creatorAddr := addrs[0] receiverAddr := addrs[1] // Create mock CLI - mockCLI := newMockCLI(t) - creatorCLI := mockCLI.client(paymentCreator.ListenAddr) - receiverCLI := mockCLI.client(paymentReceiver.ListenAddr) + mockCLI := clitest.NewMockCLI(t, Commands) + creatorCLI := mockCLI.Client(paymentCreator.ListenAddr) + receiverCLI := mockCLI.Client(paymentReceiver.ListenAddr) // creator: paych add-funds channelAmt := "100000" - cmd := []string{creatorAddr.String(), receiverAddr.String(), channelAmt} - chstr := creatorCLI.runCmd(paychAddFundsCmd, cmd) + cmd := []string{"paych", "add-funds", creatorAddr.String(), receiverAddr.String(), channelAmt} + chstr := creatorCLI.RunCmd(cmd) chAddr, err := address.NewFromString(chstr) require.NoError(t, err) @@ -203,39 +199,39 @@ func TestPaymentChannelVouchers(t *testing.T) { // creator: paych voucher create // Note: implied --lane=0 voucherAmt1 := 100 - cmd = []string{chAddr.String(), strconv.Itoa(voucherAmt1)} - voucher1 := creatorCLI.runCmd(paychVoucherCreateCmd, cmd) + cmd = []string{"paych", "voucher", "create", chAddr.String(), strconv.Itoa(voucherAmt1)} + voucher1 := creatorCLI.RunCmd(cmd) vouchers = append(vouchers, voucherSpec{serialized: voucher1, lane: 0, amt: voucherAmt1}) // creator: paych voucher create --lane=5 lane5 := "--lane=5" voucherAmt2 := 50 - cmd = []string{lane5, chAddr.String(), strconv.Itoa(voucherAmt2)} - voucher2 := creatorCLI.runCmd(paychVoucherCreateCmd, cmd) + cmd = []string{"paych", "voucher", "create", lane5, chAddr.String(), strconv.Itoa(voucherAmt2)} + voucher2 := creatorCLI.RunCmd(cmd) vouchers = append(vouchers, voucherSpec{serialized: voucher2, lane: 5, amt: voucherAmt2}) // creator: paych voucher create --lane=5 voucherAmt3 := 70 - cmd = []string{lane5, chAddr.String(), strconv.Itoa(voucherAmt3)} - voucher3 := creatorCLI.runCmd(paychVoucherCreateCmd, cmd) + cmd = []string{"paych", "voucher", "create", lane5, chAddr.String(), strconv.Itoa(voucherAmt3)} + voucher3 := creatorCLI.RunCmd(cmd) vouchers = append(vouchers, voucherSpec{serialized: voucher3, lane: 5, amt: voucherAmt3}) // creator: paych voucher create --lane=5 voucherAmt4 := 80 - cmd = []string{lane5, chAddr.String(), strconv.Itoa(voucherAmt4)} - voucher4 := creatorCLI.runCmd(paychVoucherCreateCmd, cmd) + cmd = []string{"paych", "voucher", "create", lane5, chAddr.String(), strconv.Itoa(voucherAmt4)} + voucher4 := creatorCLI.RunCmd(cmd) vouchers = append(vouchers, voucherSpec{serialized: voucher4, lane: 5, amt: voucherAmt4}) // creator: paych voucher list --export - cmd = []string{"--export", chAddr.String()} - list := creatorCLI.runCmd(paychVoucherListCmd, cmd) + cmd = []string{"paych", "voucher", "list", "--export", chAddr.String()} + list := creatorCLI.RunCmd(cmd) // Check that voucher list output is correct on creator checkVoucherOutput(t, list, vouchers) // creator: paych voucher best-spendable - cmd = []string{"--export", chAddr.String()} - bestSpendable := creatorCLI.runCmd(paychVoucherBestSpendableCmd, cmd) + cmd = []string{"paych", "voucher", "best-spendable", "--export", chAddr.String()} + bestSpendable := creatorCLI.RunCmd(cmd) // Check that best spendable output is correct on creator bestVouchers := []voucherSpec{ @@ -245,31 +241,31 @@ func TestPaymentChannelVouchers(t *testing.T) { checkVoucherOutput(t, bestSpendable, bestVouchers) // receiver: paych voucher add - cmd = []string{chAddr.String(), voucher1} - receiverCLI.runCmd(paychVoucherAddCmd, cmd) + cmd = []string{"paych", "voucher", "add", chAddr.String(), voucher1} + receiverCLI.RunCmd(cmd) // receiver: paych voucher add - cmd = []string{chAddr.String(), voucher2} - receiverCLI.runCmd(paychVoucherAddCmd, cmd) + cmd = []string{"paych", "voucher", "add", chAddr.String(), voucher2} + receiverCLI.RunCmd(cmd) // receiver: paych voucher add - cmd = []string{chAddr.String(), voucher3} - receiverCLI.runCmd(paychVoucherAddCmd, cmd) + cmd = []string{"paych", "voucher", "add", chAddr.String(), voucher3} + receiverCLI.RunCmd(cmd) // receiver: paych voucher add - cmd = []string{chAddr.String(), voucher4} - receiverCLI.runCmd(paychVoucherAddCmd, cmd) + cmd = []string{"paych", "voucher", "add", chAddr.String(), voucher4} + receiverCLI.RunCmd(cmd) // receiver: paych voucher list --export - cmd = []string{"--export", chAddr.String()} - list = receiverCLI.runCmd(paychVoucherListCmd, cmd) + cmd = []string{"paych", "voucher", "list", "--export", chAddr.String()} + list = receiverCLI.RunCmd(cmd) // Check that voucher list output is correct on receiver checkVoucherOutput(t, list, vouchers) // receiver: paych voucher best-spendable - cmd = []string{"--export", chAddr.String()} - bestSpendable = receiverCLI.runCmd(paychVoucherBestSpendableCmd, cmd) + cmd = []string{"paych", "voucher", "best-spendable", "--export", chAddr.String()} + bestSpendable = receiverCLI.RunCmd(cmd) // Check that best spendable output is correct on receiver bestVouchers = []voucherSpec{ @@ -279,12 +275,12 @@ func TestPaymentChannelVouchers(t *testing.T) { checkVoucherOutput(t, bestSpendable, bestVouchers) // receiver: paych voucher submit - cmd = []string{chAddr.String(), voucher1} - receiverCLI.runCmd(paychVoucherSubmitCmd, cmd) + cmd = []string{"paych", "voucher", "submit", chAddr.String(), voucher1} + receiverCLI.RunCmd(cmd) // receiver: paych voucher best-spendable - cmd = []string{"--export", chAddr.String()} - bestSpendable = receiverCLI.runCmd(paychVoucherBestSpendableCmd, cmd) + cmd = []string{"paych", "voucher", "best-spendable", "--export", chAddr.String()} + bestSpendable = receiverCLI.RunCmd(cmd) // Check that best spendable output no longer includes submitted voucher bestVouchers = []voucherSpec{ @@ -295,12 +291,12 @@ func TestPaymentChannelVouchers(t *testing.T) { // There are three vouchers in lane 5: 50, 70, 80 // Submit the voucher for 50. Best spendable should still be 80. // receiver: paych voucher submit - cmd = []string{chAddr.String(), voucher2} - receiverCLI.runCmd(paychVoucherSubmitCmd, cmd) + cmd = []string{"paych", "voucher", "submit", chAddr.String(), voucher2} + receiverCLI.RunCmd(cmd) // receiver: paych voucher best-spendable - cmd = []string{"--export", chAddr.String()} - bestSpendable = receiverCLI.runCmd(paychVoucherBestSpendableCmd, cmd) + cmd = []string{"paych", "voucher", "best-spendable", "--export", chAddr.String()} + bestSpendable = receiverCLI.RunCmd(cmd) // Check that best spendable output still includes the voucher for 80 bestVouchers = []voucherSpec{ @@ -310,12 +306,12 @@ func TestPaymentChannelVouchers(t *testing.T) { // Submit the voucher for 80 // receiver: paych voucher submit - cmd = []string{chAddr.String(), voucher4} - receiverCLI.runCmd(paychVoucherSubmitCmd, cmd) + cmd = []string{"paych", "voucher", "submit", chAddr.String(), voucher4} + receiverCLI.RunCmd(cmd) // receiver: paych voucher best-spendable - cmd = []string{"--export", chAddr.String()} - bestSpendable = receiverCLI.runCmd(paychVoucherBestSpendableCmd, cmd) + cmd = []string{"paych", "voucher", "best-spendable", "--export", chAddr.String()} + bestSpendable = receiverCLI.RunCmd(cmd) // Check that best spendable output no longer includes submitted voucher bestVouchers = []voucherSpec{} @@ -329,19 +325,19 @@ func TestPaymentChannelVoucherCreateShortfall(t *testing.T) { blocktime := 5 * time.Millisecond ctx := context.Background() - nodes, addrs := startTwoNodesOneMiner(ctx, t, blocktime) + nodes, addrs := clitest.StartTwoNodesOneMiner(ctx, t, blocktime) paymentCreator := nodes[0] creatorAddr := addrs[0] receiverAddr := addrs[1] // Create mock CLI - mockCLI := newMockCLI(t) - creatorCLI := mockCLI.client(paymentCreator.ListenAddr) + mockCLI := clitest.NewMockCLI(t, Commands) + creatorCLI := mockCLI.Client(paymentCreator.ListenAddr) // creator: paych add-funds channelAmt := 100 - cmd := []string{creatorAddr.String(), receiverAddr.String(), fmt.Sprintf("%d", channelAmt)} - chstr := creatorCLI.runCmd(paychAddFundsCmd, cmd) + cmd := []string{"paych", "add-funds", creatorAddr.String(), receiverAddr.String(), fmt.Sprintf("%d", channelAmt)} + chstr := creatorCLI.RunCmd(cmd) chAddr, err := address.NewFromString(chstr) require.NoError(t, err) @@ -349,15 +345,15 @@ func TestPaymentChannelVoucherCreateShortfall(t *testing.T) { // creator: paych voucher create --lane=1 voucherAmt1 := 60 lane1 := "--lane=1" - cmd = []string{lane1, chAddr.String(), strconv.Itoa(voucherAmt1)} - voucher1 := creatorCLI.runCmd(paychVoucherCreateCmd, cmd) + cmd = []string{"paych", "voucher", "create", lane1, chAddr.String(), strconv.Itoa(voucherAmt1)} + voucher1 := creatorCLI.RunCmd(cmd) fmt.Println(voucher1) // creator: paych voucher create --lane=2 lane2 := "--lane=2" voucherAmt2 := 70 - cmd = []string{lane2, chAddr.String(), strconv.Itoa(voucherAmt2)} - _, err = creatorCLI.runCmdRaw(paychVoucherCreateCmd, cmd) + cmd = []string{"paych", "voucher", "create", lane2, chAddr.String(), strconv.Itoa(voucherAmt2)} + _, err = creatorCLI.RunCmdRaw(cmd) // Should fail because channel doesn't have required amount require.Error(t, err) @@ -388,129 +384,6 @@ func checkVoucherOutput(t *testing.T, list string, vouchers []voucherSpec) { } } -func startTwoNodesOneMiner(ctx context.Context, t *testing.T, blocktime time.Duration) ([]test.TestNode, []address.Address) { - n, sn := builder.RPCMockSbBuilder(t, test.TwoFull, test.OneMiner) - - paymentCreator := n[0] - paymentReceiver := n[1] - miner := sn[0] - - // Get everyone connected - addrs, err := paymentCreator.NetAddrsListen(ctx) - if err != nil { - t.Fatal(err) - } - - if err := paymentReceiver.NetConnect(ctx, addrs); err != nil { - t.Fatal(err) - } - - if err := miner.NetConnect(ctx, addrs); err != nil { - t.Fatal(err) - } - - // Start mining blocks - bm := test.NewBlockMiner(ctx, t, miner, blocktime) - bm.MineBlocks() - - // Send some funds to register the receiver - receiverAddr, err := paymentReceiver.WalletNew(ctx, types.KTSecp256k1) - if err != nil { - t.Fatal(err) - } - - test.SendFunds(ctx, t, paymentCreator, receiverAddr, abi.NewTokenAmount(1e18)) - - // Get the creator's address - creatorAddr, err := paymentCreator.WalletDefaultAddress(ctx) - if err != nil { - t.Fatal(err) - } - - // Create mock CLI - return n, []address.Address{creatorAddr, receiverAddr} -} - -type mockCLI struct { - t *testing.T - cctx *cli.Context - out *bytes.Buffer -} - -// TODO: refactor to use the methods in cli/test/mockcli.go -func newMockCLI(t *testing.T) *mockCLI { - // Create a CLI App with an --api-url flag so that we can specify which node - // the command should be executed against - app := cli.NewApp() - app.Flags = []cli.Flag{ - &cli.StringFlag{ - Name: "api-url", - Hidden: true, - }, - } - var out bytes.Buffer - app.Writer = &out - app.Setup() - - cctx := cli.NewContext(app, &flag.FlagSet{}, nil) - return &mockCLI{t: t, cctx: cctx, out: &out} -} - -func (c *mockCLI) client(addr multiaddr.Multiaddr) *mockCLIClient { - return &mockCLIClient{t: c.t, addr: addr, cctx: c.cctx, out: c.out} -} - -// mockCLIClient runs commands against a particular node -type mockCLIClient struct { - t *testing.T - addr multiaddr.Multiaddr - cctx *cli.Context - out *bytes.Buffer -} - -func (c *mockCLIClient) runCmd(cmd *cli.Command, input []string) string { - out, err := c.runCmdRaw(cmd, input) - require.NoError(c.t, err) - - return out -} - -func (c *mockCLIClient) runCmdRaw(cmd *cli.Command, input []string) (string, error) { - // prepend --api-url= - apiFlag := "--api-url=" + c.addr.String() - input = append([]string{apiFlag}, input...) - - fs := c.flagSet(cmd) - err := fs.Parse(input) - require.NoError(c.t, err) - - err = cmd.Action(cli.NewContext(c.cctx.App, fs, c.cctx)) - - // Get the output - str := strings.TrimSpace(c.out.String()) - c.out.Reset() - return str, err -} - -func (c *mockCLIClient) flagSet(cmd *cli.Command) *flag.FlagSet { - // Apply app level flags (so we can process --api-url flag) - fs := &flag.FlagSet{} - for _, f := range c.cctx.App.Flags { - err := f.Apply(fs) - if err != nil { - c.t.Fatal(err) - } - } - // Apply command level flags - for _, f := range cmd.Flags { - err := f.Apply(fs) - if err != nil { - c.t.Fatal(err) - } - } - return fs -} - // waitForHeight waits for the node to reach the given chain epoch func waitForHeight(ctx context.Context, t *testing.T, node test.TestNode, height abi.ChainEpoch) { atHeight := make(chan struct{}) diff --git a/cli/test/client.go b/cli/test/client.go index 3a5146219..aefc97479 100644 --- a/cli/test/client.go +++ b/cli/test/client.go @@ -25,8 +25,8 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) defer cancel() // Create mock CLI - mockCLI := newMockCLI(t, cmds) - clientCLI := mockCLI.client(clientNode.ListenAddr) + mockCLI := NewMockCLI(t, cmds) + clientCLI := mockCLI.Client(clientNode.ListenAddr) // Get the miner address addrs, err := clientNode.StateListMiners(ctx, types.EmptyTSK) @@ -40,7 +40,7 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) cmd := []string{ "client", "query-ask", minerAddr.String(), } - out := clientCLI.runCmd(cmd) + out := clientCLI.RunCmd(cmd) require.Regexp(t, regexp.MustCompile("Ask:"), out) // Create a deal (non-interactive) @@ -53,7 +53,7 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) cmd = []string{ "client", "deal", dataCid.String(), minerAddr.String(), price, duration, } - out = clientCLI.runCmd(cmd) + out = clientCLI.RunCmd(cmd) fmt.Println("client deal", out) // Create a deal (interactive) @@ -77,7 +77,7 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) "no", "yes", } - out = clientCLI.runInteractiveCmd(cmd, interactiveCmds) + out = clientCLI.RunInteractiveCmd(cmd, interactiveCmds) fmt.Println("client deal:\n", out) // Wait for provider to start sealing deal @@ -85,7 +85,7 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) for dealStatus != "StorageDealSealing" { // client list-deals cmd = []string{"client", "list-deals"} - out = clientCLI.runCmd(cmd) + out = clientCLI.RunCmd(cmd) fmt.Println("list-deals:\n", out) lines := strings.Split(out, "\n") @@ -109,7 +109,7 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) cmd = []string{ "client", "retrieve", dataCid.String(), path, } - out = clientCLI.runCmd(cmd) + out = clientCLI.RunCmd(cmd) fmt.Println("retrieve:\n", out) require.Regexp(t, regexp.MustCompile("Success"), out) } diff --git a/cli/test/mockcli.go b/cli/test/mockcli.go index c7eb70092..dc6d6fd4a 100644 --- a/cli/test/mockcli.go +++ b/cli/test/mockcli.go @@ -11,14 +11,14 @@ import ( lcli "github.com/urfave/cli/v2" ) -type mockCLI struct { +type MockCLI struct { t *testing.T cmds []*lcli.Command cctx *lcli.Context out *bytes.Buffer } -func newMockCLI(t *testing.T, cmds []*lcli.Command) *mockCLI { +func NewMockCLI(t *testing.T, cmds []*lcli.Command) *MockCLI { // Create a CLI App with an --api-url flag so that we can specify which node // the command should be executed against app := &lcli.App{ @@ -36,15 +36,15 @@ func newMockCLI(t *testing.T, cmds []*lcli.Command) *mockCLI { app.Setup() cctx := lcli.NewContext(app, &flag.FlagSet{}, nil) - return &mockCLI{t: t, cmds: cmds, cctx: cctx, out: &out} + return &MockCLI{t: t, cmds: cmds, cctx: cctx, out: &out} } -func (c *mockCLI) client(addr multiaddr.Multiaddr) *mockCLIClient { - return &mockCLIClient{t: c.t, cmds: c.cmds, addr: addr, cctx: c.cctx, out: c.out} +func (c *MockCLI) Client(addr multiaddr.Multiaddr) *MockCLIClient { + return &MockCLIClient{t: c.t, cmds: c.cmds, addr: addr, cctx: c.cctx, out: c.out} } -// mockCLIClient runs commands against a particular node -type mockCLIClient struct { +// MockCLIClient runs commands against a particular node +type MockCLIClient struct { t *testing.T cmds []*lcli.Command addr multiaddr.Multiaddr @@ -52,7 +52,7 @@ type mockCLIClient struct { out *bytes.Buffer } -func (c *mockCLIClient) run(cmd []string, params []string, args []string) string { +func (c *MockCLIClient) run(cmd []string, params []string, args []string) string { // Add parameter --api-url= apiFlag := "--api-url=" + c.addr.String() params = append([]string{apiFlag}, params...) @@ -66,28 +66,48 @@ func (c *mockCLIClient) run(cmd []string, params []string, args []string) string return str } -func (c *mockCLIClient) runCmd(input []string) string { - cmd := c.cmdByNameSub(input[0], input[1]) - out, err := c.runCmdRaw(cmd, input[2:]) +func (c *MockCLIClient) RunCmd(input []string) string { + out, err := c.RunCmdRaw(input) require.NoError(c.t, err) return out } -func (c *mockCLIClient) cmdByNameSub(name string, sub string) *lcli.Command { - for _, c := range c.cmds { - if c.Name == name { - for _, s := range c.Subcommands { - if s.Name == sub { - return s - } - } +// Given an input, find the corresponding command or sub-command. +// eg "paych add-funds" +func (c *MockCLIClient) cmdByNameSub(input []string) (*lcli.Command, []string) { + name := input[0] + for _, cmd := range c.cmds { + if cmd.Name == name { + return c.findSubcommand(cmd, input[1:]) } } - return nil + return nil, []string{} } -func (c *mockCLIClient) runCmdRaw(cmd *lcli.Command, input []string) (string, error) { +func (c *MockCLIClient) findSubcommand(cmd *lcli.Command, input []string) (*lcli.Command, []string) { + // If there are no sub-commands, return the current command + if len(cmd.Subcommands) == 0 { + return cmd, input + } + + // Check each sub-command for a match against the name + subName := input[0] + for _, subCmd := range cmd.Subcommands { + if subCmd.Name == subName { + // Found a match, recursively search for sub-commands + return c.findSubcommand(subCmd, input[1:]) + } + } + return nil, []string{} +} + +func (c *MockCLIClient) RunCmdRaw(input []string) (string, error) { + cmd, input := c.cmdByNameSub(input) + if cmd == nil { + panic("Could not find command " + input[0] + " " + input[1]) + } + // prepend --api-url= apiFlag := "--api-url=" + c.addr.String() input = append([]string{apiFlag}, input...) @@ -104,7 +124,7 @@ func (c *mockCLIClient) runCmdRaw(cmd *lcli.Command, input []string) (string, er return str, err } -func (c *mockCLIClient) flagSet(cmd *lcli.Command) *flag.FlagSet { +func (c *MockCLIClient) flagSet(cmd *lcli.Command) *flag.FlagSet { // Apply app level flags (so we can process --api-url flag) fs := &flag.FlagSet{} for _, f := range c.cctx.App.Flags { @@ -123,11 +143,11 @@ func (c *mockCLIClient) flagSet(cmd *lcli.Command) *flag.FlagSet { return fs } -func (c *mockCLIClient) runInteractiveCmd(cmd []string, interactive []string) string { +func (c *MockCLIClient) RunInteractiveCmd(cmd []string, interactive []string) string { c.toStdin(strings.Join(interactive, "\n") + "\n") - return c.runCmd(cmd) + return c.RunCmd(cmd) } -func (c *mockCLIClient) toStdin(s string) { +func (c *MockCLIClient) toStdin(s string) { c.cctx.App.Metadata["stdin"] = bytes.NewBufferString(s) } diff --git a/cli/test/multisig.go b/cli/test/multisig.go index d2c0238d2..f7c0d88d7 100644 --- a/cli/test/multisig.go +++ b/cli/test/multisig.go @@ -18,8 +18,8 @@ func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNod ctx := context.Background() // Create mock CLI - mockCLI := newMockCLI(t, cmds) - clientCLI := mockCLI.client(clientNode.ListenAddr) + mockCLI := NewMockCLI(t, cmds) + clientCLI := mockCLI.Client(clientNode.ListenAddr) // Create some wallets on the node to use for testing multisig var walletAddrs []address.Address @@ -48,7 +48,7 @@ func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNod walletAddrs[1].String(), walletAddrs[2].String(), } - out := clientCLI.runCmd(cmd) + out := clientCLI.RunCmd(cmd) fmt.Println(out) // Extract msig robust address from output @@ -68,12 +68,12 @@ func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNod msigRobustAddr, walletAddrs[3].String(), } - out = clientCLI.runCmd(cmd) + out = clientCLI.RunCmd(cmd) fmt.Println(out) // msig inspect cmd = []string{"msig", "inspect", "--vesting", "--decode-params", msigRobustAddr} - out = clientCLI.runCmd(cmd) + out = clientCLI.RunCmd(cmd) fmt.Println(out) // Expect correct balance @@ -96,6 +96,6 @@ func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNod walletAddrs[3].String(), "false", } - out = clientCLI.runCmd(cmd) + out = clientCLI.RunCmd(cmd) fmt.Println(out) } diff --git a/cli/test/net.go b/cli/test/net.go index d13993d16..836b81a8f 100644 --- a/cli/test/net.go +++ b/cli/test/net.go @@ -5,6 +5,9 @@ import ( "testing" "time" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/go-address" "github.com/filecoin-project/lotus/api/test" test2 "github.com/filecoin-project/lotus/node/test" @@ -39,3 +42,46 @@ func StartOneNodeOneMiner(ctx context.Context, t *testing.T, blocktime time.Dura // Create mock CLI return full, fullAddr } + +func StartTwoNodesOneMiner(ctx context.Context, t *testing.T, blocktime time.Duration) ([]test.TestNode, []address.Address) { + n, sn := test2.RPCMockSbBuilder(t, test.TwoFull, test.OneMiner) + + fullNode1 := n[0] + fullNode2 := n[1] + miner := sn[0] + + // Get everyone connected + addrs, err := fullNode1.NetAddrsListen(ctx) + if err != nil { + t.Fatal(err) + } + + if err := fullNode2.NetConnect(ctx, addrs); err != nil { + t.Fatal(err) + } + + if err := miner.NetConnect(ctx, addrs); err != nil { + t.Fatal(err) + } + + // Start mining blocks + bm := test.NewBlockMiner(ctx, t, miner, blocktime) + bm.MineBlocks() + + // Send some funds to register the second node + fullNodeAddr2, err := fullNode2.WalletNew(ctx, types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + + test.SendFunds(ctx, t, fullNode1, fullNodeAddr2, abi.NewTokenAmount(1e18)) + + // Get the first node's address + fullNodeAddr1, err := fullNode1.WalletDefaultAddress(ctx) + if err != nil { + t.Fatal(err) + } + + // Create mock CLI + return n, []address.Address{fullNodeAddr1, fullNodeAddr2} +} From 1fefcc2b46868d5bbc493dcb511c31e0372b8066 Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Mon, 26 Oct 2020 14:26:46 +0100 Subject: [PATCH 262/313] refactor: simplify cli test RunCmd --- cli/paych_test.go | 125 ++++++++++++++++++++----------------------- cli/test/client.go | 22 ++------ cli/test/mockcli.go | 22 ++------ cli/test/multisig.go | 18 +++---- 4 files changed, 75 insertions(+), 112 deletions(-) diff --git a/cli/paych_test.go b/cli/paych_test.go index 777574105..fcd9c99a3 100644 --- a/cli/paych_test.go +++ b/cli/paych_test.go @@ -37,6 +37,7 @@ func init() { // commands func TestPaymentChannels(t *testing.T) { _ = os.Setenv("BELLMAN_NO_GPU", "1") + clitest.QuietMiningLogs() blocktime := 5 * time.Millisecond ctx := context.Background() @@ -53,8 +54,7 @@ func TestPaymentChannels(t *testing.T) { // creator: paych add-funds channelAmt := "100000" - cmd := []string{"paych", "add-funds", creatorAddr.String(), receiverAddr.String(), channelAmt} - chstr := creatorCLI.RunCmd(cmd) + chstr := creatorCLI.RunCmd("paych", "add-funds", creatorAddr.String(), receiverAddr.String(), channelAmt) chAddr, err := address.NewFromString(chstr) require.NoError(t, err) @@ -62,16 +62,13 @@ func TestPaymentChannels(t *testing.T) { // creator: paych voucher create voucherAmt := 100 vamt := strconv.Itoa(voucherAmt) - cmd = []string{"paych", "voucher", "create", chAddr.String(), vamt} - voucher := creatorCLI.RunCmd(cmd) + voucher := creatorCLI.RunCmd("paych", "voucher", "create", chAddr.String(), vamt) // receiver: paych voucher add - cmd = []string{"paych", "voucher", "add", chAddr.String(), voucher} - receiverCLI.RunCmd(cmd) + receiverCLI.RunCmd("paych", "voucher", "add", chAddr.String(), voucher) // creator: paych settle - cmd = []string{"paych", "settle", chAddr.String()} - creatorCLI.RunCmd(cmd) + creatorCLI.RunCmd("paych", "settle", chAddr.String()) // Wait for the chain to reach the settle height chState := getPaychState(ctx, t, paymentReceiver, chAddr) @@ -80,8 +77,7 @@ func TestPaymentChannels(t *testing.T) { waitForHeight(ctx, t, paymentReceiver, sa) // receiver: paych collect - cmd = []string{"paych", "collect", chAddr.String()} - receiverCLI.RunCmd(cmd) + receiverCLI.RunCmd("paych", "collect", chAddr.String()) } type voucherSpec struct { @@ -93,6 +89,7 @@ type voucherSpec struct { // TestPaymentChannelStatus tests the payment channel status CLI command func TestPaymentChannelStatus(t *testing.T) { _ = os.Setenv("BELLMAN_NO_GPU", "1") + clitest.QuietMiningLogs() blocktime := 5 * time.Millisecond ctx := context.Background() @@ -106,8 +103,7 @@ func TestPaymentChannelStatus(t *testing.T) { creatorCLI := mockCLI.Client(paymentCreator.ListenAddr) // creator: paych status-by-from-to - cmd := []string{"paych", "status-by-from-to", creatorAddr.String(), receiverAddr.String()} - out := creatorCLI.RunCmd(cmd) + out := creatorCLI.RunCmd("paych", "status-by-from-to", creatorAddr.String(), receiverAddr.String()) fmt.Println(out) noChannelState := "Channel does not exist" require.Regexp(t, regexp.MustCompile(noChannelState), out) @@ -116,14 +112,17 @@ func TestPaymentChannelStatus(t *testing.T) { create := make(chan string) go func() { // creator: paych add-funds - cmd := []string{"paych", "add-funds", creatorAddr.String(), receiverAddr.String(), fmt.Sprintf("%d", channelAmt)} - create <- creatorCLI.RunCmd(cmd) + create <- creatorCLI.RunCmd( + "paych", + "add-funds", + creatorAddr.String(), + receiverAddr.String(), + fmt.Sprintf("%d", channelAmt)) }() // Wait for the output to stop being "Channel does not exist" for regexp.MustCompile(noChannelState).MatchString(out) { - cmd := []string{"paych", "status-by-from-to", creatorAddr.String(), receiverAddr.String()} - out = creatorCLI.RunCmd(cmd) + out = creatorCLI.RunCmd("paych", "status-by-from-to", creatorAddr.String(), receiverAddr.String()) } fmt.Println(out) @@ -143,8 +142,7 @@ func TestPaymentChannelStatus(t *testing.T) { // Wait for create channel to complete chstr := <-create - cmd = []string{"paych", "status", chstr} - out = creatorCLI.RunCmd(cmd) + out = creatorCLI.RunCmd("paych", "status", chstr) fmt.Println(out) // Output should have the channel address require.Regexp(t, regexp.MustCompile("Channel.*"+chstr), out) @@ -156,11 +154,9 @@ func TestPaymentChannelStatus(t *testing.T) { // creator: paych voucher create voucherAmt := uint64(10) - cmd = []string{"paych", "voucher", "create", chAddr.String(), fmt.Sprintf("%d", voucherAmt)} - creatorCLI.RunCmd(cmd) + creatorCLI.RunCmd("paych", "voucher", "create", chAddr.String(), fmt.Sprintf("%d", voucherAmt)) - cmd = []string{"paych", "status", chstr} - out = creatorCLI.RunCmd(cmd) + out = creatorCLI.RunCmd("paych", "status", chstr) fmt.Println(out) voucherAmtAtto := types.BigMul(types.NewInt(voucherAmt), types.NewInt(build.FilecoinPrecision)) voucherAmtStr := fmt.Sprintf("%d", voucherAmtAtto) @@ -172,6 +168,7 @@ func TestPaymentChannelStatus(t *testing.T) { // channel voucher commands func TestPaymentChannelVouchers(t *testing.T) { _ = os.Setenv("BELLMAN_NO_GPU", "1") + clitest.QuietMiningLogs() blocktime := 5 * time.Millisecond ctx := context.Background() @@ -188,8 +185,7 @@ func TestPaymentChannelVouchers(t *testing.T) { // creator: paych add-funds channelAmt := "100000" - cmd := []string{"paych", "add-funds", creatorAddr.String(), receiverAddr.String(), channelAmt} - chstr := creatorCLI.RunCmd(cmd) + chstr := creatorCLI.RunCmd("paych", "add-funds", creatorAddr.String(), receiverAddr.String(), channelAmt) chAddr, err := address.NewFromString(chstr) require.NoError(t, err) @@ -199,39 +195,33 @@ func TestPaymentChannelVouchers(t *testing.T) { // creator: paych voucher create // Note: implied --lane=0 voucherAmt1 := 100 - cmd = []string{"paych", "voucher", "create", chAddr.String(), strconv.Itoa(voucherAmt1)} - voucher1 := creatorCLI.RunCmd(cmd) + voucher1 := creatorCLI.RunCmd("paych", "voucher", "create", chAddr.String(), strconv.Itoa(voucherAmt1)) vouchers = append(vouchers, voucherSpec{serialized: voucher1, lane: 0, amt: voucherAmt1}) // creator: paych voucher create --lane=5 lane5 := "--lane=5" voucherAmt2 := 50 - cmd = []string{"paych", "voucher", "create", lane5, chAddr.String(), strconv.Itoa(voucherAmt2)} - voucher2 := creatorCLI.RunCmd(cmd) + voucher2 := creatorCLI.RunCmd("paych", "voucher", "create", lane5, chAddr.String(), strconv.Itoa(voucherAmt2)) vouchers = append(vouchers, voucherSpec{serialized: voucher2, lane: 5, amt: voucherAmt2}) // creator: paych voucher create --lane=5 voucherAmt3 := 70 - cmd = []string{"paych", "voucher", "create", lane5, chAddr.String(), strconv.Itoa(voucherAmt3)} - voucher3 := creatorCLI.RunCmd(cmd) + voucher3 := creatorCLI.RunCmd("paych", "voucher", "create", lane5, chAddr.String(), strconv.Itoa(voucherAmt3)) vouchers = append(vouchers, voucherSpec{serialized: voucher3, lane: 5, amt: voucherAmt3}) // creator: paych voucher create --lane=5 voucherAmt4 := 80 - cmd = []string{"paych", "voucher", "create", lane5, chAddr.String(), strconv.Itoa(voucherAmt4)} - voucher4 := creatorCLI.RunCmd(cmd) + voucher4 := creatorCLI.RunCmd("paych", "voucher", "create", lane5, chAddr.String(), strconv.Itoa(voucherAmt4)) vouchers = append(vouchers, voucherSpec{serialized: voucher4, lane: 5, amt: voucherAmt4}) // creator: paych voucher list --export - cmd = []string{"paych", "voucher", "list", "--export", chAddr.String()} - list := creatorCLI.RunCmd(cmd) + list := creatorCLI.RunCmd("paych", "voucher", "list", "--export", chAddr.String()) // Check that voucher list output is correct on creator checkVoucherOutput(t, list, vouchers) // creator: paych voucher best-spendable - cmd = []string{"paych", "voucher", "best-spendable", "--export", chAddr.String()} - bestSpendable := creatorCLI.RunCmd(cmd) + bestSpendable := creatorCLI.RunCmd("paych", "voucher", "best-spendable", "--export", chAddr.String()) // Check that best spendable output is correct on creator bestVouchers := []voucherSpec{ @@ -241,31 +231,25 @@ func TestPaymentChannelVouchers(t *testing.T) { checkVoucherOutput(t, bestSpendable, bestVouchers) // receiver: paych voucher add - cmd = []string{"paych", "voucher", "add", chAddr.String(), voucher1} - receiverCLI.RunCmd(cmd) + receiverCLI.RunCmd("paych", "voucher", "add", chAddr.String(), voucher1) // receiver: paych voucher add - cmd = []string{"paych", "voucher", "add", chAddr.String(), voucher2} - receiverCLI.RunCmd(cmd) + receiverCLI.RunCmd("paych", "voucher", "add", chAddr.String(), voucher2) // receiver: paych voucher add - cmd = []string{"paych", "voucher", "add", chAddr.String(), voucher3} - receiverCLI.RunCmd(cmd) + receiverCLI.RunCmd("paych", "voucher", "add", chAddr.String(), voucher3) // receiver: paych voucher add - cmd = []string{"paych", "voucher", "add", chAddr.String(), voucher4} - receiverCLI.RunCmd(cmd) + receiverCLI.RunCmd("paych", "voucher", "add", chAddr.String(), voucher4) // receiver: paych voucher list --export - cmd = []string{"paych", "voucher", "list", "--export", chAddr.String()} - list = receiverCLI.RunCmd(cmd) + list = receiverCLI.RunCmd("paych", "voucher", "list", "--export", chAddr.String()) // Check that voucher list output is correct on receiver checkVoucherOutput(t, list, vouchers) // receiver: paych voucher best-spendable - cmd = []string{"paych", "voucher", "best-spendable", "--export", chAddr.String()} - bestSpendable = receiverCLI.RunCmd(cmd) + bestSpendable = receiverCLI.RunCmd("paych", "voucher", "best-spendable", "--export", chAddr.String()) // Check that best spendable output is correct on receiver bestVouchers = []voucherSpec{ @@ -275,12 +259,10 @@ func TestPaymentChannelVouchers(t *testing.T) { checkVoucherOutput(t, bestSpendable, bestVouchers) // receiver: paych voucher submit - cmd = []string{"paych", "voucher", "submit", chAddr.String(), voucher1} - receiverCLI.RunCmd(cmd) + receiverCLI.RunCmd("paych", "voucher", "submit", chAddr.String(), voucher1) // receiver: paych voucher best-spendable - cmd = []string{"paych", "voucher", "best-spendable", "--export", chAddr.String()} - bestSpendable = receiverCLI.RunCmd(cmd) + bestSpendable = receiverCLI.RunCmd("paych", "voucher", "best-spendable", "--export", chAddr.String()) // Check that best spendable output no longer includes submitted voucher bestVouchers = []voucherSpec{ @@ -291,12 +273,10 @@ func TestPaymentChannelVouchers(t *testing.T) { // There are three vouchers in lane 5: 50, 70, 80 // Submit the voucher for 50. Best spendable should still be 80. // receiver: paych voucher submit - cmd = []string{"paych", "voucher", "submit", chAddr.String(), voucher2} - receiverCLI.RunCmd(cmd) + receiverCLI.RunCmd("paych", "voucher", "submit", chAddr.String(), voucher2) // receiver: paych voucher best-spendable - cmd = []string{"paych", "voucher", "best-spendable", "--export", chAddr.String()} - bestSpendable = receiverCLI.RunCmd(cmd) + bestSpendable = receiverCLI.RunCmd("paych", "voucher", "best-spendable", "--export", chAddr.String()) // Check that best spendable output still includes the voucher for 80 bestVouchers = []voucherSpec{ @@ -306,12 +286,10 @@ func TestPaymentChannelVouchers(t *testing.T) { // Submit the voucher for 80 // receiver: paych voucher submit - cmd = []string{"paych", "voucher", "submit", chAddr.String(), voucher4} - receiverCLI.RunCmd(cmd) + receiverCLI.RunCmd("paych", "voucher", "submit", chAddr.String(), voucher4) // receiver: paych voucher best-spendable - cmd = []string{"paych", "voucher", "best-spendable", "--export", chAddr.String()} - bestSpendable = receiverCLI.RunCmd(cmd) + bestSpendable = receiverCLI.RunCmd("paych", "voucher", "best-spendable", "--export", chAddr.String()) // Check that best spendable output no longer includes submitted voucher bestVouchers = []voucherSpec{} @@ -322,6 +300,7 @@ func TestPaymentChannelVouchers(t *testing.T) { // is greater than what's left in the channel, voucher create fails func TestPaymentChannelVoucherCreateShortfall(t *testing.T) { _ = os.Setenv("BELLMAN_NO_GPU", "1") + clitest.QuietMiningLogs() blocktime := 5 * time.Millisecond ctx := context.Background() @@ -336,8 +315,12 @@ func TestPaymentChannelVoucherCreateShortfall(t *testing.T) { // creator: paych add-funds channelAmt := 100 - cmd := []string{"paych", "add-funds", creatorAddr.String(), receiverAddr.String(), fmt.Sprintf("%d", channelAmt)} - chstr := creatorCLI.RunCmd(cmd) + chstr := creatorCLI.RunCmd( + "paych", + "add-funds", + creatorAddr.String(), + receiverAddr.String(), + fmt.Sprintf("%d", channelAmt)) chAddr, err := address.NewFromString(chstr) require.NoError(t, err) @@ -345,15 +328,25 @@ func TestPaymentChannelVoucherCreateShortfall(t *testing.T) { // creator: paych voucher create --lane=1 voucherAmt1 := 60 lane1 := "--lane=1" - cmd = []string{"paych", "voucher", "create", lane1, chAddr.String(), strconv.Itoa(voucherAmt1)} - voucher1 := creatorCLI.RunCmd(cmd) + voucher1 := creatorCLI.RunCmd( + "paych", + "voucher", + "create", + lane1, + chAddr.String(), + strconv.Itoa(voucherAmt1)) fmt.Println(voucher1) // creator: paych voucher create --lane=2 lane2 := "--lane=2" voucherAmt2 := 70 - cmd = []string{"paych", "voucher", "create", lane2, chAddr.String(), strconv.Itoa(voucherAmt2)} - _, err = creatorCLI.RunCmdRaw(cmd) + _, err = creatorCLI.RunCmdRaw( + "paych", + "voucher", + "create", + lane2, + chAddr.String(), + strconv.Itoa(voucherAmt2)) // Should fail because channel doesn't have required amount require.Error(t, err) diff --git a/cli/test/client.go b/cli/test/client.go index aefc97479..c74f881b0 100644 --- a/cli/test/client.go +++ b/cli/test/client.go @@ -37,10 +37,7 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) fmt.Println("Miner:", minerAddr) // client query-ask - cmd := []string{ - "client", "query-ask", minerAddr.String(), - } - out := clientCLI.RunCmd(cmd) + out := clientCLI.RunCmd("client", "query-ask", minerAddr.String()) require.Regexp(t, regexp.MustCompile("Ask:"), out) // Create a deal (non-interactive) @@ -50,10 +47,7 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) dataCid := res.Root price := "1000000attofil" duration := fmt.Sprintf("%d", build.MinDealDuration) - cmd = []string{ - "client", "deal", dataCid.String(), minerAddr.String(), price, duration, - } - out = clientCLI.RunCmd(cmd) + out = clientCLI.RunCmd("client", "deal", dataCid.String(), minerAddr.String(), price, duration) fmt.Println("client deal", out) // Create a deal (interactive) @@ -67,9 +61,7 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) require.NoError(t, err) dataCid2 := res.Root duration = fmt.Sprintf("%d", build.MinDealDuration/builtin.EpochsInDay) - cmd = []string{ - "client", "deal", - } + cmd := []string{"client", "deal"} interactiveCmds := []string{ dataCid2.String(), duration, @@ -84,8 +76,7 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) dealStatus := "" for dealStatus != "StorageDealSealing" { // client list-deals - cmd = []string{"client", "list-deals"} - out = clientCLI.RunCmd(cmd) + out = clientCLI.RunCmd("client", "list-deals") fmt.Println("list-deals:\n", out) lines := strings.Split(out, "\n") @@ -106,10 +97,7 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) tmpdir, err := ioutil.TempDir(os.TempDir(), "test-cli-client") require.NoError(t, err) path := filepath.Join(tmpdir, "outfile.dat") - cmd = []string{ - "client", "retrieve", dataCid.String(), path, - } - out = clientCLI.RunCmd(cmd) + out = clientCLI.RunCmd("client", "retrieve", dataCid.String(), path) fmt.Println("retrieve:\n", out) require.Regexp(t, regexp.MustCompile("Success"), out) } diff --git a/cli/test/mockcli.go b/cli/test/mockcli.go index dc6d6fd4a..65b0bc30a 100644 --- a/cli/test/mockcli.go +++ b/cli/test/mockcli.go @@ -52,22 +52,8 @@ type MockCLIClient struct { out *bytes.Buffer } -func (c *MockCLIClient) run(cmd []string, params []string, args []string) string { - // Add parameter --api-url= - apiFlag := "--api-url=" + c.addr.String() - params = append([]string{apiFlag}, params...) - - err := c.cctx.App.Run(append(append(cmd, params...), args...)) - require.NoError(c.t, err) - - // Get the output - str := strings.TrimSpace(c.out.String()) - c.out.Reset() - return str -} - -func (c *MockCLIClient) RunCmd(input []string) string { - out, err := c.RunCmdRaw(input) +func (c *MockCLIClient) RunCmd(input ...string) string { + out, err := c.RunCmdRaw(input...) require.NoError(c.t, err) return out @@ -102,7 +88,7 @@ func (c *MockCLIClient) findSubcommand(cmd *lcli.Command, input []string) (*lcli return nil, []string{} } -func (c *MockCLIClient) RunCmdRaw(input []string) (string, error) { +func (c *MockCLIClient) RunCmdRaw(input ...string) (string, error) { cmd, input := c.cmdByNameSub(input) if cmd == nil { panic("Could not find command " + input[0] + " " + input[1]) @@ -145,7 +131,7 @@ func (c *MockCLIClient) flagSet(cmd *lcli.Command) *flag.FlagSet { func (c *MockCLIClient) RunInteractiveCmd(cmd []string, interactive []string) string { c.toStdin(strings.Join(interactive, "\n") + "\n") - return c.RunCmd(cmd) + return c.RunCmd(cmd...) } func (c *MockCLIClient) toStdin(s string) { diff --git a/cli/test/multisig.go b/cli/test/multisig.go index f7c0d88d7..dd867d0b5 100644 --- a/cli/test/multisig.go +++ b/cli/test/multisig.go @@ -39,7 +39,7 @@ func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNod paramDuration := "--duration=50" paramRequired := fmt.Sprintf("--required=%d", threshold) paramValue := fmt.Sprintf("--value=%dattofil", amtAtto) - cmd := []string{ + out := clientCLI.RunCmd( "msig", "create", paramRequired, paramDuration, @@ -47,8 +47,7 @@ func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNod walletAddrs[0].String(), walletAddrs[1].String(), walletAddrs[2].String(), - } - out := clientCLI.RunCmd(cmd) + ) fmt.Println(out) // Extract msig robust address from output @@ -62,18 +61,16 @@ func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNod // Propose to add a new address to the msig // msig add-propose --from= paramFrom := fmt.Sprintf("--from=%s", walletAddrs[0]) - cmd = []string{ + out = clientCLI.RunCmd( "msig", "add-propose", paramFrom, msigRobustAddr, walletAddrs[3].String(), - } - out = clientCLI.RunCmd(cmd) + ) fmt.Println(out) // msig inspect - cmd = []string{"msig", "inspect", "--vesting", "--decode-params", msigRobustAddr} - out = clientCLI.RunCmd(cmd) + out = clientCLI.RunCmd("msig", "inspect", "--vesting", "--decode-params", msigRobustAddr) fmt.Println(out) // Expect correct balance @@ -87,7 +84,7 @@ func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNod // msig add-approve --from= 0 false txnID := "0" paramFrom = fmt.Sprintf("--from=%s", walletAddrs[1]) - cmd = []string{ + out = clientCLI.RunCmd( "msig", "add-approve", paramFrom, msigRobustAddr, @@ -95,7 +92,6 @@ func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNod txnID, walletAddrs[3].String(), "false", - } - out = clientCLI.RunCmd(cmd) + ) fmt.Println(out) } From 31a474a1ca15208787f5b38c342455bc6f2cebd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 26 Oct 2020 15:16:10 +0100 Subject: [PATCH 263/313] Move CommPWriter to lib/ --- lib/commp/writer.go | 113 ++++++++++++++++++++++++++++++++ lib/commp/writer_test.go | 88 +++++++++++++++++++++++++ node/impl/client/client.go | 112 ++----------------------------- node/impl/client/client_test.go | 87 ------------------------ 4 files changed, 207 insertions(+), 193 deletions(-) create mode 100644 lib/commp/writer.go create mode 100644 lib/commp/writer_test.go diff --git a/lib/commp/writer.go b/lib/commp/writer.go new file mode 100644 index 000000000..4c5e3350c --- /dev/null +++ b/lib/commp/writer.go @@ -0,0 +1,113 @@ +package commp + +import ( + "bytes" + "math/bits" + + "github.com/ipfs/go-cid" + "golang.org/x/xerrors" + + ffi "github.com/filecoin-project/filecoin-ffi" + "github.com/filecoin-project/go-padreader" + "github.com/filecoin-project/go-state-types/abi" + + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" + "github.com/filecoin-project/lotus/extern/sector-storage/zerocomm" +) + +const commPBufPad = abi.PaddedPieceSize(8 << 20) +const CommPBuf = abi.UnpaddedPieceSize(commPBufPad - (commPBufPad / 128)) // can't use .Unpadded() for const + +type Writer struct { + len int64 + buf [CommPBuf]byte + leaves []cid.Cid +} + +func (w *Writer) Write(p []byte) (int, error) { + n := len(p) + for len(p) > 0 { + buffered := int(w.len % int64(len(w.buf))) + toBuffer := len(w.buf) - buffered + if toBuffer > len(p) { + toBuffer = len(p) + } + + copied := copy(w.buf[buffered:], p[:toBuffer]) + p = p[copied:] + w.len += int64(copied) + + if copied > 0 && w.len%int64(len(w.buf)) == 0 { + leaf, err := ffiwrapper.GeneratePieceCIDFromFile(abi.RegisteredSealProof_StackedDrg32GiBV1, bytes.NewReader(w.buf[:]), CommPBuf) + if err != nil { + return 0, err + } + w.leaves = append(w.leaves, leaf) + } + } + return n, nil +} + +func (w *Writer) Sum() (api.DataCIDSize, error) { + // process last non-zero leaf if exists + lastLen := w.len % int64(len(w.buf)) + rawLen := w.len + + // process remaining bit of data + if lastLen != 0 { + if len(w.leaves) != 0 { + copy(w.buf[lastLen:], make([]byte, int(int64(CommPBuf)-lastLen))) + lastLen = int64(CommPBuf) + } + + r, sz := padreader.New(bytes.NewReader(w.buf[:lastLen]), uint64(lastLen)) + p, err := ffiwrapper.GeneratePieceCIDFromFile(abi.RegisteredSealProof_StackedDrg32GiBV1, r, sz) + if err != nil { + return api.DataCIDSize{}, err + } + + if sz < CommPBuf { // special case for pieces smaller than 16MiB + return api.DataCIDSize{ + PayloadSize: w.len, + PieceSize: sz.Padded(), + PieceCID: p, + }, nil + } + + w.leaves = append(w.leaves, p) + } + + // pad with zero pieces to power-of-two size + fillerLeaves := (1 << (bits.Len(uint(len(w.leaves) - 1)))) - len(w.leaves) + for i := 0; i < fillerLeaves; i++ { + w.leaves = append(w.leaves, zerocomm.ZeroPieceCommitment(CommPBuf)) + } + + if len(w.leaves) == 1 { + return api.DataCIDSize{ + PayloadSize: rawLen, + PieceSize: abi.PaddedPieceSize(len(w.leaves)) * commPBufPad, + PieceCID: w.leaves[0], + }, nil + } + + pieces := make([]abi.PieceInfo, len(w.leaves)) + for i, leaf := range w.leaves { + pieces[i] = abi.PieceInfo{ + Size: commPBufPad, + PieceCID: leaf, + } + } + + p, err := ffi.GenerateUnsealedCID(abi.RegisteredSealProof_StackedDrg32GiBV1, pieces) + if err != nil { + return api.DataCIDSize{}, xerrors.Errorf("generating unsealed CID: %w", err) + } + + return api.DataCIDSize{ + PayloadSize: rawLen, + PieceSize: abi.PaddedPieceSize(len(w.leaves)) * commPBufPad, + PieceCID: p, + }, nil +} diff --git a/lib/commp/writer_test.go b/lib/commp/writer_test.go new file mode 100644 index 000000000..284648e4e --- /dev/null +++ b/lib/commp/writer_test.go @@ -0,0 +1,88 @@ +package commp + +import ( + "bytes" + "crypto/rand" + "fmt" + "io" + "io/ioutil" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/filecoin-project/go-padreader" + "github.com/filecoin-project/go-state-types/abi" + + "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" + "github.com/filecoin-project/lotus/extern/sector-storage/zerocomm" +) + +func TestWriterZero(t *testing.T) { + for i, s := range []struct { + writes []int + expect abi.PaddedPieceSize + }{ + {writes: []int{200}, expect: 256}, + {writes: []int{200, 200}, expect: 512}, + + {writes: []int{int(CommPBuf)}, expect: commPBufPad}, + {writes: []int{int(CommPBuf) * 2}, expect: 2 * commPBufPad}, + {writes: []int{int(CommPBuf), int(CommPBuf), int(CommPBuf)}, expect: 4 * commPBufPad}, + {writes: []int{int(CommPBuf), int(CommPBuf), int(CommPBuf), int(CommPBuf), int(CommPBuf), int(CommPBuf), int(CommPBuf), int(CommPBuf), int(CommPBuf)}, expect: 16 * commPBufPad}, + + {writes: []int{200, int(CommPBuf)}, expect: 2 * commPBufPad}, + } { + s := s + t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { + w := &Writer{} + var rawSum int64 + for _, write := range s.writes { + rawSum += int64(write) + _, err := w.Write(make([]byte, write)) + require.NoError(t, err) + } + + p, err := w.Sum() + require.NoError(t, err) + require.Equal(t, rawSum, p.PayloadSize) + require.Equal(t, s.expect, p.PieceSize) + require.Equal(t, zerocomm.ZeroPieceCommitment(s.expect.Unpadded()).String(), p.PieceCID.String()) + }) + } +} + +func TestWriterData(t *testing.T) { + dataLen := float64(CommPBuf) * 6.78 + data, _ := ioutil.ReadAll(io.LimitReader(rand.Reader, int64(dataLen))) + + pr, sz := padreader.New(bytes.NewReader(data), uint64(dataLen)) + exp, err := ffiwrapper.GeneratePieceCIDFromFile(abi.RegisteredSealProof_StackedDrg32GiBV1, pr, sz) + require.NoError(t, err) + + w := &Writer{} + _, err = io.Copy(w, bytes.NewReader(data)) + require.NoError(t, err) + + res, err := w.Sum() + require.NoError(t, err) + + require.Equal(t, exp.String(), res.PieceCID.String()) +} + +func BenchmarkWriterZero(b *testing.B) { + buf := make([]byte, int(CommPBuf)*b.N) + b.SetBytes(int64(CommPBuf)) + b.ResetTimer() + + w := &Writer{} + + _, err := w.Write(buf) + require.NoError(b, err) + o, err := w.Sum() + + b.StopTimer() + + require.NoError(b, err) + require.Equal(b, zerocomm.ZeroPieceCommitment(o.PieceSize.Unpadded()).String(), o.PieceCID.String()) + require.Equal(b, int64(CommPBuf)*int64(b.N), o.PayloadSize) +} diff --git a/node/impl/client/client.go b/node/impl/client/client.go index 63158e581..aa6a81dad 100644 --- a/node/impl/client/client.go +++ b/node/impl/client/client.go @@ -2,18 +2,16 @@ package client import ( "bufio" - "bytes" "context" "fmt" "io" - "math/bits" "os" - "github.com/filecoin-project/go-state-types/dline" - - "github.com/filecoin-project/go-state-types/big" "golang.org/x/xerrors" + "github.com/filecoin-project/go-padreader" + "github.com/filecoin-project/go-state-types/big" + "github.com/filecoin-project/go-state-types/dline" "github.com/ipfs/go-blockservice" "github.com/ipfs/go-cid" "github.com/ipfs/go-cidutil" @@ -34,7 +32,6 @@ import ( mh "github.com/multiformats/go-multihash" "go.uber.org/fx" - ffi "github.com/filecoin-project/filecoin-ffi" "github.com/filecoin-project/go-address" datatransfer "github.com/filecoin-project/go-data-transfer" "github.com/filecoin-project/go-fil-markets/discovery" @@ -44,17 +41,16 @@ import ( "github.com/filecoin-project/go-fil-markets/shared" "github.com/filecoin-project/go-fil-markets/storagemarket" "github.com/filecoin-project/go-multistore" - "github.com/filecoin-project/go-padreader" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" - "github.com/filecoin-project/lotus/extern/sector-storage/zerocomm" marketevents "github.com/filecoin-project/lotus/markets/loggers" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/lib/commp" "github.com/filecoin-project/lotus/markets/utils" "github.com/filecoin-project/lotus/node/impl/full" "github.com/filecoin-project/lotus/node/impl/paych" @@ -714,107 +710,11 @@ func (a *API) ClientDealSize(ctx context.Context, root cid.Cid) (api.DataSize, e }, nil } -const commPBufPad = abi.PaddedPieceSize(8 << 20) -const commPBuf = abi.UnpaddedPieceSize(commPBufPad - (commPBufPad / 128)) // can't use .Unpadded() for const - -type commPWriter struct { - len int64 - buf [commPBuf]byte - leaves []cid.Cid -} - -func (w *commPWriter) Write(p []byte) (int, error) { - n := len(p) - for len(p) > 0 { - buffered := int(w.len % int64(len(w.buf))) - toBuffer := len(w.buf) - buffered - if toBuffer > len(p) { - toBuffer = len(p) - } - - copied := copy(w.buf[buffered:], p[:toBuffer]) - p = p[copied:] - w.len += int64(copied) - - if copied > 0 && w.len%int64(len(w.buf)) == 0 { - leaf, err := ffiwrapper.GeneratePieceCIDFromFile(abi.RegisteredSealProof_StackedDrg32GiBV1, bytes.NewReader(w.buf[:]), commPBuf) - if err != nil { - return 0, err - } - w.leaves = append(w.leaves, leaf) - } - } - return n, nil -} - -func (w *commPWriter) Sum() (api.DataCIDSize, error) { - // process last non-zero leaf if exists - lastLen := w.len % int64(len(w.buf)) - rawLen := w.len - - // process remaining bit of data - if lastLen != 0 { - if len(w.leaves) != 0 { - copy(w.buf[lastLen:], make([]byte, int(int64(commPBuf)-lastLen))) - lastLen = int64(commPBuf) - } - - r, sz := padreader.New(bytes.NewReader(w.buf[:lastLen]), uint64(lastLen)) - p, err := ffiwrapper.GeneratePieceCIDFromFile(abi.RegisteredSealProof_StackedDrg32GiBV1, r, sz) - if err != nil { - return api.DataCIDSize{}, err - } - - if sz < commPBuf { // special case for pieces smaller than 16MiB - return api.DataCIDSize{ - PayloadSize: w.len, - PieceSize: sz.Padded(), - PieceCID: p, - }, nil - } - - w.leaves = append(w.leaves, p) - } - - // pad with zero pieces to power-of-two size - fillerLeaves := (1 << (bits.Len(uint(len(w.leaves) - 1)))) - len(w.leaves) - for i := 0; i < fillerLeaves; i++ { - w.leaves = append(w.leaves, zerocomm.ZeroPieceCommitment(commPBuf)) - } - - if len(w.leaves) == 1 { - return api.DataCIDSize{ - PayloadSize: rawLen, - PieceSize: abi.PaddedPieceSize(len(w.leaves)) * commPBufPad, - PieceCID: w.leaves[0], - }, nil - } - - pieces := make([]abi.PieceInfo, len(w.leaves)) - for i, leaf := range w.leaves { - pieces[i] = abi.PieceInfo{ - Size: commPBufPad, - PieceCID: leaf, - } - } - - p, err := ffi.GenerateUnsealedCID(abi.RegisteredSealProof_StackedDrg32GiBV1, pieces) - if err != nil { - return api.DataCIDSize{}, xerrors.Errorf("generating unsealed CID: %w", err) - } - - return api.DataCIDSize{ - PayloadSize: rawLen, - PieceSize: abi.PaddedPieceSize(len(w.leaves)) * commPBufPad, - PieceCID: p, - }, nil -} - func (a *API) ClientDealPieceCID(ctx context.Context, root cid.Cid) (api.DataCIDSize, error) { dag := merkledag.NewDAGService(blockservice.New(a.CombinedBstore, offline.Exchange(a.CombinedBstore))) - w := &commPWriter{} - bw := bufio.NewWriterSize(w, int(commPBuf)) + w := &commp.Writer{} + bw := bufio.NewWriterSize(w, int(commp.CommPBuf)) err := car.WriteCar(ctx, dag, []cid.Cid{root}, w) if err != nil { diff --git a/node/impl/client/client_test.go b/node/impl/client/client_test.go index 00e7b828c..da13c8ef3 100644 --- a/node/impl/client/client_test.go +++ b/node/impl/client/client_test.go @@ -1,88 +1 @@ package client - -import ( - "bytes" - "crypto/rand" - "fmt" - "io" - "io/ioutil" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/filecoin-project/go-padreader" - "github.com/filecoin-project/go-state-types/abi" - - "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" - "github.com/filecoin-project/lotus/extern/sector-storage/zerocomm" -) - -func TestClientDealPieceCIDZero(t *testing.T) { - for i, s := range []struct { - writes []int - expect abi.PaddedPieceSize - }{ - {writes: []int{200}, expect: 256}, - {writes: []int{200, 200}, expect: 512}, - - {writes: []int{int(commPBuf)}, expect: commPBufPad}, - {writes: []int{int(commPBuf) * 2}, expect: 2 * commPBufPad}, - {writes: []int{int(commPBuf), int(commPBuf), int(commPBuf)}, expect: 4 * commPBufPad}, - {writes: []int{int(commPBuf), int(commPBuf), int(commPBuf), int(commPBuf), int(commPBuf), int(commPBuf), int(commPBuf), int(commPBuf), int(commPBuf)}, expect: 16 * commPBufPad}, - - {writes: []int{200, int(commPBuf)}, expect: 2 * commPBufPad}, - } { - s := s - t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { - w := &commPWriter{} - var rawSum int64 - for _, write := range s.writes { - rawSum += int64(write) - _, err := w.Write(make([]byte, write)) - require.NoError(t, err) - } - - p, err := w.Sum() - require.NoError(t, err) - require.Equal(t, rawSum, p.PayloadSize) - require.Equal(t, s.expect, p.PieceSize) - require.Equal(t, zerocomm.ZeroPieceCommitment(s.expect.Unpadded()).String(), p.PieceCID.String()) - }) - } -} - -func TestClientDealPieceCIDData(t *testing.T) { - dataLen := float64(commPBuf) * 6.78 - data, _ := ioutil.ReadAll(io.LimitReader(rand.Reader, int64(dataLen))) - - pr, sz := padreader.New(bytes.NewReader(data), uint64(dataLen)) - exp, err := ffiwrapper.GeneratePieceCIDFromFile(abi.RegisteredSealProof_StackedDrg32GiBV1, pr, sz) - require.NoError(t, err) - - w := &commPWriter{} - _, err = io.Copy(w, bytes.NewReader(data)) - require.NoError(t, err) - - res, err := w.Sum() - require.NoError(t, err) - - require.Equal(t, exp.String(), res.PieceCID.String()) -} - -func BenchmarkClientDealPieceCIDZero(b *testing.B) { - buf := make([]byte, int(commPBuf)*b.N) - b.SetBytes(int64(commPBuf)) - b.ResetTimer() - - w := &commPWriter{} - - _, err := w.Write(buf) - require.NoError(b, err) - o, err := w.Sum() - - b.StopTimer() - - require.NoError(b, err) - require.Equal(b, zerocomm.ZeroPieceCommitment(o.PieceSize.Unpadded()).String(), o.PieceCID.String()) - require.Equal(b, int64(commPBuf)*int64(b.N), o.PayloadSize) -} From 8923524f6a9d732671a37bfa33c38eab4334af48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 26 Oct 2020 15:32:52 +0100 Subject: [PATCH 264/313] Make EarlyExpiration in sectors list less scary --- cmd/lotus-storage-miner/sectors.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/lotus-storage-miner/sectors.go b/cmd/lotus-storage-miner/sectors.go index 0c3ef58d6..967e2d413 100644 --- a/cmd/lotus-storage-miner/sectors.go +++ b/cmd/lotus-storage-miner/sectors.go @@ -219,7 +219,7 @@ var sectorsListCmd = &cli.Command{ tablewriter.Col("Deals"), tablewriter.Col("DealWeight"), tablewriter.NewLineCol("Error"), - tablewriter.NewLineCol("EarlyExpiration")) + tablewriter.NewLineCol("RecoveryTimeout")) fast := cctx.Bool("fast") @@ -281,7 +281,7 @@ var sectorsListCmd = &cli.Command{ } if st.Early > 0 { - m["EarlyExpiration"] = color.YellowString(lcli.EpochTime(head.Height(), st.Early)) + m["RecoveryTimeout"] = color.YellowString(lcli.EpochTime(head.Height(), st.Early)) } } } From ea6afe84db823a26e5c2ed85f03c2b0f16ef6049 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Tue, 20 Oct 2020 17:36:23 +0200 Subject: [PATCH 265/313] Add election run-dummy command Signed-off-by: Jakub Sztandera --- cmd/lotus-shed/election.go | 65 ++++++++++++++++++++++++++++++++++++++ cmd/lotus-shed/main.go | 1 + 2 files changed, 66 insertions(+) create mode 100644 cmd/lotus-shed/election.go diff --git a/cmd/lotus-shed/election.go b/cmd/lotus-shed/election.go new file mode 100644 index 000000000..bc053dea4 --- /dev/null +++ b/cmd/lotus-shed/election.go @@ -0,0 +1,65 @@ +package main + +import ( + "encoding/binary" + "fmt" + + "github.com/filecoin-project/lotus/chain/types" + lcli "github.com/filecoin-project/lotus/cli" + "github.com/urfave/cli/v2" + "golang.org/x/xerrors" +) + +var electionCmd = &cli.Command{ + Name: "election", + Usage: "commands related to leader election", + Subcommands: []*cli.Command{ + electionRunDummy, + }, +} + +var electionRunDummy = &cli.Command{ + Name: "run-dummy", + Usage: "runs dummy elections with given power", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "network-power", + }, + &cli.StringFlag{ + Name: "miner-power", + }, + &cli.Uint64Flag{ + Name: "seed", + Value: 4, + }, + }, + Action: func(cctx *cli.Context) error { + ctx := lcli.ReqContext(cctx) + minerPow, err := types.BigFromString(cctx.String("miner-power")) + if err != nil { + return xerrors.Errorf("decoding miner-power: %w", err) + } + networkPow, err := types.BigFromString(cctx.String("network-power")) + if err != nil { + return xerrors.Errorf("decoding miner-power: %w", err) + } + + ep := &types.ElectionProof{} + ep.VRFProof = make([]byte, 32) + binary.BigEndian.PutUint64(ep.VRFProof, cctx.Uint64("seed")) + + i := uint64(0) + for { + if ctx.Err() != nil { + return ctx.Err() + } + binary.BigEndian.PutUint64(ep.VRFProof[8:], i) + j := ep.ComputeWinCount(minerPow, networkPow) + _, err := fmt.Printf("%t, %d\n", j != 0, j) + if err != nil { + return err + } + i++ + } + }, +} diff --git a/cmd/lotus-shed/main.go b/cmd/lotus-shed/main.go index 8201ec111..eef357596 100644 --- a/cmd/lotus-shed/main.go +++ b/cmd/lotus-shed/main.go @@ -46,6 +46,7 @@ func main() { ledgerCmd, sectorsCmd, msgCmd, + electionCmd, } app := &cli.App{ From cced3bf9ee9cc9c51e72c85b06aa14ba44ddbb22 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Tue, 20 Oct 2020 17:45:03 +0200 Subject: [PATCH 266/313] Randomize seed Signed-off-by: Jakub Sztandera --- cmd/lotus-shed/election.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cmd/lotus-shed/election.go b/cmd/lotus-shed/election.go index bc053dea4..ffe30d163 100644 --- a/cmd/lotus-shed/election.go +++ b/cmd/lotus-shed/election.go @@ -3,6 +3,7 @@ package main import ( "encoding/binary" "fmt" + "math/rand" "github.com/filecoin-project/lotus/chain/types" lcli "github.com/filecoin-project/lotus/cli" @@ -30,7 +31,7 @@ var electionRunDummy = &cli.Command{ }, &cli.Uint64Flag{ Name: "seed", - Value: 4, + Value: 0, }, }, Action: func(cctx *cli.Context) error { @@ -46,7 +47,11 @@ var electionRunDummy = &cli.Command{ ep := &types.ElectionProof{} ep.VRFProof = make([]byte, 32) - binary.BigEndian.PutUint64(ep.VRFProof, cctx.Uint64("seed")) + seed := cctx.Uint64("seed") + if seed == 0 { + seed = rand.Uint64() + } + binary.BigEndian.PutUint64(ep.VRFProof, seed) i := uint64(0) for { From 8141f7b6a6c913d9c0a59e76a58feb7319ad1a34 Mon Sep 17 00:00:00 2001 From: Ingar Shu Date: Fri, 23 Oct 2020 14:51:15 -0700 Subject: [PATCH 267/313] Expose ClientDealSize API via client stat CLI --- cli/client.go | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/cli/client.go b/cli/client.go index b25a5e8ca..524fdf900 100644 --- a/cli/client.go +++ b/cli/client.go @@ -84,6 +84,7 @@ var clientCmd = &cli.Command{ WithCategory("data", clientImportCmd), WithCategory("data", clientDropCmd), WithCategory("data", clientLocalCmd), + WithCategory("data", clientStat), WithCategory("retrieval", clientFindCmd), WithCategory("retrieval", clientRetrieveCmd), WithCategory("util", clientCommPCmd), @@ -1639,6 +1640,39 @@ var clientInfoCmd = &cli.Command{ }, } +var clientStat = &cli.Command{ + Name: "stat", + Usage: "Print information about a locally stored file (piece size, etc)", + ArgsUsage: "", + Action: func(cctx *cli.Context) error { + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + if !cctx.Args().Present() || cctx.NArg() != 1 { + return fmt.Errorf("must specify cid of data") + } + + dataCid, err := cid.Parse(cctx.Args().First()) + if err != nil { + return fmt.Errorf("parsing data cid: %w", err) + } + + ds, err := api.ClientDealSize(ctx, dataCid) + if err != nil { + return err + } + + fmt.Printf("Piece Size : %v\n", ds.PieceSize) + fmt.Printf("Payload Size: %v\n", ds.PayloadSize) + + return nil + }, +} + var clientRestartTransfer = &cli.Command{ Name: "restart-transfer", Usage: "Force restart a stalled data transfer", From 0d384050fa623437654f47a7fb8a06fa3986f27d Mon Sep 17 00:00:00 2001 From: frrist Date: Mon, 26 Oct 2020 14:20:25 -0700 Subject: [PATCH 268/313] polish: add Equals method to MinerInfo shim --- chain/actors/builtin/miner/miner.go | 1 + chain/actors/builtin/miner/v0.go | 9 +++++++++ chain/actors/builtin/miner/v2.go | 9 +++++++++ 3 files changed, 19 insertions(+) diff --git a/chain/actors/builtin/miner/miner.go b/chain/actors/builtin/miner/miner.go index aad41e8a9..5821d092b 100644 --- a/chain/actors/builtin/miner/miner.go +++ b/chain/actors/builtin/miner/miner.go @@ -77,6 +77,7 @@ type State interface { DeadlinesChanged(State) (bool, error) Info() (MinerInfo, error) + MinerInfoChanged(State) (bool, error) DeadlineInfo(epoch abi.ChainEpoch) (*dline.Info, error) diff --git a/chain/actors/builtin/miner/v0.go b/chain/actors/builtin/miner/v0.go index c79f4a2f7..69160e4e0 100644 --- a/chain/actors/builtin/miner/v0.go +++ b/chain/actors/builtin/miner/v0.go @@ -277,6 +277,15 @@ func (s *state0) DeadlinesChanged(other State) (bool, error) { return !s.State.Deadlines.Equals(other0.Deadlines), nil } +func (s *state0) MinerInfoChanged(other State) (bool, error) { + other0, ok := other.(*state0) + if !ok { + // treat an upgrade as a change, always + return true, nil + } + return !s.State.Info.Equals(other0.State.Info), nil +} + func (s *state0) Info() (MinerInfo, error) { info, err := s.State.GetInfo(s.store) if err != nil { diff --git a/chain/actors/builtin/miner/v2.go b/chain/actors/builtin/miner/v2.go index c686fa483..2c67484ea 100644 --- a/chain/actors/builtin/miner/v2.go +++ b/chain/actors/builtin/miner/v2.go @@ -276,6 +276,15 @@ func (s *state2) DeadlinesChanged(other State) (bool, error) { return !s.State.Deadlines.Equals(other2.Deadlines), nil } +func (s *state2) MinerInfoChanged(other State) (bool, error) { + other0, ok := other.(*state2) + if !ok { + // treat an upgrade as a change, always + return true, nil + } + return !s.State.Info.Equals(other0.State.Info), nil +} + func (s *state2) Info() (MinerInfo, error) { info, err := s.State.GetInfo(s.store) if err != nil { From 0d06f8fa2bcaa455a9b8a476eee2ef13abe926c0 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 20 Oct 2020 20:35:18 -0700 Subject: [PATCH 269/313] Add commands to change the worker key --- cmd/lotus-storage-miner/actor.go | 220 ++++++++++++++++++++++++++ cmd/lotus-storage-miner/actor_test.go | 131 +++++++++++++++ node/modules/storageminer.go | 14 +- storage/miner.go | 20 ++- storage/wdpost_run.go | 44 ++---- storage/wdpost_run_test.go | 2 - storage/wdpost_sched.go | 8 +- 7 files changed, 386 insertions(+), 53 deletions(-) create mode 100644 cmd/lotus-storage-miner/actor_test.go diff --git a/cmd/lotus-storage-miner/actor.go b/cmd/lotus-storage-miner/actor.go index 611ea8f19..69486eaf5 100644 --- a/cmd/lotus-storage-miner/actor.go +++ b/cmd/lotus-storage-miner/actor.go @@ -40,6 +40,8 @@ var actorCmd = &cli.Command{ actorSetPeeridCmd, actorSetOwnerCmd, actorControl, + actorProposeChangeWorker, + actorConfirmChangeWorker, }, } @@ -698,3 +700,221 @@ var actorSetOwnerCmd = &cli.Command{ return nil }, } + +var actorProposeChangeWorker = &cli.Command{ + Name: "propose-change-worker", + Usage: "Propose a worker address change", + ArgsUsage: "[address]", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "really-do-it", + Usage: "Actually send transaction performing the action", + Value: false, + }, + }, + Action: func(cctx *cli.Context) error { + if !cctx.Args().Present() { + return fmt.Errorf("must pass address of new worker address") + } + + nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx) + if err != nil { + return err + } + defer closer() + + api, acloser, err := lcli.GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer acloser() + + ctx := lcli.ReqContext(cctx) + + na, err := address.NewFromString(cctx.Args().First()) + if err != nil { + return err + } + + newAddr, err := api.StateLookupID(ctx, na, types.EmptyTSK) + if err != nil { + return err + } + + maddr, err := nodeApi.ActorAddress(ctx) + if err != nil { + return err + } + + mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK) + if err != nil { + return err + } + + if mi.NewWorker.Empty() { + if mi.Worker == newAddr { + return fmt.Errorf("worker address already set to %s", na) + } + } else { + if mi.NewWorker == newAddr { + return fmt.Errorf("change to worker address %s already pending", na) + } + } + + if !cctx.Bool("really-do-it") { + fmt.Fprintln(cctx.App.Writer, "Pass --really-do-it to actually execute this action") + return nil + } + + cwp := &miner2.ChangeWorkerAddressParams{ + NewWorker: newAddr, + NewControlAddrs: mi.ControlAddresses, + } + + sp, err := actors.SerializeParams(cwp) + if err != nil { + return xerrors.Errorf("serializing params: %w", err) + } + + smsg, err := api.MpoolPushMessage(ctx, &types.Message{ + From: mi.Owner, + To: maddr, + Method: miner.Methods.ChangeWorkerAddress, + Value: big.Zero(), + Params: sp, + }, nil) + if err != nil { + return xerrors.Errorf("mpool push: %w", err) + } + + fmt.Fprintln(cctx.App.Writer, "Propose Message CID:", smsg.Cid()) + + // wait for it to get mined into a block + wait, err := api.StateWaitMsg(ctx, smsg.Cid(), build.MessageConfidence) + if err != nil { + return err + } + + // check it executed successfully + if wait.Receipt.ExitCode != 0 { + fmt.Fprintln(cctx.App.Writer, "Propose worker change failed!") + return err + } + + mi, err = api.StateMinerInfo(ctx, maddr, wait.TipSet) + if err != nil { + return err + } + if mi.NewWorker != newAddr { + return fmt.Errorf("Proposed worker address change not reflected on chain: expected '%s', found '%s'", na, mi.NewWorker) + } + + fmt.Fprintf(cctx.App.Writer, "Worker key change to %s successfully proposed.\n", na) + fmt.Fprintf(cctx.App.Writer, "Call 'confirm-change-worker' at or after height %d to complete.\n", mi.WorkerChangeEpoch) + + return nil + }, +} + +var actorConfirmChangeWorker = &cli.Command{ + Name: "confirm-change-worker", + Usage: "Confirm a worker address change", + ArgsUsage: "[address]", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "really-do-it", + Usage: "Actually send transaction performing the action", + Value: false, + }, + }, + Action: func(cctx *cli.Context) error { + if !cctx.Args().Present() { + return fmt.Errorf("must pass address of new worker address") + } + + nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx) + if err != nil { + return err + } + defer closer() + + api, acloser, err := lcli.GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer acloser() + + ctx := lcli.ReqContext(cctx) + + na, err := address.NewFromString(cctx.Args().First()) + if err != nil { + return err + } + + newAddr, err := api.StateLookupID(ctx, na, types.EmptyTSK) + if err != nil { + return err + } + + maddr, err := nodeApi.ActorAddress(ctx) + if err != nil { + return err + } + + mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK) + if err != nil { + return err + } + + if mi.NewWorker.Empty() { + return xerrors.Errorf("no worker key change proposed") + } else if mi.NewWorker != newAddr { + return xerrors.Errorf("worker key %s does not match current worker key proposal %s", newAddr, mi.NewWorker) + } + + if head, err := api.ChainHead(ctx); err != nil { + return xerrors.Errorf("failed to get the chain head: %w", err) + } else if head.Height() < mi.WorkerChangeEpoch { + return xerrors.Errorf("worker key change cannot be confirmed until %d, current height is %d", mi.WorkerChangeEpoch, head.Height()) + } + + if !cctx.Bool("really-do-it") { + fmt.Fprintln(cctx.App.Writer, "Pass --really-do-it to actually execute this action") + return nil + } + + smsg, err := api.MpoolPushMessage(ctx, &types.Message{ + From: mi.Owner, + To: maddr, + Method: miner.Methods.ConfirmUpdateWorkerKey, + Value: big.Zero(), + }, nil) + if err != nil { + return xerrors.Errorf("mpool push: %w", err) + } + + fmt.Fprintln(cctx.App.Writer, "Confirm Message CID:", smsg.Cid()) + + // wait for it to get mined into a block + wait, err := api.StateWaitMsg(ctx, smsg.Cid(), build.MessageConfidence) + if err != nil { + return err + } + + // check it executed successfully + if wait.Receipt.ExitCode != 0 { + fmt.Fprintln(cctx.App.Writer, "Worker change failed!") + return err + } + + mi, err = api.StateMinerInfo(ctx, maddr, wait.TipSet) + if err != nil { + return err + } + if mi.Worker != newAddr { + return fmt.Errorf("Confirmed worker address change not reflected on chain: expected '%s', found '%s'", newAddr, mi.Worker) + } + + return nil + }, +} diff --git a/cmd/lotus-storage-miner/actor_test.go b/cmd/lotus-storage-miner/actor_test.go new file mode 100644 index 000000000..58c0169f8 --- /dev/null +++ b/cmd/lotus-storage-miner/actor_test.go @@ -0,0 +1,131 @@ +package main + +import ( + "bytes" + "context" + "flag" + "fmt" + "regexp" + "strconv" + "sync/atomic" + "testing" + "time" + + logging "github.com/ipfs/go-log/v2" + "github.com/stretchr/testify/require" + "github.com/urfave/cli/v2" + + "github.com/filecoin-project/go-state-types/abi" + + "github.com/filecoin-project/lotus/api/test" + "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/actors/policy" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/lib/lotuslog" + "github.com/filecoin-project/lotus/node/repo" + builder "github.com/filecoin-project/lotus/node/test" +) + +func TestWorkerKeyChange(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode") + } + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + _ = logging.SetLogLevel("*", "INFO") + + policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048)) + policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1) + policy.SetMinVerifiedDealSize(abi.NewStoragePower(256)) + + lotuslog.SetupLogLevels() + logging.SetLogLevel("miner", "ERROR") + logging.SetLogLevel("chainstore", "ERROR") + logging.SetLogLevel("chain", "ERROR") + logging.SetLogLevel("sub", "ERROR") + logging.SetLogLevel("storageminer", "ERROR") + + blocktime := 1 * time.Millisecond + + n, sn := builder.MockSbBuilder(t, []test.FullNodeOpts{test.FullNodeWithUpgradeAt(1)}, test.OneMiner) + + output := bytes.NewBuffer(nil) + run := func(cmd *cli.Command, args ...string) error { + app := cli.NewApp() + app.Metadata = map[string]interface{}{ + "repoType": repo.StorageMiner, + "testnode-full": n[0], + "testnode-storage": sn[0], + } + app.Writer = output + build.RunningNodeType = build.NodeMiner + + fs := flag.NewFlagSet("", flag.ContinueOnError) + for _, f := range cmd.Flags { + if err := f.Apply(fs); err != nil { + return err + } + } + require.NoError(t, fs.Parse(args)) + + cctx := cli.NewContext(app, fs, nil) + return cmd.Action(cctx) + } + + // setup miner + mine := int64(1) + done := make(chan struct{}) + go func() { + defer close(done) + for atomic.LoadInt64(&mine) == 1 { + time.Sleep(blocktime) + if err := sn[0].MineOne(ctx, test.MineNext); err != nil { + t.Error(err) + } + } + }() + defer func() { + atomic.AddInt64(&mine, -1) + fmt.Println("shutting down mining") + <-done + }() + + client := n[0] + + newKey, err := client.WalletNew(ctx, types.KTBLS) + require.NoError(t, err) + + // Initialize wallet. + test.SendFunds(ctx, t, client, newKey, abi.NewTokenAmount(0)) + + require.NoError(t, run(actorProposeChangeWorker, "--really-do-it", newKey.String())) + + result := output.String() + output.Reset() + + require.Contains(t, result, fmt.Sprintf("Worker key change to %s successfully proposed.", newKey)) + + epochRe := regexp.MustCompile("at or after height (?P[0-9]+) to complete") + matches := epochRe.FindStringSubmatch(result) + require.NotNil(t, matches) + targetEpoch, err := strconv.Atoi(matches[1]) + require.NoError(t, err) + require.NotZero(t, targetEpoch) + + // Too early. + require.Error(t, run(actorConfirmChangeWorker, "--really-do-it", newKey.String())) + output.Reset() + + for { + head, err := client.ChainHead(ctx) + require.NoError(t, err) + if head.Height() >= abi.ChainEpoch(targetEpoch) { + break + } + build.Clock.Sleep(10 * blocktime) + } + require.NoError(t, run(actorConfirmChangeWorker, "--really-do-it", newKey.String())) + output.Reset() +} diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 66b16e9f3..eef67cfc4 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -186,22 +186,12 @@ func StorageMiner(fc config.MinerFeeConfig) func(params StorageMinerParams) (*st ctx := helpers.LifecycleCtx(mctx, lc) - mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK) + fps, err := storage.NewWindowedPoStScheduler(api, fc, sealer, sealer, j, maddr) if err != nil { return nil, err } - worker, err := api.StateAccountKey(ctx, mi.Worker, types.EmptyTSK) - if err != nil { - return nil, err - } - - fps, err := storage.NewWindowedPoStScheduler(api, fc, sealer, sealer, j, maddr, worker) - if err != nil { - return nil, err - } - - sm, err := storage.NewMiner(api, maddr, worker, h, ds, sealer, sc, verif, gsd, fc, j) + sm, err := storage.NewMiner(api, maddr, h, ds, sealer, sc, verif, gsd, fc, j) if err != nil { return nil, err } diff --git a/storage/miner.go b/storage/miner.go index b5a2fd6a5..b982e9087 100644 --- a/storage/miner.go +++ b/storage/miner.go @@ -49,8 +49,7 @@ type Miner struct { sc sealing.SectorIDCounter verif ffiwrapper.Verifier - maddr address.Address - worker address.Address + maddr address.Address getSealConfig dtypes.GetSealingConfigFunc sealing *sealing.Sealing @@ -111,7 +110,7 @@ type storageMinerApi interface { WalletHas(context.Context, address.Address) (bool, error) } -func NewMiner(api storageMinerApi, maddr, worker address.Address, h host.Host, ds datastore.Batching, sealer sectorstorage.SectorManager, sc sealing.SectorIDCounter, verif ffiwrapper.Verifier, gsd dtypes.GetSealingConfigFunc, feeCfg config.MinerFeeConfig, journal journal.Journal) (*Miner, error) { +func NewMiner(api storageMinerApi, maddr address.Address, h host.Host, ds datastore.Batching, sealer sectorstorage.SectorManager, sc sealing.SectorIDCounter, verif ffiwrapper.Verifier, gsd dtypes.GetSealingConfigFunc, feeCfg config.MinerFeeConfig, journal journal.Journal) (*Miner, error) { m := &Miner{ api: api, feeCfg: feeCfg, @@ -122,7 +121,6 @@ func NewMiner(api storageMinerApi, maddr, worker address.Address, h host.Host, d verif: verif, maddr: maddr, - worker: worker, getSealConfig: gsd, journal: journal, sealingEvtType: journal.RegisterEventType("storage", "sealing_states"), @@ -174,7 +172,17 @@ func (m *Miner) Stop(ctx context.Context) error { } func (m *Miner) runPreflightChecks(ctx context.Context) error { - has, err := m.api.WalletHas(ctx, m.worker) + mi, err := m.api.StateMinerInfo(ctx, m.maddr, types.EmptyTSK) + if err != nil { + return xerrors.Errorf("failed to resolve miner info: %w", err) + } + + workerKey, err := m.api.StateAccountKey(ctx, mi.Worker, types.EmptyTSK) + if err != nil { + return xerrors.Errorf("failed to resolve worker key: %w", err) + } + + has, err := m.api.WalletHas(ctx, workerKey) if err != nil { return xerrors.Errorf("failed to check wallet for worker key: %w", err) } @@ -183,7 +191,7 @@ func (m *Miner) runPreflightChecks(ctx context.Context) error { return errors.New("key for worker not found in local wallet") } - log.Infof("starting up miner %s, worker addr %s", m.maddr, m.worker) + log.Infof("starting up miner %s, worker addr %s", m.maddr, workerKey) return nil } diff --git a/storage/wdpost_run.go b/storage/wdpost_run.go index f456ff68d..87438fec3 100644 --- a/storage/wdpost_run.go +++ b/storage/wdpost_run.go @@ -292,13 +292,14 @@ func (s *WindowPoStScheduler) checkNextRecoveries(ctx context.Context, dlIdx uin msg := &types.Message{ To: s.actor, - From: s.worker, Method: miner.Methods.DeclareFaultsRecovered, Params: enc, Value: types.NewInt(0), } spec := &api.MessageSendSpec{MaxFee: abi.TokenAmount(s.feeCfg.MaxWindowPoStGasFee)} - s.setSender(ctx, msg, spec) + if err := s.setSender(ctx, msg, spec); err != nil { + return recoveries, nil, err + } sm, err := s.api.MpoolPushMessage(ctx, msg, &api.MessageSendSpec{MaxFee: abi.TokenAmount(s.feeCfg.MaxWindowPoStGasFee)}) if err != nil { @@ -376,13 +377,14 @@ func (s *WindowPoStScheduler) checkNextFaults(ctx context.Context, dlIdx uint64, msg := &types.Message{ To: s.actor, - From: s.worker, Method: miner.Methods.DeclareFaults, Params: enc, Value: types.NewInt(0), // TODO: Is there a fee? } spec := &api.MessageSendSpec{MaxFee: abi.TokenAmount(s.feeCfg.MaxWindowPoStGasFee)} - s.setSender(ctx, msg, spec) + if err := s.setSender(ctx, msg, spec); err != nil { + return faults, nil, err + } sm, err := s.api.MpoolPushMessage(ctx, msg, spec) if err != nil { @@ -716,13 +718,14 @@ func (s *WindowPoStScheduler) submitPost(ctx context.Context, proof *miner.Submi msg := &types.Message{ To: s.actor, - From: s.worker, Method: miner.Methods.SubmitWindowedPoSt, Params: enc, Value: types.NewInt(0), } spec := &api.MessageSendSpec{MaxFee: abi.TokenAmount(s.feeCfg.MaxWindowPoStGasFee)} - s.setSender(ctx, msg, spec) + if err := s.setSender(ctx, msg, spec); err != nil { + return nil, err + } // TODO: consider maybe caring about the output sm, err := s.api.MpoolPushMessage(ctx, msg, spec) @@ -750,33 +753,18 @@ func (s *WindowPoStScheduler) submitPost(ctx context.Context, proof *miner.Submi return sm, nil } -func (s *WindowPoStScheduler) setSender(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec) { +func (s *WindowPoStScheduler) setSender(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec) error { mi, err := s.api.StateMinerInfo(ctx, s.actor, types.EmptyTSK) if err != nil { - log.Errorw("error getting miner info", "error", err) - - // better than just failing - msg.From = s.worker - return - } - worker, err := s.api.StateAccountKey(ctx, mi.Worker, types.EmptyTSK) - if err != nil { - log.Errorw("error getting account key", "error", err) - - msg.From = s.worker - return - } - // worker should keep sync with state on chain, if not, will met error when estimate msg gas. - if s.worker != worker { - s.worker = worker - msg.From = s.worker + return xerrors.Errorf("error getting miner info: %w", err) } + // use the worker as a fallback + msg.From = mi.Worker gm, err := s.api.GasEstimateMessageGas(ctx, msg, spec, types.EmptyTSK) if err != nil { log.Errorw("estimating gas", "error", err) - msg.From = s.worker - return + return nil } *msg = *gm @@ -785,9 +773,9 @@ func (s *WindowPoStScheduler) setSender(ctx context.Context, msg *types.Message, pa, err := AddressFor(ctx, s.api, mi, PoStAddr, minFunds) if err != nil { log.Errorw("error selecting address for window post", "error", err) - msg.From = s.worker - return + return nil } msg.From = pa + return nil } diff --git a/storage/wdpost_run_test.go b/storage/wdpost_run_test.go index 4145a6e70..83a523fac 100644 --- a/storage/wdpost_run_test.go +++ b/storage/wdpost_run_test.go @@ -128,7 +128,6 @@ func TestWDPostDoPost(t *testing.T) { proofType := abi.RegisteredPoStProof_StackedDrgWindow2KiBV1 postAct := tutils.NewIDAddr(t, 100) - workerAct := tutils.NewIDAddr(t, 101) mockStgMinerAPI := newMockStorageMinerAPI() @@ -169,7 +168,6 @@ func TestWDPostDoPost(t *testing.T) { faultTracker: &mockFaultTracker{}, proofType: proofType, actor: postAct, - worker: workerAct, journal: journal.NilJournal(), } diff --git a/storage/wdpost_sched.go b/storage/wdpost_sched.go index 99bea2e66..1a1422e19 100644 --- a/storage/wdpost_sched.go +++ b/storage/wdpost_sched.go @@ -31,8 +31,7 @@ type WindowPoStScheduler struct { partitionSectors uint64 ch *changeHandler - actor address.Address - worker address.Address + actor address.Address evtTypes [4]journal.EventType journal journal.Journal @@ -41,7 +40,7 @@ type WindowPoStScheduler struct { // failLk sync.Mutex } -func NewWindowedPoStScheduler(api storageMinerApi, fc config.MinerFeeConfig, sb storage.Prover, ft sectorstorage.FaultTracker, j journal.Journal, actor address.Address, worker address.Address) (*WindowPoStScheduler, error) { +func NewWindowedPoStScheduler(api storageMinerApi, fc config.MinerFeeConfig, sb storage.Prover, ft sectorstorage.FaultTracker, j journal.Journal, actor address.Address) (*WindowPoStScheduler, error) { mi, err := api.StateMinerInfo(context.TODO(), actor, types.EmptyTSK) if err != nil { return nil, xerrors.Errorf("getting sector size: %w", err) @@ -60,8 +59,7 @@ func NewWindowedPoStScheduler(api storageMinerApi, fc config.MinerFeeConfig, sb proofType: rt, partitionSectors: mi.WindowPoStPartitionSectors, - actor: actor, - worker: worker, + actor: actor, evtTypes: [...]journal.EventType{ evtTypeWdPoStScheduler: j.RegisterEventType("wdpost", "scheduler"), evtTypeWdPoStProofs: j.RegisterEventType("wdpost", "proofs_processed"), From 832c0998e44c65704d154da2adf19a8447cee62b Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 23 Oct 2020 19:52:23 -0700 Subject: [PATCH 270/313] validate that block propagation works after a worker key change --- cmd/lotus-storage-miner/actor_test.go | 45 +++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/cmd/lotus-storage-miner/actor_test.go b/cmd/lotus-storage-miner/actor_test.go index 58c0169f8..949171699 100644 --- a/cmd/lotus-storage-miner/actor_test.go +++ b/cmd/lotus-storage-miner/actor_test.go @@ -44,12 +44,22 @@ func TestWorkerKeyChange(t *testing.T) { logging.SetLogLevel("miner", "ERROR") logging.SetLogLevel("chainstore", "ERROR") logging.SetLogLevel("chain", "ERROR") + logging.SetLogLevel("pubsub", "ERROR") logging.SetLogLevel("sub", "ERROR") logging.SetLogLevel("storageminer", "ERROR") blocktime := 1 * time.Millisecond - n, sn := builder.MockSbBuilder(t, []test.FullNodeOpts{test.FullNodeWithUpgradeAt(1)}, test.OneMiner) + n, sn := builder.MockSbBuilder(t, []test.FullNodeOpts{test.FullNodeWithUpgradeAt(1), test.FullNodeWithUpgradeAt(1)}, test.OneMiner) + + client1 := n[0] + client2 := n[1] + + // Connect the nodes. + addrinfo, err := client1.NetAddrsListen(ctx) + require.NoError(t, err) + err = client2.NetConnect(ctx, addrinfo) + require.NoError(t, err) output := bytes.NewBuffer(nil) run := func(cmd *cli.Command, args ...string) error { @@ -92,13 +102,11 @@ func TestWorkerKeyChange(t *testing.T) { <-done }() - client := n[0] - - newKey, err := client.WalletNew(ctx, types.KTBLS) + newKey, err := client1.WalletNew(ctx, types.KTBLS) require.NoError(t, err) // Initialize wallet. - test.SendFunds(ctx, t, client, newKey, abi.NewTokenAmount(0)) + test.SendFunds(ctx, t, client1, newKey, abi.NewTokenAmount(0)) require.NoError(t, run(actorProposeChangeWorker, "--really-do-it", newKey.String())) @@ -119,7 +127,7 @@ func TestWorkerKeyChange(t *testing.T) { output.Reset() for { - head, err := client.ChainHead(ctx) + head, err := client1.ChainHead(ctx) require.NoError(t, err) if head.Height() >= abi.ChainEpoch(targetEpoch) { break @@ -128,4 +136,29 @@ func TestWorkerKeyChange(t *testing.T) { } require.NoError(t, run(actorConfirmChangeWorker, "--really-do-it", newKey.String())) output.Reset() + + head, err := client1.ChainHead(ctx) + require.NoError(t, err) + + // Wait for finality (worker key switch). + targetHeight := head.Height() + policy.ChainFinality + for { + head, err := client1.ChainHead(ctx) + require.NoError(t, err) + if head.Height() >= targetHeight { + break + } + build.Clock.Sleep(10 * blocktime) + } + + // Make sure the other node can catch up. + for i := 0; i < 20; i++ { + head, err := client2.ChainHead(ctx) + require.NoError(t, err) + if head.Height() >= targetHeight { + return + } + build.Clock.Sleep(10 * blocktime) + } + t.Fatal("failed to reach target epoch on the second miner") } From c0f6f834b711c76f6fdfe78cfa363fbd06b89c59 Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Tue, 27 Oct 2020 11:07:54 +0100 Subject: [PATCH 271/313] fix: flaky TestCLIDealFlow --- cli/paych_test.go | 8 ++++---- cli/test/client.go | 20 ++++++++++++++++++-- cli/test/mockcli.go | 4 +++- cli/test/multisig.go | 2 +- 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/cli/paych_test.go b/cli/paych_test.go index fcd9c99a3..dac8411c5 100644 --- a/cli/paych_test.go +++ b/cli/paych_test.go @@ -48,7 +48,7 @@ func TestPaymentChannels(t *testing.T) { receiverAddr := addrs[1] // Create mock CLI - mockCLI := clitest.NewMockCLI(t, Commands) + mockCLI := clitest.NewMockCLI(ctx, t, Commands) creatorCLI := mockCLI.Client(paymentCreator.ListenAddr) receiverCLI := mockCLI.Client(paymentReceiver.ListenAddr) @@ -99,7 +99,7 @@ func TestPaymentChannelStatus(t *testing.T) { receiverAddr := addrs[1] // Create mock CLI - mockCLI := clitest.NewMockCLI(t, Commands) + mockCLI := clitest.NewMockCLI(ctx, t, Commands) creatorCLI := mockCLI.Client(paymentCreator.ListenAddr) // creator: paych status-by-from-to @@ -179,7 +179,7 @@ func TestPaymentChannelVouchers(t *testing.T) { receiverAddr := addrs[1] // Create mock CLI - mockCLI := clitest.NewMockCLI(t, Commands) + mockCLI := clitest.NewMockCLI(ctx, t, Commands) creatorCLI := mockCLI.Client(paymentCreator.ListenAddr) receiverCLI := mockCLI.Client(paymentReceiver.ListenAddr) @@ -310,7 +310,7 @@ func TestPaymentChannelVoucherCreateShortfall(t *testing.T) { receiverAddr := addrs[1] // Create mock CLI - mockCLI := clitest.NewMockCLI(t, Commands) + mockCLI := clitest.NewMockCLI(ctx, t, Commands) creatorCLI := mockCLI.Client(paymentCreator.ListenAddr) // creator: paych add-funds diff --git a/cli/test/client.go b/cli/test/client.go index c74f881b0..95abd39c2 100644 --- a/cli/test/client.go +++ b/cli/test/client.go @@ -11,6 +11,8 @@ import ( "testing" "time" + "golang.org/x/xerrors" + "github.com/filecoin-project/lotus/api/test" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/types" @@ -25,7 +27,7 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) defer cancel() // Create mock CLI - mockCLI := NewMockCLI(t, cmds) + mockCLI := NewMockCLI(ctx, t, cmds) clientCLI := mockCLI.Client(clientNode.ListenAddr) // Get the miner address @@ -74,7 +76,7 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) // Wait for provider to start sealing deal dealStatus := "" - for dealStatus != "StorageDealSealing" { + for { // client list-deals out = clientCLI.RunCmd("client", "list-deals") fmt.Println("list-deals:\n", out) @@ -88,6 +90,9 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) } dealStatus = parts[3] fmt.Println(" Deal status:", dealStatus) + if dealComplete(t, dealStatus) { + break + } time.Sleep(time.Second) } @@ -101,3 +106,14 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) fmt.Println("retrieve:\n", out) require.Regexp(t, regexp.MustCompile("Success"), out) } + +func dealComplete(t *testing.T, dealStatus string) bool { + switch dealStatus { + case "StorageDealFailing", "StorageDealError": + t.Fatal(xerrors.Errorf("Storage deal failed with status: " + dealStatus)) + case "StorageDealStaged", "StorageDealSealing", "StorageDealActive", "StorageDealExpired", "StorageDealSlashed": + return true + } + + return false +} diff --git a/cli/test/mockcli.go b/cli/test/mockcli.go index 65b0bc30a..e8eb78f1b 100644 --- a/cli/test/mockcli.go +++ b/cli/test/mockcli.go @@ -2,6 +2,7 @@ package test import ( "bytes" + "context" "flag" "strings" "testing" @@ -18,7 +19,7 @@ type MockCLI struct { out *bytes.Buffer } -func NewMockCLI(t *testing.T, cmds []*lcli.Command) *MockCLI { +func NewMockCLI(ctx context.Context, t *testing.T, cmds []*lcli.Command) *MockCLI { // Create a CLI App with an --api-url flag so that we can specify which node // the command should be executed against app := &lcli.App{ @@ -36,6 +37,7 @@ func NewMockCLI(t *testing.T, cmds []*lcli.Command) *MockCLI { app.Setup() cctx := lcli.NewContext(app, &flag.FlagSet{}, nil) + cctx.Context = ctx return &MockCLI{t: t, cmds: cmds, cctx: cctx, out: &out} } diff --git a/cli/test/multisig.go b/cli/test/multisig.go index dd867d0b5..5a60894e6 100644 --- a/cli/test/multisig.go +++ b/cli/test/multisig.go @@ -18,7 +18,7 @@ func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNod ctx := context.Background() // Create mock CLI - mockCLI := NewMockCLI(t, cmds) + mockCLI := NewMockCLI(ctx, t, cmds) clientCLI := mockCLI.Client(clientNode.ListenAddr) // Create some wallets on the node to use for testing multisig From efc8d90bc1ac829bcb6655d0c572df7a885ca858 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 27 Oct 2020 12:19:12 +0100 Subject: [PATCH 272/313] Fix flaky testMiningReal --- api/test/mining.go | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/api/test/mining.go b/api/test/mining.go index 90e8e8a45..11953b95d 100644 --- a/api/test/mining.go +++ b/api/test/mining.go @@ -58,14 +58,11 @@ func (ts *testSuite) testMiningReal(t *testing.T) { newHeads, err := api.ChainNotify(ctx) require.NoError(t, err) - initHead := (<-newHeads)[0] - if initHead.Val.Height() != 2 { - <-newHeads - } + at := (<-newHeads)[0].Val.Height() h1, err := api.ChainHead(ctx) require.NoError(t, err) - require.Equal(t, abi.ChainEpoch(2), h1.Height()) + require.Equal(t, int64(at), int64(h1.Height())) MineUntilBlock(ctx, t, apis[0], sn[0], nil) require.NoError(t, err) @@ -74,16 +71,16 @@ func (ts *testSuite) testMiningReal(t *testing.T) { h2, err := api.ChainHead(ctx) require.NoError(t, err) - require.Equal(t, abi.ChainEpoch(3), h2.Height()) + require.Greater(t, int64(h2.Height()), int64(h1.Height())) MineUntilBlock(ctx, t, apis[0], sn[0], nil) require.NoError(t, err) <-newHeads - h2, err = api.ChainHead(ctx) + h3, err := api.ChainHead(ctx) require.NoError(t, err) - require.Equal(t, abi.ChainEpoch(4), h2.Height()) + require.Greater(t, int64(h3.Height()), int64(h2.Height())) } func TestDealMining(t *testing.T, b APIBuilder, blocktime time.Duration, carExport bool) { From 843c0719e08c857f8345643629a6f2fe8fbab121 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 27 Oct 2020 14:38:46 +0100 Subject: [PATCH 273/313] Update FFI --- extern/filecoin-ffi | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index f640612a1..f0e58c2a8 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit f640612a1a1f7a2dd8b3a49e1531db0aa0f63447 +Subproject commit f0e58c2a8563ce1ac0f672d43da409dc3bb55b56 diff --git a/go.sum b/go.sum index f0ef4ea6b..3ced99135 100644 --- a/go.sum +++ b/go.sum @@ -1459,8 +1459,8 @@ github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1: github.com/whyrusleeping/yamux v1.1.5/go.mod h1:E8LnQQ8HKx5KD29HZFUwM1PxCOdPRzGwur1mcYhXcD8= github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xlab/c-for-go v0.0.0-20200718154222-87b0065af829 h1:wb7xrDzfkLgPHsSEBm+VSx6aDdi64VtV0xvP0E6j8bk= -github.com/xlab/c-for-go v0.0.0-20200718154222-87b0065af829/go.mod h1:h/1PEBwj7Ym/8kOuMWvO2ujZ6Lt+TMbySEXNhjjR87I= +github.com/xlab/c-for-go v0.0.0-20201002084316-c134bfab968f h1:nMhj+x/m7ZQsHBz0L3gpytp0v6ogokdbrQDnhB8Kh7s= +github.com/xlab/c-for-go v0.0.0-20201002084316-c134bfab968f/go.mod h1:h/1PEBwj7Ym/8kOuMWvO2ujZ6Lt+TMbySEXNhjjR87I= github.com/xlab/pkgconfig v0.0.0-20170226114623-cea12a0fd245 h1:Sw125DKxZhPUI4JLlWugkzsrlB50jR9v2khiD9FxuSo= github.com/xlab/pkgconfig v0.0.0-20170226114623-cea12a0fd245/go.mod h1:C+diUUz7pxhNY6KAoLgrTYARGWnt82zWTylZlxT92vk= github.com/xorcare/golden v0.6.0/go.mod h1:7T39/ZMvaSEZlBPoYfVFmsBLmUl3uz9IuzWj/U6FtvQ= From 84b567c790c45f467ce6274be14c50c9d8097b1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 28 Oct 2020 13:39:28 +0100 Subject: [PATCH 274/313] sched: move worker funcs to a separate file --- extern/sector-storage/sched.go | 400 ------------------------- extern/sector-storage/sched_worker.go | 411 ++++++++++++++++++++++++++ 2 files changed, 411 insertions(+), 400 deletions(-) create mode 100644 extern/sector-storage/sched_worker.go diff --git a/extern/sector-storage/sched.go b/extern/sector-storage/sched.go index a4e6a6239..34cba4cf2 100644 --- a/extern/sector-storage/sched.go +++ b/extern/sector-storage/sched.go @@ -12,7 +12,6 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/lotus/extern/sector-storage/sealtasks" - "github.com/filecoin-project/lotus/extern/sector-storage/stores" "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) @@ -531,405 +530,6 @@ func (sh *scheduler) trySched() { sh.openWindows = newOpenWindows } -// context only used for startup -func (sh *scheduler) runWorker(ctx context.Context, w Worker) error { - info, err := w.Info(ctx) - if err != nil { - return xerrors.Errorf("getting worker info: %w", err) - } - - sessID, err := w.Session(ctx) - if err != nil { - return xerrors.Errorf("getting worker session: %w", err) - } - if sessID == ClosedWorkerID { - return xerrors.Errorf("worker already closed") - } - - worker := &workerHandle{ - w: w, - info: info, - - preparing: &activeResources{}, - active: &activeResources{}, - enabled: true, - - closingMgr: make(chan struct{}), - closedMgr: make(chan struct{}), - } - - wid := WorkerID(sessID) - - sh.workersLk.Lock() - _, exist := sh.workers[wid] - if exist { - // this is ok, we're already handling this worker in a different goroutine - return nil - } - - sh.workers[wid] = worker - sh.workersLk.Unlock() - - go func() { - ctx, cancel := context.WithCancel(context.TODO()) - defer cancel() - - defer close(worker.closedMgr) - - scheduledWindows := make(chan *schedWindow, SchedWindows) - taskDone := make(chan struct{}, 1) - windowsRequested := 0 - - disable := func(ctx context.Context) error { - done := make(chan struct{}) - - // request cleanup in the main scheduler goroutine - select { - case sh.workerDisable <- workerDisableReq{ - activeWindows: worker.activeWindows, - wid: wid, - done: func() { - close(done) - }, - }: - case <-ctx.Done(): - return ctx.Err() - case <-sh.closing: - return nil - } - - // wait for cleanup to complete - select { - case <-done: - case <-ctx.Done(): - return ctx.Err() - case <-sh.closing: - return nil - } - - worker.activeWindows = worker.activeWindows[:0] - windowsRequested = 0 - return nil - } - - defer func() { - log.Warnw("Worker closing", "workerid", sessID) - - if err := disable(ctx); err != nil { - log.Warnw("failed to disable worker", "worker", wid, "error", err) - } - - sh.workersLk.Lock() - delete(sh.workers, wid) - sh.workersLk.Unlock() - }() - - heartbeatTimer := time.NewTicker(stores.HeartbeatInterval) - defer heartbeatTimer.Stop() - - for { - sh.workersLk.Lock() - enabled := worker.enabled - sh.workersLk.Unlock() - - // ask for more windows if we need them (non-blocking) - for ; enabled && windowsRequested < SchedWindows; windowsRequested++ { - select { - case sh.windowRequests <- &schedWindowRequest{ - worker: wid, - done: scheduledWindows, - }: - case <-sh.closing: - return - case <-worker.closingMgr: - return - } - } - - // wait for more windows to come in, or for tasks to get finished (blocking) - for { - - // first ping the worker and check session - { - sctx, scancel := context.WithTimeout(ctx, stores.HeartbeatInterval/2) - curSes, err := worker.w.Session(sctx) - scancel() - if err != nil { - // Likely temporary error - - log.Warnw("failed to check worker session", "error", err) - - if err := disable(ctx); err != nil { - log.Warnw("failed to disable worker with session error", "worker", wid, "error", err) - } - - select { - case <-heartbeatTimer.C: - continue - case w := <-scheduledWindows: - // was in flight when initially disabled, return - worker.wndLk.Lock() - worker.activeWindows = append(worker.activeWindows, w) - worker.wndLk.Unlock() - - if err := disable(ctx); err != nil { - log.Warnw("failed to disable worker with session error", "worker", wid, "error", err) - } - case <-sh.closing: - return - case <-worker.closingMgr: - return - } - continue - } - - if curSes != sessID { - if curSes != ClosedWorkerID { - // worker restarted - log.Warnw("worker session changed (worker restarted?)", "initial", sessID, "current", curSes) - } - - return - } - - // session looks good - if !enabled { - sh.workersLk.Lock() - worker.enabled = true - sh.workersLk.Unlock() - - // we'll send window requests on the next loop - } - } - - select { - case <-heartbeatTimer.C: - continue - case w := <-scheduledWindows: - worker.wndLk.Lock() - worker.activeWindows = append(worker.activeWindows, w) - worker.wndLk.Unlock() - case <-taskDone: - log.Debugw("task done", "workerid", wid) - case <-sh.closing: - return - case <-worker.closingMgr: - return - } - - break - } - - // process assigned windows (non-blocking) - sh.workersLk.RLock() - worker.wndLk.Lock() - - windowsRequested -= sh.workerCompactWindows(worker, wid) - assignLoop: - // process windows in order - for len(worker.activeWindows) > 0 { - firstWindow := worker.activeWindows[0] - - // process tasks within a window, preferring tasks at lower indexes - for len(firstWindow.todo) > 0 { - tidx := -1 - - worker.lk.Lock() - for t, todo := range firstWindow.todo { - needRes := ResourceTable[todo.taskType][sh.spt] - if worker.preparing.canHandleRequest(needRes, wid, "startPreparing", worker.info.Resources) { - tidx = t - break - } - } - worker.lk.Unlock() - - if tidx == -1 { - break assignLoop - } - - todo := firstWindow.todo[tidx] - - log.Debugf("assign worker sector %d", todo.sector.Number) - err := sh.assignWorker(taskDone, wid, worker, todo) - - if err != nil { - log.Error("assignWorker error: %+v", err) - go todo.respond(xerrors.Errorf("assignWorker error: %w", err)) - } - - // Note: we're not freeing window.allocated resources here very much on purpose - copy(firstWindow.todo[tidx:], firstWindow.todo[tidx+1:]) - firstWindow.todo[len(firstWindow.todo)-1] = nil - firstWindow.todo = firstWindow.todo[:len(firstWindow.todo)-1] - } - - copy(worker.activeWindows, worker.activeWindows[1:]) - worker.activeWindows[len(worker.activeWindows)-1] = nil - worker.activeWindows = worker.activeWindows[:len(worker.activeWindows)-1] - - windowsRequested-- - } - - worker.wndLk.Unlock() - sh.workersLk.RUnlock() - } - }() - - return nil -} - -func (sh *scheduler) workerCompactWindows(worker *workerHandle, wid WorkerID) int { - // move tasks from older windows to newer windows if older windows - // still can fit them - if len(worker.activeWindows) > 1 { - for wi, window := range worker.activeWindows[1:] { - lower := worker.activeWindows[wi] - var moved []int - - for ti, todo := range window.todo { - needRes := ResourceTable[todo.taskType][sh.spt] - if !lower.allocated.canHandleRequest(needRes, wid, "compactWindows", worker.info.Resources) { - continue - } - - moved = append(moved, ti) - lower.todo = append(lower.todo, todo) - lower.allocated.add(worker.info.Resources, needRes) - window.allocated.free(worker.info.Resources, needRes) - } - - if len(moved) > 0 { - newTodo := make([]*workerRequest, 0, len(window.todo)-len(moved)) - for i, t := range window.todo { - if len(moved) > 0 && moved[0] == i { - moved = moved[1:] - continue - } - - newTodo = append(newTodo, t) - } - window.todo = newTodo - } - } - } - - var compacted int - var newWindows []*schedWindow - - for _, window := range worker.activeWindows { - if len(window.todo) == 0 { - compacted++ - continue - } - - newWindows = append(newWindows, window) - } - - worker.activeWindows = newWindows - - return compacted -} - -func (sh *scheduler) assignWorker(taskDone chan struct{}, wid WorkerID, w *workerHandle, req *workerRequest) error { - needRes := ResourceTable[req.taskType][sh.spt] - - w.lk.Lock() - w.preparing.add(w.info.Resources, needRes) - w.lk.Unlock() - - go func() { - err := req.prepare(req.ctx, sh.wt.worker(wid, w.w)) - sh.workersLk.Lock() - - if err != nil { - w.lk.Lock() - w.preparing.free(w.info.Resources, needRes) - w.lk.Unlock() - sh.workersLk.Unlock() - - select { - case taskDone <- struct{}{}: - case <-sh.closing: - log.Warnf("scheduler closed while sending response (prepare error: %+v)", err) - } - - select { - case req.ret <- workerResponse{err: err}: - case <-req.ctx.Done(): - log.Warnf("request got cancelled before we could respond (prepare error: %+v)", err) - case <-sh.closing: - log.Warnf("scheduler closed while sending response (prepare error: %+v)", err) - } - return - } - - err = w.active.withResources(wid, w.info.Resources, needRes, &sh.workersLk, func() error { - w.lk.Lock() - w.preparing.free(w.info.Resources, needRes) - w.lk.Unlock() - sh.workersLk.Unlock() - defer sh.workersLk.Lock() // we MUST return locked from this function - - select { - case taskDone <- struct{}{}: - case <-sh.closing: - } - - err = req.work(req.ctx, sh.wt.worker(wid, w.w)) - - select { - case req.ret <- workerResponse{err: err}: - case <-req.ctx.Done(): - log.Warnf("request got cancelled before we could respond") - case <-sh.closing: - log.Warnf("scheduler closed while sending response") - } - - return nil - }) - - sh.workersLk.Unlock() - - // This error should always be nil, since nothing is setting it, but just to be safe: - if err != nil { - log.Errorf("error executing worker (withResources): %+v", err) - } - }() - - return nil -} - -func (sh *scheduler) workerCleanup(wid WorkerID, w *workerHandle) { - select { - case <-w.closingMgr: - default: - close(w.closingMgr) - } - - sh.workersLk.Unlock() - select { - case <-w.closedMgr: - case <-time.After(time.Second): - log.Errorf("timeout closing worker manager goroutine %d", wid) - } - sh.workersLk.Lock() - - if !w.cleanupStarted { - w.cleanupStarted = true - - newWindows := make([]*schedWindowRequest, 0, len(sh.openWindows)) - for _, window := range sh.openWindows { - if window.worker != wid { - newWindows = append(newWindows, window) - } - } - sh.openWindows = newWindows - - log.Debugf("worker %d dropped", wid) - } -} - func (sh *scheduler) schedClose() { sh.workersLk.Lock() defer sh.workersLk.Unlock() diff --git a/extern/sector-storage/sched_worker.go b/extern/sector-storage/sched_worker.go new file mode 100644 index 000000000..4897c30dc --- /dev/null +++ b/extern/sector-storage/sched_worker.go @@ -0,0 +1,411 @@ +package sectorstorage + +import ( + "context" + "time" + + "golang.org/x/xerrors" + + "github.com/filecoin-project/lotus/extern/sector-storage/stores" +) + +// context only used for startup +func (sh *scheduler) runWorker(ctx context.Context, w Worker) error { + info, err := w.Info(ctx) + if err != nil { + return xerrors.Errorf("getting worker info: %w", err) + } + + sessID, err := w.Session(ctx) + if err != nil { + return xerrors.Errorf("getting worker session: %w", err) + } + if sessID == ClosedWorkerID { + return xerrors.Errorf("worker already closed") + } + + worker := &workerHandle{ + w: w, + info: info, + + preparing: &activeResources{}, + active: &activeResources{}, + enabled: true, + + closingMgr: make(chan struct{}), + closedMgr: make(chan struct{}), + } + + wid := WorkerID(sessID) + + sh.workersLk.Lock() + _, exist := sh.workers[wid] + if exist { + log.Warnw("duplicated worker added", "id", wid) + + // this is ok, we're already handling this worker in a different goroutine + return nil + } + + sh.workers[wid] = worker + sh.workersLk.Unlock() + + go func() { + ctx, cancel := context.WithCancel(context.TODO()) + defer cancel() + + defer close(worker.closedMgr) + + scheduledWindows := make(chan *schedWindow, SchedWindows) + taskDone := make(chan struct{}, 1) + windowsRequested := 0 + + disable := func(ctx context.Context) error { + done := make(chan struct{}) + + // request cleanup in the main scheduler goroutine + select { + case sh.workerDisable <- workerDisableReq{ + activeWindows: worker.activeWindows, + wid: wid, + done: func() { + close(done) + }, + }: + case <-ctx.Done(): + return ctx.Err() + case <-sh.closing: + return nil + } + + // wait for cleanup to complete + select { + case <-done: + case <-ctx.Done(): + return ctx.Err() + case <-sh.closing: + return nil + } + + worker.activeWindows = worker.activeWindows[:0] + windowsRequested = 0 + return nil + } + + defer func() { + log.Warnw("Worker closing", "workerid", sessID) + + if err := disable(ctx); err != nil { + log.Warnw("failed to disable worker", "worker", wid, "error", err) + } + + sh.workersLk.Lock() + delete(sh.workers, wid) + sh.workersLk.Unlock() + }() + + heartbeatTimer := time.NewTicker(stores.HeartbeatInterval) + defer heartbeatTimer.Stop() + + for { + sh.workersLk.Lock() + enabled := worker.enabled + sh.workersLk.Unlock() + + // ask for more windows if we need them (non-blocking) + for ; enabled && windowsRequested < SchedWindows; windowsRequested++ { + select { + case sh.windowRequests <- &schedWindowRequest{ + worker: wid, + done: scheduledWindows, + }: + case <-sh.closing: + return + case <-worker.closingMgr: + return + } + } + + // wait for more windows to come in, or for tasks to get finished (blocking) + for { + + // first ping the worker and check session + { + sctx, scancel := context.WithTimeout(ctx, stores.HeartbeatInterval/2) + curSes, err := worker.w.Session(sctx) + scancel() + if err != nil { + // Likely temporary error + + log.Warnw("failed to check worker session", "error", err) + + if err := disable(ctx); err != nil { + log.Warnw("failed to disable worker with session error", "worker", wid, "error", err) + } + + select { + case <-heartbeatTimer.C: + continue + case w := <-scheduledWindows: + // was in flight when initially disabled, return + worker.wndLk.Lock() + worker.activeWindows = append(worker.activeWindows, w) + worker.wndLk.Unlock() + + if err := disable(ctx); err != nil { + log.Warnw("failed to disable worker with session error", "worker", wid, "error", err) + } + case <-sh.closing: + return + case <-worker.closingMgr: + return + } + continue + } + + if curSes != sessID { + if curSes != ClosedWorkerID { + // worker restarted + log.Warnw("worker session changed (worker restarted?)", "initial", sessID, "current", curSes) + } + + return + } + + // session looks good + if !enabled { + sh.workersLk.Lock() + worker.enabled = true + sh.workersLk.Unlock() + + // we'll send window requests on the next loop + } + } + + select { + case <-heartbeatTimer.C: + continue + case w := <-scheduledWindows: + worker.wndLk.Lock() + worker.activeWindows = append(worker.activeWindows, w) + worker.wndLk.Unlock() + case <-taskDone: + log.Debugw("task done", "workerid", wid) + case <-sh.closing: + return + case <-worker.closingMgr: + return + } + + break + } + + // process assigned windows (non-blocking) + sh.workersLk.RLock() + worker.wndLk.Lock() + + windowsRequested -= sh.workerCompactWindows(worker, wid) + assignLoop: + // process windows in order + for len(worker.activeWindows) > 0 { + firstWindow := worker.activeWindows[0] + + // process tasks within a window, preferring tasks at lower indexes + for len(firstWindow.todo) > 0 { + tidx := -1 + + worker.lk.Lock() + for t, todo := range firstWindow.todo { + needRes := ResourceTable[todo.taskType][sh.spt] + if worker.preparing.canHandleRequest(needRes, wid, "startPreparing", worker.info.Resources) { + tidx = t + break + } + } + worker.lk.Unlock() + + if tidx == -1 { + break assignLoop + } + + todo := firstWindow.todo[tidx] + + log.Debugf("assign worker sector %d", todo.sector.Number) + err := sh.assignWorker(taskDone, wid, worker, todo) + + if err != nil { + log.Error("assignWorker error: %+v", err) + go todo.respond(xerrors.Errorf("assignWorker error: %w", err)) + } + + // Note: we're not freeing window.allocated resources here very much on purpose + copy(firstWindow.todo[tidx:], firstWindow.todo[tidx+1:]) + firstWindow.todo[len(firstWindow.todo)-1] = nil + firstWindow.todo = firstWindow.todo[:len(firstWindow.todo)-1] + } + + copy(worker.activeWindows, worker.activeWindows[1:]) + worker.activeWindows[len(worker.activeWindows)-1] = nil + worker.activeWindows = worker.activeWindows[:len(worker.activeWindows)-1] + + windowsRequested-- + } + + worker.wndLk.Unlock() + sh.workersLk.RUnlock() + } + }() + + return nil +} + +func (sh *scheduler) workerCompactWindows(worker *workerHandle, wid WorkerID) int { + // move tasks from older windows to newer windows if older windows + // still can fit them + if len(worker.activeWindows) > 1 { + for wi, window := range worker.activeWindows[1:] { + lower := worker.activeWindows[wi] + var moved []int + + for ti, todo := range window.todo { + needRes := ResourceTable[todo.taskType][sh.spt] + if !lower.allocated.canHandleRequest(needRes, wid, "compactWindows", worker.info.Resources) { + continue + } + + moved = append(moved, ti) + lower.todo = append(lower.todo, todo) + lower.allocated.add(worker.info.Resources, needRes) + window.allocated.free(worker.info.Resources, needRes) + } + + if len(moved) > 0 { + newTodo := make([]*workerRequest, 0, len(window.todo)-len(moved)) + for i, t := range window.todo { + if len(moved) > 0 && moved[0] == i { + moved = moved[1:] + continue + } + + newTodo = append(newTodo, t) + } + window.todo = newTodo + } + } + } + + var compacted int + var newWindows []*schedWindow + + for _, window := range worker.activeWindows { + if len(window.todo) == 0 { + compacted++ + continue + } + + newWindows = append(newWindows, window) + } + + worker.activeWindows = newWindows + + return compacted +} + +func (sh *scheduler) assignWorker(taskDone chan struct{}, wid WorkerID, w *workerHandle, req *workerRequest) error { + needRes := ResourceTable[req.taskType][sh.spt] + + w.lk.Lock() + w.preparing.add(w.info.Resources, needRes) + w.lk.Unlock() + + go func() { + err := req.prepare(req.ctx, sh.wt.worker(wid, w.w)) + sh.workersLk.Lock() + + if err != nil { + w.lk.Lock() + w.preparing.free(w.info.Resources, needRes) + w.lk.Unlock() + sh.workersLk.Unlock() + + select { + case taskDone <- struct{}{}: + case <-sh.closing: + log.Warnf("scheduler closed while sending response (prepare error: %+v)", err) + } + + select { + case req.ret <- workerResponse{err: err}: + case <-req.ctx.Done(): + log.Warnf("request got cancelled before we could respond (prepare error: %+v)", err) + case <-sh.closing: + log.Warnf("scheduler closed while sending response (prepare error: %+v)", err) + } + return + } + + err = w.active.withResources(wid, w.info.Resources, needRes, &sh.workersLk, func() error { + w.lk.Lock() + w.preparing.free(w.info.Resources, needRes) + w.lk.Unlock() + sh.workersLk.Unlock() + defer sh.workersLk.Lock() // we MUST return locked from this function + + select { + case taskDone <- struct{}{}: + case <-sh.closing: + } + + err = req.work(req.ctx, sh.wt.worker(wid, w.w)) + + select { + case req.ret <- workerResponse{err: err}: + case <-req.ctx.Done(): + log.Warnf("request got cancelled before we could respond") + case <-sh.closing: + log.Warnf("scheduler closed while sending response") + } + + return nil + }) + + sh.workersLk.Unlock() + + // This error should always be nil, since nothing is setting it, but just to be safe: + if err != nil { + log.Errorf("error executing worker (withResources): %+v", err) + } + }() + + return nil +} + +func (sh *scheduler) workerCleanup(wid WorkerID, w *workerHandle) { + select { + case <-w.closingMgr: + default: + close(w.closingMgr) + } + + sh.workersLk.Unlock() + select { + case <-w.closedMgr: + case <-time.After(time.Second): + log.Errorf("timeout closing worker manager goroutine %d", wid) + } + sh.workersLk.Lock() + + if !w.cleanupStarted { + w.cleanupStarted = true + + newWindows := make([]*schedWindowRequest, 0, len(sh.openWindows)) + for _, window := range sh.openWindows { + if window.worker != wid { + newWindows = append(newWindows, window) + } + } + sh.openWindows = newWindows + + log.Debugf("worker %d dropped", wid) + } +} From 8731fe9112eb0a0e4603c596532b93108d81544e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 28 Oct 2020 14:14:38 +0100 Subject: [PATCH 275/313] sched: split worker handling into more funcs --- extern/sector-storage/sched_worker.go | 475 +++++++++++++++----------- extern/sector-storage/worker_local.go | 2 +- 2 files changed, 269 insertions(+), 208 deletions(-) diff --git a/extern/sector-storage/sched_worker.go b/extern/sector-storage/sched_worker.go index 4897c30dc..037176a11 100644 --- a/extern/sector-storage/sched_worker.go +++ b/extern/sector-storage/sched_worker.go @@ -2,13 +2,25 @@ package sectorstorage import ( "context" + "github.com/filecoin-project/lotus/extern/sector-storage/stores" "time" "golang.org/x/xerrors" - - "github.com/filecoin-project/lotus/extern/sector-storage/stores" ) +type schedWorker struct { + sh *scheduler + worker *workerHandle + + wid WorkerID + + heartbeatTimer *time.Ticker + scheduledWindows chan *schedWindow + taskDone chan struct{} + + windowsRequested int +} + // context only used for startup func (sh *scheduler) runWorker(ctx context.Context, w Worker) error { info, err := w.Info(ctx) @@ -50,215 +62,212 @@ func (sh *scheduler) runWorker(ctx context.Context, w Worker) error { sh.workers[wid] = worker sh.workersLk.Unlock() - go func() { - ctx, cancel := context.WithCancel(context.TODO()) - defer cancel() + sw := &schedWorker{ + sh: sh, + worker: worker, - defer close(worker.closedMgr) + wid: wid, - scheduledWindows := make(chan *schedWindow, SchedWindows) - taskDone := make(chan struct{}, 1) - windowsRequested := 0 + heartbeatTimer: time.NewTicker(stores.HeartbeatInterval), + scheduledWindows: make(chan *schedWindow, SchedWindows), + taskDone: make(chan struct{}, 1), - disable := func(ctx context.Context) error { - done := make(chan struct{}) + windowsRequested: 0, + } - // request cleanup in the main scheduler goroutine - select { - case sh.workerDisable <- workerDisableReq{ - activeWindows: worker.activeWindows, - wid: wid, - done: func() { - close(done) - }, - }: - case <-ctx.Done(): - return ctx.Err() - case <-sh.closing: - return nil - } - - // wait for cleanup to complete - select { - case <-done: - case <-ctx.Done(): - return ctx.Err() - case <-sh.closing: - return nil - } - - worker.activeWindows = worker.activeWindows[:0] - windowsRequested = 0 - return nil - } - - defer func() { - log.Warnw("Worker closing", "workerid", sessID) - - if err := disable(ctx); err != nil { - log.Warnw("failed to disable worker", "worker", wid, "error", err) - } - - sh.workersLk.Lock() - delete(sh.workers, wid) - sh.workersLk.Unlock() - }() - - heartbeatTimer := time.NewTicker(stores.HeartbeatInterval) - defer heartbeatTimer.Stop() - - for { - sh.workersLk.Lock() - enabled := worker.enabled - sh.workersLk.Unlock() - - // ask for more windows if we need them (non-blocking) - for ; enabled && windowsRequested < SchedWindows; windowsRequested++ { - select { - case sh.windowRequests <- &schedWindowRequest{ - worker: wid, - done: scheduledWindows, - }: - case <-sh.closing: - return - case <-worker.closingMgr: - return - } - } - - // wait for more windows to come in, or for tasks to get finished (blocking) - for { - - // first ping the worker and check session - { - sctx, scancel := context.WithTimeout(ctx, stores.HeartbeatInterval/2) - curSes, err := worker.w.Session(sctx) - scancel() - if err != nil { - // Likely temporary error - - log.Warnw("failed to check worker session", "error", err) - - if err := disable(ctx); err != nil { - log.Warnw("failed to disable worker with session error", "worker", wid, "error", err) - } - - select { - case <-heartbeatTimer.C: - continue - case w := <-scheduledWindows: - // was in flight when initially disabled, return - worker.wndLk.Lock() - worker.activeWindows = append(worker.activeWindows, w) - worker.wndLk.Unlock() - - if err := disable(ctx); err != nil { - log.Warnw("failed to disable worker with session error", "worker", wid, "error", err) - } - case <-sh.closing: - return - case <-worker.closingMgr: - return - } - continue - } - - if curSes != sessID { - if curSes != ClosedWorkerID { - // worker restarted - log.Warnw("worker session changed (worker restarted?)", "initial", sessID, "current", curSes) - } - - return - } - - // session looks good - if !enabled { - sh.workersLk.Lock() - worker.enabled = true - sh.workersLk.Unlock() - - // we'll send window requests on the next loop - } - } - - select { - case <-heartbeatTimer.C: - continue - case w := <-scheduledWindows: - worker.wndLk.Lock() - worker.activeWindows = append(worker.activeWindows, w) - worker.wndLk.Unlock() - case <-taskDone: - log.Debugw("task done", "workerid", wid) - case <-sh.closing: - return - case <-worker.closingMgr: - return - } - - break - } - - // process assigned windows (non-blocking) - sh.workersLk.RLock() - worker.wndLk.Lock() - - windowsRequested -= sh.workerCompactWindows(worker, wid) - assignLoop: - // process windows in order - for len(worker.activeWindows) > 0 { - firstWindow := worker.activeWindows[0] - - // process tasks within a window, preferring tasks at lower indexes - for len(firstWindow.todo) > 0 { - tidx := -1 - - worker.lk.Lock() - for t, todo := range firstWindow.todo { - needRes := ResourceTable[todo.taskType][sh.spt] - if worker.preparing.canHandleRequest(needRes, wid, "startPreparing", worker.info.Resources) { - tidx = t - break - } - } - worker.lk.Unlock() - - if tidx == -1 { - break assignLoop - } - - todo := firstWindow.todo[tidx] - - log.Debugf("assign worker sector %d", todo.sector.Number) - err := sh.assignWorker(taskDone, wid, worker, todo) - - if err != nil { - log.Error("assignWorker error: %+v", err) - go todo.respond(xerrors.Errorf("assignWorker error: %w", err)) - } - - // Note: we're not freeing window.allocated resources here very much on purpose - copy(firstWindow.todo[tidx:], firstWindow.todo[tidx+1:]) - firstWindow.todo[len(firstWindow.todo)-1] = nil - firstWindow.todo = firstWindow.todo[:len(firstWindow.todo)-1] - } - - copy(worker.activeWindows, worker.activeWindows[1:]) - worker.activeWindows[len(worker.activeWindows)-1] = nil - worker.activeWindows = worker.activeWindows[:len(worker.activeWindows)-1] - - windowsRequested-- - } - - worker.wndLk.Unlock() - sh.workersLk.RUnlock() - } - }() + go sw.handleWorker() return nil } +func (sw *schedWorker) handleWorker() { + worker, sh := sw.worker, sw.sh + + ctx, cancel := context.WithCancel(context.TODO()) + defer cancel() + + defer close(worker.closedMgr) + + defer func() { + log.Warnw("Worker closing", "workerid", sw.wid) + + if err := sw.disable(ctx); err != nil { + log.Warnw("failed to disable worker", "worker", sw.wid, "error", err) + } + + sh.workersLk.Lock() + delete(sh.workers, sw.wid) + sh.workersLk.Unlock() + }() + + defer sw.heartbeatTimer.Stop() + + for { + sh.workersLk.Lock() + enabled := worker.enabled + sh.workersLk.Unlock() + + // ask for more windows if we need them (non-blocking) + if enabled { + if !sw.requestWindows() { + return // graceful shutdown + } + } + + // wait for more windows to come in, or for tasks to get finished (blocking) + for { + // ping the worker and check session + if !sw.checkSession(ctx) { + return // invalid session / exiting + } + + // session looks good + if !enabled { + sh.workersLk.Lock() + worker.enabled = true + sh.workersLk.Unlock() + + // we'll send window requests on the next loop + } + + // wait for more tasks to be assigned by the main scheduler or for the worker + // to finish precessing a task + update, ok := sw.waitForUpdates() + if !ok { + return + } + if update { + break + } + } + + // process assigned windows (non-blocking) + sh.workersLk.RLock() + worker.wndLk.Lock() + + sw.windowsRequested -= sh.workerCompactWindows(worker, sw.wid) + + // send tasks to the worker + sw.processAssignedWindows() + + worker.wndLk.Unlock() + sh.workersLk.RUnlock() + } +} + +func (sw *schedWorker) disable(ctx context.Context) error { + done := make(chan struct{}) + + // request cleanup in the main scheduler goroutine + select { + case sw.sh.workerDisable <- workerDisableReq{ + activeWindows: sw.worker.activeWindows, + wid: sw.wid, + done: func() { + close(done) + }, + }: + case <-ctx.Done(): + return ctx.Err() + case <-sw.sh.closing: + return nil + } + + // wait for cleanup to complete + select { + case <-done: + case <-ctx.Done(): + return ctx.Err() + case <-sw.sh.closing: + return nil + } + + sw.worker.activeWindows = sw.worker.activeWindows[:0] + sw.windowsRequested = 0 + return nil +} + +func (sw *schedWorker) checkSession(ctx context.Context) bool { + for { + sctx, scancel := context.WithTimeout(ctx, stores.HeartbeatInterval/2) + curSes, err := sw.worker.w.Session(sctx) + scancel() + if err != nil { + // Likely temporary error + + log.Warnw("failed to check worker session", "error", err) + + if err := sw.disable(ctx); err != nil { + log.Warnw("failed to disable worker with session error", "worker", sw.wid, "error", err) + } + + select { + case <-sw.heartbeatTimer.C: + continue + case w := <-sw.scheduledWindows: + // was in flight when initially disabled, return + sw.worker.wndLk.Lock() + sw.worker.activeWindows = append(sw.worker.activeWindows, w) + sw.worker.wndLk.Unlock() + + if err := sw.disable(ctx); err != nil { + log.Warnw("failed to disable worker with session error", "worker", sw.wid, "error", err) + } + case <-sw.sh.closing: + return false + case <-sw.worker.closingMgr: + return false + } + continue + } + + if WorkerID(curSes) != sw.wid { + if curSes != ClosedWorkerID { + // worker restarted + log.Warnw("worker session changed (worker restarted?)", "initial", sw.wid, "current", curSes) + } + + return false + } + + return true + } +} + +func (sw *schedWorker) requestWindows() bool { + for ; sw.windowsRequested < SchedWindows; sw.windowsRequested++ { + select { + case sw.sh.windowRequests <- &schedWindowRequest{ + worker: sw.wid, + done: sw.scheduledWindows, + }: + case <-sw.sh.closing: + return false + case <-sw.worker.closingMgr: + return false + } + } + return true +} + +func (sw *schedWorker) waitForUpdates() (update bool, ok bool) { + select { + case <-sw.heartbeatTimer.C: + return false, true + case w := <-sw.scheduledWindows: + sw.worker.wndLk.Lock() + sw.worker.activeWindows = append(sw.worker.activeWindows, w) + sw.worker.wndLk.Unlock() + return true, true + case <-sw.taskDone: + log.Debugw("task done", "workerid", sw.wid) + return true, true + case <-sw.sh.closing: + case <-sw.worker.closingMgr: + } + return false, false +} + func (sh *scheduler) workerCompactWindows(worker *workerHandle, wid WorkerID) int { // move tasks from older windows to newer windows if older windows // still can fit them @@ -311,7 +320,59 @@ func (sh *scheduler) workerCompactWindows(worker *workerHandle, wid WorkerID) in return compacted } -func (sh *scheduler) assignWorker(taskDone chan struct{}, wid WorkerID, w *workerHandle, req *workerRequest) error { +func (sw *schedWorker) processAssignedWindows() { + worker := sw.worker + +assignLoop: + // process windows in order + for len(worker.activeWindows) > 0 { + firstWindow := worker.activeWindows[0] + + // process tasks within a window, preferring tasks at lower indexes + for len(firstWindow.todo) > 0 { + tidx := -1 + + worker.lk.Lock() + for t, todo := range firstWindow.todo { + needRes := ResourceTable[todo.taskType][sw.sh.spt] + if worker.preparing.canHandleRequest(needRes, sw.wid, "startPreparing", worker.info.Resources) { + tidx = t + break + } + } + worker.lk.Unlock() + + if tidx == -1 { + break assignLoop + } + + todo := firstWindow.todo[tidx] + + log.Debugf("assign worker sector %d", todo.sector.Number) + err := sw.startProcessingTask(sw.taskDone, todo) + + if err != nil { + log.Error("startProcessingTask error: %+v", err) + go todo.respond(xerrors.Errorf("startProcessingTask error: %w", err)) + } + + // Note: we're not freeing window.allocated resources here very much on purpose + copy(firstWindow.todo[tidx:], firstWindow.todo[tidx+1:]) + firstWindow.todo[len(firstWindow.todo)-1] = nil + firstWindow.todo = firstWindow.todo[:len(firstWindow.todo)-1] + } + + copy(worker.activeWindows, worker.activeWindows[1:]) + worker.activeWindows[len(worker.activeWindows)-1] = nil + worker.activeWindows = worker.activeWindows[:len(worker.activeWindows)-1] + + sw.windowsRequested-- + } +} + +func (sw *schedWorker) startProcessingTask(taskDone chan struct{}, req *workerRequest) error { + w, sh := sw.worker, sw.sh + needRes := ResourceTable[req.taskType][sh.spt] w.lk.Lock() @@ -319,7 +380,7 @@ func (sh *scheduler) assignWorker(taskDone chan struct{}, wid WorkerID, w *worke w.lk.Unlock() go func() { - err := req.prepare(req.ctx, sh.wt.worker(wid, w.w)) + err := req.prepare(req.ctx, sh.wt.worker(sw.wid, w.w)) sh.workersLk.Lock() if err != nil { @@ -344,7 +405,7 @@ func (sh *scheduler) assignWorker(taskDone chan struct{}, wid WorkerID, w *worke return } - err = w.active.withResources(wid, w.info.Resources, needRes, &sh.workersLk, func() error { + err = w.active.withResources(sw.wid, w.info.Resources, needRes, &sh.workersLk, func() error { w.lk.Lock() w.preparing.free(w.info.Resources, needRes) w.lk.Unlock() @@ -356,7 +417,7 @@ func (sh *scheduler) assignWorker(taskDone chan struct{}, wid WorkerID, w *worke case <-sh.closing: } - err = req.work(req.ctx, sh.wt.worker(wid, w.w)) + err = req.work(req.ctx, sh.wt.worker(sw.wid, w.w)) select { case req.ret <- workerResponse{err: err}: diff --git a/extern/sector-storage/worker_local.go b/extern/sector-storage/worker_local.go index 54b26b0ac..b6a8793c7 100644 --- a/extern/sector-storage/worker_local.go +++ b/extern/sector-storage/worker_local.go @@ -225,7 +225,7 @@ func (l *LocalWorker) asyncCall(ctx context.Context, sector abi.SectorID, rt Ret res, err := work(ctx, ci) - { + if err != nil { rb, err := json.Marshal(res) if err != nil { log.Errorf("tracking call (marshaling results): %+v", err) From 96c5ff7e7f12427115f7db0712e212d871ba4ff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 28 Oct 2020 14:23:38 +0100 Subject: [PATCH 276/313] sched: use more letters for variables --- extern/sector-storage/manager_calltracker.go | 2 +- extern/sector-storage/sched.go | 6 +- extern/sector-storage/sched_test.go | 2 +- extern/sector-storage/sched_worker.go | 72 +++++++++++--------- extern/sector-storage/selector_alloc.go | 4 +- extern/sector-storage/selector_existing.go | 4 +- extern/sector-storage/selector_task.go | 6 +- extern/sector-storage/stats.go | 2 +- 8 files changed, 52 insertions(+), 46 deletions(-) diff --git a/extern/sector-storage/manager_calltracker.go b/extern/sector-storage/manager_calltracker.go index 8315c6fe6..f0aa0445e 100644 --- a/extern/sector-storage/manager_calltracker.go +++ b/extern/sector-storage/manager_calltracker.go @@ -334,7 +334,7 @@ func (m *Manager) returnResult(callID storiface.CallID, r interface{}, serr stri err: err, } - m.sched.wt.onDone(callID) + m.sched.workTracker.onDone(callID) m.workLk.Lock() defer m.workLk.Unlock() diff --git a/extern/sector-storage/sched.go b/extern/sector-storage/sched.go index 34cba4cf2..426658c41 100644 --- a/extern/sector-storage/sched.go +++ b/extern/sector-storage/sched.go @@ -64,7 +64,7 @@ type scheduler struct { schedQueue *requestQueue openWindows []*schedWindowRequest - wt *workTracker + workTracker *workTracker info chan func(interface{}) @@ -74,7 +74,7 @@ type scheduler struct { } type workerHandle struct { - w Worker + workerRpc Worker info storiface.WorkerInfo @@ -155,7 +155,7 @@ func newScheduler(spt abi.RegisteredSealProof) *scheduler { schedQueue: &requestQueue{}, - wt: &workTracker{ + workTracker: &workTracker{ done: map[storiface.CallID]struct{}{}, running: map[storiface.CallID]trackedWork{}, }, diff --git a/extern/sector-storage/sched_test.go b/extern/sector-storage/sched_test.go index 1afa92b64..93014a117 100644 --- a/extern/sector-storage/sched_test.go +++ b/extern/sector-storage/sched_test.go @@ -530,7 +530,7 @@ func BenchmarkTrySched(b *testing.B) { sched := newScheduler(spt) sched.workers[WorkerID{}] = &workerHandle{ - w: nil, + workerRpc: nil, info: storiface.WorkerInfo{ Hostname: "t", Resources: decentWorkerResources, diff --git a/extern/sector-storage/sched_worker.go b/extern/sector-storage/sched_worker.go index 037176a11..ff43009d3 100644 --- a/extern/sector-storage/sched_worker.go +++ b/extern/sector-storage/sched_worker.go @@ -2,14 +2,15 @@ package sectorstorage import ( "context" - "github.com/filecoin-project/lotus/extern/sector-storage/stores" "time" "golang.org/x/xerrors" + + "github.com/filecoin-project/lotus/extern/sector-storage/stores" ) type schedWorker struct { - sh *scheduler + sched *scheduler worker *workerHandle wid WorkerID @@ -37,8 +38,8 @@ func (sh *scheduler) runWorker(ctx context.Context, w Worker) error { } worker := &workerHandle{ - w: w, - info: info, + workerRpc: w, + info: info, preparing: &activeResources{}, active: &activeResources{}, @@ -63,7 +64,7 @@ func (sh *scheduler) runWorker(ctx context.Context, w Worker) error { sh.workersLk.Unlock() sw := &schedWorker{ - sh: sh, + sched: sh, worker: worker, wid: wid, @@ -81,7 +82,7 @@ func (sh *scheduler) runWorker(ctx context.Context, w Worker) error { } func (sw *schedWorker) handleWorker() { - worker, sh := sw.worker, sw.sh + worker, sched := sw.worker, sw.sched ctx, cancel := context.WithCancel(context.TODO()) defer cancel() @@ -95,17 +96,17 @@ func (sw *schedWorker) handleWorker() { log.Warnw("failed to disable worker", "worker", sw.wid, "error", err) } - sh.workersLk.Lock() - delete(sh.workers, sw.wid) - sh.workersLk.Unlock() + sched.workersLk.Lock() + delete(sched.workers, sw.wid) + sched.workersLk.Unlock() }() defer sw.heartbeatTimer.Stop() for { - sh.workersLk.Lock() + sched.workersLk.Lock() enabled := worker.enabled - sh.workersLk.Unlock() + sched.workersLk.Unlock() // ask for more windows if we need them (non-blocking) if enabled { @@ -123,9 +124,9 @@ func (sw *schedWorker) handleWorker() { // session looks good if !enabled { - sh.workersLk.Lock() + sched.workersLk.Lock() worker.enabled = true - sh.workersLk.Unlock() + sched.workersLk.Unlock() // we'll send window requests on the next loop } @@ -142,16 +143,16 @@ func (sw *schedWorker) handleWorker() { } // process assigned windows (non-blocking) - sh.workersLk.RLock() + sched.workersLk.RLock() worker.wndLk.Lock() - sw.windowsRequested -= sh.workerCompactWindows(worker, sw.wid) + sw.workerCompactWindows() // send tasks to the worker sw.processAssignedWindows() worker.wndLk.Unlock() - sh.workersLk.RUnlock() + sched.workersLk.RUnlock() } } @@ -160,7 +161,7 @@ func (sw *schedWorker) disable(ctx context.Context) error { // request cleanup in the main scheduler goroutine select { - case sw.sh.workerDisable <- workerDisableReq{ + case sw.sched.workerDisable <- workerDisableReq{ activeWindows: sw.worker.activeWindows, wid: sw.wid, done: func() { @@ -169,7 +170,7 @@ func (sw *schedWorker) disable(ctx context.Context) error { }: case <-ctx.Done(): return ctx.Err() - case <-sw.sh.closing: + case <-sw.sched.closing: return nil } @@ -178,7 +179,7 @@ func (sw *schedWorker) disable(ctx context.Context) error { case <-done: case <-ctx.Done(): return ctx.Err() - case <-sw.sh.closing: + case <-sw.sched.closing: return nil } @@ -190,7 +191,7 @@ func (sw *schedWorker) disable(ctx context.Context) error { func (sw *schedWorker) checkSession(ctx context.Context) bool { for { sctx, scancel := context.WithTimeout(ctx, stores.HeartbeatInterval/2) - curSes, err := sw.worker.w.Session(sctx) + curSes, err := sw.worker.workerRpc.Session(sctx) scancel() if err != nil { // Likely temporary error @@ -213,7 +214,7 @@ func (sw *schedWorker) checkSession(ctx context.Context) bool { if err := sw.disable(ctx); err != nil { log.Warnw("failed to disable worker with session error", "worker", sw.wid, "error", err) } - case <-sw.sh.closing: + case <-sw.sched.closing: return false case <-sw.worker.closingMgr: return false @@ -237,11 +238,11 @@ func (sw *schedWorker) checkSession(ctx context.Context) bool { func (sw *schedWorker) requestWindows() bool { for ; sw.windowsRequested < SchedWindows; sw.windowsRequested++ { select { - case sw.sh.windowRequests <- &schedWindowRequest{ + case sw.sched.windowRequests <- &schedWindowRequest{ worker: sw.wid, done: sw.scheduledWindows, }: - case <-sw.sh.closing: + case <-sw.sched.closing: return false case <-sw.worker.closingMgr: return false @@ -262,13 +263,16 @@ func (sw *schedWorker) waitForUpdates() (update bool, ok bool) { case <-sw.taskDone: log.Debugw("task done", "workerid", sw.wid) return true, true - case <-sw.sh.closing: + case <-sw.sched.closing: case <-sw.worker.closingMgr: } + return false, false } -func (sh *scheduler) workerCompactWindows(worker *workerHandle, wid WorkerID) int { +func (sw *schedWorker) workerCompactWindows() { + worker := sw.worker + // move tasks from older windows to newer windows if older windows // still can fit them if len(worker.activeWindows) > 1 { @@ -277,8 +281,8 @@ func (sh *scheduler) workerCompactWindows(worker *workerHandle, wid WorkerID) in var moved []int for ti, todo := range window.todo { - needRes := ResourceTable[todo.taskType][sh.spt] - if !lower.allocated.canHandleRequest(needRes, wid, "compactWindows", worker.info.Resources) { + needRes := ResourceTable[todo.taskType][sw.sched.spt] + if !lower.allocated.canHandleRequest(needRes, sw.wid, "compactWindows", worker.info.Resources) { continue } @@ -316,8 +320,7 @@ func (sh *scheduler) workerCompactWindows(worker *workerHandle, wid WorkerID) in } worker.activeWindows = newWindows - - return compacted + sw.windowsRequested -= compacted } func (sw *schedWorker) processAssignedWindows() { @@ -334,7 +337,7 @@ assignLoop: worker.lk.Lock() for t, todo := range firstWindow.todo { - needRes := ResourceTable[todo.taskType][sw.sh.spt] + needRes := ResourceTable[todo.taskType][sw.sched.spt] if worker.preparing.canHandleRequest(needRes, sw.wid, "startPreparing", worker.info.Resources) { tidx = t break @@ -371,7 +374,7 @@ assignLoop: } func (sw *schedWorker) startProcessingTask(taskDone chan struct{}, req *workerRequest) error { - w, sh := sw.worker, sw.sh + w, sh := sw.worker, sw.sched needRes := ResourceTable[req.taskType][sh.spt] @@ -380,7 +383,8 @@ func (sw *schedWorker) startProcessingTask(taskDone chan struct{}, req *workerRe w.lk.Unlock() go func() { - err := req.prepare(req.ctx, sh.wt.worker(sw.wid, w.w)) + // first run the prepare step (e.g. fetching sector data from other worker) + err := req.prepare(req.ctx, sh.workTracker.worker(sw.wid, w.workerRpc)) sh.workersLk.Lock() if err != nil { @@ -405,6 +409,7 @@ func (sw *schedWorker) startProcessingTask(taskDone chan struct{}, req *workerRe return } + // wait (if needed) for resources in the 'active' window err = w.active.withResources(sw.wid, w.info.Resources, needRes, &sh.workersLk, func() error { w.lk.Lock() w.preparing.free(w.info.Resources, needRes) @@ -417,7 +422,8 @@ func (sw *schedWorker) startProcessingTask(taskDone chan struct{}, req *workerRe case <-sh.closing: } - err = req.work(req.ctx, sh.wt.worker(sw.wid, w.w)) + // Do the work! + err = req.work(req.ctx, sh.workTracker.worker(sw.wid, w.workerRpc)) select { case req.ret <- workerResponse{err: err}: diff --git a/extern/sector-storage/selector_alloc.go b/extern/sector-storage/selector_alloc.go index 9afa6abaa..14724fbe8 100644 --- a/extern/sector-storage/selector_alloc.go +++ b/extern/sector-storage/selector_alloc.go @@ -27,7 +27,7 @@ func newAllocSelector(index stores.SectorIndex, alloc storiface.SectorFileType, } func (s *allocSelector) Ok(ctx context.Context, task sealtasks.TaskType, spt abi.RegisteredSealProof, whnd *workerHandle) (bool, error) { - tasks, err := whnd.w.TaskTypes(ctx) + tasks, err := whnd.workerRpc.TaskTypes(ctx) if err != nil { return false, xerrors.Errorf("getting supported worker task types: %w", err) } @@ -35,7 +35,7 @@ func (s *allocSelector) Ok(ctx context.Context, task sealtasks.TaskType, spt abi return false, nil } - paths, err := whnd.w.Paths(ctx) + paths, err := whnd.workerRpc.Paths(ctx) if err != nil { return false, xerrors.Errorf("getting worker paths: %w", err) } diff --git a/extern/sector-storage/selector_existing.go b/extern/sector-storage/selector_existing.go index 025ad3f21..0e3a41aeb 100644 --- a/extern/sector-storage/selector_existing.go +++ b/extern/sector-storage/selector_existing.go @@ -29,7 +29,7 @@ func newExistingSelector(index stores.SectorIndex, sector abi.SectorID, alloc st } func (s *existingSelector) Ok(ctx context.Context, task sealtasks.TaskType, spt abi.RegisteredSealProof, whnd *workerHandle) (bool, error) { - tasks, err := whnd.w.TaskTypes(ctx) + tasks, err := whnd.workerRpc.TaskTypes(ctx) if err != nil { return false, xerrors.Errorf("getting supported worker task types: %w", err) } @@ -37,7 +37,7 @@ func (s *existingSelector) Ok(ctx context.Context, task sealtasks.TaskType, spt return false, nil } - paths, err := whnd.w.Paths(ctx) + paths, err := whnd.workerRpc.Paths(ctx) if err != nil { return false, xerrors.Errorf("getting worker paths: %w", err) } diff --git a/extern/sector-storage/selector_task.go b/extern/sector-storage/selector_task.go index 807b53103..ffed40d68 100644 --- a/extern/sector-storage/selector_task.go +++ b/extern/sector-storage/selector_task.go @@ -20,7 +20,7 @@ func newTaskSelector() *taskSelector { } func (s *taskSelector) Ok(ctx context.Context, task sealtasks.TaskType, spt abi.RegisteredSealProof, whnd *workerHandle) (bool, error) { - tasks, err := whnd.w.TaskTypes(ctx) + tasks, err := whnd.workerRpc.TaskTypes(ctx) if err != nil { return false, xerrors.Errorf("getting supported worker task types: %w", err) } @@ -30,11 +30,11 @@ func (s *taskSelector) Ok(ctx context.Context, task sealtasks.TaskType, spt abi. } func (s *taskSelector) Cmp(ctx context.Context, _ sealtasks.TaskType, a, b *workerHandle) (bool, error) { - atasks, err := a.w.TaskTypes(ctx) + atasks, err := a.workerRpc.TaskTypes(ctx) if err != nil { return false, xerrors.Errorf("getting supported worker task types: %w", err) } - btasks, err := b.w.TaskTypes(ctx) + btasks, err := b.workerRpc.TaskTypes(ctx) if err != nil { return false, xerrors.Errorf("getting supported worker task types: %w", err) } diff --git a/extern/sector-storage/stats.go b/extern/sector-storage/stats.go index f9d96fc5d..bae60b426 100644 --- a/extern/sector-storage/stats.go +++ b/extern/sector-storage/stats.go @@ -33,7 +33,7 @@ func (m *Manager) WorkerJobs() map[uuid.UUID][]storiface.WorkerJob { out := map[uuid.UUID][]storiface.WorkerJob{} calls := map[storiface.CallID]struct{}{} - for _, t := range m.sched.wt.Running() { + for _, t := range m.sched.workTracker.Running() { out[uuid.UUID(t.worker)] = append(out[uuid.UUID(t.worker)], t.job) calls[t.job.ID] = struct{}{} } From 4cf00b8b428a2934fabda1a63bedf629a5c1630d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 28 Oct 2020 14:29:17 +0100 Subject: [PATCH 277/313] worker_local: address review --- extern/sector-storage/worker_local.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/extern/sector-storage/worker_local.go b/extern/sector-storage/worker_local.go index b6a8793c7..cb1a43c53 100644 --- a/extern/sector-storage/worker_local.go +++ b/extern/sector-storage/worker_local.go @@ -35,13 +35,16 @@ type WorkerConfig struct { NoSwap bool } +// used do provide custom proofs impl (mostly used in testing) +type ExecutorFunc func() (ffiwrapper.Storage, error) + type LocalWorker struct { scfg *ffiwrapper.Config storage stores.Store localStore *stores.Local sindex stores.SectorIndex ret storiface.WorkerReturn - executor func() (ffiwrapper.Storage, error) + executor ExecutorFunc noSwap bool ct *workerCallTracker @@ -52,7 +55,7 @@ type LocalWorker struct { closing chan struct{} } -func newLocalWorker(executor func() (ffiwrapper.Storage, error), wcfg WorkerConfig, store stores.Store, local *stores.Local, sindex stores.SectorIndex, ret storiface.WorkerReturn, cst *statestore.StateStore) *LocalWorker { +func newLocalWorker(executor ExecutorFunc, wcfg WorkerConfig, store stores.Store, local *stores.Local, sindex stores.SectorIndex, ret storiface.WorkerReturn, cst *statestore.StateStore) *LocalWorker { acceptTasks := map[sealtasks.TaskType]struct{}{} for _, taskType := range wcfg.TaskTypes { acceptTasks[taskType] = struct{}{} From ed2f81da2f99b09c90aca1587f74e987ec2c8c2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 28 Oct 2020 14:34:28 +0100 Subject: [PATCH 278/313] sched: Fix tests --- extern/sector-storage/sched_test.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/extern/sector-storage/sched_test.go b/extern/sector-storage/sched_test.go index 93014a117..d63684315 100644 --- a/extern/sector-storage/sched_test.go +++ b/extern/sector-storage/sched_test.go @@ -591,8 +591,13 @@ func TestWindowCompact(t *testing.T) { wh.activeWindows = append(wh.activeWindows, window) } - n := sh.workerCompactWindows(wh, WorkerID{}) - require.Equal(t, len(start)-len(expect), n) + sw := schedWorker{ + sched: &sh, + worker: wh, + } + + sw.workerCompactWindows() + require.Equal(t, len(start)-len(expect), -sw.windowsRequested) for wi, tasks := range expect { var expectRes activeResources From 4100f6eeadabd73c7d24ab167e9f2ca4cdf53c6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 28 Oct 2020 15:10:43 +0100 Subject: [PATCH 279/313] fix TestWDPostDoPost --- extern/sector-storage/sched_test.go | 4 ++-- storage/wdpost_run_test.go | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/extern/sector-storage/sched_test.go b/extern/sector-storage/sched_test.go index d63684315..849896ff6 100644 --- a/extern/sector-storage/sched_test.go +++ b/extern/sector-storage/sched_test.go @@ -592,8 +592,8 @@ func TestWindowCompact(t *testing.T) { } sw := schedWorker{ - sched: &sh, - worker: wh, + sched: &sh, + worker: wh, } sw.workerCompactWindows() diff --git a/storage/wdpost_run_test.go b/storage/wdpost_run_test.go index 6c05f806f..a76483a5f 100644 --- a/storage/wdpost_run_test.go +++ b/storage/wdpost_run_test.go @@ -16,12 +16,14 @@ import ( "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/dline" + "github.com/filecoin-project/go-state-types/network" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" tutils "github.com/filecoin-project/specs-actors/v2/support/testing" "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/journal" @@ -91,6 +93,10 @@ func (m *mockStorageMinerAPI) StateWaitMsg(ctx context.Context, cid cid.Cid, con }, nil } +func (m *mockStorageMinerAPI) StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error) { + return build.NewestNetworkVersion, nil +} + type mockProver struct { } From 4475b9ac058e81c2873cd8a116473f115367bd68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 28 Oct 2020 15:31:15 +0100 Subject: [PATCH 280/313] Use filecoin-ffi master --- extern/filecoin-ffi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index f0e58c2a8..0226d0be6 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit f0e58c2a8563ce1ac0f672d43da409dc3bb55b56 +Subproject commit 0226d0be6f0ec441e687512cd833040414437351 From 86f9abda0de42d5f9dcac71d3f64671f7cffb8f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 28 Oct 2020 15:35:40 +0100 Subject: [PATCH 281/313] circle: Install hwloc --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f82008e9b..0364e99fa 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -34,7 +34,7 @@ commands: condition: << parameters.linux >> steps: - run: sudo apt-get update - - run: sudo apt-get install ocl-icd-opencl-dev + - run: sudo apt-get install ocl-icd-opencl-dev libhwloc-dev - run: git submodule sync - run: git submodule update --init download-params: From da7ecc1527255d4f2f09cbff097a9f483e9b6f68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 28 Oct 2020 16:15:17 +0100 Subject: [PATCH 282/313] Fix flaky sealing manager tests --- extern/sector-storage/manager_test.go | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/extern/sector-storage/manager_test.go b/extern/sector-storage/manager_test.go index 6efcc304e..938632967 100644 --- a/extern/sector-storage/manager_test.go +++ b/extern/sector-storage/manager_test.go @@ -85,9 +85,8 @@ func (t *testStorage) Stat(path string) (fsutil.FsStat, error) { var _ stores.LocalStorage = &testStorage{} -func newTestMgr(ctx context.Context, t *testing.T, ds datastore.Datastore) (*Manager, *stores.Local, *stores.Remote, *stores.Index) { +func newTestMgr(ctx context.Context, t *testing.T, ds datastore.Datastore) (*Manager, *stores.Local, *stores.Remote, *stores.Index, func()) { st := newTestStorage(t) - defer st.cleanup() si := stores.NewIndex() cfg := &ffiwrapper.Config{ @@ -126,14 +125,15 @@ func newTestMgr(ctx context.Context, t *testing.T, ds datastore.Datastore) (*Man go m.sched.runSched() - return m, lstor, stor, si + return m, lstor, stor, si, st.cleanup } func TestSimple(t *testing.T) { logging.SetAllLoggers(logging.LevelDebug) ctx := context.Background() - m, lstor, _, _ := newTestMgr(ctx, t, datastore.NewMapDatastore()) + m, lstor, _, _, cleanup := newTestMgr(ctx, t, datastore.NewMapDatastore()) + defer cleanup() localTasks := []sealtasks.TaskType{ sealtasks.TTAddPiece, sealtasks.TTPreCommit1, sealtasks.TTCommit1, sealtasks.TTFinalize, sealtasks.TTFetch, @@ -167,7 +167,8 @@ func TestRedoPC1(t *testing.T) { logging.SetAllLoggers(logging.LevelDebug) ctx := context.Background() - m, lstor, _, _ := newTestMgr(ctx, t, datastore.NewMapDatastore()) + m, lstor, _, _, cleanup := newTestMgr(ctx, t, datastore.NewMapDatastore()) + defer cleanup() localTasks := []sealtasks.TaskType{ sealtasks.TTAddPiece, sealtasks.TTPreCommit1, sealtasks.TTCommit1, sealtasks.TTFinalize, sealtasks.TTFetch, @@ -216,7 +217,8 @@ func TestRestartManager(t *testing.T) { ds := datastore.NewMapDatastore() - m, lstor, _, _ := newTestMgr(ctx, t, ds) + m, lstor, _, _, cleanup := newTestMgr(ctx, t, ds) + defer cleanup() localTasks := []sealtasks.TaskType{ sealtasks.TTAddPiece, sealtasks.TTPreCommit1, sealtasks.TTCommit1, sealtasks.TTFinalize, sealtasks.TTFetch, @@ -265,7 +267,9 @@ func TestRestartManager(t *testing.T) { cwg.Wait() require.Error(t, perr) - m, _, _, _ = newTestMgr(ctx, t, ds) + m, _, _, _, cleanup2 := newTestMgr(ctx, t, ds) + defer cleanup2() + tw.ret = m // simulate jsonrpc auto-reconnect err = m.AddWorker(ctx, tw) require.NoError(t, err) @@ -287,7 +291,8 @@ func TestRestartWorker(t *testing.T) { ds := datastore.NewMapDatastore() - m, lstor, stor, idx := newTestMgr(ctx, t, ds) + m, lstor, stor, idx, cleanup := newTestMgr(ctx, t, ds) + defer cleanup() localTasks := []sealtasks.TaskType{ sealtasks.TTAddPiece, sealtasks.TTPreCommit1, sealtasks.TTCommit1, sealtasks.TTFinalize, sealtasks.TTFetch, From f79652c28c9acc67cda2fb09761971a1a1717389 Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Wed, 28 Oct 2020 12:38:06 +0100 Subject: [PATCH 283/313] feat: cache deal states for most recent old/new tipset --- chain/events/state/mock/api.go | 69 ++++++++ chain/events/state/mock/state.go | 32 ++++ chain/events/state/mock/tipset.go | 27 +++ chain/events/state/predicates_test.go | 101 ++--------- markets/storageadapter/client.go | 23 ++- markets/storageadapter/dealstatematcher.go | 84 ++++++++++ .../storageadapter/dealstatematcher_test.go | 157 ++++++++++++++++++ markets/storageadapter/provider.go | 16 +- 8 files changed, 402 insertions(+), 107 deletions(-) create mode 100644 chain/events/state/mock/api.go create mode 100644 chain/events/state/mock/state.go create mode 100644 chain/events/state/mock/tipset.go create mode 100644 markets/storageadapter/dealstatematcher.go create mode 100644 markets/storageadapter/dealstatematcher_test.go diff --git a/chain/events/state/mock/api.go b/chain/events/state/mock/api.go new file mode 100644 index 000000000..4e8bcc94d --- /dev/null +++ b/chain/events/state/mock/api.go @@ -0,0 +1,69 @@ +package test + +import ( + "context" + "sync" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/lib/blockstore" + "github.com/ipfs/go-cid" + "golang.org/x/xerrors" +) + +type MockAPI struct { + bs blockstore.Blockstore + + lk sync.Mutex + ts map[types.TipSetKey]*types.Actor + stateGetActorCalled int +} + +func NewMockAPI(bs blockstore.Blockstore) *MockAPI { + return &MockAPI{ + bs: bs, + ts: make(map[types.TipSetKey]*types.Actor), + } +} + +func (m *MockAPI) ChainHasObj(ctx context.Context, c cid.Cid) (bool, error) { + return m.bs.Has(c) +} + +func (m *MockAPI) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) { + blk, err := m.bs.Get(c) + if err != nil { + return nil, xerrors.Errorf("blockstore get: %w", err) + } + + return blk.RawData(), nil +} + +func (m *MockAPI) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) { + m.lk.Lock() + defer m.lk.Unlock() + + m.stateGetActorCalled++ + return m.ts[tsk], nil +} + +func (m *MockAPI) StateGetActorCallCount() int { + m.lk.Lock() + defer m.lk.Unlock() + + return m.stateGetActorCalled +} + +func (m *MockAPI) ResetCallCounts() { + m.lk.Lock() + defer m.lk.Unlock() + + m.stateGetActorCalled = 0 +} + +func (m *MockAPI) SetActor(tsk types.TipSetKey, act *types.Actor) { + m.lk.Lock() + defer m.lk.Unlock() + + m.ts[tsk] = act +} diff --git a/chain/events/state/mock/state.go b/chain/events/state/mock/state.go new file mode 100644 index 000000000..bac06b59f --- /dev/null +++ b/chain/events/state/mock/state.go @@ -0,0 +1,32 @@ +package test + +import ( + "context" + "testing" + + "github.com/filecoin-project/go-state-types/abi" + "github.com/ipfs/go-cid" + + "github.com/filecoin-project/specs-actors/v2/actors/builtin/market" + "github.com/filecoin-project/specs-actors/v2/actors/util/adt" + "github.com/stretchr/testify/require" +) + +func CreateEmptyMarketState(t *testing.T, store adt.Store) *market.State { + emptyArrayCid, err := adt.MakeEmptyArray(store).Root() + require.NoError(t, err) + emptyMap, err := adt.MakeEmptyMap(store).Root() + require.NoError(t, err) + return market.ConstructState(emptyArrayCid, emptyMap, emptyMap) +} + +func CreateDealAMT(ctx context.Context, t *testing.T, store adt.Store, deals map[abi.DealID]*market.DealState) cid.Cid { + root := adt.MakeEmptyArray(store) + for dealID, dealState := range deals { + err := root.Set(uint64(dealID), dealState) + require.NoError(t, err) + } + rootCid, err := root.Root() + require.NoError(t, err) + return rootCid +} diff --git a/chain/events/state/mock/tipset.go b/chain/events/state/mock/tipset.go new file mode 100644 index 000000000..39d42d6e5 --- /dev/null +++ b/chain/events/state/mock/tipset.go @@ -0,0 +1,27 @@ +package test + +import ( + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/crypto" + "github.com/filecoin-project/lotus/chain/types" + "github.com/ipfs/go-cid" +) + +var dummyCid cid.Cid + +func init() { + dummyCid, _ = cid.Parse("bafkqaaa") +} + +func MockTipset(minerAddr address.Address, timestamp uint64) (*types.TipSet, error) { + return types.NewTipSet([]*types.BlockHeader{{ + Miner: minerAddr, + Height: 5, + ParentStateRoot: dummyCid, + Messages: dummyCid, + ParentMessageReceipts: dummyCid, + BlockSig: &crypto.Signature{Type: crypto.SigTypeBLS}, + BLSAggregate: &crypto.Signature{Type: crypto.SigTypeBLS}, + Timestamp: timestamp, + }}) +} diff --git a/chain/events/state/predicates_test.go b/chain/events/state/predicates_test.go index 9b393f6e4..8fc93d9cd 100644 --- a/chain/events/state/predicates_test.go +++ b/chain/events/state/predicates_test.go @@ -4,21 +4,19 @@ import ( "context" "testing" + test "github.com/filecoin-project/lotus/chain/events/state/mock" + "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/go-bitfield" - "github.com/stretchr/testify/require" - "golang.org/x/xerrors" - "github.com/ipfs/go-cid" cbornode "github.com/ipfs/go-ipld-cbor" + "github.com/stretchr/testify/require" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" - "github.com/filecoin-project/go-state-types/crypto" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market" miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" @@ -36,39 +34,6 @@ func init() { dummyCid, _ = cid.Parse("bafkqaaa") } -type mockAPI struct { - ts map[types.TipSetKey]*types.Actor - bs bstore.Blockstore -} - -func newMockAPI(bs bstore.Blockstore) *mockAPI { - return &mockAPI{ - bs: bs, - ts: make(map[types.TipSetKey]*types.Actor), - } -} - -func (m mockAPI) ChainHasObj(ctx context.Context, c cid.Cid) (bool, error) { - return m.bs.Has(c) -} - -func (m mockAPI) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) { - blk, err := m.bs.Get(c) - if err != nil { - return nil, xerrors.Errorf("blockstore get: %w", err) - } - - return blk.RawData(), nil -} - -func (m mockAPI) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) { - return m.ts[tsk], nil -} - -func (m mockAPI) setActor(tsk types.TipSetKey, act *types.Actor) { - m.ts[tsk] = act -} - func TestMarketPredicates(t *testing.T) { ctx := context.Background() bs := bstore.NewTemporarySync() @@ -177,14 +142,14 @@ func TestMarketPredicates(t *testing.T) { minerAddr, err := address.NewFromString("t00") require.NoError(t, err) - oldState, err := mockTipset(minerAddr, 1) + oldState, err := test.MockTipset(minerAddr, 1) require.NoError(t, err) - newState, err := mockTipset(minerAddr, 2) + newState, err := test.MockTipset(minerAddr, 2) require.NoError(t, err) - api := newMockAPI(bs) - api.setActor(oldState.Key(), &types.Actor{Code: builtin2.StorageMarketActorCodeID, Head: oldStateC}) - api.setActor(newState.Key(), &types.Actor{Code: builtin2.StorageMarketActorCodeID, Head: newStateC}) + api := test.NewMockAPI(bs) + api.SetActor(oldState.Key(), &types.Actor{Code: builtin2.StorageMarketActorCodeID, Head: oldStateC}) + api.SetActor(newState.Key(), &types.Actor{Code: builtin2.StorageMarketActorCodeID, Head: newStateC}) t.Run("deal ID predicate", func(t *testing.T) { preds := NewStatePredicates(api) @@ -239,7 +204,7 @@ func TestMarketPredicates(t *testing.T) { t.Fatal("No state change so this should not be called") return false, nil, nil }) - marketState0 := createEmptyMarketState(t, store) + marketState0 := test.CreateEmptyMarketState(t, store) marketCid, err := store.Put(ctx, marketState0) require.NoError(t, err) marketState, err := market.Load(store, &types.Actor{ @@ -352,7 +317,7 @@ func TestMarketPredicates(t *testing.T) { t.Fatal("No state change so this should not be called") return false, nil, nil }) - marketState0 := createEmptyMarketState(t, store) + marketState0 := test.CreateEmptyMarketState(t, store) marketCid, err := store.Put(ctx, marketState0) require.NoError(t, err) marketState, err := market.Load(store, &types.Actor{ @@ -394,14 +359,14 @@ func TestMinerSectorChange(t *testing.T) { newMinerC := createMinerState(ctx, t, store, owner, worker, []miner.SectorOnChainInfo{si1Ext, si2, si3}) minerAddr := nextIDAddrF() - oldState, err := mockTipset(minerAddr, 1) + oldState, err := test.MockTipset(minerAddr, 1) require.NoError(t, err) - newState, err := mockTipset(minerAddr, 2) + newState, err := test.MockTipset(minerAddr, 2) require.NoError(t, err) - api := newMockAPI(bs) - api.setActor(oldState.Key(), &types.Actor{Head: oldMinerC, Code: builtin2.StorageMinerActorCodeID}) - api.setActor(newState.Key(), &types.Actor{Head: newMinerC, Code: builtin2.StorageMinerActorCodeID}) + api := test.NewMockAPI(bs) + api.SetActor(oldState.Key(), &types.Actor{Head: oldMinerC, Code: builtin2.StorageMinerActorCodeID}) + api.SetActor(newState.Key(), &types.Actor{Head: newMinerC, Code: builtin2.StorageMinerActorCodeID}) preds := NewStatePredicates(api) @@ -449,29 +414,16 @@ func TestMinerSectorChange(t *testing.T) { require.Equal(t, si1Ext, sectorChanges.Extended[0].From) } -func mockTipset(minerAddr address.Address, timestamp uint64) (*types.TipSet, error) { - return types.NewTipSet([]*types.BlockHeader{{ - Miner: minerAddr, - Height: 5, - ParentStateRoot: dummyCid, - Messages: dummyCid, - ParentMessageReceipts: dummyCid, - BlockSig: &crypto.Signature{Type: crypto.SigTypeBLS}, - BLSAggregate: &crypto.Signature{Type: crypto.SigTypeBLS}, - Timestamp: timestamp, - }}) -} - type balance struct { available abi.TokenAmount locked abi.TokenAmount } func createMarketState(ctx context.Context, t *testing.T, store adt2.Store, deals map[abi.DealID]*market2.DealState, props map[abi.DealID]*market2.DealProposal, balances map[address.Address]balance) cid.Cid { - dealRootCid := createDealAMT(ctx, t, store, deals) + dealRootCid := test.CreateDealAMT(ctx, t, store, deals) propRootCid := createProposalAMT(ctx, t, store, props) balancesCids := createBalanceTable(ctx, t, store, balances) - state := createEmptyMarketState(t, store) + state := test.CreateEmptyMarketState(t, store) state.States = dealRootCid state.Proposals = propRootCid state.EscrowTable = balancesCids[0] @@ -482,25 +434,6 @@ func createMarketState(ctx context.Context, t *testing.T, store adt2.Store, deal return stateC } -func createEmptyMarketState(t *testing.T, store adt2.Store) *market2.State { - emptyArrayCid, err := adt2.MakeEmptyArray(store).Root() - require.NoError(t, err) - emptyMap, err := adt2.MakeEmptyMap(store).Root() - require.NoError(t, err) - return market2.ConstructState(emptyArrayCid, emptyMap, emptyMap) -} - -func createDealAMT(ctx context.Context, t *testing.T, store adt2.Store, deals map[abi.DealID]*market2.DealState) cid.Cid { - root := adt2.MakeEmptyArray(store) - for dealID, dealState := range deals { - err := root.Set(uint64(dealID), dealState) - require.NoError(t, err) - } - rootCid, err := root.Root() - require.NoError(t, err) - return rootCid -} - func createProposalAMT(ctx context.Context, t *testing.T, store adt2.Store, props map[abi.DealID]*market2.DealProposal) cid.Cid { root := adt2.MakeEmptyArray(store) for dealID, prop := range props { diff --git a/markets/storageadapter/client.go b/markets/storageadapter/client.go index f299dd4d5..e8e6fbcae 100644 --- a/markets/storageadapter/client.go +++ b/markets/storageadapter/client.go @@ -38,8 +38,9 @@ type ClientNodeAdapter struct { full.ChainAPI full.MpoolAPI - fm *market.FundMgr - ev *events.Events + fm *market.FundMgr + ev *events.Events + dsMatcher *dealStateMatcher } type clientApi struct { @@ -47,14 +48,16 @@ type clientApi struct { full.StateAPI } -func NewClientNodeAdapter(state full.StateAPI, chain full.ChainAPI, mpool full.MpoolAPI, fm *market.FundMgr) storagemarket.StorageClientNode { +func NewClientNodeAdapter(stateapi full.StateAPI, chain full.ChainAPI, mpool full.MpoolAPI, fm *market.FundMgr) storagemarket.StorageClientNode { + capi := &clientApi{chain, stateapi} return &ClientNodeAdapter{ - StateAPI: state, + StateAPI: stateapi, ChainAPI: chain, MpoolAPI: mpool, - fm: fm, - ev: events.NewEvents(context.TODO(), &clientApi{chain, state}), + fm: fm, + ev: events.NewEvents(context.TODO(), capi), + dsMatcher: newDealStateMatcher(state.NewStatePredicates(capi)), } } @@ -389,13 +392,7 @@ func (c *ClientNodeAdapter) OnDealExpiredOrSlashed(ctx context.Context, dealID a } // Watch for state changes to the deal - preds := state.NewStatePredicates(c) - dealDiff := preds.OnStorageMarketActorChanged( - preds.OnDealStateChanged( - preds.DealStateChangedForIDs([]abi.DealID{dealID}))) - match := func(oldTs, newTs *types.TipSet) (bool, events.StateChange, error) { - return dealDiff(ctx, oldTs.Key(), newTs.Key()) - } + match := c.dsMatcher.matcher(ctx, dealID) // Wait until after the end epoch for the deal and then timeout timeout := (sd.Proposal.EndEpoch - head.Height()) + 1 diff --git a/markets/storageadapter/dealstatematcher.go b/markets/storageadapter/dealstatematcher.go new file mode 100644 index 000000000..b8b47ef8e --- /dev/null +++ b/markets/storageadapter/dealstatematcher.go @@ -0,0 +1,84 @@ +package storageadapter + +import ( + "context" + "sync" + + "github.com/filecoin-project/go-state-types/abi" + actorsmarket "github.com/filecoin-project/lotus/chain/actors/builtin/market" + "github.com/filecoin-project/lotus/chain/events" + "github.com/filecoin-project/lotus/chain/events/state" + "github.com/filecoin-project/lotus/chain/types" +) + +// dealStateMatcher caches the DealStates for the most recent +// old/new tipset combination +type dealStateMatcher struct { + preds *state.StatePredicates + + lk sync.Mutex + oldTsk types.TipSetKey + newTsk types.TipSetKey + oldDealStateRoot actorsmarket.DealStates + newDealStateRoot actorsmarket.DealStates +} + +func newDealStateMatcher(preds *state.StatePredicates) *dealStateMatcher { + return &dealStateMatcher{preds: preds} +} + +// matcher returns a function that checks if the state of the given dealID +// has changed. +// It caches the DealStates for the most recent old/new tipset combination. +func (mc *dealStateMatcher) matcher(ctx context.Context, dealID abi.DealID) events.StateMatchFunc { + // The function that is called to check if the deal state has changed for + // the target deal ID + dealStateChangedForID := mc.preds.DealStateChangedForIDs([]abi.DealID{dealID}) + + // The match function is called by the events API to check if there's + // been a state change for the deal with the target deal ID + match := func(oldTs, newTs *types.TipSet) (bool, events.StateChange, error) { + mc.lk.Lock() + defer mc.lk.Unlock() + + // Check if we've already fetched the DealStates for the given tipsets + if mc.oldTsk == oldTs.Key() && mc.newTsk == newTs.Key() { + // If we fetch the DealStates and there is no difference between + // them, they are stored as nil. So we can just bail out. + if mc.oldDealStateRoot == nil || mc.newDealStateRoot == nil { + return false, nil, nil + } + + // Check if the deal state has changed for the target ID + return dealStateChangedForID(ctx, mc.oldDealStateRoot, mc.newDealStateRoot) + } + + // We haven't already fetched the DealStates for the given tipsets, so + // do so now + + // Replace dealStateChangedForID with a function that records the + // DealStates so that we can cache them + var oldDealStateRootSaved, newDealStateRootSaved actorsmarket.DealStates + recorder := func(ctx context.Context, oldDealStateRoot, newDealStateRoot actorsmarket.DealStates) (changed bool, user state.UserData, err error) { + // Record DealStates + oldDealStateRootSaved = oldDealStateRoot + newDealStateRootSaved = newDealStateRoot + + return dealStateChangedForID(ctx, oldDealStateRoot, newDealStateRoot) + } + + // Call the match function + dealDiff := mc.preds.OnStorageMarketActorChanged( + mc.preds.OnDealStateChanged(recorder)) + matched, data, err := dealDiff(ctx, oldTs.Key(), newTs.Key()) + + // Save the recorded DealStates for the tipsets + mc.oldTsk = oldTs.Key() + mc.newTsk = newTs.Key() + mc.oldDealStateRoot = oldDealStateRootSaved + mc.newDealStateRoot = newDealStateRootSaved + + return matched, data, err + } + return match +} diff --git a/markets/storageadapter/dealstatematcher_test.go b/markets/storageadapter/dealstatematcher_test.go new file mode 100644 index 000000000..d0c5277d5 --- /dev/null +++ b/markets/storageadapter/dealstatematcher_test.go @@ -0,0 +1,157 @@ +package storageadapter + +import ( + "context" + "testing" + + "github.com/filecoin-project/lotus/chain/events" + "golang.org/x/sync/errgroup" + + cbornode "github.com/ipfs/go-ipld-cbor" + + adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt" + "github.com/ipfs/go-cid" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + test "github.com/filecoin-project/lotus/chain/events/state/mock" + bstore "github.com/filecoin-project/lotus/lib/blockstore" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + + market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market" + + "github.com/stretchr/testify/require" + + "github.com/filecoin-project/lotus/chain/events/state" + "github.com/filecoin-project/lotus/chain/types" +) + +func TestDealStateMatcher(t *testing.T) { + ctx := context.Background() + bs := bstore.NewTemporarySync() + store := adt2.WrapStore(ctx, cbornode.NewCborStore(bs)) + + deal1 := &market2.DealState{ + SectorStartEpoch: 1, + LastUpdatedEpoch: 2, + } + deal2 := &market2.DealState{ + SectorStartEpoch: 4, + LastUpdatedEpoch: 5, + } + deal3 := &market2.DealState{ + SectorStartEpoch: 7, + LastUpdatedEpoch: 8, + } + deals1 := map[abi.DealID]*market2.DealState{ + abi.DealID(1): deal1, + } + deals2 := map[abi.DealID]*market2.DealState{ + abi.DealID(1): deal2, + } + deals3 := map[abi.DealID]*market2.DealState{ + abi.DealID(1): deal3, + } + + deal1StateC := createMarketState(ctx, t, store, deals1) + deal2StateC := createMarketState(ctx, t, store, deals2) + deal3StateC := createMarketState(ctx, t, store, deals3) + + minerAddr, err := address.NewFromString("t00") + require.NoError(t, err) + ts1, err := test.MockTipset(minerAddr, 1) + require.NoError(t, err) + ts2, err := test.MockTipset(minerAddr, 2) + require.NoError(t, err) + ts3, err := test.MockTipset(minerAddr, 3) + require.NoError(t, err) + + api := test.NewMockAPI(bs) + api.SetActor(ts1.Key(), &types.Actor{Code: builtin2.StorageMarketActorCodeID, Head: deal1StateC}) + api.SetActor(ts2.Key(), &types.Actor{Code: builtin2.StorageMarketActorCodeID, Head: deal2StateC}) + api.SetActor(ts3.Key(), &types.Actor{Code: builtin2.StorageMarketActorCodeID, Head: deal3StateC}) + + t.Run("caching", func(t *testing.T) { + dsm := newDealStateMatcher(state.NewStatePredicates(api)) + matcher := dsm.matcher(ctx, abi.DealID(1)) + + // Call matcher with tipsets that have the same state + ok, stateChange, err := matcher(ts1, ts1) + require.NoError(t, err) + require.False(t, ok) + require.Nil(t, stateChange) + // Should call StateGetActor once for each tipset + require.Equal(t, 2, api.StateGetActorCallCount()) + + // Call matcher with tipsets that have different state + api.ResetCallCounts() + ok, stateChange, err = matcher(ts1, ts2) + require.NoError(t, err) + require.True(t, ok) + require.NotNil(t, stateChange) + // Should call StateGetActor once for each tipset + require.Equal(t, 2, api.StateGetActorCallCount()) + + // Call matcher again with the same tipsets as above, should be cached + api.ResetCallCounts() + ok, stateChange, err = matcher(ts1, ts2) + require.NoError(t, err) + require.True(t, ok) + require.NotNil(t, stateChange) + // Should not call StateGetActor (because it should hit the cache) + require.Equal(t, 0, api.StateGetActorCallCount()) + + // Call matcher with different tipsets, should not be cached + api.ResetCallCounts() + ok, stateChange, err = matcher(ts2, ts3) + require.NoError(t, err) + require.True(t, ok) + require.NotNil(t, stateChange) + // Should call StateGetActor once for each tipset + require.Equal(t, 2, api.StateGetActorCallCount()) + }) + + t.Run("parallel", func(t *testing.T) { + api.ResetCallCounts() + dsm := newDealStateMatcher(state.NewStatePredicates(api)) + matcher := dsm.matcher(ctx, abi.DealID(1)) + + // Call matcher with lots of go-routines in parallel + var eg errgroup.Group + res := make([]struct { + ok bool + stateChange events.StateChange + }, 20) + for i := 0; i < len(res); i++ { + i := i + eg.Go(func() error { + ok, stateChange, err := matcher(ts1, ts2) + res[i].ok = ok + res[i].stateChange = stateChange + return err + }) + } + err := eg.Wait() + require.NoError(t, err) + + // All go-routines should have got the same (cached) result + for i := 1; i < len(res); i++ { + require.Equal(t, res[i].ok, res[i-1].ok) + require.Equal(t, res[i].stateChange, res[i-1].stateChange) + } + + // Only one go-routine should have called StateGetActor + // (once for each tipset) + require.Equal(t, 2, api.StateGetActorCallCount()) + }) +} + +func createMarketState(ctx context.Context, t *testing.T, store adt2.Store, deals map[abi.DealID]*market2.DealState) cid.Cid { + dealRootCid := test.CreateDealAMT(ctx, t, store, deals) + state := test.CreateEmptyMarketState(t, store) + state.States = dealRootCid + + stateC, err := store.Put(ctx, state) + require.NoError(t, err) + return stateC +} diff --git a/markets/storageadapter/provider.go b/markets/storageadapter/provider.go index ce7c8e917..8debbd198 100644 --- a/markets/storageadapter/provider.go +++ b/markets/storageadapter/provider.go @@ -51,6 +51,7 @@ type ProviderNodeAdapter struct { ev *events.Events publishSpec, addBalanceSpec *api.MessageSendSpec + dsMatcher *dealStateMatcher } func NewProviderNodeAdapter(fc *config.MinerFeeConfig) func(dag dtypes.StagingDAG, secb *sectorblocks.SectorBlocks, full api.FullNode) storagemarket.StorageProviderNode { @@ -58,9 +59,10 @@ func NewProviderNodeAdapter(fc *config.MinerFeeConfig) func(dag dtypes.StagingDA na := &ProviderNodeAdapter{ FullNode: full, - dag: dag, - secb: secb, - ev: events.NewEvents(context.TODO(), full), + dag: dag, + secb: secb, + ev: events.NewEvents(context.TODO(), full), + dsMatcher: newDealStateMatcher(state.NewStatePredicates(full)), } if fc != nil { na.publishSpec = &api.MessageSendSpec{MaxFee: abi.TokenAmount(fc.MaxPublishDealsFee)} @@ -461,13 +463,7 @@ func (n *ProviderNodeAdapter) OnDealExpiredOrSlashed(ctx context.Context, dealID } // Watch for state changes to the deal - preds := state.NewStatePredicates(n) - dealDiff := preds.OnStorageMarketActorChanged( - preds.OnDealStateChanged( - preds.DealStateChangedForIDs([]abi.DealID{dealID}))) - match := func(oldTs, newTs *types.TipSet) (bool, events.StateChange, error) { - return dealDiff(ctx, oldTs.Key(), newTs.Key()) - } + match := n.dsMatcher.matcher(ctx, dealID) // Wait until after the end epoch for the deal and then timeout timeout := (sd.Proposal.EndEpoch - head.Height()) + 1 From 5f657b4333424f2091e51e5811e73a52d7590da0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Wed, 28 Oct 2020 20:52:33 +0200 Subject: [PATCH 284/313] extern/sector-storage: fix GPU usage overwrite bug --- extern/sector-storage/sched_resources.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/extern/sector-storage/sched_resources.go b/extern/sector-storage/sched_resources.go index d6dae577b..10fe29aae 100644 --- a/extern/sector-storage/sched_resources.go +++ b/extern/sector-storage/sched_resources.go @@ -27,7 +27,9 @@ func (a *activeResources) withResources(id WorkerID, wr storiface.WorkerResource } func (a *activeResources) add(wr storiface.WorkerResources, r Resources) { - a.gpuUsed = r.CanGPU + if r.CanGPU { + a.gpuUsed = true + } a.cpuUse += r.Threads(wr.CPUs) a.memUsedMin += r.MinMemory a.memUsedMax += r.MaxMemory From e33cc5ee12f92490093629693c17838c0fefa9ef Mon Sep 17 00:00:00 2001 From: frrist Date: Wed, 28 Oct 2020 13:56:02 -0700 Subject: [PATCH 285/313] polish: add ClaimsChanged method to power shim --- chain/actors/builtin/power/power.go | 1 + chain/actors/builtin/power/v0.go | 9 +++++++++ chain/actors/builtin/power/v2.go | 9 +++++++++ 3 files changed, 19 insertions(+) diff --git a/chain/actors/builtin/power/power.go b/chain/actors/builtin/power/power.go index f941ce93e..71645df6a 100644 --- a/chain/actors/builtin/power/power.go +++ b/chain/actors/builtin/power/power.go @@ -56,6 +56,7 @@ type State interface { MinerNominalPowerMeetsConsensusMinimum(address.Address) (bool, error) ListAllMiners() ([]address.Address, error) ForEachClaim(func(miner address.Address, claim Claim) error) error + ClaimsChanged(State) (bool, error) } type Claim struct { diff --git a/chain/actors/builtin/power/v0.go b/chain/actors/builtin/power/v0.go index 3f9a65777..9719b3abf 100644 --- a/chain/actors/builtin/power/v0.go +++ b/chain/actors/builtin/power/v0.go @@ -115,3 +115,12 @@ func (s *state0) ForEachClaim(cb func(miner address.Address, claim Claim) error) }) }) } + +func (s *state0) ClaimsChanged(other State) (bool, error) { + other0, ok := other.(*state0) + if !ok { + // treat an upgrade as a change, always + return true, nil + } + return !s.State.Claims.Equals(other0.State.Claims), nil +} diff --git a/chain/actors/builtin/power/v2.go b/chain/actors/builtin/power/v2.go index 0c15f0669..f4036f798 100644 --- a/chain/actors/builtin/power/v2.go +++ b/chain/actors/builtin/power/v2.go @@ -115,3 +115,12 @@ func (s *state2) ForEachClaim(cb func(miner address.Address, claim Claim) error) }) }) } + +func (s *state2) ClaimsChanged(other State) (bool, error) { + other2, ok := other.(*state2) + if !ok { + // treat an upgrade as a change, always + return true, nil + } + return !s.State.Claims.Equals(other2.State.Claims), nil +} From 553408d57348d290fe544d7464bd9b452117ccc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 27 Oct 2020 17:28:44 +0100 Subject: [PATCH 286/313] worker: Commands to pause/resume task processing --- api/api_worker.go | 14 ++++++++++ api/apistruct/struct.go | 24 ++++++++++++++++- cmd/lotus-seal-worker/cli.go | 51 +++++++++++++++++++++++++++++++++++ cmd/lotus-seal-worker/info.go | 12 +++++++++ cmd/lotus-seal-worker/main.go | 2 ++ cmd/lotus-seal-worker/rpc.go | 34 +++++++++++++++++++++++ 6 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 cmd/lotus-seal-worker/cli.go diff --git a/api/api_worker.go b/api/api_worker.go index 036748ec6..805b23bc1 100644 --- a/api/api_worker.go +++ b/api/api_worker.go @@ -28,5 +28,19 @@ type WorkerAPI interface { StorageAddLocal(ctx context.Context, path string) error + // SetEnabled marks the worker as enabled/disabled. Not that this setting + // may take a few seconds to propagate to task scheduler + SetEnabled(ctx context.Context, enabled bool) error + + Enabled(ctx context.Context) (bool, error) + + // WaitQuiet blocks until there are no tasks running + WaitQuiet(ctx context.Context) error + + // returns a random UUID of worker session, generated randomly when worker + // process starts + ProcessSession(context.Context) (uuid.UUID, error) + + // Like ProcessSession, but returns an error when worker is disabled Session(context.Context) (uuid.UUID, error) } diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 3a4ae75a8..5448e318e 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -385,7 +385,13 @@ type WorkerStruct struct { Remove func(ctx context.Context, sector abi.SectorID) error `perm:"admin"` StorageAddLocal func(ctx context.Context, path string) error `perm:"admin"` - Session func(context.Context) (uuid.UUID, error) `perm:"admin"` + SetEnabled func(ctx context.Context, enabled bool) error `perm:"admin"` + Enabled func(ctx context.Context) (bool, error) `perm:"admin"` + + WaitQuiet func(ctx context.Context) error `perm:"admin"` + + ProcessSession func(context.Context) (uuid.UUID, error) `perm:"admin"` + Session func(context.Context) (uuid.UUID, error) `perm:"admin"` } } @@ -1544,6 +1550,22 @@ func (w *WorkerStruct) StorageAddLocal(ctx context.Context, path string) error { return w.Internal.StorageAddLocal(ctx, path) } +func (w *WorkerStruct) SetEnabled(ctx context.Context, enabled bool) error { + return w.Internal.SetEnabled(ctx, enabled) +} + +func (w *WorkerStruct) Enabled(ctx context.Context) (bool, error) { + return w.Internal.Enabled(ctx) +} + +func (w *WorkerStruct) WaitQuiet(ctx context.Context) error { + return w.Internal.WaitQuiet(ctx) +} + +func (w *WorkerStruct) ProcessSession(ctx context.Context) (uuid.UUID, error) { + return w.Internal.ProcessSession(ctx) +} + func (w *WorkerStruct) Session(ctx context.Context) (uuid.UUID, error) { return w.Internal.Session(ctx) } diff --git a/cmd/lotus-seal-worker/cli.go b/cmd/lotus-seal-worker/cli.go new file mode 100644 index 000000000..b1501fca7 --- /dev/null +++ b/cmd/lotus-seal-worker/cli.go @@ -0,0 +1,51 @@ +package main + +import ( + "github.com/urfave/cli/v2" + "golang.org/x/xerrors" + + lcli "github.com/filecoin-project/lotus/cli" +) + +var setCmd = &cli.Command{ + Name: "set", + Usage: "Manage worker settings", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "enabled", + Usage: "enable/disable new task processing", + Value: true, + }, + }, + Action: func(cctx *cli.Context) error { + api, closer, err := lcli.GetWorkerAPI(cctx) + if err != nil { + return err + } + defer closer() + + ctx := lcli.ReqContext(cctx) + + if err := api.SetEnabled(ctx, cctx.Bool("enabled")); err != nil { + return xerrors.Errorf("SetEnabled: %w", err) + } + + return nil + }, +} + +var waitQuietCmd = &cli.Command{ + Name: "wait-quiet", + Usage: "Block until all running tasks exit", + Action: func(cctx *cli.Context) error { + api, closer, err := lcli.GetWorkerAPI(cctx) + if err != nil { + return err + } + defer closer() + + ctx := lcli.ReqContext(cctx) + + return api.WaitQuiet(ctx) + }, +} diff --git a/cmd/lotus-seal-worker/info.go b/cmd/lotus-seal-worker/info.go index 9b08a0c80..3388d8a59 100644 --- a/cmd/lotus-seal-worker/info.go +++ b/cmd/lotus-seal-worker/info.go @@ -32,6 +32,18 @@ var infoCmd = &cli.Command{ cli.VersionPrinter(cctx) fmt.Println() + sess, err := api.ProcessSession(ctx) + if err != nil { + return xerrors.Errorf("getting session: %w", err) + } + fmt.Printf("Session: %s\n", sess) + + enabled, err := api.Enabled(ctx) + if err != nil { + return xerrors.Errorf("checking worker status: %w", err) + } + fmt.Printf("Enabled: %t", enabled) + info, err := api.Info(ctx) if err != nil { return xerrors.Errorf("getting info: %w", err) diff --git a/cmd/lotus-seal-worker/main.go b/cmd/lotus-seal-worker/main.go index 36c9d5eff..6c2fce582 100644 --- a/cmd/lotus-seal-worker/main.go +++ b/cmd/lotus-seal-worker/main.go @@ -58,6 +58,8 @@ func main() { runCmd, infoCmd, storageCmd, + setCmd, + waitQuietCmd, } app := &cli.App{ diff --git a/cmd/lotus-seal-worker/rpc.go b/cmd/lotus-seal-worker/rpc.go index b543babbf..f4e8494d0 100644 --- a/cmd/lotus-seal-worker/rpc.go +++ b/cmd/lotus-seal-worker/rpc.go @@ -2,7 +2,9 @@ package main import ( "context" + "sync/atomic" + "github.com/google/uuid" "github.com/mitchellh/go-homedir" "golang.org/x/xerrors" @@ -17,6 +19,8 @@ type worker struct { localStore *stores.Local ls stores.LocalStorage + + disabled int64 } func (w *worker) Version(context.Context) (build.Version, error) { @@ -42,4 +46,34 @@ func (w *worker) StorageAddLocal(ctx context.Context, path string) error { return nil } +func (w *worker) SetEnabled(ctx context.Context, enabled bool) error { + disabled := int64(1) + if enabled { + disabled = 0 + } + atomic.StoreInt64(&w.disabled, disabled) + return nil +} + +func (w *worker) Enabled(ctx context.Context) (bool, error) { + return atomic.LoadInt64(&w.disabled) == 0, nil +} + +func (w *worker) WaitQuiet(ctx context.Context) error { + w.LocalWorker.WaitQuiet() // uses WaitGroup under the hood so no ctx :/ + return nil +} + +func (w *worker) ProcessSession(ctx context.Context) (uuid.UUID, error) { + return w.LocalWorker.Session(ctx) +} + +func (w *worker) Session(ctx context.Context) (uuid.UUID, error) { + if atomic.LoadInt64(&w.disabled) == 1 { + return uuid.UUID{}, xerrors.Errorf("worker disabled") + } + + return w.LocalWorker.Session(ctx) +} + var _ storiface.WorkerCalls = &worker{} From ecc1d94b3abda33bd43e9a53a5227da345b51714 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Wed, 28 Oct 2020 22:17:01 +0100 Subject: [PATCH 287/313] Reduce badger ValueTreshold to 128 It should significntly size of the LSM index, and thus increase the performance with bigger datastores Signed-off-by: Jakub Sztandera --- node/repo/fsrepo_ds.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/repo/fsrepo_ds.go b/node/repo/fsrepo_ds.go index aa91d2514..28d737210 100644 --- a/node/repo/fsrepo_ds.go +++ b/node/repo/fsrepo_ds.go @@ -32,7 +32,7 @@ func chainBadgerDs(path string, readonly bool) (datastore.Batching, error) { opts.ReadOnly = readonly opts.Options = dgbadger.DefaultOptions("").WithTruncate(true). - WithValueThreshold(1 << 10) + WithValueThreshold(128) return badger.NewDatastore(path, &opts) } From 0297be4b9a70f65d7645b60af55948a48d4dd888 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Wed, 28 Oct 2020 23:24:45 +0100 Subject: [PATCH 288/313] Add `lotus-shed datastore rewrite` command Signed-off-by: Jakub Sztandera --- cmd/lotus-shed/datastore.go | 65 +++++++++++++++++++++++++++++++++++++ node/repo/fsrepo_ds.go | 23 +++++++------ 2 files changed, 78 insertions(+), 10 deletions(-) diff --git a/cmd/lotus-shed/datastore.go b/cmd/lotus-shed/datastore.go index c6bac6815..854845346 100644 --- a/cmd/lotus-shed/datastore.go +++ b/cmd/lotus-shed/datastore.go @@ -1,17 +1,22 @@ package main import ( + "bufio" "encoding/json" "fmt" + "io" "os" "strings" "github.com/docker/go-units" "github.com/ipfs/go-datastore" dsq "github.com/ipfs/go-datastore/query" + badgerds "github.com/ipfs/go-ds-badger2" logging "github.com/ipfs/go-log" + "github.com/mitchellh/go-homedir" "github.com/polydawn/refmt/cbor" "github.com/urfave/cli/v2" + "go.uber.org/multierr" "golang.org/x/xerrors" "github.com/filecoin-project/lotus/lib/backupds" @@ -25,6 +30,7 @@ var datastoreCmd = &cli.Command{ datastoreBackupCmd, datastoreListCmd, datastoreGetCmd, + datastoreRewriteCmd, }, } @@ -288,3 +294,62 @@ func printVal(enc string, val []byte) error { return nil } + +var datastoreRewriteCmd = &cli.Command{ + Name: "rewrite", + Description: "rewrites badger datastore to compact it and possibly change params", + ArgsUsage: "source destination", + Action: func(cctx *cli.Context) error { + if cctx.NArg() != 2 { + return xerrors.Errorf("expected 2 arguments, got %d", cctx.NArg()) + } + fromPath, err := homedir.Expand(cctx.Args().Get(0)) + if err != nil { + return xerrors.Errorf("cannot get fromPath: %w", err) + } + toPath, err := homedir.Expand(cctx.Args().Get(1)) + if err != nil { + return xerrors.Errorf("cannot get toPath: %w", err) + } + + opts := repo.ChainBadgerOptions() + opts.Options = opts.Options.WithSyncWrites(false) + to, err := badgerds.NewDatastore(toPath, &opts) + if err != nil { + return xerrors.Errorf("opennig 'to' datastore: %w", err) + } + + opts.Options = opts.Options.WithReadOnly(false) + from, err := badgerds.NewDatastore(fromPath, &opts) + if err != nil { + return xerrors.Errorf("opennig 'from' datastore: %w", err) + } + + pr, pw := io.Pipe() + errCh := make(chan error) + go func() { + bw := bufio.NewWriterSize(pw, 64<<20) + _, err := from.DB.Backup(bw, 0) + bw.Flush() + pw.CloseWithError(err) + errCh <- err + }() + go func() { + err := to.DB.Load(pr, 256) + errCh <- err + }() + + err = <-errCh + if err != nil { + select { + case nerr := <-errCh: + err = multierr.Append(err, nerr) + default: + } + return err + } + + err = <-errCh + return err + }, +} diff --git a/node/repo/fsrepo_ds.go b/node/repo/fsrepo_ds.go index 28d737210..e7746cb8e 100644 --- a/node/repo/fsrepo_ds.go +++ b/node/repo/fsrepo_ds.go @@ -4,18 +4,27 @@ import ( "os" "path/filepath" - "github.com/ipfs/go-datastore" + dgbadger "github.com/dgraph-io/badger/v2" + ldbopts "github.com/syndtr/goleveldb/leveldb/opt" "golang.org/x/xerrors" - dgbadger "github.com/dgraph-io/badger/v2" + "github.com/ipfs/go-datastore" badger "github.com/ipfs/go-ds-badger2" levelds "github.com/ipfs/go-ds-leveldb" measure "github.com/ipfs/go-ds-measure" - ldbopts "github.com/syndtr/goleveldb/leveldb/opt" ) type dsCtor func(path string, readonly bool) (datastore.Batching, error) +func ChainBadgerOptions() badger.Options { + opts := badger.DefaultOptions + opts.GcInterval = 0 // disable GC for chain datastore + + opts.Options = dgbadger.DefaultOptions("").WithTruncate(true). + WithValueThreshold(128) + return opts +} + var fsDatastores = map[string]dsCtor{ "chain": chainBadgerDs, "metadata": levelDs, @@ -27,13 +36,8 @@ var fsDatastores = map[string]dsCtor{ } func chainBadgerDs(path string, readonly bool) (datastore.Batching, error) { - opts := badger.DefaultOptions - opts.GcInterval = 0 // disable GC for chain datastore + opts := ChainBadgerOptions() opts.ReadOnly = readonly - - opts.Options = dgbadger.DefaultOptions("").WithTruncate(true). - WithValueThreshold(128) - return badger.NewDatastore(path, &opts) } @@ -43,7 +47,6 @@ func badgerDs(path string, readonly bool) (datastore.Batching, error) { opts.Options = dgbadger.DefaultOptions("").WithTruncate(true). WithValueThreshold(1 << 10) - return badger.NewDatastore(path, &opts) } From a2c66dd102741201302db03761853d8dabb68720 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Wed, 28 Oct 2020 23:30:28 +0100 Subject: [PATCH 289/313] make linter happy Signed-off-by: Jakub Sztandera --- cmd/lotus-shed/datastore.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/lotus-shed/datastore.go b/cmd/lotus-shed/datastore.go index 854845346..9730d857f 100644 --- a/cmd/lotus-shed/datastore.go +++ b/cmd/lotus-shed/datastore.go @@ -330,8 +330,8 @@ var datastoreRewriteCmd = &cli.Command{ go func() { bw := bufio.NewWriterSize(pw, 64<<20) _, err := from.DB.Backup(bw, 0) - bw.Flush() - pw.CloseWithError(err) + _ = bw.Flush() + _ = pw.CloseWithError(err) errCh <- err }() go func() { From c80e8cb7d3cdd2d859fbbe19a00d85553fbae427 Mon Sep 17 00:00:00 2001 From: jennijuju Date: Wed, 28 Oct 2020 19:04:03 -0400 Subject: [PATCH 290/313] Add miner available balance and power info to state minor info --- cli/state.go | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/cli/state.go b/cli/state.go index d0fcc4f95..7b189644c 100644 --- a/cli/state.go +++ b/cli/state.go @@ -15,13 +15,13 @@ import ( "strings" "time" + "github.com/fatih/color" "github.com/filecoin-project/lotus/chain/actors/builtin" - "github.com/multiformats/go-multiaddr" - "github.com/ipfs/go-cid" cbor "github.com/ipfs/go-ipld-cbor" "github.com/libp2p/go-libp2p-core/peer" + "github.com/multiformats/go-multiaddr" "github.com/multiformats/go-multihash" "github.com/urfave/cli/v2" cbg "github.com/whyrusleeping/cbor-gen" @@ -107,13 +107,18 @@ var stateMinerInfo = &cli.Command{ return err } + availableBalance, err := api.StateMinerAvailableBalance(ctx, addr, ts.Key()) + if err != nil { + return xerrors.Errorf("getting miner available balance: %w", err) + } + fmt.Printf("Miner available balance: %sss\n", types.FIL(availableBalance)) fmt.Printf("Owner:\t%s\n", mi.Owner) fmt.Printf("Worker:\t%s\n", mi.Worker) for i, controlAddress := range mi.ControlAddresses { fmt.Printf("Control %d: \t%s\n", i, controlAddress) } + fmt.Printf("PeerID:\t%s\n", mi.PeerId) - fmt.Printf("SectorSize:\t%s (%d)\n", types.SizeStr(types.NewInt(uint64(mi.SectorSize))), mi.SectorSize) fmt.Printf("Multiaddrs: \t") for _, addr := range mi.Multiaddrs { a, err := multiaddr.NewMultiaddrBytes(addr) @@ -122,6 +127,26 @@ var stateMinerInfo = &cli.Command{ } fmt.Printf("%s ", a) } + + fmt.Printf("SectorSize:\t%s (%d)\n", types.SizeStr(types.NewInt(uint64(mi.SectorSize))), mi.SectorSize) + pow, err := api.StateMinerPower(ctx, addr, ts.Key()) + if err != nil { + return err + } + + rpercI := types.BigDiv(types.BigMul(pow.MinerPower.RawBytePower, types.NewInt(1000000)), pow.TotalPower.RawBytePower) + qpercI := types.BigDiv(types.BigMul(pow.MinerPower.QualityAdjPower, types.NewInt(1000000)), pow.TotalPower.QualityAdjPower) + + fmt.Printf("Byte Power: %s / %s (%0.4f%%)\n", + color.BlueString(types.SizeStr(pow.MinerPower.RawBytePower)), + types.SizeStr(pow.TotalPower.RawBytePower), + float64(rpercI.Int64())/10000) + + fmt.Printf("Actual Power: %s / %s (%0.4f%%)\n", + color.GreenString(types.DeciStr(pow.MinerPower.QualityAdjPower)), + types.DeciStr(pow.TotalPower.QualityAdjPower), + float64(qpercI.Int64())/10000) + fmt.Println() cd, err := api.StateMinerProvingDeadline(ctx, addr, ts.Key()) From 7b8dae92d97edca6e5006c07446c024c516311f3 Mon Sep 17 00:00:00 2001 From: frrist Date: Wed, 28 Oct 2020 16:52:52 -0700 Subject: [PATCH 291/313] feat: add power actor claim diff method --- chain/actors/builtin/power/diff.go | 117 ++++++++++++++++++++++++++++ chain/actors/builtin/power/power.go | 5 ++ chain/actors/builtin/power/v0.go | 19 +++++ chain/actors/builtin/power/v2.go | 22 ++++++ 4 files changed, 163 insertions(+) create mode 100644 chain/actors/builtin/power/diff.go diff --git a/chain/actors/builtin/power/diff.go b/chain/actors/builtin/power/diff.go new file mode 100644 index 000000000..3daa70569 --- /dev/null +++ b/chain/actors/builtin/power/diff.go @@ -0,0 +1,117 @@ +package power + +import ( + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + cbg "github.com/whyrusleeping/cbor-gen" + + "github.com/filecoin-project/lotus/chain/actors/adt" +) + +type ClaimChanges struct { + Added []ClaimInfo + Modified []ClaimModification + Removed []ClaimInfo +} + +type ClaimModification struct { + Miner address.Address + From Claim + To Claim +} + +type ClaimInfo struct { + Miner address.Address + Claim Claim +} + +func DiffClaims(pre, cur State) (*ClaimChanges, error) { + results := new(ClaimChanges) + + prec, err := pre.claims() + if err != nil { + return nil, err + } + + curc, err := cur.claims() + if err != nil { + return nil, err + } + + if err := adt.DiffAdtMap(prec, curc, &claimDiffer{results, pre, cur}); err != nil { + return nil, err + } + + return results, nil +} + +type claimDiffer struct { + Results *ClaimChanges + pre, after State +} + +func (c *claimDiffer) AsKey(key string) (abi.Keyer, error) { + addr, err := address.NewFromBytes([]byte(key)) + if err != nil { + return nil, err + } + return abi.AddrKey(addr), nil +} + +func (c *claimDiffer) Add(key string, val *cbg.Deferred) error { + ci, err := c.after.decodeClaim(val) + if err != nil { + return err + } + addr, err := address.NewFromBytes([]byte(key)) + if err != nil { + return err + } + c.Results.Added = append(c.Results.Added, ClaimInfo{ + Miner: addr, + Claim: ci, + }) + return nil +} + +func (c *claimDiffer) Modify(key string, from, to *cbg.Deferred) error { + ciFrom, err := c.pre.decodeClaim(from) + if err != nil { + return err + } + + ciTo, err := c.after.decodeClaim(to) + if err != nil { + return err + } + + addr, err := address.NewFromBytes([]byte(key)) + if err != nil { + return err + } + + if ciFrom != ciTo { + c.Results.Modified = append(c.Results.Modified, ClaimModification{ + Miner: addr, + From: ciFrom, + To: ciTo, + }) + } + return nil +} + +func (c *claimDiffer) Remove(key string, val *cbg.Deferred) error { + ci, err := c.after.decodeClaim(val) + if err != nil { + return err + } + addr, err := address.NewFromBytes([]byte(key)) + if err != nil { + return err + } + c.Results.Removed = append(c.Results.Removed, ClaimInfo{ + Miner: addr, + Claim: ci, + }) + return nil +} diff --git a/chain/actors/builtin/power/power.go b/chain/actors/builtin/power/power.go index 71645df6a..e0cf0d700 100644 --- a/chain/actors/builtin/power/power.go +++ b/chain/actors/builtin/power/power.go @@ -4,6 +4,7 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/big" "github.com/ipfs/go-cid" + cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" "github.com/filecoin-project/go-state-types/abi" @@ -57,6 +58,10 @@ type State interface { ListAllMiners() ([]address.Address, error) ForEachClaim(func(miner address.Address, claim Claim) error) error ClaimsChanged(State) (bool, error) + + // Diff helpers. Used by Diff* functions internally. + claims() (adt.Map, error) + decodeClaim(*cbg.Deferred) (Claim, error) } type Claim struct { diff --git a/chain/actors/builtin/power/v0.go b/chain/actors/builtin/power/v0.go index 9719b3abf..7636b612b 100644 --- a/chain/actors/builtin/power/v0.go +++ b/chain/actors/builtin/power/v0.go @@ -1,9 +1,12 @@ package power import ( + "bytes" + "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" + cbg "github.com/whyrusleeping/cbor-gen" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/builtin" @@ -124,3 +127,19 @@ func (s *state0) ClaimsChanged(other State) (bool, error) { } return !s.State.Claims.Equals(other0.State.Claims), nil } + +func (s *state0) claims() (adt.Map, error) { + return adt0.AsMap(s.store, s.Claims) +} + +func (s *state0) decodeClaim(val *cbg.Deferred) (Claim, error) { + var ci power0.Claim + if err := ci.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { + return Claim{}, err + } + return fromV0Claim(ci), nil +} + +func fromV0Claim(v0 power0.Claim) Claim { + return (Claim)(v0) +} diff --git a/chain/actors/builtin/power/v2.go b/chain/actors/builtin/power/v2.go index f4036f798..012dc2a4f 100644 --- a/chain/actors/builtin/power/v2.go +++ b/chain/actors/builtin/power/v2.go @@ -1,9 +1,12 @@ package power import ( + "bytes" + "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" + cbg "github.com/whyrusleeping/cbor-gen" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/builtin" @@ -124,3 +127,22 @@ func (s *state2) ClaimsChanged(other State) (bool, error) { } return !s.State.Claims.Equals(other2.State.Claims), nil } + +func (s *state2) claims() (adt.Map, error) { + return adt2.AsMap(s.store, s.Claims) +} + +func (s *state2) decodeClaim(val *cbg.Deferred) (Claim, error) { + var ci power2.Claim + if err := ci.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { + return Claim{}, err + } + return fromV2Claim(ci), nil +} + +func fromV2Claim(v2 power2.Claim) Claim { + return Claim{ + RawBytePower: v2.RawBytePower, + QualityAdjPower: v2.QualityAdjPower, + } +} From ae905bd0563744a183718260734a8b59b248c7fa Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Thu, 29 Oct 2020 01:05:31 +0100 Subject: [PATCH 292/313] Fix closing Signed-off-by: Jakub Sztandera --- cmd/lotus-shed/datastore.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/lotus-shed/datastore.go b/cmd/lotus-shed/datastore.go index 9730d857f..83422e77b 100644 --- a/cmd/lotus-shed/datastore.go +++ b/cmd/lotus-shed/datastore.go @@ -350,6 +350,9 @@ var datastoreRewriteCmd = &cli.Command{ } err = <-errCh - return err + if err != nil { + return err + } + return multierr.Append(from.Close(), to.Close()) }, } From 33459f1b368784de8c0094eaa772d6dc1eec5d1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 29 Oct 2020 10:26:02 +0100 Subject: [PATCH 293/313] storagefsm: Fix GetTicket loop when the sector is already precommitted --- extern/storage-sealing/states_sealing.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/extern/storage-sealing/states_sealing.go b/extern/storage-sealing/states_sealing.go index d4e5535a2..a1aee4cde 100644 --- a/extern/storage-sealing/states_sealing.go +++ b/extern/storage-sealing/states_sealing.go @@ -127,14 +127,25 @@ func (m *Sealing) handlePreCommit1(ctx statemachine.Context, sector SectorInfo) } } - _, height, err := m.api.ChainHead(ctx.Context()) + tok, height, err := m.api.ChainHead(ctx.Context()) if err != nil { log.Errorf("handlePreCommit1: api error, not proceeding: %+v", err) return nil } if height-sector.TicketEpoch > MaxTicketAge { - return ctx.Send(SectorOldTicket{}) + pci, err := m.api.StateSectorPreCommitInfo(ctx.Context(), m.maddr, sector.SectorNumber, tok) + if err != nil { + log.Errorf("getting precommit info: %+v", err) + } + + if pci == nil { + return ctx.Send(SectorOldTicket{}) // go get new ticket + } + + // TODO: allow configuring expected seal durations, if we're here, it's + // pretty unlikely that we'll precommit on time (unless the miner + // process has just restarted and the worker had the result ready) } pc1o, err := m.sealer.SealPreCommit1(sector.sealingCtx(ctx.Context()), m.minerSector(sector.SectorNumber), sector.TicketValue, sector.pieceInfos()) From e168f7a91725990dd82dfc3e25345750a83d487a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 29 Oct 2020 10:33:08 +0100 Subject: [PATCH 294/313] cli: miner-info review --- cli/state.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/state.go b/cli/state.go index 7b189644c..cfa5dc5da 100644 --- a/cli/state.go +++ b/cli/state.go @@ -111,7 +111,7 @@ var stateMinerInfo = &cli.Command{ if err != nil { return xerrors.Errorf("getting miner available balance: %w", err) } - fmt.Printf("Miner available balance: %sss\n", types.FIL(availableBalance)) + fmt.Printf("Available Balance: %s\n", types.FIL(availableBalance)) fmt.Printf("Owner:\t%s\n", mi.Owner) fmt.Printf("Worker:\t%s\n", mi.Worker) for i, controlAddress := range mi.ControlAddresses { From ea5bb5cdab239ad46d0c16bb98618d1062416c2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 29 Oct 2020 12:14:21 +0100 Subject: [PATCH 295/313] sectorstorage: Fix manager restart edge-case --- extern/sector-storage/manager_calltracker.go | 39 +++-- extern/sector-storage/manager_test.go | 149 +++++++++++-------- extern/sector-storage/testworker_test.go | 47 +----- 3 files changed, 114 insertions(+), 121 deletions(-) diff --git a/extern/sector-storage/manager_calltracker.go b/extern/sector-storage/manager_calltracker.go index f0aa0445e..cba363778 100644 --- a/extern/sector-storage/manager_calltracker.go +++ b/extern/sector-storage/manager_calltracker.go @@ -251,19 +251,7 @@ func (m *Manager) waitWork(ctx context.Context, wid WorkID) (interface{}, error) return nil, xerrors.Errorf("something else in waiting on callRes") } - ch, ok := m.waitRes[wid] - if !ok { - ch = make(chan struct{}) - m.waitRes[wid] = ch - } - m.workLk.Unlock() - - select { - case <-ch: - m.workLk.Lock() - defer m.workLk.Unlock() - - res := m.results[wid] + done := func() { delete(m.results, wid) _, ok := m.callToWork[ws.WorkerCall] @@ -276,6 +264,31 @@ func (m *Manager) waitWork(ctx context.Context, wid WorkID) (interface{}, error) // Not great, but not worth discarding potentially multi-hour computation over this log.Errorf("marking work as done: %+v", err) } + } + + // the result can already be there if the work was running, manager restarted, + // and the worker has delivered the result before we entered waitWork + res, ok := m.results[wid] + if ok { + done() + return res.r, res.err + } + + ch, ok := m.waitRes[wid] + if !ok { + ch = make(chan struct{}) + m.waitRes[wid] = ch + } + + m.workLk.Unlock() + + select { + case <-ch: + m.workLk.Lock() + defer m.workLk.Unlock() + + res := m.results[wid] + done() return res.r, res.err case <-ctx.Done(): diff --git a/extern/sector-storage/manager_test.go b/extern/sector-storage/manager_test.go index 938632967..215e5dc90 100644 --- a/extern/sector-storage/manager_test.go +++ b/extern/sector-storage/manager_test.go @@ -210,76 +210,97 @@ func TestRedoPC1(t *testing.T) { // Manager restarts in the middle of a task, restarts it, it completes func TestRestartManager(t *testing.T) { - logging.SetAllLoggers(logging.LevelDebug) + test := func(returnBeforeCall bool) func(*testing.T) { + return func(t *testing.T) { + logging.SetAllLoggers(logging.LevelDebug) - ctx, done := context.WithCancel(context.Background()) - defer done() + ctx, done := context.WithCancel(context.Background()) + defer done() - ds := datastore.NewMapDatastore() + ds := datastore.NewMapDatastore() - m, lstor, _, _, cleanup := newTestMgr(ctx, t, ds) - defer cleanup() + m, lstor, _, _, cleanup := newTestMgr(ctx, t, ds) + defer cleanup() - localTasks := []sealtasks.TaskType{ - sealtasks.TTAddPiece, sealtasks.TTPreCommit1, sealtasks.TTCommit1, sealtasks.TTFinalize, sealtasks.TTFetch, + localTasks := []sealtasks.TaskType{ + sealtasks.TTAddPiece, sealtasks.TTPreCommit1, sealtasks.TTCommit1, sealtasks.TTFinalize, sealtasks.TTFetch, + } + + tw := newTestWorker(WorkerConfig{ + SealProof: abi.RegisteredSealProof_StackedDrg2KiBV1, + TaskTypes: localTasks, + }, lstor, m) + + err := m.AddWorker(ctx, tw) + require.NoError(t, err) + + sid := abi.SectorID{Miner: 1000, Number: 1} + + pi, err := m.AddPiece(ctx, sid, nil, 1016, strings.NewReader(strings.Repeat("testthis", 127))) + require.NoError(t, err) + require.Equal(t, abi.PaddedPieceSize(1024), pi.Size) + + piz, err := m.AddPiece(ctx, sid, nil, 1016, bytes.NewReader(make([]byte, 1016)[:])) + require.NoError(t, err) + require.Equal(t, abi.PaddedPieceSize(1024), piz.Size) + + pieces := []abi.PieceInfo{pi, piz} + + ticket := abi.SealRandomness{0, 9, 9, 9, 9, 9, 9, 9} + + tw.pc1lk.Lock() + tw.pc1wait = &sync.WaitGroup{} + tw.pc1wait.Add(1) + + var cwg sync.WaitGroup + cwg.Add(1) + + var perr error + go func() { + defer cwg.Done() + _, perr = m.SealPreCommit1(ctx, sid, ticket, pieces) + }() + + tw.pc1wait.Wait() + + require.NoError(t, m.Close(ctx)) + tw.ret = nil + + cwg.Wait() + require.Error(t, perr) + + m, _, _, _, cleanup2 := newTestMgr(ctx, t, ds) + defer cleanup2() + + tw.ret = m // simulate jsonrpc auto-reconnect + err = m.AddWorker(ctx, tw) + require.NoError(t, err) + + if returnBeforeCall { + tw.pc1lk.Unlock() + time.Sleep(100 * time.Millisecond) + + _, err = m.SealPreCommit1(ctx, sid, ticket, pieces) + } else { + done := make(chan struct{}) + go func() { + defer close(done) + _, err = m.SealPreCommit1(ctx, sid, ticket, pieces) + }() + + time.Sleep(100 * time.Millisecond) + tw.pc1lk.Unlock() + <-done + } + + require.NoError(t, err) + + require.Equal(t, 1, tw.pc1s) + } } - tw := newTestWorker(WorkerConfig{ - SealProof: abi.RegisteredSealProof_StackedDrg2KiBV1, - TaskTypes: localTasks, - }, lstor, m) - - err := m.AddWorker(ctx, tw) - require.NoError(t, err) - - sid := abi.SectorID{Miner: 1000, Number: 1} - - pi, err := m.AddPiece(ctx, sid, nil, 1016, strings.NewReader(strings.Repeat("testthis", 127))) - require.NoError(t, err) - require.Equal(t, abi.PaddedPieceSize(1024), pi.Size) - - piz, err := m.AddPiece(ctx, sid, nil, 1016, bytes.NewReader(make([]byte, 1016)[:])) - require.NoError(t, err) - require.Equal(t, abi.PaddedPieceSize(1024), piz.Size) - - pieces := []abi.PieceInfo{pi, piz} - - ticket := abi.SealRandomness{0, 9, 9, 9, 9, 9, 9, 9} - - tw.pc1lk.Lock() - tw.pc1wait = &sync.WaitGroup{} - tw.pc1wait.Add(1) - - var cwg sync.WaitGroup - cwg.Add(1) - - var perr error - go func() { - defer cwg.Done() - _, perr = m.SealPreCommit1(ctx, sid, ticket, pieces) - }() - - tw.pc1wait.Wait() - - require.NoError(t, m.Close(ctx)) - tw.ret = nil - - cwg.Wait() - require.Error(t, perr) - - m, _, _, _, cleanup2 := newTestMgr(ctx, t, ds) - defer cleanup2() - - tw.ret = m // simulate jsonrpc auto-reconnect - err = m.AddWorker(ctx, tw) - require.NoError(t, err) - - tw.pc1lk.Unlock() - - _, err = m.SealPreCommit1(ctx, sid, ticket, pieces) - require.NoError(t, err) - - require.Equal(t, 1, tw.pc1s) + t.Run("callThenReturn", test(false)) + t.Run("returnThenCall", test(true)) } // Worker restarts in the middle of a task, task fails after restart diff --git a/extern/sector-storage/testworker_test.go b/extern/sector-storage/testworker_test.go index fda25643a..d04afb0cc 100644 --- a/extern/sector-storage/testworker_test.go +++ b/extern/sector-storage/testworker_test.go @@ -2,14 +2,11 @@ package sectorstorage import ( "context" - "io" "sync" - "github.com/google/uuid" - "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/specs-storage/storage" + "github.com/google/uuid" "github.com/filecoin-project/lotus/extern/sector-storage/mock" "github.com/filecoin-project/lotus/extern/sector-storage/sealtasks" @@ -29,6 +26,8 @@ type testWorker struct { pc1wait *sync.WaitGroup session uuid.UUID + + Worker } func newTestWorker(wcfg WorkerConfig, lstor *stores.Local, ret storiface.WorkerReturn) *testWorker { @@ -64,18 +63,6 @@ func (t *testWorker) asyncCall(sector abi.SectorID, work func(ci storiface.CallI return ci, nil } -func (t *testWorker) NewSector(ctx context.Context, sector abi.SectorID) error { - panic("implement me") -} - -func (t *testWorker) UnsealPiece(ctx context.Context, id abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, randomness abi.SealRandomness, cid cid.Cid) (storiface.CallID, error) { - panic("implement me") -} - -func (t *testWorker) ReadPiece(ctx context.Context, writer io.Writer, id abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize) (storiface.CallID, error) { - panic("implement me") -} - func (t *testWorker) AddPiece(ctx context.Context, sector abi.SectorID, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage.Data) (storiface.CallID, error) { return t.asyncCall(sector, func(ci storiface.CallID) { p, err := t.mockSeal.AddPiece(ctx, sector, pieceSizes, newPieceSize, pieceData) @@ -103,34 +90,6 @@ func (t *testWorker) SealPreCommit1(ctx context.Context, sector abi.SectorID, ti }) } -func (t *testWorker) SealPreCommit2(ctx context.Context, sector abi.SectorID, pc1o storage.PreCommit1Out) (storiface.CallID, error) { - panic("implement me") -} - -func (t *testWorker) SealCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storiface.CallID, error) { - panic("implement me") -} - -func (t *testWorker) SealCommit2(ctx context.Context, sector abi.SectorID, c1o storage.Commit1Out) (storiface.CallID, error) { - panic("implement me") -} - -func (t *testWorker) FinalizeSector(ctx context.Context, sector abi.SectorID, keepUnsealed []storage.Range) (storiface.CallID, error) { - panic("implement me") -} - -func (t *testWorker) ReleaseUnsealed(ctx context.Context, sector abi.SectorID, safeToFree []storage.Range) (storiface.CallID, error) { - panic("implement me") -} - -func (t *testWorker) Remove(ctx context.Context, sector abi.SectorID) (storiface.CallID, error) { - panic("implement me") -} - -func (t *testWorker) MoveStorage(ctx context.Context, sector abi.SectorID, types storiface.SectorFileType) (storiface.CallID, error) { - panic("implement me") -} - func (t *testWorker) Fetch(ctx context.Context, sector abi.SectorID, fileType storiface.SectorFileType, ptype storiface.PathType, am storiface.AcquireMode) (storiface.CallID, error) { return t.asyncCall(sector, func(ci storiface.CallID) { if err := t.ret.ReturnFetch(ctx, ci, ""); err != nil { From c6b03ce62b951f9f051aaf49e0388d01b9b7ebed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 29 Oct 2020 15:18:30 +0100 Subject: [PATCH 296/313] sectorstorage: Missing unlock in waitWork --- extern/sector-storage/manager_calltracker.go | 1 + extern/sector-storage/manager_test.go | 3 +++ 2 files changed, 4 insertions(+) diff --git a/extern/sector-storage/manager_calltracker.go b/extern/sector-storage/manager_calltracker.go index cba363778..8a1c1e4f9 100644 --- a/extern/sector-storage/manager_calltracker.go +++ b/extern/sector-storage/manager_calltracker.go @@ -271,6 +271,7 @@ func (m *Manager) waitWork(ctx context.Context, wid WorkID) (interface{}, error) res, ok := m.results[wid] if ok { done() + m.workLk.Unlock() return res.r, res.err } diff --git a/extern/sector-storage/manager_test.go b/extern/sector-storage/manager_test.go index 215e5dc90..0e3e7bc9d 100644 --- a/extern/sector-storage/manager_test.go +++ b/extern/sector-storage/manager_test.go @@ -296,6 +296,9 @@ func TestRestartManager(t *testing.T) { require.NoError(t, err) require.Equal(t, 1, tw.pc1s) + + ws := m.WorkerJobs() + require.Empty(t, ws) } } From ad9a5acb7f2d73d69c15bd250bdea6530c5a6a27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 29 Oct 2020 19:10:20 +0100 Subject: [PATCH 297/313] miner sectors list: flags for events/seal time --- cmd/lotus-storage-miner/sectors.go | 57 ++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/cmd/lotus-storage-miner/sectors.go b/cmd/lotus-storage-miner/sectors.go index 967e2d413..e2e94cf69 100644 --- a/cmd/lotus-storage-miner/sectors.go +++ b/cmd/lotus-storage-miner/sectors.go @@ -5,6 +5,7 @@ import ( "os" "sort" "strconv" + "strings" "time" "github.com/docker/go-units" @@ -155,6 +156,14 @@ var sectorsListCmd = &cli.Command{ Name: "fast", Usage: "don't show on-chain info for better performance", }, + &cli.BoolFlag{ + Name: "events", + Usage: "display number of events the sector has received", + }, + &cli.BoolFlag{ + Name: "seal-time", + Usage: "display how long it took for the sector to be sealed", + }, }, Action: func(cctx *cli.Context) error { color.NoColor = !cctx.Bool("color") @@ -216,6 +225,8 @@ var sectorsListCmd = &cli.Command{ tablewriter.Col("OnChain"), tablewriter.Col("Active"), tablewriter.Col("Expiration"), + tablewriter.Col("SealTime"), + tablewriter.Col("Events"), tablewriter.Col("Deals"), tablewriter.Col("DealWeight"), tablewriter.NewLineCol("Error"), @@ -286,6 +297,52 @@ var sectorsListCmd = &cli.Command{ } } + if cctx.Bool("events") { + var events int + for _, sectorLog := range st.Log { + if !strings.HasPrefix(sectorLog.Kind, "event") { + continue + } + if sectorLog.Kind == "event;sealing.SectorRestart" { + continue + } + events++ + } + + pieces := len(st.Deals) + + switch { + case events < 12+pieces: + m["Events"] = color.GreenString("%d", events) + case events < 20+pieces: + m["Events"] = color.YellowString("%d", events) + default: + m["Events"] = color.RedString("%d", events) + } + } + + if cctx.Bool("seal-time") && len(st.Log) > 1 { + start := time.Unix(int64(st.Log[0].Timestamp), 0) + + for _, sectorLog := range st.Log { + if sectorLog.Kind == "event;sealing.SectorProving" { + end := time.Unix(int64(sectorLog.Timestamp), 0) + dur := end.Sub(start) + + switch { + case dur < 12*time.Hour: + m["SealTime"] = color.GreenString("%s", dur) + case dur < 24*time.Hour: + m["SealTime"] = color.YellowString("%s", dur) + default: + m["SealTime"] = color.RedString("%s", dur) + } + + break + } + } + } + tw.Write(m) } } From 7d0f27935366ead115a7bdd2784214781ee488da Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Thu, 29 Oct 2020 15:16:45 -0300 Subject: [PATCH 298/313] make IPFS online mode configurable Signed-off-by: Ignacio Hagopian --- lib/ipfsbstore/ipfsbstore.go | 8 ++++---- node/builder.go | 2 +- node/config/def.go | 1 + node/modules/ipfsclient.go | 6 +++--- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/lib/ipfsbstore/ipfsbstore.go b/lib/ipfsbstore/ipfsbstore.go index 748afee51..e66f3da89 100644 --- a/lib/ipfsbstore/ipfsbstore.go +++ b/lib/ipfsbstore/ipfsbstore.go @@ -25,12 +25,12 @@ type IpfsBstore struct { api iface.CoreAPI } -func NewIpfsBstore(ctx context.Context) (*IpfsBstore, error) { +func NewIpfsBstore(ctx context.Context, onlineMode bool) (*IpfsBstore, error) { localApi, err := httpapi.NewLocalApi() if err != nil { return nil, xerrors.Errorf("getting local ipfs api: %w", err) } - api, err := localApi.WithOptions(options.Api.Offline(true)) + api, err := localApi.WithOptions(options.Api.Offline(!onlineMode)) if err != nil { return nil, xerrors.Errorf("setting offline mode: %s", err) } @@ -41,12 +41,12 @@ func NewIpfsBstore(ctx context.Context) (*IpfsBstore, error) { }, nil } -func NewRemoteIpfsBstore(ctx context.Context, maddr multiaddr.Multiaddr) (*IpfsBstore, error) { +func NewRemoteIpfsBstore(ctx context.Context, maddr multiaddr.Multiaddr, onlineMode bool) (*IpfsBstore, error) { httpApi, err := httpapi.NewApi(maddr) if err != nil { return nil, xerrors.Errorf("setting remote ipfs api: %w", err) } - api, err := httpApi.WithOptions(options.Api.Offline(true)) + api, err := httpApi.WithOptions(options.Api.Offline(!onlineMode)) if err != nil { return nil, xerrors.Errorf("applying offline mode: %s", err) } diff --git a/node/builder.go b/node/builder.go index 1d632c35c..cd3228d02 100644 --- a/node/builder.go +++ b/node/builder.go @@ -452,7 +452,7 @@ func ConfigFullNode(c interface{}) Option { return Options( ConfigCommon(&cfg.Common), If(cfg.Client.UseIpfs, - Override(new(dtypes.ClientBlockstore), modules.IpfsClientBlockstore(ipfsMaddr)), + Override(new(dtypes.ClientBlockstore), modules.IpfsClientBlockstore(ipfsMaddr, cfg.Client.IpfsOnlineMode)), If(cfg.Client.IpfsUseForRetrieval, Override(new(dtypes.ClientRetrievalStoreManager), modules.ClientBlockstoreRetrievalStoreManager), ), diff --git a/node/config/def.go b/node/config/def.go index 1298ed45a..0b7425d6d 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -105,6 +105,7 @@ type Metrics struct { type Client struct { UseIpfs bool + IpfsOnlineMode bool IpfsMAddr string IpfsUseForRetrieval bool } diff --git a/node/modules/ipfsclient.go b/node/modules/ipfsclient.go index 24e595fdb..a2d5de88d 100644 --- a/node/modules/ipfsclient.go +++ b/node/modules/ipfsclient.go @@ -16,7 +16,7 @@ import ( // If ipfsMaddr is empty, a local IPFS node is assumed considering IPFS_PATH configuration. // If ipfsMaddr is not empty, it will connect to the remote IPFS node with the provided multiaddress. // The flag useForRetrieval indicates if the IPFS node will also be used for storing retrieving deals. -func IpfsClientBlockstore(ipfsMaddr string) func(helpers.MetricsCtx, fx.Lifecycle, dtypes.ClientImportMgr) (dtypes.ClientBlockstore, error) { +func IpfsClientBlockstore(ipfsMaddr string, onlineMode bool) func(helpers.MetricsCtx, fx.Lifecycle, dtypes.ClientImportMgr) (dtypes.ClientBlockstore, error) { return func(mctx helpers.MetricsCtx, lc fx.Lifecycle, localStore dtypes.ClientImportMgr) (dtypes.ClientBlockstore, error) { var err error var ipfsbs blockstore.Blockstore @@ -26,9 +26,9 @@ func IpfsClientBlockstore(ipfsMaddr string) func(helpers.MetricsCtx, fx.Lifecycl if err != nil { return nil, xerrors.Errorf("parsing ipfs multiaddr: %w", err) } - ipfsbs, err = ipfsbstore.NewRemoteIpfsBstore(helpers.LifecycleCtx(mctx, lc), ma) + ipfsbs, err = ipfsbstore.NewRemoteIpfsBstore(helpers.LifecycleCtx(mctx, lc), ma, onlineMode) } else { - ipfsbs, err = ipfsbstore.NewIpfsBstore(helpers.LifecycleCtx(mctx, lc)) + ipfsbs, err = ipfsbstore.NewIpfsBstore(helpers.LifecycleCtx(mctx, lc), onlineMode) } if err != nil { return nil, xerrors.Errorf("constructing ipfs blockstore: %w", err) From d8d92914022060d41d0bd789495a1c0e5717eb21 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Thu, 29 Oct 2020 20:34:48 +0100 Subject: [PATCH 299/313] Prep for gas balancing Signed-off-by: Jakub Sztandera --- chain/vm/gas.go | 1 + chain/vm/gas_v0.go | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/chain/vm/gas.go b/chain/vm/gas.go index cbe5bab13..95551f153 100644 --- a/chain/vm/gas.go +++ b/chain/vm/gas.go @@ -126,6 +126,7 @@ var prices = map[abi.ChainEpoch]Pricelist{ scale: 85639, }, }, + verifyPostDiscount: true, verifyConsensusFault: 495422, }, } diff --git a/chain/vm/gas_v0.go b/chain/vm/gas_v0.go index 7a7fb364d..e4028039b 100644 --- a/chain/vm/gas_v0.go +++ b/chain/vm/gas_v0.go @@ -90,6 +90,7 @@ type pricelistV0 struct { computeUnsealedSectorCidBase int64 verifySealBase int64 verifyPostLookup map[abi.RegisteredPoStProof]scalingCost + verifyPostDiscount bool verifyConsensusFault int64 } @@ -201,7 +202,9 @@ func (pl *pricelistV0) OnVerifyPost(info proof2.WindowPoStVerifyInfo) GasCharge } gasUsed := cost.flat + int64(len(info.ChallengedSectors))*cost.scale - gasUsed /= 2 // XXX: this is an artificial discount + if pl.verifyPostDiscount { + gasUsed /= 2 // XXX: this is an artificial discount + } return newGasCharge("OnVerifyPost", gasUsed, 0). WithExtra(map[string]interface{}{ From ae7889f8303ce39987262f57810e88931c81ea2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 29 Oct 2020 20:50:04 +0100 Subject: [PATCH 300/313] Config for default max gas fee --- chain/messagepool/messagepool.go | 12 ++++++++---- cli/mpool.go | 8 +++++++- node/builder.go | 1 + node/config/def.go | 10 ++++++++++ node/impl/full/gas.go | 10 ++++++---- node/modules/core.go | 27 +++++++++++++++++++++++++++ node/modules/dtypes/mpool.go | 3 +++ 7 files changed, 62 insertions(+), 9 deletions(-) diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index 79ab572ba..8c8a8af15 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -59,8 +59,6 @@ var MaxUntrustedActorPendingMessages = 10 var MaxNonceGap = uint64(4) -var DefaultMaxFee = abi.TokenAmount(types.MustParseFIL("0.007")) - var ( ErrMessageTooBig = errors.New("message too big") @@ -183,9 +181,15 @@ func ComputeMinRBF(curPrem abi.TokenAmount) abi.TokenAmount { return types.BigAdd(minPrice, types.NewInt(1)) } -func CapGasFee(msg *types.Message, maxFee abi.TokenAmount) { +func CapGasFee(mff dtypes.DefaultMaxFeeFunc, msg *types.Message, maxFee abi.TokenAmount) { if maxFee.Equals(big.Zero()) { - maxFee = DefaultMaxFee + mf, err := mff() + if err != nil { + log.Errorf("failed to get default max gas fee: %+v", err) + mf = big.Zero() + } + + maxFee = mf } gl := types.NewInt(uint64(msg.GasLimit)) diff --git a/cli/mpool.go b/cli/mpool.go index 8f3e937b6..4979f6ddc 100644 --- a/cli/mpool.go +++ b/cli/mpool.go @@ -19,6 +19,7 @@ import ( "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/messagepool" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/node/config" ) var mpoolCmd = &cli.Command{ @@ -434,7 +435,12 @@ var mpoolReplaceCmd = &cli.Command{ msg.GasPremium = big.Max(retm.GasPremium, minRBF) msg.GasFeeCap = big.Max(retm.GasFeeCap, msg.GasPremium) - messagepool.CapGasFee(&msg, mss.Get().MaxFee) + + mff := func() (abi.TokenAmount, error) { + return abi.TokenAmount(config.DefaultDefaultMaxFee), nil + } + + messagepool.CapGasFee(mff, &msg, mss.Get().MaxFee) } else { msg.GasLimit = cctx.Int64("gas-limit") msg.GasPremium, err = types.BigFromString(cctx.String("gas-premium")) diff --git a/node/builder.go b/node/builder.go index bb039cb76..e33e1e469 100644 --- a/node/builder.go +++ b/node/builder.go @@ -268,6 +268,7 @@ func Online() Option { Override(new(*chain.Syncer), modules.NewSyncer), Override(new(exchange.Client), exchange.NewClient), Override(new(*messagepool.MessagePool), modules.MessagePool), + Override(new(dtypes.DefaultMaxFeeFunc), modules.NewDefaultMaxFeeFunc), Override(new(modules.Genesis), modules.ErrorGenesis), Override(new(dtypes.AfterGenesisSet), modules.SetGenesis), diff --git a/node/config/def.go b/node/config/def.go index 1298ed45a..9a2850f92 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -23,6 +23,7 @@ type FullNode struct { Client Client Metrics Metrics Wallet Wallet + Fees FeeConfig } // // Common @@ -115,6 +116,10 @@ type Wallet struct { DisableLocal bool } +type FeeConfig struct { + DefaultMaxFee types.FIL +} + func defCommon() Common { return Common{ API: API{ @@ -142,10 +147,15 @@ func defCommon() Common { } +var DefaultDefaultMaxFee = types.MustParseFIL("0.007") + // DefaultFullNode returns the default config func DefaultFullNode() *FullNode { return &FullNode{ Common: defCommon(), + Fees: FeeConfig{ + DefaultMaxFee: DefaultDefaultMaxFee, + }, } } diff --git a/node/impl/full/gas.go b/node/impl/full/gas.go index e0cbd2192..5d21121ee 100644 --- a/node/impl/full/gas.go +++ b/node/impl/full/gas.go @@ -23,6 +23,7 @@ import ( "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/node/modules/dtypes" ) type GasModuleAPI interface { @@ -34,9 +35,10 @@ type GasModuleAPI interface { // Injection (for example with a thin RPC client). type GasModule struct { fx.In - Stmgr *stmgr.StateManager - Chain *store.ChainStore - Mpool *messagepool.MessagePool + Stmgr *stmgr.StateManager + Chain *store.ChainStore + Mpool *messagepool.MessagePool + GetMaxFee dtypes.DefaultMaxFeeFunc } var _ GasModuleAPI = (*GasModule)(nil) @@ -291,7 +293,7 @@ func (m *GasModule) GasEstimateMessageGas(ctx context.Context, msg *types.Messag msg.GasFeeCap = feeCap } - messagepool.CapGasFee(msg, spec.Get().MaxFee) + messagepool.CapGasFee(m.GetMaxFee, msg, spec.Get().MaxFee) return msg, nil } diff --git a/node/modules/core.go b/node/modules/core.go index a695d8651..823b0131e 100644 --- a/node/modules/core.go +++ b/node/modules/core.go @@ -15,11 +15,13 @@ import ( "golang.org/x/xerrors" "github.com/filecoin-project/go-jsonrpc/auth" + "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/lotus/api/apistruct" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/lib/addrutil" + "github.com/filecoin-project/lotus/node/config" "github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/repo" ) @@ -105,3 +107,28 @@ func DrandBootstrap(ds dtypes.DrandSchedule) (dtypes.DrandBootstrap, error) { } return res, nil } + +func NewDefaultMaxFeeFunc(r repo.LockedRepo) dtypes.DefaultMaxFeeFunc { + return func() (out abi.TokenAmount, err error) { + err = readNodeCfg(r, func(cfg *config.FullNode) { + out = abi.TokenAmount(cfg.Fees.DefaultMaxFee) + }) + return + } +} + +func readNodeCfg(r repo.LockedRepo, accessor func(node *config.FullNode)) error { + raw, err := r.Config() + if err != nil { + return err + } + + cfg, ok := raw.(*config.FullNode) + if !ok { + return xerrors.New("expected config.FullNode") + } + + accessor(cfg) + + return nil +} diff --git a/node/modules/dtypes/mpool.go b/node/modules/dtypes/mpool.go index 1c64449f8..df96b8d0e 100644 --- a/node/modules/dtypes/mpool.go +++ b/node/modules/dtypes/mpool.go @@ -5,6 +5,7 @@ import ( "sync" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" ) type MpoolLocker struct { @@ -33,3 +34,5 @@ func (ml *MpoolLocker) TakeLock(ctx context.Context, a address.Address) (func(), <-lk }, nil } + +type DefaultMaxFeeFunc func() (abi.TokenAmount, error) From 5ff42505e86b690816fb67ef10078ee34fdbbeed Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Tue, 29 Sep 2020 03:01:52 -0400 Subject: [PATCH 301/313] Add a StateDecodeParams method --- api/api_full.go | 2 ++ api/apistruct/struct.go | 5 +++++ chain/stmgr/utils.go | 8 ++++++++ cli/state.go | 9 ++++----- documentation/en/api-methods.md | 26 ++++++++++++++++++++++++++ node/impl/full/state.go | 18 ++++++++++++++++++ 6 files changed, 63 insertions(+), 5 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index bb1eb1595..0b9fb71d2 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -344,6 +344,8 @@ type FullNode interface { StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*ActorState, error) // StateListMessages looks back and returns all messages with a matching to or from address, stopping at the given height. StateListMessages(ctx context.Context, match *MessageMatch, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) + // StateDecodeParams attempts to decode the provided params, based on the recipient actor address and method number. + StateDecodeParams(ctx context.Context, toAddr address.Address, method abi.MethodNum, params []byte, tsk types.TipSetKey) (interface{}, error) // StateNetworkName returns the name of the network the node is synced to StateNetworkName(context.Context) (dtypes.NetworkName, error) diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 3a4ae75a8..35f279c3d 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -215,6 +215,7 @@ type FullNodeStruct struct { StateGetReceipt func(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error) `perm:"read"` StateMinerSectorCount func(context.Context, address.Address, types.TipSetKey) (api.MinerSectors, error) `perm:"read"` StateListMessages func(ctx context.Context, match *api.MessageMatch, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"` + StateDecodeParams func(context.Context, address.Address, abi.MethodNum, []byte, types.TipSetKey) (interface{}, error) `perm:"read"` StateCompute func(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (*api.ComputeStateOutput, error) `perm:"read"` StateVerifierStatus func(context.Context, address.Address, types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` StateVerifiedClientStatus func(context.Context, address.Address, types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` @@ -1014,6 +1015,10 @@ func (c *FullNodeStruct) StateListMessages(ctx context.Context, match *api.Messa return c.Internal.StateListMessages(ctx, match, tsk, toht) } +func (c *FullNodeStruct) StateDecodeParams(ctx context.Context, toAddr address.Address, method abi.MethodNum, params []byte, tsk types.TipSetKey) (interface{}, error) { + return c.Internal.StateDecodeParams(ctx, toAddr, method, params, tsk) +} + func (c *FullNodeStruct) StateCompute(ctx context.Context, height abi.ChainEpoch, msgs []*types.Message, tsk types.TipSetKey) (*api.ComputeStateOutput, error) { return c.Internal.StateCompute(ctx, height, msgs, tsk) } diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index 5b144281d..78121cc4c 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -614,6 +614,14 @@ func GetReturnType(ctx context.Context, sm *StateManager, to address.Address, me return reflect.New(m.Ret.Elem()).Interface().(cbg.CBORUnmarshaler), nil } +func GetParamType(actCode cid.Cid, method abi.MethodNum) (cbg.CBORUnmarshaler, error) { + m, found := MethodsMap[actCode][method] + if !found { + return nil, fmt.Errorf("unknown method %d for actor %s", method, actCode) + } + return reflect.New(m.Params.Elem()).Interface().(cbg.CBORUnmarshaler), nil +} + func minerHasMinPower(ctx context.Context, sm *StateManager, addr address.Address, ts *types.TipSet) (bool, error) { pact, err := sm.LoadActor(ctx, power.Address, ts) if err != nil { diff --git a/cli/state.go b/cli/state.go index 13aa5c39b..c17a4f438 100644 --- a/cli/state.go +++ b/cli/state.go @@ -1299,12 +1299,11 @@ func sumGas(changes []*types.GasTrace) types.GasTrace { } func JsonParams(code cid.Cid, method abi.MethodNum, params []byte) (string, error) { - methodMeta, found := stmgr.MethodsMap[code][method] - if !found { - return "", fmt.Errorf("method %d not found on actor %s", method, code) + p, err := stmgr.GetParamType(code, method) + if err != nil { + return "", err } - re := reflect.New(methodMeta.Params.Elem()) - p := re.Interface().(cbg.CBORUnmarshaler) + if err := p.UnmarshalCBOR(bytes.NewReader(params)); err != nil { return "", err } diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index 4e18d85c9..4ab89d688 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -140,6 +140,7 @@ * [StateCirculatingSupply](#StateCirculatingSupply) * [StateCompute](#StateCompute) * [StateDealProviderCollateralBounds](#StateDealProviderCollateralBounds) + * [StateDecodeParams](#StateDecodeParams) * [StateGetActor](#StateGetActor) * [StateGetReceipt](#StateGetReceipt) * [StateListActors](#StateListActors) @@ -3387,6 +3388,31 @@ Response: } ``` +### StateDecodeParams +StateDecodeParams attempts to decode the provided params, based on the recipient actor address and method number. + + +Perms: read + +Inputs: +```json +[ + "f01234", + 1, + "Ynl0ZSBhcnJheQ==", + [ + { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + { + "/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve" + } + ] +] +``` + +Response: `{}` + ### StateGetActor StateGetActor returns the indicated actor's nonce and balance. diff --git a/node/impl/full/state.go b/node/impl/full/state.go index 9a6c772ae..126ff0d7b 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -491,6 +491,24 @@ func (a *StateAPI) StateReadState(ctx context.Context, actor address.Address, ts }, nil } +func (a *StateAPI) StateDecodeParams(ctx context.Context, toAddr address.Address, method abi.MethodNum, params []byte, tsk types.TipSetKey) (interface{}, error) { + act, err := a.StateGetActor(ctx, toAddr, tsk) + if err != nil { + return nil, xerrors.Errorf("getting actor: %w", err) + } + + paramType, err := stmgr.GetParamType(act.Code, method) + if err != nil { + return nil, xerrors.Errorf("getting params type: %w", err) + } + + if err = paramType.UnmarshalCBOR(bytes.NewReader(params)); err != nil { + return nil, err + } + + return paramType, nil +} + // This is on StateAPI because miner.Miner requires this, and MinerAPI requires miner.Miner func (a *StateAPI) MinerGetBaseInfo(ctx context.Context, maddr address.Address, epoch abi.ChainEpoch, tsk types.TipSetKey) (*api.MiningBaseInfo, error) { return stmgr.MinerGetBaseInfo(ctx, a.StateManager, a.Beacon, tsk, epoch, maddr, a.ProofVerifier) From 7fbb868513ac723549daabc03a70f497490fa540 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 30 Oct 2020 11:07:35 +0100 Subject: [PATCH 302/313] Debug flag to force running sealing scheduler --- api/api_storage.go | 2 +- api/apistruct/struct.go | 6 +++--- cmd/lotus-storage-miner/sealing.go | 7 ++++++- extern/sector-storage/manager.go | 10 +++++++++- node/impl/storminer.go | 4 ++-- 5 files changed, 21 insertions(+), 8 deletions(-) diff --git a/api/api_storage.go b/api/api_storage.go index 2176456b7..d003ec776 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -70,7 +70,7 @@ type StorageMiner interface { storiface.WorkerReturn // SealingSchedDiag dumps internal sealing scheduler state - SealingSchedDiag(context.Context) (interface{}, error) + SealingSchedDiag(ctx context.Context, doSched bool) (interface{}, error) stores.SectorIndex diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 3a4ae75a8..4381c36ad 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -321,7 +321,7 @@ type StorageMinerStruct struct { ReturnReadPiece func(ctx context.Context, callID storiface.CallID, ok bool, err string) error `perm:"admin" retry:"true"` ReturnFetch func(ctx context.Context, callID storiface.CallID, err string) error `perm:"admin" retry:"true"` - SealingSchedDiag func(context.Context) (interface{}, error) `perm:"admin"` + SealingSchedDiag func(context.Context, bool) (interface{}, error) `perm:"admin"` StorageList func(context.Context) (map[stores.ID][]stores.Decl, error) `perm:"admin"` StorageLocal func(context.Context) (map[stores.ID]string, error) `perm:"admin"` @@ -1298,8 +1298,8 @@ func (c *StorageMinerStruct) ReturnFetch(ctx context.Context, callID storiface.C return c.Internal.ReturnFetch(ctx, callID, err) } -func (c *StorageMinerStruct) SealingSchedDiag(ctx context.Context) (interface{}, error) { - return c.Internal.SealingSchedDiag(ctx) +func (c *StorageMinerStruct) SealingSchedDiag(ctx context.Context, doSched bool) (interface{}, error) { + return c.Internal.SealingSchedDiag(ctx, doSched) } func (c *StorageMinerStruct) StorageAttach(ctx context.Context, si stores.StorageInfo, st fsutil.FsStat) error { diff --git a/cmd/lotus-storage-miner/sealing.go b/cmd/lotus-storage-miner/sealing.go index 440d4aaea..49003fc26 100644 --- a/cmd/lotus-storage-miner/sealing.go +++ b/cmd/lotus-storage-miner/sealing.go @@ -215,6 +215,11 @@ var sealingJobsCmd = &cli.Command{ var sealingSchedDiagCmd = &cli.Command{ Name: "sched-diag", Usage: "Dump internal scheduler state", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "force-sched", + }, + }, Action: func(cctx *cli.Context) error { nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx) if err != nil { @@ -224,7 +229,7 @@ var sealingSchedDiagCmd = &cli.Command{ ctx := lcli.ReqContext(cctx) - st, err := nodeApi.SealingSchedDiag(ctx) + st, err := nodeApi.SealingSchedDiag(ctx, cctx.Bool("force-sched")) if err != nil { return err } diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index f32a363e7..9a41dcd44 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -679,7 +679,15 @@ func (m *Manager) FsStat(ctx context.Context, id stores.ID) (fsutil.FsStat, erro return m.storage.FsStat(ctx, id) } -func (m *Manager) SchedDiag(ctx context.Context) (interface{}, error) { +func (m *Manager) SchedDiag(ctx context.Context, doSched bool) (interface{}, error) { + if doSched { + select { + case m.sched.workerChange <- struct{}{}: + case <-ctx.Done(): + return nil, ctx.Err() + } + } + return m.sched.Info(ctx) } diff --git a/node/impl/storminer.go b/node/impl/storminer.go index dee48f5de..a58621c97 100644 --- a/node/impl/storminer.go +++ b/node/impl/storminer.go @@ -296,8 +296,8 @@ func (sm *StorageMinerAPI) WorkerConnect(ctx context.Context, url string) error return sm.StorageMgr.AddWorker(ctx, w) } -func (sm *StorageMinerAPI) SealingSchedDiag(ctx context.Context) (interface{}, error) { - return sm.StorageMgr.SchedDiag(ctx) +func (sm *StorageMinerAPI) SealingSchedDiag(ctx context.Context, doSched bool) (interface{}, error) { + return sm.StorageMgr.SchedDiag(ctx, doSched) } func (sm *StorageMinerAPI) MarketImportDealData(ctx context.Context, propCid cid.Cid, path string) error { From 79a8ff04fd5362a367fd7d6469e5287a47baa571 Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Fri, 30 Oct 2020 14:00:32 +0100 Subject: [PATCH 303/313] refactor: simplify chain event Called API --- chain/events/events_called.go | 35 +++++++++++------------------- chain/events/events_test.go | 6 ++--- chain/events/utils.go | 6 ++--- markets/storageadapter/client.go | 20 ++++++++--------- markets/storageadapter/provider.go | 20 ++++++++--------- paychmgr/settler/settler.go | 12 +++++----- 6 files changed, 45 insertions(+), 54 deletions(-) diff --git a/chain/events/events_called.go b/chain/events/events_called.go index 753206093..7f39e9038 100644 --- a/chain/events/events_called.go +++ b/chain/events/events_called.go @@ -459,7 +459,7 @@ type messageEvents struct { hcAPI headChangeAPI lk sync.RWMutex - matchers map[triggerID][]MsgMatchFunc + matchers map[triggerID]MsgMatchFunc } func newMessageEvents(ctx context.Context, hcAPI headChangeAPI, cs eventAPI) messageEvents { @@ -467,7 +467,7 @@ func newMessageEvents(ctx context.Context, hcAPI headChangeAPI, cs eventAPI) mes ctx: ctx, cs: cs, hcAPI: hcAPI, - matchers: map[triggerID][]MsgMatchFunc{}, + matchers: make(map[triggerID]MsgMatchFunc), } } @@ -482,32 +482,23 @@ func (me *messageEvents) checkNewCalls(ts *types.TipSet) (map[triggerID]eventDat me.lk.RLock() defer me.lk.RUnlock() + // For each message in the tipset res := make(map[triggerID]eventData) me.messagesForTs(pts, func(msg *types.Message) { // TODO: provide receipts - for tid, matchFns := range me.matchers { - var matched bool - var once bool - for _, matchFn := range matchFns { - matchOne, ok, err := matchFn(msg) - if err != nil { - log.Errorf("event matcher failed: %s", err) - continue - } - matched = ok - once = matchOne - - if matched { - break - } + // Run each trigger's matcher against the message + for tid, matchFn := range me.matchers { + matched, err := matchFn(msg) + if err != nil { + log.Errorf("event matcher failed: %s", err) + continue } + // If there was a match, include the message in the results for the + // trigger if matched { res[tid] = msg - if once { - break - } } } }) @@ -555,7 +546,7 @@ func (me *messageEvents) messagesForTs(ts *types.TipSet, consume func(*types.Mes // `curH`-`ts.Height` = `confidence` type MsgHandler func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH abi.ChainEpoch) (more bool, err error) -type MsgMatchFunc func(msg *types.Message) (matchOnce bool, matched bool, err error) +type MsgMatchFunc func(msg *types.Message) (matched bool, err error) // Called registers a callback which is triggered when a specified method is // called on an actor, or a timeout is reached. @@ -607,7 +598,7 @@ func (me *messageEvents) Called(check CheckFunc, msgHnd MsgHandler, rev RevertHa me.lk.Lock() defer me.lk.Unlock() - me.matchers[id] = append(me.matchers[id], mf) + me.matchers[id] = mf return nil } diff --git a/chain/events/events_test.go b/chain/events/events_test.go index 0e4fd34b2..3957f425c 100644 --- a/chain/events/events_test.go +++ b/chain/events/events_test.go @@ -572,9 +572,9 @@ func TestAtChainedConfidenceNull(t *testing.T) { require.Equal(t, false, reverted) } -func matchAddrMethod(to address.Address, m abi.MethodNum) func(msg *types.Message) (matchOnce bool, matched bool, err error) { - return func(msg *types.Message) (matchOnce bool, matched bool, err error) { - return true, to == msg.To && m == msg.Method, nil +func matchAddrMethod(to address.Address, m abi.MethodNum) func(msg *types.Message) (matched bool, err error) { + return func(msg *types.Message) (matched bool, err error) { + return to == msg.To && m == msg.Method, nil } } diff --git a/chain/events/utils.go b/chain/events/utils.go index e50dbc6fe..c26ca5b83 100644 --- a/chain/events/utils.go +++ b/chain/events/utils.go @@ -34,11 +34,11 @@ func (me *messageEvents) CheckMsg(ctx context.Context, smsg types.ChainMsg, hnd } func (me *messageEvents) MatchMsg(inmsg *types.Message) MsgMatchFunc { - return func(msg *types.Message) (matchOnce bool, matched bool, err error) { + return func(msg *types.Message) (matched bool, err error) { if msg.From == inmsg.From && msg.Nonce == inmsg.Nonce && !inmsg.Equals(msg) { - return true, false, xerrors.Errorf("matching msg %s from %s, nonce %d: got duplicate origin/nonce msg %d", inmsg.Cid(), inmsg.From, inmsg.Nonce, msg.Nonce) + return false, xerrors.Errorf("matching msg %s from %s, nonce %d: got duplicate origin/nonce msg %d", inmsg.Cid(), inmsg.From, inmsg.Nonce, msg.Nonce) } - return true, inmsg.Equals(msg), nil + return inmsg.Equals(msg), nil } } diff --git a/markets/storageadapter/client.go b/markets/storageadapter/client.go index f299dd4d5..3533f3f0e 100644 --- a/markets/storageadapter/client.go +++ b/markets/storageadapter/client.go @@ -263,44 +263,44 @@ func (c *ClientNodeAdapter) OnDealSectorCommitted(ctx context.Context, provider var sectorNumber abi.SectorNumber var sectorFound bool - matchEvent := func(msg *types.Message) (matchOnce bool, matched bool, err error) { + matchEvent := func(msg *types.Message) (matched bool, err error) { if msg.To != provider { - return true, false, nil + return false, nil } switch msg.Method { case miner2.MethodsMiner.PreCommitSector: var params miner.SectorPreCommitInfo if err := params.UnmarshalCBOR(bytes.NewReader(msg.Params)); err != nil { - return true, false, xerrors.Errorf("unmarshal pre commit: %w", err) + return false, xerrors.Errorf("unmarshal pre commit: %w", err) } for _, did := range params.DealIDs { if did == dealId { sectorNumber = params.SectorNumber sectorFound = true - return true, false, nil + return false, nil } } - return true, false, nil + return false, nil case miner2.MethodsMiner.ProveCommitSector: var params miner.ProveCommitSectorParams if err := params.UnmarshalCBOR(bytes.NewReader(msg.Params)); err != nil { - return true, false, xerrors.Errorf("failed to unmarshal prove commit sector params: %w", err) + return false, xerrors.Errorf("failed to unmarshal prove commit sector params: %w", err) } if !sectorFound { - return true, false, nil + return false, nil } if params.SectorNumber != sectorNumber { - return true, false, nil + return false, nil } - return false, true, nil + return true, nil default: - return true, false, nil + return false, nil } } diff --git a/markets/storageadapter/provider.go b/markets/storageadapter/provider.go index ce7c8e917..b247d6876 100644 --- a/markets/storageadapter/provider.go +++ b/markets/storageadapter/provider.go @@ -307,44 +307,44 @@ func (n *ProviderNodeAdapter) OnDealSectorCommitted(ctx context.Context, provide var sectorNumber abi.SectorNumber var sectorFound bool - matchEvent := func(msg *types.Message) (matchOnce bool, matched bool, err error) { + matchEvent := func(msg *types.Message) (matched bool, err error) { if msg.To != provider { - return true, false, nil + return false, nil } switch msg.Method { case miner.Methods.PreCommitSector: var params miner.SectorPreCommitInfo if err := params.UnmarshalCBOR(bytes.NewReader(msg.Params)); err != nil { - return true, false, xerrors.Errorf("unmarshal pre commit: %w", err) + return false, xerrors.Errorf("unmarshal pre commit: %w", err) } for _, did := range params.DealIDs { if did == dealID { sectorNumber = params.SectorNumber sectorFound = true - return true, false, nil + return false, nil } } - return true, false, nil + return false, nil case miner.Methods.ProveCommitSector: var params miner.ProveCommitSectorParams if err := params.UnmarshalCBOR(bytes.NewReader(msg.Params)); err != nil { - return true, false, xerrors.Errorf("failed to unmarshal prove commit sector params: %w", err) + return false, xerrors.Errorf("failed to unmarshal prove commit sector params: %w", err) } if !sectorFound { - return true, false, nil + return false, nil } if params.SectorNumber != sectorNumber { - return true, false, nil + return false, nil } - return false, true, nil + return true, nil default: - return true, false, nil + return false, nil } } diff --git a/paychmgr/settler/settler.go b/paychmgr/settler/settler.go index d2a0900b5..41aaca665 100644 --- a/paychmgr/settler/settler.go +++ b/paychmgr/settler/settler.go @@ -103,27 +103,27 @@ func (pcs *paymentChannelSettler) revertHandler(ctx context.Context, ts *types.T return nil } -func (pcs *paymentChannelSettler) matcher(msg *types.Message) (matchOnce bool, matched bool, err error) { +func (pcs *paymentChannelSettler) matcher(msg *types.Message) (matched bool, err error) { // Check if this is a settle payment channel message if msg.Method != paych.Methods.Settle { - return false, false, nil + return false, nil } // Check if this payment channel is of concern to this node (i.e. tracked in payment channel store), // and its inbound (i.e. we're getting vouchers that we may need to redeem) trackedAddresses, err := pcs.api.PaychList(pcs.ctx) if err != nil { - return false, false, err + return false, err } for _, addr := range trackedAddresses { if msg.To == addr { status, err := pcs.api.PaychStatus(pcs.ctx, addr) if err != nil { - return false, false, err + return false, err } if status.Direction == api.PCHInbound { - return false, true, nil + return true, nil } } } - return false, false, nil + return false, nil } From af1d45d9691d150c35ee6dceebb4d5924c90e74f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 30 Oct 2020 18:00:48 +0100 Subject: [PATCH 304/313] worker: Handle multiple manager restarts while waiting for tasks --- cmd/lotus-seal-worker/main.go | 48 ++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/cmd/lotus-seal-worker/main.go b/cmd/lotus-seal-worker/main.go index 36c9d5eff..0bb33db14 100644 --- a/cmd/lotus-seal-worker/main.go +++ b/cmd/lotus-seal-worker/main.go @@ -451,14 +451,24 @@ var runCmd = &cli.Command{ return xerrors.Errorf("getting miner session: %w", err) } + waitQuietCh := func() chan struct{} { + out := make(chan struct{}) + go func() { + workerApi.LocalWorker.WaitQuiet() + close(out) + }() + return out + } + go func() { heartbeats := time.NewTicker(stores.HeartbeatInterval) defer heartbeats.Stop() - var connected, reconnect bool + var redeclareStorage bool + var readyCh chan struct{} for { // If we're reconnecting, redeclare storage first - if reconnect { + if redeclareStorage { log.Info("Redeclaring local storage") if err := localStore.Redeclare(ctx); err != nil { @@ -471,14 +481,13 @@ var runCmd = &cli.Command{ } continue } - - connected = false } - log.Info("Making sure no local tasks are running") - // TODO: we could get rid of this, but that requires tracking resources for restarted tasks correctly - workerApi.LocalWorker.WaitQuiet() + if readyCh == nil { + log.Info("Making sure no local tasks are running") + readyCh = waitQuietCh() + } for { curSession, err := nodeApi.Session(ctx) @@ -489,29 +498,28 @@ var runCmd = &cli.Command{ minerSession = curSession break } - - if !connected { - if err := nodeApi.WorkerConnect(ctx, "http://"+address+"/rpc/v0"); err != nil { - log.Errorf("Registering worker failed: %+v", err) - cancel() - return - } - - log.Info("Worker registered successfully, waiting for tasks") - connected = true - } } select { + case <-readyCh: + if err := nodeApi.WorkerConnect(ctx, "http://"+address+"/rpc/v0"); err != nil { + log.Errorf("Registering worker failed: %+v", err) + cancel() + return + } + + log.Info("Worker registered successfully, waiting for tasks") + + readyCh = nil + case <-heartbeats.C: case <-ctx.Done(): return // graceful shutdown - case <-heartbeats.C: } } log.Errorf("LOTUS-MINER CONNECTION LOST") - reconnect = true + redeclareStorage = true } }() From 774e2ecebf41b05ace9ade63266696a0d9c61921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 30 Oct 2020 18:01:37 +0100 Subject: [PATCH 305/313] sched: Fix worker reenabling --- extern/sector-storage/manager_test.go | 57 +++++++++++++++++++++++++++ extern/sector-storage/sched_worker.go | 27 ++++++------- extern/sector-storage/worker_local.go | 10 ++++- 3 files changed, 78 insertions(+), 16 deletions(-) diff --git a/extern/sector-storage/manager_test.go b/extern/sector-storage/manager_test.go index 0e3e7bc9d..ff5561a64 100644 --- a/extern/sector-storage/manager_test.go +++ b/extern/sector-storage/manager_test.go @@ -10,6 +10,7 @@ import ( "path/filepath" "strings" "sync" + "sync/atomic" "testing" "time" @@ -376,3 +377,59 @@ func TestRestartWorker(t *testing.T) { require.NoError(t, err) require.Empty(t, uf) } + +func TestReenableWorker(t *testing.T) { + logging.SetAllLoggers(logging.LevelDebug) + stores.HeartbeatInterval = 5 * time.Millisecond + + ctx, done := context.WithCancel(context.Background()) + defer done() + + ds := datastore.NewMapDatastore() + + m, lstor, stor, idx, cleanup := newTestMgr(ctx, t, ds) + defer cleanup() + + localTasks := []sealtasks.TaskType{ + sealtasks.TTAddPiece, sealtasks.TTPreCommit1, sealtasks.TTCommit1, sealtasks.TTFinalize, sealtasks.TTFetch, + } + + wds := datastore.NewMapDatastore() + + arch := make(chan chan apres) + w := newLocalWorker(func() (ffiwrapper.Storage, error) { + return &testExec{apch: arch}, nil + }, WorkerConfig{ + SealProof: 0, + TaskTypes: localTasks, + }, stor, lstor, idx, m, statestore.New(wds)) + + err := m.AddWorker(ctx, w) + require.NoError(t, err) + + time.Sleep(time.Millisecond * 100) + + // disable + atomic.StoreInt64(&w.testDisable, 1) + + for i := 0; i < 100; i++ { + if !m.WorkerStats()[w.session].Enabled { + break + } + + time.Sleep(time.Millisecond * 3) + } + require.False(t, m.WorkerStats()[w.session].Enabled) + + // reenable + atomic.StoreInt64(&w.testDisable, 0) + + for i := 0; i < 100; i++ { + if m.WorkerStats()[w.session].Enabled { + break + } + + time.Sleep(time.Millisecond * 3) + } + require.True(t, m.WorkerStats()[w.session].Enabled) +} diff --git a/extern/sector-storage/sched_worker.go b/extern/sector-storage/sched_worker.go index ff43009d3..450c7088e 100644 --- a/extern/sector-storage/sched_worker.go +++ b/extern/sector-storage/sched_worker.go @@ -104,14 +104,16 @@ func (sw *schedWorker) handleWorker() { defer sw.heartbeatTimer.Stop() for { - sched.workersLk.Lock() - enabled := worker.enabled - sched.workersLk.Unlock() + { + sched.workersLk.Lock() + enabled := worker.enabled + sched.workersLk.Unlock() - // ask for more windows if we need them (non-blocking) - if enabled { - if !sw.requestWindows() { - return // graceful shutdown + // ask for more windows if we need them (non-blocking) + if enabled { + if !sw.requestWindows() { + return // graceful shutdown + } } } @@ -123,13 +125,10 @@ func (sw *schedWorker) handleWorker() { } // session looks good - if !enabled { - sched.workersLk.Lock() - worker.enabled = true - sched.workersLk.Unlock() - - // we'll send window requests on the next loop - } + sched.workersLk.Lock() + worker.enabled = true + // we'll send window requests on the next loop + sched.workersLk.Unlock() // wait for more tasks to be assigned by the main scheduler or for the worker // to finish precessing a task diff --git a/extern/sector-storage/worker_local.go b/extern/sector-storage/worker_local.go index cb1a43c53..ae2b325ca 100644 --- a/extern/sector-storage/worker_local.go +++ b/extern/sector-storage/worker_local.go @@ -8,6 +8,7 @@ import ( "reflect" "runtime" "sync" + "sync/atomic" "time" "github.com/elastic/go-sysinfo" @@ -51,8 +52,9 @@ type LocalWorker struct { acceptTasks map[sealtasks.TaskType]struct{} running sync.WaitGroup - session uuid.UUID - closing chan struct{} + session uuid.UUID + testDisable int64 + closing chan struct{} } func newLocalWorker(executor ExecutorFunc, wcfg WorkerConfig, store stores.Store, local *stores.Local, sindex stores.SectorIndex, ret storiface.WorkerReturn, cst *statestore.StateStore) *LocalWorker { @@ -501,6 +503,10 @@ func (l *LocalWorker) Info(context.Context) (storiface.WorkerInfo, error) { } func (l *LocalWorker) Session(ctx context.Context) (uuid.UUID, error) { + if atomic.LoadInt64(&l.testDisable) == 1 { + return uuid.UUID{}, xerrors.Errorf("disabled") + } + select { case <-l.closing: return ClosedWorkerID, nil From f90a387f96d3748aede2e74a76eb5b28bf8abbfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 30 Oct 2020 18:32:16 +0100 Subject: [PATCH 306/313] sched: Print worker UUIDs in shed-diag correctly --- extern/sector-storage/sched.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/extern/sector-storage/sched.go b/extern/sector-storage/sched.go index 426658c41..549a16a96 100644 --- a/extern/sector-storage/sched.go +++ b/extern/sector-storage/sched.go @@ -7,6 +7,7 @@ import ( "sync" "time" + "github.com/google/uuid" "golang.org/x/xerrors" "github.com/filecoin-project/go-state-types/abi" @@ -217,7 +218,7 @@ type SchedDiagRequestInfo struct { type SchedDiagInfo struct { Requests []SchedDiagRequestInfo - OpenWindows []WorkerID + OpenWindows []string } func (sh *scheduler) runSched() { @@ -324,7 +325,7 @@ func (sh *scheduler) diag() SchedDiagInfo { defer sh.workersLk.RUnlock() for _, window := range sh.openWindows { - out.OpenWindows = append(out.OpenWindows, window.worker) + out.OpenWindows = append(out.OpenWindows, uuid.UUID(window.worker).String()) } return out From 69e44ebf0754ab248ad81b2c5d271e695db2fe3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 30 Oct 2020 18:32:59 +0100 Subject: [PATCH 307/313] sched: re-register worker windows after re-enabling correctly --- extern/sector-storage/manager_test.go | 18 ++++++++++++++++++ extern/sector-storage/sched_worker.go | 15 +++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/extern/sector-storage/manager_test.go b/extern/sector-storage/manager_test.go index ff5561a64..f69d62b17 100644 --- a/extern/sector-storage/manager_test.go +++ b/extern/sector-storage/manager_test.go @@ -409,6 +409,9 @@ func TestReenableWorker(t *testing.T) { time.Sleep(time.Millisecond * 100) + i, _ := m.sched.Info(ctx) + require.Len(t, i.(SchedDiagInfo).OpenWindows, 2) + // disable atomic.StoreInt64(&w.testDisable, 1) @@ -421,6 +424,9 @@ func TestReenableWorker(t *testing.T) { } require.False(t, m.WorkerStats()[w.session].Enabled) + i, _ = m.sched.Info(ctx) + require.Len(t, i.(SchedDiagInfo).OpenWindows, 0) + // reenable atomic.StoreInt64(&w.testDisable, 0) @@ -432,4 +438,16 @@ func TestReenableWorker(t *testing.T) { time.Sleep(time.Millisecond * 3) } require.True(t, m.WorkerStats()[w.session].Enabled) + + for i := 0; i < 100; i++ { + info, _ := m.sched.Info(ctx) + if len(info.(SchedDiagInfo).OpenWindows) != 0 { + break + } + + time.Sleep(time.Millisecond * 3) + } + + i, _ = m.sched.Info(ctx) + require.Len(t, i.(SchedDiagInfo).OpenWindows, 2) } diff --git a/extern/sector-storage/sched_worker.go b/extern/sector-storage/sched_worker.go index 450c7088e..e56e9056d 100644 --- a/extern/sector-storage/sched_worker.go +++ b/extern/sector-storage/sched_worker.go @@ -125,10 +125,17 @@ func (sw *schedWorker) handleWorker() { } // session looks good - sched.workersLk.Lock() - worker.enabled = true - // we'll send window requests on the next loop - sched.workersLk.Unlock() + { + sched.workersLk.Lock() + enabled := worker.enabled + worker.enabled = true + sched.workersLk.Unlock() + + if !enabled { + // go send window requests + break + } + } // wait for more tasks to be assigned by the main scheduler or for the worker // to finish precessing a task From 8afceee7a99904d305a8f7d22ac8504457dbee3a Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Fri, 30 Oct 2020 19:21:25 +0100 Subject: [PATCH 308/313] Fix messagepool accounting Signed-off-by: Jakub Sztandera --- chain/messagepool/selection.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/chain/messagepool/selection.go b/chain/messagepool/selection.go index 4ade92a79..d79ed9f55 100644 --- a/chain/messagepool/selection.go +++ b/chain/messagepool/selection.go @@ -750,13 +750,7 @@ func (mp *MessagePool) createMessageChains(actor address.Address, mset map[uint6 break } balance = new(big.Int).Sub(balance, required) - - value := m.Message.Value.Int - if balance.Cmp(value) >= 0 { - // Note: we only account for the value if the balance doesn't drop below 0 - // otherwise the message will fail and the miner can reap the gas rewards - balance = new(big.Int).Sub(balance, value) - } + balance = new(big.Int).Sub(balance, m.Message.Value.Int) gasReward := mp.getGasReward(m, baseFee) rewards = append(rewards, gasReward) From 885c6c94d38167f395268c96c747ea6810fec87b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 30 Oct 2020 19:39:31 +0100 Subject: [PATCH 309/313] Add sync status to miner info command --- cmd/lotus-storage-miner/info.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/cmd/lotus-storage-miner/info.go b/cmd/lotus-storage-miner/info.go index 213d62e6e..b16b4dde8 100644 --- a/cmd/lotus-storage-miner/info.go +++ b/cmd/lotus-storage-miner/info.go @@ -59,6 +59,24 @@ func infoCmdAct(cctx *cli.Context) error { ctx := lcli.ReqContext(cctx) + fmt.Print("Full node: ") + + head, err := api.ChainHead(ctx) + if err != nil { + return err + } + + switch { + case time.Now().Unix()-int64(head.MinTimestamp()) < int64(build.BlockDelaySecs*3/2): // within 1.5 epochs + fmt.Printf("[%s]", color.GreenString("sync ok")) + case time.Now().Unix()-int64(head.MinTimestamp()) < int64(build.BlockDelaySecs*5): // within 5 epochs + fmt.Printf("[%s]", color.YellowString("sync slow (%s behind)", time.Now().Sub(time.Unix(int64(head.MinTimestamp()), 0)).Truncate(time.Second))) + default: + fmt.Printf("[%s]", color.RedString("sync behind! (%s behind)", time.Now().Sub(time.Unix(int64(head.MinTimestamp()), 0)).Truncate(time.Second))) + } + + fmt.Println() + maddr, err := getActorAddress(ctx, nodeApi, cctx.String("actor")) if err != nil { return err From 12f61197394a44b1779c68eba2322e26b831726e Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 30 Oct 2020 20:56:33 +0200 Subject: [PATCH 310/313] don't include messages that drop the balance below zero --- chain/messagepool/selection.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/chain/messagepool/selection.go b/chain/messagepool/selection.go index d79ed9f55..5a8200bf8 100644 --- a/chain/messagepool/selection.go +++ b/chain/messagepool/selection.go @@ -750,7 +750,12 @@ func (mp *MessagePool) createMessageChains(actor address.Address, mset map[uint6 break } balance = new(big.Int).Sub(balance, required) - balance = new(big.Int).Sub(balance, m.Message.Value.Int) + + value := m.Message.Value.Int + if balance.Cmp(value) < 0 { + break + } + balance = new(big.Int).Sub(balance, value) gasReward := mp.getGasReward(m, baseFee) rewards = append(rewards, gasReward) From 6985af5e88b9aa20aec2871741abbe6dd7dc6086 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 28 Oct 2020 18:10:29 -0700 Subject: [PATCH 311/313] keep retrying the proof until we run out of sectors to skip If we have a bunch of corrupted but not missing sectors on disk, we may need to retry many times before we get a proof to pass. Simply giving up doesn't help anyone. --- storage/wdpost_run.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/storage/wdpost_run.go b/storage/wdpost_run.go index 87438fec3..e7bd74162 100644 --- a/storage/wdpost_run.go +++ b/storage/wdpost_run.go @@ -510,10 +510,10 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di dline.Info, ts *ty skipCount := uint64(0) postSkipped := bitfield.New() - var postOut []proof2.PoStProof - somethingToProve := true + somethingToProve := false - for retries := 0; retries < 5; retries++ { + // Retry until we run out of sectors to prove. + for retries := 0; ; retries++ { var partitions []miner.PoStPartition var sinfos []proof2.SectorInfo for partIdx, partition := range batch { @@ -567,7 +567,6 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di dline.Info, ts *ty if len(sinfos) == 0 { // nothing to prove for this batch - somethingToProve = false break } @@ -585,24 +584,31 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di dline.Info, ts *ty return nil, err } - var ps []abi.SectorID - postOut, ps, err = s.prover.GenerateWindowPoSt(ctx, abi.ActorID(mid), sinfos, abi.PoStRandomness(rand)) + postOut, ps, err := s.prover.GenerateWindowPoSt(ctx, abi.ActorID(mid), sinfos, abi.PoStRandomness(rand)) elapsed := time.Since(tsStart) log.Infow("computing window post", "batch", batchIdx, "elapsed", elapsed) if err == nil { - // Proof generation successful, stop retrying - params.Partitions = append(params.Partitions, partitions...) + if len(postOut) == 0 { + return nil, xerrors.Errorf("received no proofs back from generate window post") + } + // Proof generation successful, stop retrying + somethingToProve = true + params.Partitions = partitions + params.Proofs = postOut break } // Proof generation failed, so retry if len(ps) == 0 { + // If we didn't skip any new sectors, we failed + // for some other reason and we need to abort. return nil, xerrors.Errorf("running window post failed: %w", err) } + // TODO: maybe mark these as faulty somewhere? log.Warnw("generate window post skipped sectors", "sectors", ps, "error", err, "try", retries) @@ -617,12 +623,6 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di dline.Info, ts *ty continue } - if len(postOut) == 0 { - return nil, xerrors.Errorf("received no proofs back from generate window post") - } - - params.Proofs = postOut - posts = append(posts, params) } From 22742a9ba0b1d3c543036c6f3d36081da966e92f Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Wed, 28 Oct 2020 18:53:11 +0100 Subject: [PATCH 312/313] bootstrap: don't return early when one drand resolution fails Signed-off-by: Jakub Sztandera --- node/modules/core.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/modules/core.go b/node/modules/core.go index 823b0131e..259c1ba3a 100644 --- a/node/modules/core.go +++ b/node/modules/core.go @@ -101,7 +101,7 @@ func DrandBootstrap(ds dtypes.DrandSchedule) (dtypes.DrandBootstrap, error) { addrs, err := addrutil.ParseAddresses(context.TODO(), d.Config.Relays) if err != nil { log.Errorf("reoslving drand relays addresses: %+v", err) - return res, nil + continue } res = append(res, addrs...) } From 077bc83f7f7bc454ce27b0f44e0de6351d1331c1 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 30 Oct 2020 14:00:41 -0700 Subject: [PATCH 313/313] explicitly abort PoSt on context cancellation --- storage/wdpost_run.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/storage/wdpost_run.go b/storage/wdpost_run.go index e7bd74162..f1da4f221 100644 --- a/storage/wdpost_run.go +++ b/storage/wdpost_run.go @@ -612,6 +612,15 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di dline.Info, ts *ty log.Warnw("generate window post skipped sectors", "sectors", ps, "error", err, "try", retries) + // Explicitly make sure we haven't aborted this PoSt + // (GenerateWindowPoSt may or may not check this). + // Otherwise, we could try to continue proving a + // deadline after the deadline has ended. + if ctx.Err() != nil { + log.Warnw("aborting PoSt due to context cancellation", "error", ctx.Err(), "deadline", di.Index) + return nil, ctx.Err() + } + skipCount += uint64(len(ps)) for _, sector := range ps { postSkipped.Set(uint64(sector.Number))