From 695f6cfe4553ba1ebca9dd6365ac46256effe47a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Fri, 17 Jul 2020 14:22:37 +0100 Subject: [PATCH 01/40] wip in-memory journal. --- chain/events/events_height.go | 6 +- chain/store/store.go | 17 ++- cmd/lotus-seal-worker/main.go | 1 + cmd/lotus-storage-miner/main.go | 1 + journal/events.go | 16 +++ journal/filesystem.go | 131 +++++++++++++++++ journal/journal.go | 148 -------------------- journal/memory.go | 239 ++++++++++++++++++++++++++++++++ journal/memory_test.go | 178 ++++++++++++++++++++++++ journal/types.go | 60 ++++++++ node/builder.go | 6 +- node/modules/core.go | 6 - storage/wdpost_run.go | 2 +- 13 files changed, 643 insertions(+), 168 deletions(-) create mode 100644 journal/events.go create mode 100644 journal/filesystem.go delete mode 100644 journal/journal.go create mode 100644 journal/memory.go create mode 100644 journal/memory_test.go create mode 100644 journal/types.go diff --git a/chain/events/events_height.go b/chain/events/events_height.go index 24d758a31..b419f06d2 100644 --- a/chain/events/events_height.go +++ b/chain/events/events_height.go @@ -26,7 +26,6 @@ type heightEvents struct { } func (e *heightEvents) headChangeAt(rev, app []*types.TipSet) error { - ctx, span := trace.StartSpan(e.ctx, "events.HeightHeadChange") defer span.End() span.AddAttributes(trace.Int64Attribute("endHeight", int64(app[0].Height()))) @@ -144,12 +143,11 @@ func (e *heightEvents) headChangeAt(rev, app []*types.TipSet) error { } // ChainAt invokes the specified `HeightHandler` when the chain reaches the -// specified height+confidence threshold. If the chain is rolled-back under the -// specified height, `RevertHandler` will be called. +// specified height+confidence threshold. If the chain is rolled-back under the +// specified height, `RevertHandler` will be called. // // ts passed to handlers is the tipset at the specified, or above, if lower tipsets were null func (e *heightEvents) ChainAt(hnd HeightHandler, rev RevertHandler, confidence int, h abi.ChainEpoch) error { - e.lk.Lock() // Tricky locking, check your locks if you modify this function! bestH := e.tsc.best().Height() diff --git a/chain/store/store.go b/chain/store/store.go index fa31f6b08..ec134df1a 100644 --- a/chain/store/store.go +++ b/chain/store/store.go @@ -85,9 +85,10 @@ type ChainStore struct { tsCache *lru.ARCCache vmcalls runtime.Syscalls + journal journal.Journal } -func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls runtime.Syscalls) *ChainStore { +func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls runtime.Syscalls, journal journal.Journal) *ChainStore { c, _ := lru.NewARC(2048) tsc, _ := lru.NewARC(4096) cs := &ChainStore{ @@ -98,6 +99,7 @@ func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls runtime.Sys mmCache: c, tsCache: tsc, vmcalls: vmcalls, + journal: journal, } ci := NewChainIndex(cs.LoadTipSet) @@ -326,12 +328,13 @@ func (cs *ChainStore) reorgWorker(ctx context.Context, initialNotifees []ReorgNo continue } - journal.Add("sync", map[string]interface{}{ - "op": "headChange", - "from": r.old.Key(), - "to": r.new.Key(), - "rev": len(revert), - "apply": len(apply), + cs.journal.AddEntry(journal.EventType{"sync", "head_change"}, map[string]interface{}{ + "from": r.old.Key(), + "from_height": r.old.Height(), + "to": r.new.Key(), + "to_height": r.new.Height(), + "rev_cnt": len(revert), + "apply_cnt": len(apply), }) // reverse the apply array diff --git a/cmd/lotus-seal-worker/main.go b/cmd/lotus-seal-worker/main.go index bf0b420f0..805777e7a 100644 --- a/cmd/lotus-seal-worker/main.go +++ b/cmd/lotus-seal-worker/main.go @@ -37,6 +37,7 @@ import ( var log = logging.Logger("main") const FlagWorkerRepo = "worker-repo" + // TODO remove after deprecation period const FlagWorkerRepoDeprecation = "workerrepo" diff --git a/cmd/lotus-storage-miner/main.go b/cmd/lotus-storage-miner/main.go index 9576aae0b..5fec6ad22 100644 --- a/cmd/lotus-storage-miner/main.go +++ b/cmd/lotus-storage-miner/main.go @@ -22,6 +22,7 @@ import ( var log = logging.Logger("main") const FlagMinerRepo = "miner-repo" + // TODO remove after deprecation period const FlagMinerRepoDeprecation = "storagerepo" diff --git a/journal/events.go b/journal/events.go new file mode 100644 index 000000000..b6b5a15d4 --- /dev/null +++ b/journal/events.go @@ -0,0 +1,16 @@ +package journal + +import ( + "github.com/filecoin-project/specs-actors/actors/abi" + + "github.com/filecoin-project/lotus/chain/types" +) + +type HeadChangeEvt struct { + From types.TipSetKey `json:"from"` + FromHeight abi.ChainEpoch `json:"from_height"` + To types.TipSetKey `json:"to"` + ToHeight abi.ChainEpoch `json:"to_height"` + RevertCount int `json:"rev_cnt"` + ApplyCount int `json:"apply_cnt"` +} diff --git a/journal/filesystem.go b/journal/filesystem.go new file mode 100644 index 000000000..d49f77ff9 --- /dev/null +++ b/journal/filesystem.go @@ -0,0 +1,131 @@ +package journal + +import ( + "context" + "encoding/json" + "fmt" + "os" + "path/filepath" + "sync" + "time" + + logging "github.com/ipfs/go-log" + "go.uber.org/fx" + "golang.org/x/xerrors" + + "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/node/repo" +) + +var log = logging.Logger("journal") + +// fsJournal is a basic journal backed by files on a filesystem. +type fsJournal struct { + disabledTracker + + dir string + sizeLimit int64 + + lk sync.Mutex + fi *os.File + fSize int64 + + incoming chan *Entry + + closing chan struct{} +} + +// OpenFSJournal constructs a rolling filesystem journal, with a default +// per-file size limit of 1GiB. +func OpenFSJournal(lr repo.LockedRepo, lc fx.Lifecycle, disabled []EventType) (Journal, error) { + dir := filepath.Join(lr.Path(), "journal") + if err := os.MkdirAll(dir, 0755); err != nil { + return nil, fmt.Errorf("failed to mk directory %s for file journal: %w", dir, err) + } + + f := &fsJournal{ + disabledTracker: newDisabledTracker(disabled), + dir: dir, + sizeLimit: 1 << 30, + incoming: make(chan *Entry, 32), + closing: make(chan struct{}), + } + + if err := f.rollJournalFile(); err != nil { + return nil, err + } + + lc.Append(fx.Hook{ + OnStop: func(_ context.Context) error { return f.Close() }, + }) + + go f.runLoop() + + return f, nil +} + +func (f *fsJournal) AddEntry(evtType EventType, obj interface{}) { + je := &Entry{ + EventType: evtType, + Timestamp: build.Clock.Now(), + Data: obj, + } + select { + case f.incoming <- je: + case <-f.closing: + log.Warnw("journal closed but tried to log event", "entry", je) + } +} + +func (f *fsJournal) Close() error { + close(f.closing) + return nil +} + +func (f *fsJournal) putEntry(je *Entry) error { + b, err := json.Marshal(je) + if err != nil { + return err + } + n, err := f.fi.Write(append(b, '\n')) + if err != nil { + return err + } + + f.fSize += int64(n) + + if f.fSize >= f.sizeLimit { + _ = f.rollJournalFile() + } + + return nil +} + +func (f *fsJournal) rollJournalFile() error { + if f.fi != nil { + _ = f.fi.Close() + } + + nfi, err := os.Create(filepath.Join(f.dir, fmt.Sprintf("lotus-journal-%s.ndjson", build.Clock.Now().Format(time.RFC3339)))) + if err != nil { + return xerrors.Errorf("failed to open journal file: %w", err) + } + + f.fi = nfi + f.fSize = 0 + return nil +} + +func (f *fsJournal) runLoop() { + for { + select { + case je := <-f.incoming: + if err := f.putEntry(je); err != nil { + log.Errorw("failed to write out journal entry", "entry", je, "err", err) + } + case <-f.closing: + _ = f.fi.Close() + return + } + } +} diff --git a/journal/journal.go b/journal/journal.go deleted file mode 100644 index 8d509d51c..000000000 --- a/journal/journal.go +++ /dev/null @@ -1,148 +0,0 @@ -package journal - -import ( - "encoding/json" - "fmt" - "os" - "path/filepath" - "sync" - "time" - - logging "github.com/ipfs/go-log" - "golang.org/x/xerrors" - - "github.com/filecoin-project/lotus/build" -) - -func InitializeSystemJournal(dir string) error { - if err := os.MkdirAll(dir, 0755); err != nil { - return err - } - j, err := OpenFSJournal(dir) - if err != nil { - return err - } - currentJournal = j - return nil -} - -func Add(sys string, val interface{}) { - if currentJournal == nil { - log.Warn("no journal configured") - return - } - currentJournal.AddEntry(sys, val) -} - -var log = logging.Logger("journal") - -var currentJournal Journal - -type Journal interface { - AddEntry(system string, obj interface{}) - Close() error -} - -// fsJournal is a basic journal backed by files on a filesystem -type fsJournal struct { - fi *os.File - fSize int64 - - lk sync.Mutex - - journalDir string - - incoming chan *JournalEntry - journalSizeLimit int64 - - closing chan struct{} -} - -func OpenFSJournal(dir string) (*fsJournal, error) { - fsj := &fsJournal{ - journalDir: dir, - incoming: make(chan *JournalEntry, 32), - journalSizeLimit: 1 << 30, - closing: make(chan struct{}), - } - - if err := fsj.rollJournalFile(); err != nil { - return nil, err - } - - go fsj.runLoop() - - return fsj, nil -} - -type JournalEntry struct { - System string - Timestamp time.Time - Val interface{} -} - -func (fsj *fsJournal) putEntry(je *JournalEntry) error { - b, err := json.Marshal(je) - if err != nil { - return err - } - n, err := fsj.fi.Write(append(b, '\n')) - if err != nil { - return err - } - - fsj.fSize += int64(n) - - if fsj.fSize >= fsj.journalSizeLimit { - fsj.rollJournalFile() - } - - return nil -} - -func (fsj *fsJournal) rollJournalFile() error { - if fsj.fi != nil { - fsj.fi.Close() - } - - nfi, err := os.Create(filepath.Join(fsj.journalDir, fmt.Sprintf("lotus-journal-%s.ndjson", build.Clock.Now().Format(time.RFC3339)))) - if err != nil { - return xerrors.Errorf("failed to open journal file: %w", err) - } - - fsj.fi = nfi - fsj.fSize = 0 - return nil -} - -func (fsj *fsJournal) runLoop() { - for { - select { - case je := <-fsj.incoming: - if err := fsj.putEntry(je); err != nil { - log.Errorw("failed to write out journal entry", "entry", je, "err", err) - } - case <-fsj.closing: - fsj.fi.Close() - return - } - } -} - -func (fsj *fsJournal) AddEntry(system string, obj interface{}) { - je := &JournalEntry{ - System: system, - Timestamp: build.Clock.Now(), - Val: obj, - } - select { - case fsj.incoming <- je: - case <-fsj.closing: - log.Warnw("journal closed but tried to log event", "entry", je) - } -} - -func (fsj *fsJournal) Close() error { - close(fsj.closing) - return nil -} diff --git a/journal/memory.go b/journal/memory.go new file mode 100644 index 000000000..483722635 --- /dev/null +++ b/journal/memory.go @@ -0,0 +1,239 @@ +package journal + +import ( + "context" + "sync/atomic" + + "go.uber.org/fx" + + "github.com/filecoin-project/lotus/build" +) + +// Control messages. +type ( + clearCtrl struct{} + addObserverCtrl struct { + observer *observer + replay bool + } + rmObserverCtrl *observer + getEntriesCtrl chan []*Entry +) + +type MemJournal struct { + disabledTracker + + entries []*Entry + index map[string]map[string][]*Entry + observers []observer + + incomingCh chan *Entry + controlCh chan interface{} + + state int32 // guarded by atomic; 0=closed, 1=running. + closed chan struct{} +} + +var _ Journal = (*MemJournal)(nil) + +type observer struct { + accept map[EventType]struct{} + ch chan *Entry +} + +func (o *observer) dispatch(entry *Entry) { + if o.accept == nil { + o.ch <- entry + } + if _, ok := o.accept[entry.EventType]; ok { + o.ch <- entry + } +} + +func NewMemoryJournal(lc fx.Lifecycle, disabled []EventType) *MemJournal { + m := &MemJournal{ + disabledTracker: newDisabledTracker(disabled), + + index: make(map[string]map[string][]*Entry, 16), + observers: make([]observer, 0, 16), + incomingCh: make(chan *Entry, 256), + controlCh: make(chan interface{}, 16), + state: 1, + closed: make(chan struct{}), + } + + lc.Append(fx.Hook{ + OnStop: func(_ context.Context) error { return m.Close() }, + }) + + go m.process() + + return m +} + +func (m *MemJournal) AddEntry(evtType EventType, obj interface{}) { + entry := &Entry{ + EventType: evtType, + Timestamp: build.Clock.Now(), + Data: obj, + } + + select { + case m.incomingCh <- entry: + case <-m.closed: + } +} + +func (m *MemJournal) Close() error { + if !atomic.CompareAndSwapInt32(&m.state, 1, 0) { + // already closed. + return nil + } + close(m.closed) + return nil +} + +func (m *MemJournal) Clear() { + select { + case m.controlCh <- clearCtrl{}: + case <-m.closed: + } +} + +// Observe starts observing events that are recorded in the MemJournal, and +// returns a channel where new events will be sent. When replay is true, all +// entries that have been recorded prior to the observer being registered will +// be replayed. To restrict the event types this observer will sent, use the +// include argument. If no include set is passed, the observer will receive all +// events types. +func (m *MemJournal) Observe(ctx context.Context, replay bool, include ...EventType) <-chan *Entry { + var acc map[EventType]struct{} + if include != nil { + acc = make(map[EventType]struct{}, 16) + for _, et := range include { + acc[et] = struct{}{} + } + } + + ch := make(chan *Entry, 256) + o := &observer{ + accept: acc, + ch: ch, + } + + // watch the context, and fire the "remove observer" control message upon + // cancellation. + go func() { + <-ctx.Done() + select { + case m.controlCh <- rmObserverCtrl(o): + case <-m.closed: + } + }() + + select { + case m.controlCh <- addObserverCtrl{o, replay}: + case <-m.closed: + // we are already stopped. + close(ch) + } + + return ch +} + +// Entries gets a snapshot of stored entries. +func (m *MemJournal) Entries() []*Entry { + ch := make(chan []*Entry) + m.controlCh <- getEntriesCtrl(ch) + return <-ch +} + +func (m *MemJournal) process() { + processCtrlMsg := func(message interface{}) { + switch msg := message.(type) { + case addObserverCtrl: + // adding an observer. + m.observers = append(m.observers, *msg.observer) + + if msg.replay { + // replay all existing entries. + for _, e := range m.entries { + msg.observer.dispatch(e) + } + } + case rmObserverCtrl: + // removing an observer; find the observer, close its channel. + // then discard it from our list by replacing it with the last + // observer and reslicing. + for i, o := range m.observers { + if o.ch == msg.ch { + close(o.ch) + m.observers[i] = m.observers[len(m.observers)-1] + m.observers = m.observers[:len(m.observers)-1] + } + } + case clearCtrl: + m.entries = m.entries[0:0] + // carry over system and event names; there are unlikely to change; + // just reslice the entry slices, so we are not thrashing memory. + for _, events := range m.index { + for ev := range events { + events[ev] = events[ev][0:0] + } + } + case getEntriesCtrl: + cpy := make([]*Entry, len(m.entries)) + copy(cpy, m.entries) + msg <- cpy + close(msg) + } + } + + processClose := func() { + m.entries = nil + m.index = make(map[string]map[string][]*Entry, 16) + for _, o := range m.observers { + close(o.ch) + } + m.observers = nil + } + + for { + // Drain all control messages first! + select { + case msg := <-m.controlCh: + processCtrlMsg(msg) + continue + case <-m.closed: + processClose() + return + default: + } + + // Now consume and pipe messages. + select { + case entry := <-m.incomingCh: + m.entries = append(m.entries, entry) + events := m.index[entry.System] + if events == nil { + events = make(map[string][]*Entry, 16) + m.index[entry.System] = events + } + + entries := events[entry.Event] + events[entry.Event] = append(entries, entry) + + for _, o := range m.observers { + o.dispatch(entry) + } + + case msg := <-m.controlCh: + processCtrlMsg(msg) + continue + + case <-m.closed: + processClose() + return + } + } +} diff --git a/journal/memory_test.go b/journal/memory_test.go new file mode 100644 index 000000000..10b3a90cb --- /dev/null +++ b/journal/memory_test.go @@ -0,0 +1,178 @@ +package journal + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/types" + + "github.com/filecoin-project/specs-actors/actors/abi" + + "github.com/raulk/clock" + "github.com/stretchr/testify/require" + "go.uber.org/fx/fxtest" +) + +func TestMemJournal_AddEntry(t *testing.T) { + lc := fxtest.NewLifecycle(t) + defer lc.RequireStop() + + clk := clock.NewMock() + build.Clock = clk + + journal := NewMemoryJournal(lc, nil) + addEntries(journal, 100) + + require.Eventually(t, func() bool { return len(journal.Entries()) == 100 }, 1*time.Second, 100*time.Millisecond) + + entries := journal.Entries() + cnt := make(map[string]int, 10) + for i, e := range entries { + require.EqualValues(t, "spaceship", e.System) + require.Equal(t, HeadChangeEvt{ + From: types.TipSetKey{}, + FromHeight: abi.ChainEpoch(i), + To: types.TipSetKey{}, + ToHeight: abi.ChainEpoch(i), + RevertCount: i, + ApplyCount: i, + }, e.Data) + require.Equal(t, build.Clock.Now(), e.Timestamp) + cnt[e.Event]++ + } + + // we received 10 entries of each event type. + for _, c := range cnt { + require.Equal(t, 10, c) + } +} + +func TestMemJournal_Close(t *testing.T) { + lc := fxtest.NewLifecycle(t) + defer lc.RequireStop() + + journal := NewMemoryJournal(lc, nil) + addEntries(journal, 100) + + require.Eventually(t, func() bool { return len(journal.Entries()) == 100 }, 1*time.Second, 100*time.Millisecond) + + o1 := journal.Observe(context.TODO(), false) + o2 := journal.Observe(context.TODO(), false) + o3 := journal.Observe(context.TODO(), false) + + time.Sleep(500 * time.Millisecond) + + // Close the journal. + require.NoError(t, journal.Close()) + + time.Sleep(500 * time.Millisecond) + +NextChannel: + for _, ch := range []<-chan *Entry{o1, o2, o3} { + for { + select { + case _, more := <-ch: + if more { + // keep consuming + } else { + continue NextChannel + } + default: + t.Fatal("nothing more to consume, and channel is not closed") + } + } + } +} + +func TestMemJournal_Clear(t *testing.T) { + lc := fxtest.NewLifecycle(t) + defer lc.RequireStop() + + journal := NewMemoryJournal(lc, nil) + addEntries(journal, 100) + + require.Eventually(t, func() bool { return len(journal.Entries()) == 100 }, 1*time.Second, 100*time.Millisecond) + + journal.Clear() + require.Empty(t, journal.Entries()) + require.Empty(t, journal.Entries()) + require.Empty(t, journal.Entries()) +} + +func TestMemJournal_Observe(t *testing.T) { + lc := fxtest.NewLifecycle(t) + defer lc.RequireStop() + + journal := NewMemoryJournal(lc, nil) + addEntries(journal, 100) + + require.Eventually(t, func() bool { return len(journal.Entries()) == 100 }, 1*time.Second, 100*time.Millisecond) + + o1 := journal.Observe(context.TODO(), false, EventType{"spaceship", "wheezing-1"}) + o2 := journal.Observe(context.TODO(), true, EventType{"spaceship", "wheezing-1"}, EventType{"spaceship", "wheezing-2"}) + o3 := journal.Observe(context.TODO(), true) + + time.Sleep(1 * time.Second) + + require.Len(t, o1, 0) // no replay + require.Len(t, o2, 20) // replay with include set + require.Len(t, o3, 100) // replay with no include set (all entries) + + // add another 100 entries and assert what the observers have seen. + addEntries(journal, 100) + + require.Eventually(t, func() bool { return len(journal.Entries()) == 200 }, 1*time.Second, 100*time.Millisecond) + + // note: we're able to queue items because the observer channel buffer size is 256. + require.Len(t, o1, 10) // should have 0 old entries + 10 new entries + require.Len(t, o2, 40) // should have 20 old entries + 20 new entries + require.Len(t, o3, 200) // should have 100 old entries + 100 new entries +} + +func TestMemJournal_ObserverCancellation(t *testing.T) { + lc := fxtest.NewLifecycle(t) + defer lc.RequireStop() + + journal := NewMemoryJournal(lc, nil) + + ctx, cancel := context.WithCancel(context.TODO()) + o1 := journal.Observe(ctx, false) + o2 := journal.Observe(context.TODO(), false) + addEntries(journal, 100) + + require.Eventually(t, func() bool { return len(journal.Entries()) == 100 }, 1*time.Second, 100*time.Millisecond) + + // all observers have received the 100 entries. + require.Len(t, o1, 100) + require.Len(t, o2, 100) + + // cancel o1's context. + cancel() + time.Sleep(500 * time.Millisecond) + + // add 50 new entries + addEntries(journal, 50) + + require.Eventually(t, func() bool { return len(journal.Entries()) == 150 }, 1*time.Second, 100*time.Millisecond) + + require.Len(t, o1, 100) // has not moved. + require.Len(t, o2, 150) // should have 100 old entries + 50 new entries + +} + +func addEntries(journal *MemJournal, count int) { + for i := 0; i < count; i++ { + eventIdx := i % 10 + journal.AddEntry(EventType{"spaceship", fmt.Sprintf("wheezing-%d", eventIdx)}, HeadChangeEvt{ + From: types.TipSetKey{}, + FromHeight: abi.ChainEpoch(i), + To: types.TipSetKey{}, + ToHeight: abi.ChainEpoch(i), + RevertCount: i, + ApplyCount: i, + }) + } +} diff --git a/journal/types.go b/journal/types.go new file mode 100644 index 000000000..d8c897cfa --- /dev/null +++ b/journal/types.go @@ -0,0 +1,60 @@ +package journal + +import "time" + +// EventType represents the signature of an event. +type EventType struct { + System string + Event string +} + +// Journal represents an audit trail of system actions. +// +// Every entry is tagged with a timestamp, a system name, and an event name. +// The supplied data can be any type, as long as it is JSON serializable, +// including structs, map[string]interface{}, or primitive types. +// +// For cleanliness and type safety, we recommend to use typed events. See the +// *Evt struct types in this package for more info. +type Journal interface { + // IsEnabled allows components to check if a given event type is enabled. + // All event types are enabled by default, and specific event types can only + // be disabled at construction type. Components are advised to check if the + // journal event types they record are enabled as soon as possible, and hold + // on to the answer all throughout the lifetime of the process. + IsEnabled(evtType EventType) bool + + // AddEntry adds an entry to this journal. See godocs on the Journal type + // for more info. + AddEntry(evtType EventType, data interface{}) + + // Close closes this journal for further writing. + Close() error +} + +// Entry represents a journal entry. +// +// See godocs on Journal for more information. +type Entry struct { + EventType + + Timestamp time.Time + Data interface{} +} + +// disabledTracker is an embeddable mixin that takes care of tracking disabled +// event types. +type disabledTracker map[EventType]struct{} + +func newDisabledTracker(disabled []EventType) disabledTracker { + dis := make(map[EventType]struct{}, len(disabled)) + for _, et := range disabled { + dis[et] = struct{}{} + } + return dis +} + +func (d disabledTracker) IsEnabled(evtType EventType) bool { + _, ok := d[evtType] + return !ok +} diff --git a/node/builder.go b/node/builder.go index 780497dba..90b150a8a 100644 --- a/node/builder.go +++ b/node/builder.go @@ -41,6 +41,7 @@ import ( "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/chain/wallet" + "github.com/filecoin-project/lotus/journal" "github.com/filecoin-project/lotus/lib/peermgr" _ "github.com/filecoin-project/lotus/lib/sigs/bls" _ "github.com/filecoin-project/lotus/lib/sigs/secp" @@ -119,7 +120,7 @@ const ( ExtractApiKey HeadMetricsKey RunPeerTaggerKey - JournalKey + InitJournalKey SetApiEndpointKey @@ -151,8 +152,9 @@ func defaults() []Option { Override(new(record.Validator), modules.RecordValidator), Override(new(dtypes.Bootstrapper), dtypes.Bootstrapper(false)), Override(new(dtypes.ShutdownChan), make(chan struct{})), - Override(JournalKey, modules.SetupJournal), + Override(new(journal.Journal), journal.OpenFSJournal), + Override(InitJournalKey, func(j *journal.Journal) { /* forces the creation of the journal at startup */ }), // Filecoin modules } diff --git a/node/modules/core.go b/node/modules/core.go index 84179bd63..ca9872d90 100644 --- a/node/modules/core.go +++ b/node/modules/core.go @@ -6,7 +6,6 @@ import ( "errors" "io" "io/ioutil" - "path/filepath" "github.com/gbrlsnchs/jwt/v3" logging "github.com/ipfs/go-log/v2" @@ -19,7 +18,6 @@ import ( "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/journal" "github.com/filecoin-project/lotus/lib/addrutil" "github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/repo" @@ -95,7 +93,3 @@ func BuiltinBootstrap() (dtypes.BootstrapPeers, error) { func DrandBootstrap() (dtypes.DrandBootstrap, error) { return build.DrandBootstrap() } - -func SetupJournal(lr repo.LockedRepo) error { - return journal.InitializeSystemJournal(filepath.Join(lr.Path(), "journal")) -} diff --git a/storage/wdpost_run.go b/storage/wdpost_run.go index 8e404610c..66bb0d53e 100644 --- a/storage/wdpost_run.go +++ b/storage/wdpost_run.go @@ -256,7 +256,7 @@ func (s *WindowPoStScheduler) checkNextFaults(ctx context.Context, deadline uint Method: builtin.MethodsMiner.DeclareFaults, Params: enc, Value: types.NewInt(0), // TODO: Is there a fee? - GasLimit: 100_000_000, // i dont know help + GasLimit: 100_000_000, // i dont know help GasPrice: types.NewInt(2), } From bef7d64e666242c19e4f76cb88422c64947e8f00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Fri, 17 Jul 2020 18:35:15 +0100 Subject: [PATCH 02/40] refactor EventType construction. --- journal/filesystem.go | 12 +++---- journal/memory.go | 15 ++++++-- journal/memory_test.go | 13 ++++--- journal/types.go | 80 ++++++++++++++++++++++++++++++++---------- 4 files changed, 89 insertions(+), 31 deletions(-) diff --git a/journal/filesystem.go b/journal/filesystem.go index d49f77ff9..dbc6d2c27 100644 --- a/journal/filesystem.go +++ b/journal/filesystem.go @@ -21,7 +21,7 @@ var log = logging.Logger("journal") // fsJournal is a basic journal backed by files on a filesystem. type fsJournal struct { - disabledTracker + *eventTypeFactory dir string sizeLimit int64 @@ -44,11 +44,11 @@ func OpenFSJournal(lr repo.LockedRepo, lc fx.Lifecycle, disabled []EventType) (J } f := &fsJournal{ - disabledTracker: newDisabledTracker(disabled), - dir: dir, - sizeLimit: 1 << 30, - incoming: make(chan *Entry, 32), - closing: make(chan struct{}), + eventTypeFactory: newEventTypeFactory(disabled), + dir: dir, + sizeLimit: 1 << 30, + incoming: make(chan *Entry, 32), + closing: make(chan struct{}), } if err := f.rollJournalFile(); err != nil { diff --git a/journal/memory.go b/journal/memory.go index 483722635..c1472ccca 100644 --- a/journal/memory.go +++ b/journal/memory.go @@ -21,7 +21,7 @@ type ( ) type MemJournal struct { - disabledTracker + *eventTypeFactory entries []*Entry index map[string]map[string][]*Entry @@ -52,7 +52,7 @@ func (o *observer) dispatch(entry *Entry) { func NewMemoryJournal(lc fx.Lifecycle, disabled []EventType) *MemJournal { m := &MemJournal{ - disabledTracker: newDisabledTracker(disabled), + eventTypeFactory: newEventTypeFactory(disabled), index: make(map[string]map[string][]*Entry, 16), observers: make([]observer, 0, 16), @@ -72,6 +72,11 @@ func NewMemoryJournal(lc fx.Lifecycle, disabled []EventType) *MemJournal { } func (m *MemJournal) AddEntry(evtType EventType, obj interface{}) { + if !evtType.enabled || !evtType.safe { + // tried to record a disabled event type, or used an invalid EventType. + return + } + entry := &Entry{ EventType: evtType, Timestamp: build.Clock.Now(), @@ -109,8 +114,12 @@ func (m *MemJournal) Clear() { func (m *MemJournal) Observe(ctx context.Context, replay bool, include ...EventType) <-chan *Entry { var acc map[EventType]struct{} if include != nil { - acc = make(map[EventType]struct{}, 16) + acc = make(map[EventType]struct{}, len(include)) for _, et := range include { + if !et.enabled { + // skip over disabled event type. + continue + } acc[et] = struct{}{} } } diff --git a/journal/memory_test.go b/journal/memory_test.go index 10b3a90cb..442a7f46d 100644 --- a/journal/memory_test.go +++ b/journal/memory_test.go @@ -111,8 +111,11 @@ func TestMemJournal_Observe(t *testing.T) { require.Eventually(t, func() bool { return len(journal.Entries()) == 100 }, 1*time.Second, 100*time.Millisecond) - o1 := journal.Observe(context.TODO(), false, EventType{"spaceship", "wheezing-1"}) - o2 := journal.Observe(context.TODO(), true, EventType{"spaceship", "wheezing-1"}, EventType{"spaceship", "wheezing-2"}) + et1 := journal.RegisterEventType("spaceship", "wheezing-1") + et2 := journal.RegisterEventType("spaceship", "wheezing-2") + + o1 := journal.Observe(context.TODO(), false, et1) + o2 := journal.Observe(context.TODO(), true, et1, et2) o3 := journal.Observe(context.TODO(), true) time.Sleep(1 * time.Second) @@ -160,13 +163,15 @@ func TestMemJournal_ObserverCancellation(t *testing.T) { require.Len(t, o1, 100) // has not moved. require.Len(t, o2, 150) // should have 100 old entries + 50 new entries - } func addEntries(journal *MemJournal, count int) { for i := 0; i < count; i++ { eventIdx := i % 10 - journal.AddEntry(EventType{"spaceship", fmt.Sprintf("wheezing-%d", eventIdx)}, HeadChangeEvt{ + + // RegisterEventType is not _really_ intended to be used this way (on every write). + et := journal.RegisterEventType("spaceship", fmt.Sprintf("wheezing-%d", eventIdx)) + journal.AddEntry(et, HeadChangeEvt{ From: types.TipSetKey{}, FromHeight: abi.ChainEpoch(i), To: types.TipSetKey{}, diff --git a/journal/types.go b/journal/types.go index d8c897cfa..7a166d58a 100644 --- a/journal/types.go +++ b/journal/types.go @@ -1,11 +1,32 @@ package journal -import "time" +import ( + "sync" + "time" +) // EventType represents the signature of an event. type EventType struct { System string Event string + + // enabled stores whether this event type is enabled. + enabled bool + + // safe is a sentinel marker that's set to true if this EventType was + // constructed correctly (via Journal#RegisterEventType). + safe bool +} + +// Enabled returns whether this event type is enabled in the journaling +// subsystem. Users are advised to check this before actually attempting to +// add a journal entry, as it helps bypass object construction for events that +// would be discarded anyway. +// +// All event types are enabled by default, and specific event types can only +// be disabled at Journal construction time. +func (et EventType) Enabled() bool { + return et.enabled } // Journal represents an audit trail of system actions. @@ -17,12 +38,11 @@ type EventType struct { // For cleanliness and type safety, we recommend to use typed events. See the // *Evt struct types in this package for more info. type Journal interface { - // IsEnabled allows components to check if a given event type is enabled. - // All event types are enabled by default, and specific event types can only - // be disabled at construction type. Components are advised to check if the - // journal event types they record are enabled as soon as possible, and hold - // on to the answer all throughout the lifetime of the process. - IsEnabled(evtType EventType) bool + // RegisterEventType introduces a new event type to this journal, and + // returns an EventType token that components can later use to check whether + // journalling for that type is enabled/suppressed, and to tag journal + // entries appropriately. + RegisterEventType(system, event string) EventType // AddEntry adds an entry to this journal. See godocs on the Journal type // for more info. @@ -42,19 +62,43 @@ type Entry struct { Data interface{} } -// disabledTracker is an embeddable mixin that takes care of tracking disabled -// event types. -type disabledTracker map[EventType]struct{} +// eventTypeFactory is an embeddable mixin that takes care of tracking disabled +// event types, and returning initialized/safe EventTypes when requested. +type eventTypeFactory struct { + sync.Mutex -func newDisabledTracker(disabled []EventType) disabledTracker { - dis := make(map[EventType]struct{}, len(disabled)) - for _, et := range disabled { - dis[et] = struct{}{} + m map[string]EventType +} + +func newEventTypeFactory(disabled []EventType) *eventTypeFactory { + ret := &eventTypeFactory{ + m: make(map[string]EventType, len(disabled)+32), // + extra capacity. } - return dis + + for _, et := range disabled { + et.enabled, et.safe = false, true + ret.m[et.System+":"+et.Event] = et + } + + return ret } -func (d disabledTracker) IsEnabled(evtType EventType) bool { - _, ok := d[evtType] - return !ok +func (d *eventTypeFactory) RegisterEventType(system, event string) EventType { + d.Lock() + defer d.Unlock() + + key := system + ":" + event + if et, ok := d.m[key]; ok { + return et + } + + et := EventType{ + System: system, + Event: event, + enabled: true, + safe: true, + } + + d.m[key] = et + return et } From 4bcf01938c151cf4a0d1c4cbf99fe18b36f885f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Fri, 17 Jul 2020 18:54:26 +0100 Subject: [PATCH 03/40] use new journal from chain/store pkg. --- chain/store/store.go | 33 +++++++++++++++++++++++---------- journal/sugar.go | 11 +++++++++++ 2 files changed, 34 insertions(+), 10 deletions(-) create mode 100644 journal/sugar.go diff --git a/chain/store/store.go b/chain/store/store.go index ec134df1a..fd670eee9 100644 --- a/chain/store/store.go +++ b/chain/store/store.go @@ -54,6 +54,11 @@ var blockValidationCacheKeyPrefix = dstore.NewKey("blockValidation") // ReorgNotifee represents a callback that gets called upon reorgs. type ReorgNotifee func(rev, app []*types.TipSet) error +// Journal event types. +const ( + evtTypeHeadChange = iota +) + // ChainStore is the main point of access to chain data. // // Raw chain data is stored in the Blockstore, with relevant markers (genesis, @@ -85,10 +90,12 @@ type ChainStore struct { tsCache *lru.ARCCache vmcalls runtime.Syscalls - journal journal.Journal + + journal journal.Journal + evtTypes [1]journal.EventType } -func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls runtime.Syscalls, journal journal.Journal) *ChainStore { +func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls runtime.Syscalls, jrnl journal.Journal) *ChainStore { c, _ := lru.NewARC(2048) tsc, _ := lru.NewARC(4096) cs := &ChainStore{ @@ -99,7 +106,11 @@ func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls runtime.Sys mmCache: c, tsCache: tsc, vmcalls: vmcalls, - journal: journal, + journal: jrnl, + } + + cs.evtTypes = [1]journal.EventType{ + evtTypeHeadChange: jrnl.RegisterEventType("sync", "head_change"), } ci := NewChainIndex(cs.LoadTipSet) @@ -328,13 +339,15 @@ func (cs *ChainStore) reorgWorker(ctx context.Context, initialNotifees []ReorgNo continue } - cs.journal.AddEntry(journal.EventType{"sync", "head_change"}, map[string]interface{}{ - "from": r.old.Key(), - "from_height": r.old.Height(), - "to": r.new.Key(), - "to_height": r.new.Height(), - "rev_cnt": len(revert), - "apply_cnt": len(apply), + journal.MaybeAddEntry(cs.journal, cs.evtTypes[evtTypeHeadChange], func() interface{} { + return journal.HeadChangeEvt{ + From: r.old.Key(), + FromHeight: r.old.Height(), + To: r.new.Key(), + ToHeight: r.new.Height(), + RevertCount: len(revert), + ApplyCount: len(apply), + } }) // reverse the apply array diff --git a/journal/sugar.go b/journal/sugar.go new file mode 100644 index 000000000..6ed1bfc32 --- /dev/null +++ b/journal/sugar.go @@ -0,0 +1,11 @@ +package journal + +// MaybeAddEntry is a convenience function that evaluates if the EventType is +// enabled, and if so, it calls the supplier to create the entry and +// subsequently journal.AddEntry on the provided journal to record it. +func MaybeAddEntry(journal Journal, evtType EventType, supplier func() interface{}) { + if !evtType.Enabled() { + return + } + journal.AddEntry(evtType, supplier()) +} From becbff0b134e84e37e4cd03349964ef13ac67f4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Fri, 17 Jul 2020 19:09:18 +0100 Subject: [PATCH 04/40] add NilJournal; fix call sites to ChainStore constructor. --- chain/blocksync/graphsync_client.go | 3 ++- chain/gen/gen.go | 3 ++- chain/gen/genesis/genesis.go | 3 ++- chain/validation/applier.go | 3 ++- cmd/lotus-bench/import.go | 3 ++- cmd/lotus/daemon.go | 3 ++- journal/nil.go | 16 ++++++++++++++++ journal/sugar.go | 6 ++++++ node/modules/chain.go | 5 +++-- 9 files changed, 37 insertions(+), 8 deletions(-) create mode 100644 journal/nil.go diff --git a/chain/blocksync/graphsync_client.go b/chain/blocksync/graphsync_client.go index 03e4a30e5..338ee61bf 100644 --- a/chain/blocksync/graphsync_client.go +++ b/chain/blocksync/graphsync_client.go @@ -12,6 +12,7 @@ import ( store "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/journal" cidlink "github.com/ipld/go-ipld-prime/linking/cid" basicnode "github.com/ipld/go-ipld-prime/node/basic" @@ -138,7 +139,7 @@ func (bs *BlockSync) fetchBlocksGraphSync(ctx context.Context, p peer.ID, req *B } // Now pull the data we fetched out of the chainstore (where it should now be persisted) - tempcs := store.NewChainStore(bs.bserv.Blockstore(), datastore.NewMapDatastore(), nil) + tempcs := store.NewChainStore(bs.bserv.Blockstore(), datastore.NewMapDatastore(), nil, journal.NilJournal()) opts := ParseBSOptions(req.Options) tsk := types.NewTipSetKey(req.Start...) diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 990383ad6..2658772ff 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -36,6 +36,7 @@ import ( "github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/lotus/cmd/lotus-seed/seed" "github.com/filecoin-project/lotus/genesis" + "github.com/filecoin-project/lotus/journal" "github.com/filecoin-project/lotus/lib/sigs" "github.com/filecoin-project/lotus/node/repo" "github.com/filecoin-project/sector-storage/ffiwrapper" @@ -204,7 +205,7 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) { return nil, xerrors.Errorf("make genesis block failed: %w", err) } - cs := store.NewChainStore(bs, ds, sys) + cs := store.NewChainStore(bs, ds, sys, journal.NilJournal()) genfb := &types.FullBlock{Header: genb.Genesis} gents := store.NewFullTipSet([]*types.FullBlock{genfb}) diff --git a/chain/gen/genesis/genesis.go b/chain/gen/genesis/genesis.go index b5b9dfe28..0f99f22a5 100644 --- a/chain/gen/genesis/genesis.go +++ b/chain/gen/genesis/genesis.go @@ -24,6 +24,7 @@ import ( "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/genesis" + "github.com/filecoin-project/lotus/journal" ) const AccountStart = 100 @@ -302,7 +303,7 @@ func MakeGenesisBlock(ctx context.Context, bs bstore.Blockstore, sys runtime.Sys } // temp chainstore - cs := store.NewChainStore(bs, datastore.NewMapDatastore(), sys) + cs := store.NewChainStore(bs, datastore.NewMapDatastore(), sys, journal.NilJournal()) // Verify PreSealed Data stateroot, err = VerifyPreSealedData(ctx, cs, stateroot, template) diff --git a/chain/validation/applier.go b/chain/validation/applier.go index 153c8ca71..7bde26495 100644 --- a/chain/validation/applier.go +++ b/chain/validation/applier.go @@ -20,6 +20,7 @@ import ( "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/vm" + "github.com/filecoin-project/lotus/journal" ) // Applier applies messages to state trees and storage. @@ -67,7 +68,7 @@ func (a *Applier) ApplySignedMessage(epoch abi.ChainEpoch, msg *vtypes.SignedMes } func (a *Applier) ApplyTipSetMessages(epoch abi.ChainEpoch, blocks []vtypes.BlockMessagesInfo, rnd vstate.RandomnessSource) (vtypes.ApplyTipSetResult, error) { - cs := store.NewChainStore(a.stateWrapper.bs, a.stateWrapper.ds, a.syscalls) + cs := store.NewChainStore(a.stateWrapper.bs, a.stateWrapper.ds, a.syscalls, journal.NilJournal()) sm := stmgr.NewStateManager(cs) var bms []stmgr.BlockMessages diff --git a/cmd/lotus-bench/import.go b/cmd/lotus-bench/import.go index 3c56a5707..9bd520ff9 100644 --- a/cmd/lotus-bench/import.go +++ b/cmd/lotus-bench/import.go @@ -21,6 +21,7 @@ import ( "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/vm" + "github.com/filecoin-project/lotus/journal" _ "github.com/filecoin-project/lotus/lib/sigs/bls" _ "github.com/filecoin-project/lotus/lib/sigs/secp" "github.com/filecoin-project/sector-storage/ffiwrapper" @@ -85,7 +86,7 @@ var importBenchCmd = &cli.Command{ } bs = cbs ds := datastore.NewMapDatastore() - cs := store.NewChainStore(bs, ds, vm.Syscalls(ffiwrapper.ProofVerifier)) + cs := store.NewChainStore(bs, ds, vm.Syscalls(ffiwrapper.ProofVerifier), journal.NilJournal()) stm := stmgr.NewStateManager(cs) prof, err := os.Create("import-bench.prof") diff --git a/cmd/lotus/daemon.go b/cmd/lotus/daemon.go index bb17c0d87..49c052d0f 100644 --- a/cmd/lotus/daemon.go +++ b/cmd/lotus/daemon.go @@ -13,6 +13,7 @@ import ( "strings" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/journal" paramfetch "github.com/filecoin-project/go-paramfetch" blockstore "github.com/ipfs/go-ipfs-blockstore" @@ -336,7 +337,7 @@ func ImportChain(r repo.Repo, fname string) error { bs := blockstore.NewBlockstore(ds) - cst := store.NewChainStore(bs, mds, vm.Syscalls(ffiwrapper.ProofVerifier)) + cst := store.NewChainStore(bs, mds, vm.Syscalls(ffiwrapper.ProofVerifier), journal.NilJournal()) log.Info("importing chain from file...") ts, err := cst.Import(fi) diff --git a/journal/nil.go b/journal/nil.go new file mode 100644 index 000000000..0123fe585 --- /dev/null +++ b/journal/nil.go @@ -0,0 +1,16 @@ +package journal + +type nilJournal struct{} + +// nilj is a singleton nil journal. +var nilj Journal = &nilJournal{} + +func NilJournal() Journal { + return nilj +} + +func (n *nilJournal) RegisterEventType(_, _ string) EventType { return EventType{} } + +func (n *nilJournal) AddEntry(_ EventType, _ interface{}) {} + +func (n *nilJournal) Close() error { return nil } diff --git a/journal/sugar.go b/journal/sugar.go index 6ed1bfc32..9ee59f2c7 100644 --- a/journal/sugar.go +++ b/journal/sugar.go @@ -3,7 +3,13 @@ package journal // MaybeAddEntry is a convenience function that evaluates if the EventType is // enabled, and if so, it calls the supplier to create the entry and // subsequently journal.AddEntry on the provided journal to record it. +// +// This is safe to call with a nil Journal, either because the value is nil, +// or because a journal obtained through NilJournal() is in use. func MaybeAddEntry(journal Journal, evtType EventType, supplier func() interface{}) { + if journal == nil || journal == nilj { + return + } if !evtType.Enabled() { return } diff --git a/node/modules/chain.go b/node/modules/chain.go index 229a97cc4..9f5ac05a3 100644 --- a/node/modules/chain.go +++ b/node/modules/chain.go @@ -26,6 +26,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/journal" "github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/helpers" "github.com/filecoin-project/lotus/node/repo" @@ -83,8 +84,8 @@ func ChainBlockservice(bs dtypes.ChainBlockstore, rem dtypes.ChainExchange) dtyp return blockservice.New(bs, rem) } -func ChainStore(lc fx.Lifecycle, bs dtypes.ChainBlockstore, ds dtypes.MetadataDS, syscalls runtime.Syscalls) *store.ChainStore { - chain := store.NewChainStore(bs, ds, syscalls) +func ChainStore(lc fx.Lifecycle, bs dtypes.ChainBlockstore, ds dtypes.MetadataDS, syscalls runtime.Syscalls, journal journal.Journal) *store.ChainStore { + chain := store.NewChainStore(bs, ds, syscalls, journal) if err := chain.Load(); err != nil { log.Warnf("loading chain state from disk: %s", err) From 226786c1daeae33a5d4ef9b11ec572c97c300d40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Mon, 20 Jul 2020 14:45:17 +0100 Subject: [PATCH 05/40] wip --- api/api_full.go | 2 +- api/apistruct/struct.go | 2 +- chain/gen/genesis/genesis.go | 14 ++--- chain/store/store.go | 11 +++- journal/events.go | 16 ------ journal/filesystem.go | 2 +- journal/memory.go | 2 +- journal/types.go | 5 +- node/builder.go | 1 + node/modules/storageminer.go | 32 ++++++++++- storage/journal_events.go | 34 ++++++++++++ storage/wdpost_run.go | 104 ++++++++++++++++++++++++++++++++--- storage/wdpost_sched.go | 27 ++++++++- 13 files changed, 210 insertions(+), 42 deletions(-) delete mode 100644 journal/events.go create mode 100644 storage/journal_events.go diff --git a/api/api_full.go b/api/api_full.go index 9821b4557..895c1e65b 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -375,7 +375,7 @@ type FileRef struct { type MinerSectors struct { Sectors uint64 - Active uint64 + Active uint64 } type SectorExpiration struct { diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 326e98453..d5efd5266 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -127,7 +127,7 @@ type FullNodeStruct struct { StateNetworkName func(context.Context) (dtypes.NetworkName, error) `perm:"read"` StateMinerSectors func(context.Context, address.Address, *abi.BitField, bool, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"` - StateMinerActiveSectors func(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"` + StateMinerActiveSectors func(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"` StateMinerProvingDeadline func(context.Context, address.Address, types.TipSetKey) (*miner.DeadlineInfo, error) `perm:"read"` StateMinerPower func(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error) `perm:"read"` StateMinerInfo func(context.Context, address.Address, types.TipSetKey) (api.MinerInfo, error) `perm:"read"` diff --git a/chain/gen/genesis/genesis.go b/chain/gen/genesis/genesis.go index f72ab7bdd..22376a088 100644 --- a/chain/gen/genesis/genesis.go +++ b/chain/gen/genesis/genesis.go @@ -209,7 +209,7 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge // var newAddress address.Address - if (info.Type == genesis.TAccount) { + if info.Type == genesis.TAccount { var ainfo genesis.AccountMeta if err := json.Unmarshal(info.Meta, &ainfo); err != nil { return nil, xerrors.Errorf("unmarshaling account meta: %w", err) @@ -226,7 +226,7 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge if err != nil { return nil, xerrors.Errorf("setting account from actmap: %w", err) } - } else if (info.Type == genesis.TMultisig) { + } else if info.Type == genesis.TMultisig { var ainfo genesis.MultisigMeta if err := json.Unmarshal(info.Meta, &ainfo); err != nil { return nil, xerrors.Errorf("unmarshaling account meta: %w", err) @@ -238,12 +238,12 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge } st, err := cst.Put(ctx, &multisig.State{ - Signers: ainfo.Signers, + Signers: ainfo.Signers, NumApprovalsThreshold: uint64(ainfo.Threshold), - StartEpoch: abi.ChainEpoch(ainfo.VestingStart), - UnlockDuration: abi.ChainEpoch(ainfo.VestingDuration), - PendingTxns: pending, - InitialBalance: info.Balance, + StartEpoch: abi.ChainEpoch(ainfo.VestingStart), + UnlockDuration: abi.ChainEpoch(ainfo.VestingDuration), + PendingTxns: pending, + InitialBalance: info.Balance, }) if err != nil { return nil, err diff --git a/chain/store/store.go b/chain/store/store.go index 8ab599aa3..ba7a54ed3 100644 --- a/chain/store/store.go +++ b/chain/store/store.go @@ -59,6 +59,15 @@ const ( evtTypeHeadChange = iota ) +type HeadChangeEvt struct { + From types.TipSetKey + FromHeight abi.ChainEpoch + To types.TipSetKey + ToHeight abi.ChainEpoch + RevertCount int + ApplyCount int +} + // ChainStore is the main point of access to chain data. // // Raw chain data is stored in the Blockstore, with relevant markers (genesis, @@ -340,7 +349,7 @@ func (cs *ChainStore) reorgWorker(ctx context.Context, initialNotifees []ReorgNo } journal.MaybeAddEntry(cs.journal, cs.evtTypes[evtTypeHeadChange], func() interface{} { - return journal.HeadChangeEvt{ + return HeadChangeEvt{ From: r.old.Key(), FromHeight: r.old.Height(), To: r.new.Key(), diff --git a/journal/events.go b/journal/events.go deleted file mode 100644 index b6b5a15d4..000000000 --- a/journal/events.go +++ /dev/null @@ -1,16 +0,0 @@ -package journal - -import ( - "github.com/filecoin-project/specs-actors/actors/abi" - - "github.com/filecoin-project/lotus/chain/types" -) - -type HeadChangeEvt struct { - From types.TipSetKey `json:"from"` - FromHeight abi.ChainEpoch `json:"from_height"` - To types.TipSetKey `json:"to"` - ToHeight abi.ChainEpoch `json:"to_height"` - RevertCount int `json:"rev_cnt"` - ApplyCount int `json:"apply_cnt"` -} diff --git a/journal/filesystem.go b/journal/filesystem.go index dbc6d2c27..7aa470a2e 100644 --- a/journal/filesystem.go +++ b/journal/filesystem.go @@ -37,7 +37,7 @@ type fsJournal struct { // OpenFSJournal constructs a rolling filesystem journal, with a default // per-file size limit of 1GiB. -func OpenFSJournal(lr repo.LockedRepo, lc fx.Lifecycle, disabled []EventType) (Journal, error) { +func OpenFSJournal(lr repo.LockedRepo, lc fx.Lifecycle, disabled DisabledEvents) (Journal, error) { dir := filepath.Join(lr.Path(), "journal") if err := os.MkdirAll(dir, 0755); err != nil { return nil, fmt.Errorf("failed to mk directory %s for file journal: %w", dir, err) diff --git a/journal/memory.go b/journal/memory.go index c1472ccca..5471d3e11 100644 --- a/journal/memory.go +++ b/journal/memory.go @@ -50,7 +50,7 @@ func (o *observer) dispatch(entry *Entry) { } } -func NewMemoryJournal(lc fx.Lifecycle, disabled []EventType) *MemJournal { +func NewMemoryJournal(lc fx.Lifecycle, disabled DisabledEvents) *MemJournal { m := &MemJournal{ eventTypeFactory: newEventTypeFactory(disabled), diff --git a/journal/types.go b/journal/types.go index 7a166d58a..95349b24e 100644 --- a/journal/types.go +++ b/journal/types.go @@ -5,6 +5,9 @@ import ( "time" ) +// DisabledEvents is the set of event types whose journaling is suppressed. +type DisabledEvents []EventType + // EventType represents the signature of an event. type EventType struct { System string @@ -70,7 +73,7 @@ type eventTypeFactory struct { m map[string]EventType } -func newEventTypeFactory(disabled []EventType) *eventTypeFactory { +func newEventTypeFactory(disabled DisabledEvents) *eventTypeFactory { ret := &eventTypeFactory{ m: make(map[string]EventType, len(disabled)+32), // + extra capacity. } diff --git a/node/builder.go b/node/builder.go index 90b150a8a..eab575d20 100644 --- a/node/builder.go +++ b/node/builder.go @@ -153,6 +153,7 @@ func defaults() []Option { Override(new(dtypes.Bootstrapper), dtypes.Bootstrapper(false)), Override(new(dtypes.ShutdownChan), make(chan struct{})), Override(new(journal.Journal), journal.OpenFSJournal), + Override(new(journal.DisabledEvents), journal.DisabledEvents{}), Override(InitJournalKey, func(j *journal.Journal) { /* forces the creation of the journal at startup */ }), // Filecoin modules diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 1a22fdd95..d97dbd3fb 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -42,6 +42,7 @@ import ( paramfetch "github.com/filecoin-project/go-paramfetch" "github.com/filecoin-project/go-statestore" "github.com/filecoin-project/go-storedcounter" + "github.com/filecoin-project/lotus/journal" "github.com/filecoin-project/lotus/node/config" sectorstorage "github.com/filecoin-project/sector-storage" "github.com/filecoin-project/sector-storage/ffiwrapper" @@ -137,7 +138,34 @@ func SectorIDCounter(ds dtypes.MetadataDS) sealing.SectorIDCounter { return &sidsc{sc} } -func StorageMiner(mctx helpers.MetricsCtx, lc fx.Lifecycle, api lapi.FullNode, h host.Host, ds dtypes.MetadataDS, sealer sectorstorage.SectorManager, sc sealing.SectorIDCounter, verif ffiwrapper.Verifier, gsd dtypes.GetSealingDelayFunc) (*storage.Miner, error) { +type StorageMinerParams struct { + fx.In + + Lifecycle fx.Lifecycle + MetricsCtx helpers.MetricsCtx + API lapi.FullNode + Host host.Host + MetadataDS dtypes.MetadataDS + Sealer sectorstorage.SectorManager + SectorIDCounter sealing.SectorIDCounter + Verifier ffiwrapper.Verifier + GetSealingDelayFn dtypes.GetSealingDelayFunc + Journal journal.Journal +} + +func StorageMiner(params StorageMinerParams) (*storage.Miner, error) { + var ( + ds = params.MetadataDS + mctx = params.MetricsCtx + lc = params.Lifecycle + api = params.API + sealer = params.Sealer + h = params.Host + sc = params.SectorIDCounter + verif = params.Verifier + gsd = params.GetSealingDelayFn + jrnl = params.Journal + ) maddr, err := minerAddrFromDS(ds) if err != nil { return nil, err @@ -155,7 +183,7 @@ func StorageMiner(mctx helpers.MetricsCtx, lc fx.Lifecycle, api lapi.FullNode, h return nil, err } - fps, err := storage.NewWindowedPoStScheduler(api, sealer, sealer, maddr, worker) + fps, err := storage.NewWindowedPoStScheduler(api, sealer, sealer, maddr, worker, jrnl) if err != nil { return nil, err } diff --git a/storage/journal_events.go b/storage/journal_events.go new file mode 100644 index 000000000..d87c1ce43 --- /dev/null +++ b/storage/journal_events.go @@ -0,0 +1,34 @@ +package storage + +import ( + "github.com/filecoin-project/specs-actors/actors/abi" + "github.com/filecoin-project/specs-actors/actors/builtin/miner" + "github.com/ipfs/go-cid" +) + +type WindowPoStEvt struct { + State string + Deadline *miner.DeadlineInfo + Height abi.ChainEpoch + TipSet []cid.Cid + Error error `json:",omitempty"` + + Proofs *WindowPoStEvt_Proofs `json:",omitempty"` + Recoveries *WindowPoStEvt_Recoveries `json:",omitempty"` + Faults *WindowPoStEvt_Faults `json:",omitempty"` +} + +type WindowPoStEvt_Proofs struct { + Partitions []miner.PoStPartition + MessageCID cid.Cid +} + +type WindowPoStEvt_Recoveries struct { + Declarations []miner.RecoveryDeclaration + MessageCID cid.Cid +} + +type WindowPoStEvt_Faults struct { + Declarations []miner.FaultDeclaration + MessageCID cid.Cid +} diff --git a/storage/wdpost_run.go b/storage/wdpost_run.go index c7d99b2fc..681e9e3d5 100644 --- a/storage/wdpost_run.go +++ b/storage/wdpost_run.go @@ -14,17 +14,29 @@ import ( "github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin/miner" "github.com/filecoin-project/specs-actors/actors/crypto" + "github.com/ipfs/go-cid" "go.opencensus.io/trace" "golang.org/x/xerrors" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/journal" ) var errNoPartitions = errors.New("no partitions") -func (s *WindowPoStScheduler) failPost(deadline *miner.DeadlineInfo) { +func (s *WindowPoStScheduler) failPost(err error, deadline *miner.DeadlineInfo) { + journal.MaybeAddEntry(s.jrnl, s.evtTypes[evtTypeWindowPoSt], func() interface{} { + return WindowPoStEvt{ + State: "failed", + Deadline: s.activeDeadline, + Height: s.cur.Height(), + TipSet: s.cur.Cids(), + Error: err, + } + }) + log.Errorf("TODO") /*s.failLk.Lock() if eps > s.failed { @@ -39,6 +51,15 @@ func (s *WindowPoStScheduler) doPost(ctx context.Context, deadline *miner.Deadli s.abort = abort s.activeDeadline = deadline + journal.MaybeAddEntry(s.jrnl, s.evtTypes[evtTypeWindowPoSt], func() interface{} { + return WindowPoStEvt{ + State: "started", + Deadline: s.activeDeadline, + Height: s.cur.Height(), + TipSet: s.cur.Cids(), + } + }) + go func() { defer abort() @@ -52,14 +73,23 @@ func (s *WindowPoStScheduler) doPost(ctx context.Context, deadline *miner.Deadli case nil: if err := s.submitPost(ctx, proof); err != nil { log.Errorf("submitPost failed: %+v", err) - s.failPost(deadline) + s.failPost(err, deadline) return } default: log.Errorf("runPost failed: %+v", err) - s.failPost(deadline) + s.failPost(err, deadline) return } + + journal.MaybeAddEntry(s.jrnl, s.evtTypes[evtTypeWindowPoSt], func() interface{} { + return WindowPoStEvt{ + State: "succeeded", + Deadline: s.activeDeadline, + Height: s.cur.Height(), + TipSet: s.cur.Cids(), + } + }) }() } @@ -112,11 +142,29 @@ func (s *WindowPoStScheduler) checkNextRecoveries(ctx context.Context, dlIdx uin ctx, span := trace.StartSpan(ctx, "storage.checkNextRecoveries") defer span.End() + var sm *types.SignedMessage + faulty := uint64(0) params := &miner.DeclareFaultsRecoveredParams{ Recoveries: []miner.RecoveryDeclaration{}, } - faulty := uint64(0) + defer journal.MaybeAddEntry(s.jrnl, s.evtTypes[evtTypeWindowPoSt], func() interface{} { + var mcid cid.Cid + if sm != nil { + mcid = sm.Cid() + } + + return WindowPoStEvt{ + State: "recoveries_processed", + Deadline: s.activeDeadline, + Height: s.cur.Height(), + TipSet: s.cur.Cids(), + Recoveries: &WindowPoStEvt_Recoveries{ + Declarations: params.Recoveries, + MessageCID: mcid, + }, + } + }) for partIdx, partition := range partitions { unrecovered, err := bitfield.SubtractBitField(partition.Faults, partition.Recoveries) @@ -180,7 +228,8 @@ func (s *WindowPoStScheduler) checkNextRecoveries(ctx context.Context, dlIdx uin GasPrice: types.NewInt(2), } - sm, err := s.api.MpoolPushMessage(ctx, msg) + var err error + sm, err = s.api.MpoolPushMessage(ctx, msg) if err != nil { return xerrors.Errorf("pushing message to mpool: %w", err) } @@ -203,11 +252,28 @@ func (s *WindowPoStScheduler) checkNextFaults(ctx context.Context, dlIdx uint64, ctx, span := trace.StartSpan(ctx, "storage.checkNextFaults") defer span.End() + var sm *types.SignedMessage + bad := uint64(0) params := &miner.DeclareFaultsParams{ Faults: []miner.FaultDeclaration{}, } - bad := uint64(0) + defer journal.MaybeAddEntry(s.jrnl, s.evtTypes[evtTypeWindowPoSt], func() interface{} { + var mcid cid.Cid + if sm != nil { + mcid = sm.Cid() + } + return WindowPoStEvt{ + State: "faults_processed", + Deadline: s.activeDeadline, + Height: s.cur.Height(), + TipSet: s.cur.Cids(), + Faults: &WindowPoStEvt_Faults{ + Declarations: params.Faults, + MessageCID: mcid, + }, + } + }) for partIdx, partition := range partitions { toCheck, err := partition.ActiveSectors() @@ -264,7 +330,8 @@ func (s *WindowPoStScheduler) checkNextFaults(ctx context.Context, dlIdx uint64, GasPrice: types.NewInt(2), } - sm, err := s.api.MpoolPushMessage(ctx, msg) + var err error + sm, err = s.api.MpoolPushMessage(ctx, msg) if err != nil { return xerrors.Errorf("pushing message to mpool: %w", err) } @@ -450,6 +517,26 @@ func (s *WindowPoStScheduler) submitPost(ctx context.Context, proof *miner.Submi ctx, span := trace.StartSpan(ctx, "storage.commitPost") defer span.End() + var sm *types.SignedMessage + + defer journal.MaybeAddEntry(s.jrnl, s.evtTypes[evtTypeWindowPoSt], func() interface{} { + var mcid cid.Cid + if sm != nil { + mcid = sm.Cid() + } + + return WindowPoStEvt{ + State: "proofs_processed", + Deadline: s.activeDeadline, + Height: s.cur.Height(), + TipSet: s.cur.Cids(), + Proofs: &WindowPoStEvt_Proofs{ + Partitions: proof.Partitions, + MessageCID: mcid, + }, + } + }) + enc, aerr := actors.SerializeParams(proof) if aerr != nil { return xerrors.Errorf("could not serialize submit post parameters: %w", aerr) @@ -467,7 +554,8 @@ func (s *WindowPoStScheduler) submitPost(ctx context.Context, proof *miner.Submi } // TODO: consider maybe caring about the output - sm, err := s.api.MpoolPushMessage(ctx, msg) + var err error + sm, err = s.api.MpoolPushMessage(ctx, msg) if err != nil { return xerrors.Errorf("pushing message to mpool: %w", err) } diff --git a/storage/wdpost_sched.go b/storage/wdpost_sched.go index 8e3221ef9..83d37d24b 100644 --- a/storage/wdpost_sched.go +++ b/storage/wdpost_sched.go @@ -17,10 +17,16 @@ import ( "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/journal" ) const StartConfidence = 4 // TODO: config +// Journal event types. +const ( + evtTypeWindowPoSt = iota +) + type WindowPoStScheduler struct { api storageMinerApi prover storage.Prover @@ -36,12 +42,14 @@ type WindowPoStScheduler struct { // if a post is in progress, this indicates for which ElectionPeriodStart activeDeadline *miner.DeadlineInfo abort context.CancelFunc + jrnl journal.Journal + evtTypes [1]journal.EventType - //failed abi.ChainEpoch // eps - //failLk sync.Mutex + // failed abi.ChainEpoch // eps + // failLk sync.Mutex } -func NewWindowedPoStScheduler(api storageMinerApi, sb storage.Prover, ft sectorstorage.FaultTracker, actor address.Address, worker address.Address) (*WindowPoStScheduler, error) { +func NewWindowedPoStScheduler(api storageMinerApi, sb storage.Prover, ft sectorstorage.FaultTracker, actor address.Address, worker address.Address, jrnl journal.Journal) (*WindowPoStScheduler, error) { mi, err := api.StateMinerInfo(context.TODO(), actor, types.EmptyTSK) if err != nil { return nil, xerrors.Errorf("getting sector size: %w", err) @@ -61,6 +69,10 @@ func NewWindowedPoStScheduler(api storageMinerApi, sb storage.Prover, ft sectors actor: actor, worker: worker, + jrnl: jrnl, + evtTypes: [...]journal.EventType{ + evtTypeWindowPoSt: jrnl.RegisterEventType("storage", "wdpost"), + }, }, nil } @@ -214,6 +226,15 @@ func (s *WindowPoStScheduler) abortActivePoSt() { s.abort() } + journal.MaybeAddEntry(s.jrnl, s.evtTypes[evtTypeWindowPoSt], func() interface{} { + return WindowPoStEvt{ + State: "abort", + Deadline: s.activeDeadline, + Height: s.cur.Height(), + TipSet: s.cur.Cids(), + } + }) + log.Warnf("Aborting Window PoSt (Deadline: %+v)", s.activeDeadline) s.activeDeadline = nil From 7459ec6bbafa709a34fa27bacd2bda51110023a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Mon, 20 Jul 2020 16:37:24 +0100 Subject: [PATCH 06/40] add mpool journal events; fix dependency injection. --- chain/messagepool/messagepool.go | 54 ++++++++++++++++++++++++++- chain/messagepool/messagepool_test.go | 4 +- node/builder.go | 2 +- node/modules/chain.go | 4 +- 4 files changed, 58 insertions(+), 6 deletions(-) diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index 7b2f19bbd..2f420b308 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -28,6 +28,7 @@ import ( "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/journal" "github.com/filecoin-project/lotus/lib/sigs" "github.com/filecoin-project/lotus/node/modules/dtypes" @@ -65,6 +66,20 @@ const ( localUpdates = "update" ) +// Journal event types. +const ( + evtTypeMpoolAdd = iota + evtTypeMpoolRemove + evtTypeMpoolRepub +) + +// MessagePoolEvt is the journal event type emitted by the MessagePool. +type MessagePoolEvt struct { + Action string + MessageCIDs []cid.Cid + Error error `json:",omitempty"` +} + type MessagePool struct { lk sync.Mutex @@ -93,6 +108,9 @@ type MessagePool struct { netName dtypes.NetworkName sigValCache *lru.TwoQueueCache + + jrnl journal.Journal + evtTypes [3]journal.EventType } type msgSet struct { @@ -185,7 +203,7 @@ func (mpp *mpoolProvider) LoadTipSet(tsk types.TipSetKey) (*types.TipSet, error) return mpp.sm.ChainStore().LoadTipSet(tsk) } -func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName) (*MessagePool, error) { +func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName, jrnl journal.Journal) (*MessagePool, error) { cache, _ := lru.New2Q(build.BlsSignatureCacheSize) verifcache, _ := lru.New2Q(build.VerifSigCacheSize) @@ -202,6 +220,12 @@ func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName) (*Messa localMsgs: namespace.Wrap(ds, datastore.NewKey(localMsgsDs)), api: api, netName: netName, + jrnl: jrnl, + evtTypes: [...]journal.EventType{ + evtTypeMpoolAdd: jrnl.RegisterEventType("mpool", "add"), + evtTypeMpoolRemove: jrnl.RegisterEventType("mpool", "remove"), + evtTypeMpoolRepub: jrnl.RegisterEventType("mpool", "repub"), + }, } if err := mp.loadLocal(); err != nil { @@ -284,6 +308,19 @@ func (mp *MessagePool) repubLocal() { if errout != nil { log.Errorf("errors while republishing: %+v", errout) } + + journal.MaybeAddEntry(mp.jrnl, mp.evtTypes[evtTypeMpoolRepub], func() interface{} { + cids := make([]cid.Cid, 0, len(outputMsgs)) + for _, m := range outputMsgs { + cids = append(cids, m.Cid()) + } + return MessagePoolEvt{ + Action: "repub", + MessageCIDs: cids, + Error: errout, + } + }) + case <-mp.closer: mp.repubTk.Stop() return @@ -448,6 +485,14 @@ func (mp *MessagePool) addLocked(m *types.SignedMessage) error { Type: api.MpoolAdd, Message: m, }, localUpdates) + + journal.MaybeAddEntry(mp.jrnl, mp.evtTypes[evtTypeMpoolAdd], func() interface{} { + return MessagePoolEvt{ + Action: "add", + MessageCIDs: []cid.Cid{m.Cid()}, + } + }) + return nil } @@ -580,6 +625,13 @@ func (mp *MessagePool) Remove(from address.Address, nonce uint64) { Type: api.MpoolRemove, Message: m, }, localUpdates) + + journal.MaybeAddEntry(mp.jrnl, mp.evtTypes[evtTypeMpoolRemove], func() interface{} { + return MessagePoolEvt{ + Action: "remove", + MessageCIDs: []cid.Cid{m.Cid()}, + } + }) } // NB: This deletes any message with the given nonce. This makes sense diff --git a/chain/messagepool/messagepool_test.go b/chain/messagepool/messagepool_test.go index d1dedd534..64af26e9a 100644 --- a/chain/messagepool/messagepool_test.go +++ b/chain/messagepool/messagepool_test.go @@ -147,7 +147,7 @@ func TestMessagePool(t *testing.T) { ds := datastore.NewMapDatastore() - mp, err := New(tma, ds, "mptest") + mp, err := New(tma, ds, "mptest", nil) if err != nil { t.Fatal(err) } @@ -188,7 +188,7 @@ func TestRevertMessages(t *testing.T) { ds := datastore.NewMapDatastore() - mp, err := New(tma, ds, "mptest") + mp, err := New(tma, ds, "mptest", nil) if err != nil { t.Fatal(err) } diff --git a/node/builder.go b/node/builder.go index eab575d20..98ae568da 100644 --- a/node/builder.go +++ b/node/builder.go @@ -155,7 +155,7 @@ func defaults() []Option { Override(new(journal.Journal), journal.OpenFSJournal), Override(new(journal.DisabledEvents), journal.DisabledEvents{}), - Override(InitJournalKey, func(j *journal.Journal) { /* forces the creation of the journal at startup */ }), + Override(InitJournalKey, func(j journal.Journal) { /* forces the creation of the journal at startup */ }), // Filecoin modules } diff --git a/node/modules/chain.go b/node/modules/chain.go index 9f5ac05a3..b647cfb98 100644 --- a/node/modules/chain.go +++ b/node/modules/chain.go @@ -47,9 +47,9 @@ func ChainExchange(mctx helpers.MetricsCtx, lc fx.Lifecycle, host host.Host, rt return exch } -func MessagePool(lc fx.Lifecycle, sm *stmgr.StateManager, ps *pubsub.PubSub, ds dtypes.MetadataDS, nn dtypes.NetworkName) (*messagepool.MessagePool, error) { +func MessagePool(lc fx.Lifecycle, sm *stmgr.StateManager, ps *pubsub.PubSub, ds dtypes.MetadataDS, nn dtypes.NetworkName, jrnl journal.Journal) (*messagepool.MessagePool, error) { mpp := messagepool.NewProvider(sm, ps) - mp, err := messagepool.New(mpp, ds, nn) + mp, err := messagepool.New(mpp, ds, nn, jrnl) if err != nil { return nil, xerrors.Errorf("constructing mpool: %w", err) } From d6e6eedd581565fa69dccae8ecbb648b9f2272e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Tue, 21 Jul 2020 13:02:51 +0100 Subject: [PATCH 07/40] pipe sealing events to the journal. --- go.mod | 2 +- go.sum | 4 +-- node/modules/storageminer.go | 2 +- storage/journal_events.go | 34 ------------------ storage/miner.go | 32 +++++++++++++++-- storage/wdpost_run.go | 12 +++---- storage/wdpost_sched.go | 68 ++++++++++++++++++++++++------------ 7 files changed, 85 insertions(+), 69 deletions(-) delete mode 100644 storage/journal_events.go diff --git a/go.mod b/go.mod index d4170d4cd..6b905b9d9 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( github.com/filecoin-project/sector-storage v0.0.0-20200717213554-a109ef9cbeab github.com/filecoin-project/specs-actors v0.7.3-0.20200717200758-365408676dbb github.com/filecoin-project/specs-storage v0.1.1-0.20200622113353-88a9704877ea - github.com/filecoin-project/storage-fsm v0.0.0-20200717125541-d575c3a5f7f2 + github.com/filecoin-project/storage-fsm v0.0.0-20200721113842-ab98dc7ab341 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 92dba878a..0ffae068c 100644 --- a/go.sum +++ b/go.sum @@ -275,8 +275,8 @@ github.com/filecoin-project/specs-storage v0.1.0 h1:PkDgTOT5W5Ao7752onjDl4QSv+sg github.com/filecoin-project/specs-storage v0.1.0/go.mod h1:Pr5ntAaxsh+sLG/LYiL4tKzvA83Vk5vLODYhfNwOg7k= github.com/filecoin-project/specs-storage v0.1.1-0.20200622113353-88a9704877ea h1:iixjULRQFPn7Q9KlIqfwLJnlAXO10bbkI+xy5GKGdLY= github.com/filecoin-project/specs-storage v0.1.1-0.20200622113353-88a9704877ea/go.mod h1:Pr5ntAaxsh+sLG/LYiL4tKzvA83Vk5vLODYhfNwOg7k= -github.com/filecoin-project/storage-fsm v0.0.0-20200717125541-d575c3a5f7f2 h1:A9zUXOMuVnSTp9a0i0KtHkB05hA8mRWVLls6Op9Czuo= -github.com/filecoin-project/storage-fsm v0.0.0-20200717125541-d575c3a5f7f2/go.mod h1:1CGbd11KkHuyWPT+xwwCol1zl/jnlpiKD2L4fzKxaiI= +github.com/filecoin-project/storage-fsm v0.0.0-20200721113842-ab98dc7ab341 h1:4catrjuFXo/VcQcmvAMyeBYEp35IHFi+Tqz0dNAJp54= +github.com/filecoin-project/storage-fsm v0.0.0-20200721113842-ab98dc7ab341/go.mod h1:1CGbd11KkHuyWPT+xwwCol1zl/jnlpiKD2L4fzKxaiI= 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= diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index d97dbd3fb..96f5beba1 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -188,7 +188,7 @@ func StorageMiner(params StorageMinerParams) (*storage.Miner, error) { return nil, err } - sm, err := storage.NewMiner(api, maddr, worker, h, ds, sealer, sc, verif, gsd) + sm, err := storage.NewMiner(api, maddr, worker, h, ds, sealer, sc, verif, gsd, jrnl) if err != nil { return nil, err } diff --git a/storage/journal_events.go b/storage/journal_events.go deleted file mode 100644 index d87c1ce43..000000000 --- a/storage/journal_events.go +++ /dev/null @@ -1,34 +0,0 @@ -package storage - -import ( - "github.com/filecoin-project/specs-actors/actors/abi" - "github.com/filecoin-project/specs-actors/actors/builtin/miner" - "github.com/ipfs/go-cid" -) - -type WindowPoStEvt struct { - State string - Deadline *miner.DeadlineInfo - Height abi.ChainEpoch - TipSet []cid.Cid - Error error `json:",omitempty"` - - Proofs *WindowPoStEvt_Proofs `json:",omitempty"` - Recoveries *WindowPoStEvt_Recoveries `json:",omitempty"` - Faults *WindowPoStEvt_Faults `json:",omitempty"` -} - -type WindowPoStEvt_Proofs struct { - Partitions []miner.PoStPartition - MessageCID cid.Cid -} - -type WindowPoStEvt_Recoveries struct { - Declarations []miner.RecoveryDeclaration - MessageCID cid.Cid -} - -type WindowPoStEvt_Faults struct { - Declarations []miner.FaultDeclaration - MessageCID cid.Cid -} diff --git a/storage/miner.go b/storage/miner.go index c4a3cccc3..6f16b9cfe 100644 --- a/storage/miner.go +++ b/storage/miner.go @@ -24,6 +24,7 @@ import ( "github.com/filecoin-project/lotus/chain/events" "github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/journal" "github.com/filecoin-project/lotus/node/modules/dtypes" sealing "github.com/filecoin-project/storage-fsm" ) @@ -43,6 +44,18 @@ type Miner struct { getSealDelay dtypes.GetSealingDelayFunc sealing *sealing.Sealing + + jrnl journal.Journal + sealingEvtType journal.EventType +} + +// SealingStateEvt is a journal event that records a sector state transition. +type SealingStateEvt struct { + SectorNumber abi.SectorNumber + SectorType abi.RegisteredSealProof + From sealing.SectorState + After sealing.SectorState + Error string } type storageMinerApi interface { @@ -80,7 +93,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.GetSealingDelayFunc) (*Miner, 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.GetSealingDelayFunc, jrnl journal.Journal) (*Miner, error) { m := &Miner{ api: api, h: h, @@ -92,6 +105,9 @@ func NewMiner(api storageMinerApi, maddr, worker address.Address, h host.Host, d maddr: maddr, worker: worker, getSealDelay: gsd, + + jrnl: jrnl, + sealingEvtType: jrnl.RegisterEventType("storage", "sealing_states"), } return m, nil @@ -110,13 +126,25 @@ func (m *Miner) Run(ctx context.Context) error { evts := events.NewEvents(ctx, m.api) adaptedAPI := NewSealingAPIAdapter(m.api) pcp := sealing.NewBasicPreCommitPolicy(adaptedAPI, miner.MaxSectorExpirationExtension-(miner.WPoStProvingPeriod*2), md.PeriodStart%miner.WPoStProvingPeriod) - m.sealing = sealing.New(adaptedAPI, NewEventsAdapter(evts), m.maddr, m.ds, m.sealer, m.sc, m.verif, &pcp, sealing.GetSealingDelayFunc(m.getSealDelay)) + m.sealing = sealing.New(adaptedAPI, NewEventsAdapter(evts), m.maddr, m.ds, m.sealer, m.sc, m.verif, &pcp, sealing.GetSealingDelayFunc(m.getSealDelay), m.handleSealingNotifications) go m.sealing.Run(ctx) //nolint:errcheck // logged intside the function return nil } +func (m *Miner) handleSealingNotifications(before, after sealing.SectorInfo) { + journal.MaybeAddEntry(m.jrnl, m.sealingEvtType, func() interface{} { + return SealingStateEvt{ + SectorNumber: before.SectorNumber, + SectorType: before.SectorType, + From: before.State, + After: after.State, + Error: after.LastErr, + } + }) +} + func (m *Miner) Stop(ctx context.Context) error { return m.sealing.Stop(ctx) } diff --git a/storage/wdpost_run.go b/storage/wdpost_run.go index 681e9e3d5..191ac5319 100644 --- a/storage/wdpost_run.go +++ b/storage/wdpost_run.go @@ -27,7 +27,7 @@ import ( var errNoPartitions = errors.New("no partitions") func (s *WindowPoStScheduler) failPost(err error, deadline *miner.DeadlineInfo) { - journal.MaybeAddEntry(s.jrnl, s.evtTypes[evtTypeWindowPoSt], func() interface{} { + journal.MaybeAddEntry(s.jrnl, s.wdPoStEvtType, func() interface{} { return WindowPoStEvt{ State: "failed", Deadline: s.activeDeadline, @@ -51,7 +51,7 @@ func (s *WindowPoStScheduler) doPost(ctx context.Context, deadline *miner.Deadli s.abort = abort s.activeDeadline = deadline - journal.MaybeAddEntry(s.jrnl, s.evtTypes[evtTypeWindowPoSt], func() interface{} { + journal.MaybeAddEntry(s.jrnl, s.wdPoStEvtType, func() interface{} { return WindowPoStEvt{ State: "started", Deadline: s.activeDeadline, @@ -82,7 +82,7 @@ func (s *WindowPoStScheduler) doPost(ctx context.Context, deadline *miner.Deadli return } - journal.MaybeAddEntry(s.jrnl, s.evtTypes[evtTypeWindowPoSt], func() interface{} { + journal.MaybeAddEntry(s.jrnl, s.wdPoStEvtType, func() interface{} { return WindowPoStEvt{ State: "succeeded", Deadline: s.activeDeadline, @@ -148,7 +148,7 @@ func (s *WindowPoStScheduler) checkNextRecoveries(ctx context.Context, dlIdx uin Recoveries: []miner.RecoveryDeclaration{}, } - defer journal.MaybeAddEntry(s.jrnl, s.evtTypes[evtTypeWindowPoSt], func() interface{} { + defer journal.MaybeAddEntry(s.jrnl, s.wdPoStEvtType, func() interface{} { var mcid cid.Cid if sm != nil { mcid = sm.Cid() @@ -258,7 +258,7 @@ func (s *WindowPoStScheduler) checkNextFaults(ctx context.Context, dlIdx uint64, Faults: []miner.FaultDeclaration{}, } - defer journal.MaybeAddEntry(s.jrnl, s.evtTypes[evtTypeWindowPoSt], func() interface{} { + defer journal.MaybeAddEntry(s.jrnl, s.wdPoStEvtType, func() interface{} { var mcid cid.Cid if sm != nil { mcid = sm.Cid() @@ -519,7 +519,7 @@ func (s *WindowPoStScheduler) submitPost(ctx context.Context, proof *miner.Submi var sm *types.SignedMessage - defer journal.MaybeAddEntry(s.jrnl, s.evtTypes[evtTypeWindowPoSt], func() interface{} { + defer journal.MaybeAddEntry(s.jrnl, s.wdPoStEvtType, func() interface{} { var mcid cid.Cid if sm != nil { mcid = sm.Cid() diff --git a/storage/wdpost_sched.go b/storage/wdpost_sched.go index 83d37d24b..3bc591bb7 100644 --- a/storage/wdpost_sched.go +++ b/storage/wdpost_sched.go @@ -4,6 +4,7 @@ import ( "context" "time" + "github.com/ipfs/go-cid" "go.opencensus.io/trace" "golang.org/x/xerrors" @@ -22,10 +23,32 @@ import ( const StartConfidence = 4 // TODO: config -// Journal event types. -const ( - evtTypeWindowPoSt = iota -) +type WindowPoStEvt struct { + State string + Deadline *miner.DeadlineInfo + Height abi.ChainEpoch + TipSet []cid.Cid + Error error `json:",omitempty"` + + Proofs *WindowPoStEvt_Proofs `json:",omitempty"` + Recoveries *WindowPoStEvt_Recoveries `json:",omitempty"` + Faults *WindowPoStEvt_Faults `json:",omitempty"` +} + +type WindowPoStEvt_Proofs struct { + Partitions []miner.PoStPartition + MessageCID cid.Cid `json:",omitempty"` +} + +type WindowPoStEvt_Recoveries struct { + Declarations []miner.RecoveryDeclaration + MessageCID cid.Cid `json:",omitempty"` +} + +type WindowPoStEvt_Faults struct { + Declarations []miner.FaultDeclaration + MessageCID cid.Cid `json:",omitempty"` +} type WindowPoStScheduler struct { api storageMinerApi @@ -42,8 +65,9 @@ type WindowPoStScheduler struct { // if a post is in progress, this indicates for which ElectionPeriodStart activeDeadline *miner.DeadlineInfo abort context.CancelFunc - jrnl journal.Journal - evtTypes [1]journal.EventType + + jrnl journal.Journal + wdPoStEvtType journal.EventType // failed abi.ChainEpoch // eps // failLk sync.Mutex @@ -67,12 +91,10 @@ func NewWindowedPoStScheduler(api storageMinerApi, sb storage.Prover, ft sectors proofType: rt, partitionSectors: mi.WindowPoStPartitionSectors, - actor: actor, - worker: worker, - jrnl: jrnl, - evtTypes: [...]journal.EventType{ - evtTypeWindowPoSt: jrnl.RegisterEventType("storage", "wdpost"), - }, + actor: actor, + worker: worker, + jrnl: jrnl, + wdPoStEvtType: jrnl.RegisterEventType("storage", "wdpost"), }, nil } @@ -224,19 +246,19 @@ func (s *WindowPoStScheduler) abortActivePoSt() { if s.abort != nil { s.abort() + + journal.MaybeAddEntry(s.jrnl, s.wdPoStEvtType, func() interface{} { + return WindowPoStEvt{ + State: "abort", + Deadline: s.activeDeadline, + Height: s.cur.Height(), + TipSet: s.cur.Cids(), + } + }) + + log.Warnf("Aborting Window PoSt (Deadline: %+v)", s.activeDeadline) } - journal.MaybeAddEntry(s.jrnl, s.evtTypes[evtTypeWindowPoSt], func() interface{} { - return WindowPoStEvt{ - State: "abort", - Deadline: s.activeDeadline, - Height: s.cur.Height(), - TipSet: s.cur.Cids(), - } - }) - - log.Warnf("Aborting Window PoSt (Deadline: %+v)", s.activeDeadline) - s.activeDeadline = nil s.abort = nil } From 3bd9d55a156c5f43ecf44be24a7eb53435745edd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Tue, 21 Jul 2020 13:10:29 +0100 Subject: [PATCH 08/40] message pool: write message(s) in journal entries. --- chain/messagepool/messagepool.go | 33 ++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index 2f420b308..dcd7acf50 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -73,11 +73,17 @@ const ( evtTypeMpoolRepub ) -// MessagePoolEvt is the journal event type emitted by the MessagePool. +// MessagePoolEvt is the journal entry for message pool events. type MessagePoolEvt struct { - Action string - MessageCIDs []cid.Cid - Error error `json:",omitempty"` + Action string + Messages []MessagePoolEvt_Message + Error error `json:",omitempty"` +} + +type MessagePoolEvt_Message struct { + types.Message + + CID cid.Cid } type MessagePool struct { @@ -310,14 +316,14 @@ func (mp *MessagePool) repubLocal() { } journal.MaybeAddEntry(mp.jrnl, mp.evtTypes[evtTypeMpoolRepub], func() interface{} { - cids := make([]cid.Cid, 0, len(outputMsgs)) + msgs := make([]MessagePoolEvt_Message, 0, len(outputMsgs)) for _, m := range outputMsgs { - cids = append(cids, m.Cid()) + msgs = append(msgs, MessagePoolEvt_Message{Message: m.Message, CID: m.Cid()}) } return MessagePoolEvt{ - Action: "repub", - MessageCIDs: cids, - Error: errout, + Action: "repub", + Messages: msgs, + Error: errout, } }) @@ -488,8 +494,8 @@ func (mp *MessagePool) addLocked(m *types.SignedMessage) error { journal.MaybeAddEntry(mp.jrnl, mp.evtTypes[evtTypeMpoolAdd], func() interface{} { return MessagePoolEvt{ - Action: "add", - MessageCIDs: []cid.Cid{m.Cid()}, + Action: "add", + Messages: []MessagePoolEvt_Message{{Message: m.Message, CID: m.Cid()}}, } }) @@ -628,9 +634,8 @@ func (mp *MessagePool) Remove(from address.Address, nonce uint64) { journal.MaybeAddEntry(mp.jrnl, mp.evtTypes[evtTypeMpoolRemove], func() interface{} { return MessagePoolEvt{ - Action: "remove", - MessageCIDs: []cid.Cid{m.Cid()}, - } + Action: "remove", + Messages: []MessagePoolEvt_Message{{Message: m.Message, CID: m.Cid()}}} }) } From cb8e209f7806170fb48a8528934878a8815e7c62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Tue, 21 Jul 2020 13:13:09 +0100 Subject: [PATCH 09/40] journal: disable noisy message pool events. --- node/builder.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/node/builder.go b/node/builder.go index 98ae568da..a5933a272 100644 --- a/node/builder.go +++ b/node/builder.go @@ -153,7 +153,12 @@ func defaults() []Option { Override(new(dtypes.Bootstrapper), dtypes.Bootstrapper(false)), Override(new(dtypes.ShutdownChan), make(chan struct{})), Override(new(journal.Journal), journal.OpenFSJournal), - Override(new(journal.DisabledEvents), journal.DisabledEvents{}), + + // By default, disable noisy mpool events; keep only mpool:repub on. + Override(new(journal.DisabledEvents), journal.DisabledEvents{ + journal.EventType{System: "mpool", Event: "add"}, + journal.EventType{System: "mpool", Event: "remove"}, + }), Override(InitJournalKey, func(j journal.Journal) { /* forces the creation of the journal at startup */ }), // Filecoin modules From d547c2588c0b84f0660f1332aa9e0ae4f0509483 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Tue, 21 Jul 2020 17:26:44 +0100 Subject: [PATCH 10/40] record deals events in journal. --- markets/storageadapter/client.go | 26 +++++++++- markets/storageadapter/journal_events.go | 64 ++++++++++++++++++++++++ markets/storageadapter/provider.go | 49 ++++++++++++++++-- 3 files changed, 132 insertions(+), 7 deletions(-) create mode 100644 markets/storageadapter/journal_events.go diff --git a/markets/storageadapter/client.go b/markets/storageadapter/client.go index 2bb762e28..1da85fa69 100644 --- a/markets/storageadapter/client.go +++ b/markets/storageadapter/client.go @@ -7,6 +7,7 @@ import ( "context" "github.com/filecoin-project/lotus/chain/events/state" + "github.com/filecoin-project/lotus/journal" "golang.org/x/xerrors" @@ -43,6 +44,9 @@ type ClientNodeAdapter struct { cs *store.ChainStore fm *market.FundMgr ev *events.Events + + jrnl journal.Journal + evtTypes [4]journal.EventType } type clientApi struct { @@ -50,7 +54,7 @@ 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, sm *stmgr.StateManager, cs *store.ChainStore, fm *market.FundMgr, jrnl journal.Journal) storagemarket.StorageClientNode { return &ClientNodeAdapter{ StateAPI: state, ChainAPI: chain, @@ -60,6 +64,13 @@ func NewClientNodeAdapter(state full.StateAPI, chain full.ChainAPI, mpool full.M cs: cs, fm: fm, ev: events.NewEvents(context.TODO(), &clientApi{chain, state}), + + jrnl: jrnl, + evtTypes: [...]journal.EventType{ + evtTypeDealSectorCommitted: jrnl.RegisterEventType("markets:storage:client", "deal_sector_committed"), + evtTypeDealExpired: jrnl.RegisterEventType("markets:storage:client", "deal_expired"), + evtTypeDealSlashed: jrnl.RegisterEventType("markets:storage:client", "deal_slashed"), + }, } } @@ -235,7 +246,14 @@ func (c *ClientNodeAdapter) ValidatePublishedDeal(ctx context.Context, deal stor return 0, err } - return res.IDs[dealIdx], nil + dealID := res.IDs[dealIdx] + journal.MaybeAddEntry(c.jrnl, c.evtTypes[evtTypeDealAccepted], func() interface{} { + deal := deal // copy and strip fields we don't want to log to the journal + deal.ClientSignature = crypto.Signature{} + return ClientDealAcceptedEvt{ID: dealID, Deal: deal, Height: c.cs.GetHeaviestTipSet().Height()} + }) + + return dealID, nil } func (c *ClientNodeAdapter) OnDealSectorCommitted(ctx context.Context, provider address.Address, dealId abi.DealID, cb storagemarket.DealSectorCommittedCallback) error { @@ -278,6 +296,10 @@ func (c *ClientNodeAdapter) OnDealSectorCommitted(ctx context.Context, provider log.Infof("Storage deal %d activated at epoch %d", dealId, sd.State.SectorStartEpoch) + journal.MaybeAddEntry(c.jrnl, c.evtTypes[evtTypeDealSectorCommitted], func() interface{} { + return ClientDealSectorCommittedEvt{ID: dealId, State: sd.State, Height: curH} + }) + cb(nil) return false, nil diff --git a/markets/storageadapter/journal_events.go b/markets/storageadapter/journal_events.go new file mode 100644 index 000000000..6192738df --- /dev/null +++ b/markets/storageadapter/journal_events.go @@ -0,0 +1,64 @@ +package storageadapter + +import ( + "github.com/filecoin-project/go-fil-markets/storagemarket" + "github.com/filecoin-project/specs-actors/actors/abi" + "github.com/filecoin-project/specs-actors/actors/builtin/market" +) + +// Journal entry types emitted from this module. +const ( + evtTypeDealAccepted = iota + evtTypeDealSectorCommitted + evtTypeDealExpired + evtTypeDealSlashed +) + +type ClientDealAcceptedEvt struct { + ID abi.DealID + Deal storagemarket.ClientDeal + Height abi.ChainEpoch +} + +type ClientDealSectorCommittedEvt struct { + ID abi.DealID + State market.DealState + Height abi.ChainEpoch +} + +type ClientDealExpiredEvt struct { + ID abi.DealID + State market.DealState + Height abi.ChainEpoch +} + +type ClientDealSlashedEvt struct { + ID abi.DealID + State market.DealState + Height abi.ChainEpoch +} + +type MinerDealAcceptedEvt struct { + ID abi.DealID + Deal storagemarket.MinerDeal + State market.DealState + Height abi.ChainEpoch +} + +type MinerDealSectorCommittedEvt struct { + ID abi.DealID + State market.DealState + Height abi.ChainEpoch +} + +type MinerDealExpiredEvt struct { + ID abi.DealID + State market.DealState + Height abi.ChainEpoch +} + +type MinerDealSlashedEvt struct { + ID abi.DealID + State market.DealState + Height abi.ChainEpoch +} diff --git a/markets/storageadapter/provider.go b/markets/storageadapter/provider.go index 9e1a101cc..2aa9c45df 100644 --- a/markets/storageadapter/provider.go +++ b/markets/storageadapter/provider.go @@ -28,6 +28,7 @@ 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/journal" "github.com/filecoin-project/lotus/lib/sigs" "github.com/filecoin-project/lotus/markets/utils" "github.com/filecoin-project/lotus/node/modules/dtypes" @@ -45,14 +46,25 @@ type ProviderNodeAdapter struct { secb *sectorblocks.SectorBlocks ev *events.Events + + jrnl journal.Journal + evtTypes [4]journal.EventType } -func NewProviderNodeAdapter(dag dtypes.StagingDAG, secb *sectorblocks.SectorBlocks, full api.FullNode) storagemarket.StorageProviderNode { +func NewProviderNodeAdapter(dag dtypes.StagingDAG, secb *sectorblocks.SectorBlocks, full api.FullNode, jrnl journal.Journal) storagemarket.StorageProviderNode { return &ProviderNodeAdapter{ FullNode: full, dag: dag, secb: secb, ev: events.NewEvents(context.TODO(), full), + + jrnl: jrnl, + evtTypes: [...]journal.EventType{ + evtTypeDealAccepted: jrnl.RegisterEventType("markets:storage:provider", "deal_complete"), + evtTypeDealSectorCommitted: jrnl.RegisterEventType("markets:storage:provider", "deal_sector_committed"), + evtTypeDealExpired: jrnl.RegisterEventType("markets:storage:provider", "deal_expired"), + evtTypeDealSlashed: jrnl.RegisterEventType("markets:storage:provider", "deal_slashed"), + }, } } @@ -100,8 +112,15 @@ func (n *ProviderNodeAdapter) OnDealComplete(ctx context.Context, deal storagema if err != nil { return xerrors.Errorf("AddPiece failed: %s", err) } + log.Warnf("New Deal: deal %d", deal.DealID) + journal.MaybeAddEntry(n.jrnl, n.evtTypes[evtTypeDealAccepted], func() interface{} { + deal := deal // copy and strip fields we don't want to log to the journal + deal.ClientSignature = crypto.Signature{} + return MinerDealAcceptedEvt{ID: deal.DealID, Deal: deal} + }) + return nil } @@ -268,6 +287,10 @@ func (n *ProviderNodeAdapter) OnDealSectorCommitted(ctx context.Context, provide log.Infof("Storage deal %d activated at epoch %d", dealID, sd.State.SectorStartEpoch) + journal.MaybeAddEntry(n.jrnl, n.evtTypes[evtTypeDealSectorCommitted], func() interface{} { + return MinerDealSectorCommittedEvt{ID: dealID, State: sd.State, Height: curH} + }) + cb(nil) return false, nil @@ -369,15 +392,23 @@ func (n *ProviderNodeAdapter) OnDealExpiredOrSlashed(ctx context.Context, dealID // Called immediately to check if the deal has already expired or been slashed checkFunc := func(ts *types.TipSet) (done bool, more bool, err error) { + height := ts.Height() + // Check if the deal has already expired - if sd.Proposal.EndEpoch <= ts.Height() { + if sd.Proposal.EndEpoch <= height { onDealExpired(nil) + journal.MaybeAddEntry(n.jrnl, n.evtTypes[evtTypeDealExpired], func() interface{} { + return MinerDealExpiredEvt{ID: dealID, State: sd.State, Height: height} + }) return true, false, nil } // If there is no deal assume it's already been slashed if sd.State.SectorStartEpoch < 0 { - onDealSlashed(ts.Height(), nil) + onDealSlashed(height, nil) + journal.MaybeAddEntry(n.jrnl, n.evtTypes[evtTypeDealSlashed], func() interface{} { + return MinerDealSlashedEvt{ID: dealID, State: sd.State, Height: height} + }) return true, false, nil } @@ -389,9 +420,14 @@ func (n *ProviderNodeAdapter) OnDealExpiredOrSlashed(ctx context.Context, dealID // Called when there was a match against the state change we're looking for // and the chain has advanced to the confidence height stateChanged := func(ts *types.TipSet, ts2 *types.TipSet, states events.StateChange, h abi.ChainEpoch) (more bool, err error) { + height := ts2.Height() + // Check if the deal has already expired - if sd.Proposal.EndEpoch <= ts2.Height() { + if sd.Proposal.EndEpoch <= height { onDealExpired(nil) + journal.MaybeAddEntry(n.jrnl, n.evtTypes[evtTypeDealExpired], func() interface{} { + return MinerDealExpiredEvt{ID: dealID, State: sd.State, Height: height} + }) return false, nil } @@ -414,7 +450,10 @@ func (n *ProviderNodeAdapter) OnDealExpiredOrSlashed(ctx context.Context, dealID // Deal was slashed if deal.To == nil { - onDealSlashed(ts2.Height(), nil) + onDealSlashed(height, nil) + journal.MaybeAddEntry(n.jrnl, n.evtTypes[evtTypeDealSlashed], func() interface{} { + return MinerDealSlashedEvt{ID: dealID, State: sd.State, Height: height} + }) return false, nil } From 4e82cf369c92d2f611cb1c62832aac448ac32280 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Tue, 21 Jul 2020 17:32:01 +0100 Subject: [PATCH 11/40] rename journal entries to journal events. --- chain/messagepool/messagepool.go | 6 +++--- chain/store/store.go | 2 +- go.sum | 2 ++ journal/filesystem.go | 18 ++++++++-------- journal/memory.go | 34 +++++++++++++++--------------- journal/memory_test.go | 4 ++-- journal/nil.go | 2 +- journal/sugar.go | 10 ++++----- journal/types.go | 8 +++---- markets/storageadapter/client.go | 4 ++-- markets/storageadapter/provider.go | 12 +++++------ storage/miner.go | 2 +- storage/wdpost_run.go | 12 +++++------ storage/wdpost_sched.go | 2 +- 14 files changed, 60 insertions(+), 58 deletions(-) diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index dcd7acf50..28cf1b263 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -315,7 +315,7 @@ func (mp *MessagePool) repubLocal() { log.Errorf("errors while republishing: %+v", errout) } - journal.MaybeAddEntry(mp.jrnl, mp.evtTypes[evtTypeMpoolRepub], func() interface{} { + journal.MaybeRecordEvent(mp.jrnl, mp.evtTypes[evtTypeMpoolRepub], func() interface{} { msgs := make([]MessagePoolEvt_Message, 0, len(outputMsgs)) for _, m := range outputMsgs { msgs = append(msgs, MessagePoolEvt_Message{Message: m.Message, CID: m.Cid()}) @@ -492,7 +492,7 @@ func (mp *MessagePool) addLocked(m *types.SignedMessage) error { Message: m, }, localUpdates) - journal.MaybeAddEntry(mp.jrnl, mp.evtTypes[evtTypeMpoolAdd], func() interface{} { + journal.MaybeRecordEvent(mp.jrnl, mp.evtTypes[evtTypeMpoolAdd], func() interface{} { return MessagePoolEvt{ Action: "add", Messages: []MessagePoolEvt_Message{{Message: m.Message, CID: m.Cid()}}, @@ -632,7 +632,7 @@ func (mp *MessagePool) Remove(from address.Address, nonce uint64) { Message: m, }, localUpdates) - journal.MaybeAddEntry(mp.jrnl, mp.evtTypes[evtTypeMpoolRemove], func() interface{} { + journal.MaybeRecordEvent(mp.jrnl, mp.evtTypes[evtTypeMpoolRemove], func() interface{} { return MessagePoolEvt{ Action: "remove", Messages: []MessagePoolEvt_Message{{Message: m.Message, CID: m.Cid()}}} diff --git a/chain/store/store.go b/chain/store/store.go index ba7a54ed3..07ac57ac4 100644 --- a/chain/store/store.go +++ b/chain/store/store.go @@ -348,7 +348,7 @@ func (cs *ChainStore) reorgWorker(ctx context.Context, initialNotifees []ReorgNo continue } - journal.MaybeAddEntry(cs.journal, cs.evtTypes[evtTypeHeadChange], func() interface{} { + journal.MaybeRecordEvent(cs.journal, cs.evtTypes[evtTypeHeadChange], func() interface{} { return HeadChangeEvt{ From: r.old.Key(), FromHeight: r.old.Height(), diff --git a/go.sum b/go.sum index 0ffae068c..4d99d3d46 100644 --- a/go.sum +++ b/go.sum @@ -82,6 +82,7 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.32.11 h1:1nYF+Tfccn/hnAZsuwPPMSCVUVnx3j6LKOpx/WhgH0A= github.com/aws/aws-sdk-go v1.32.11/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg= @@ -656,6 +657,7 @@ github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc= github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8l6qbCUTSiRLG/iKnW3K3/QfPPuSsBt4= github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak= diff --git a/journal/filesystem.go b/journal/filesystem.go index 7aa470a2e..0f953b4e2 100644 --- a/journal/filesystem.go +++ b/journal/filesystem.go @@ -30,7 +30,7 @@ type fsJournal struct { fi *os.File fSize int64 - incoming chan *Entry + incoming chan *Event closing chan struct{} } @@ -47,7 +47,7 @@ func OpenFSJournal(lr repo.LockedRepo, lc fx.Lifecycle, disabled DisabledEvents) eventTypeFactory: newEventTypeFactory(disabled), dir: dir, sizeLimit: 1 << 30, - incoming: make(chan *Entry, 32), + incoming: make(chan *Event, 32), closing: make(chan struct{}), } @@ -64,8 +64,8 @@ func OpenFSJournal(lr repo.LockedRepo, lc fx.Lifecycle, disabled DisabledEvents) return f, nil } -func (f *fsJournal) AddEntry(evtType EventType, obj interface{}) { - je := &Entry{ +func (f *fsJournal) RecordEvent(evtType EventType, obj interface{}) { + je := &Event{ EventType: evtType, Timestamp: build.Clock.Now(), Data: obj, @@ -73,7 +73,7 @@ func (f *fsJournal) AddEntry(evtType EventType, obj interface{}) { select { case f.incoming <- je: case <-f.closing: - log.Warnw("journal closed but tried to log event", "entry", je) + log.Warnw("journal closed but tried to log event", "event", je) } } @@ -82,8 +82,8 @@ func (f *fsJournal) Close() error { return nil } -func (f *fsJournal) putEntry(je *Entry) error { - b, err := json.Marshal(je) +func (f *fsJournal) putEvent(evt *Event) error { + b, err := json.Marshal(evt) if err != nil { return err } @@ -120,8 +120,8 @@ func (f *fsJournal) runLoop() { for { select { case je := <-f.incoming: - if err := f.putEntry(je); err != nil { - log.Errorw("failed to write out journal entry", "entry", je, "err", err) + if err := f.putEvent(je); err != nil { + log.Errorw("failed to write out journal event", "event", je, "err", err) } case <-f.closing: _ = f.fi.Close() diff --git a/journal/memory.go b/journal/memory.go index 5471d3e11..6676b9696 100644 --- a/journal/memory.go +++ b/journal/memory.go @@ -17,17 +17,17 @@ type ( replay bool } rmObserverCtrl *observer - getEntriesCtrl chan []*Entry + getEntriesCtrl chan []*Event ) type MemJournal struct { *eventTypeFactory - entries []*Entry - index map[string]map[string][]*Entry + entries []*Event + index map[string]map[string][]*Event observers []observer - incomingCh chan *Entry + incomingCh chan *Event controlCh chan interface{} state int32 // guarded by atomic; 0=closed, 1=running. @@ -38,10 +38,10 @@ var _ Journal = (*MemJournal)(nil) type observer struct { accept map[EventType]struct{} - ch chan *Entry + ch chan *Event } -func (o *observer) dispatch(entry *Entry) { +func (o *observer) dispatch(entry *Event) { if o.accept == nil { o.ch <- entry } @@ -54,9 +54,9 @@ func NewMemoryJournal(lc fx.Lifecycle, disabled DisabledEvents) *MemJournal { m := &MemJournal{ eventTypeFactory: newEventTypeFactory(disabled), - index: make(map[string]map[string][]*Entry, 16), + index: make(map[string]map[string][]*Event, 16), observers: make([]observer, 0, 16), - incomingCh: make(chan *Entry, 256), + incomingCh: make(chan *Event, 256), controlCh: make(chan interface{}, 16), state: 1, closed: make(chan struct{}), @@ -71,13 +71,13 @@ func NewMemoryJournal(lc fx.Lifecycle, disabled DisabledEvents) *MemJournal { return m } -func (m *MemJournal) AddEntry(evtType EventType, obj interface{}) { +func (m *MemJournal) RecordEvent(evtType EventType, obj interface{}) { if !evtType.enabled || !evtType.safe { // tried to record a disabled event type, or used an invalid EventType. return } - entry := &Entry{ + entry := &Event{ EventType: evtType, Timestamp: build.Clock.Now(), Data: obj, @@ -111,7 +111,7 @@ func (m *MemJournal) Clear() { // be replayed. To restrict the event types this observer will sent, use the // include argument. If no include set is passed, the observer will receive all // events types. -func (m *MemJournal) Observe(ctx context.Context, replay bool, include ...EventType) <-chan *Entry { +func (m *MemJournal) Observe(ctx context.Context, replay bool, include ...EventType) <-chan *Event { var acc map[EventType]struct{} if include != nil { acc = make(map[EventType]struct{}, len(include)) @@ -124,7 +124,7 @@ func (m *MemJournal) Observe(ctx context.Context, replay bool, include ...EventT } } - ch := make(chan *Entry, 256) + ch := make(chan *Event, 256) o := &observer{ accept: acc, ch: ch, @@ -151,8 +151,8 @@ func (m *MemJournal) Observe(ctx context.Context, replay bool, include ...EventT } // Entries gets a snapshot of stored entries. -func (m *MemJournal) Entries() []*Entry { - ch := make(chan []*Entry) +func (m *MemJournal) Entries() []*Event { + ch := make(chan []*Event) m.controlCh <- getEntriesCtrl(ch) return <-ch } @@ -191,7 +191,7 @@ func (m *MemJournal) process() { } } case getEntriesCtrl: - cpy := make([]*Entry, len(m.entries)) + cpy := make([]*Event, len(m.entries)) copy(cpy, m.entries) msg <- cpy close(msg) @@ -200,7 +200,7 @@ func (m *MemJournal) process() { processClose := func() { m.entries = nil - m.index = make(map[string]map[string][]*Entry, 16) + m.index = make(map[string]map[string][]*Event, 16) for _, o := range m.observers { close(o.ch) } @@ -225,7 +225,7 @@ func (m *MemJournal) process() { m.entries = append(m.entries, entry) events := m.index[entry.System] if events == nil { - events = make(map[string][]*Entry, 16) + events = make(map[string][]*Event, 16) m.index[entry.System] = events } diff --git a/journal/memory_test.go b/journal/memory_test.go index 442a7f46d..db38085e3 100644 --- a/journal/memory_test.go +++ b/journal/memory_test.go @@ -71,7 +71,7 @@ func TestMemJournal_Close(t *testing.T) { time.Sleep(500 * time.Millisecond) NextChannel: - for _, ch := range []<-chan *Entry{o1, o2, o3} { + for _, ch := range []<-chan *Event{o1, o2, o3} { for { select { case _, more := <-ch: @@ -171,7 +171,7 @@ func addEntries(journal *MemJournal, count int) { // RegisterEventType is not _really_ intended to be used this way (on every write). et := journal.RegisterEventType("spaceship", fmt.Sprintf("wheezing-%d", eventIdx)) - journal.AddEntry(et, HeadChangeEvt{ + journal.RecordEvent(et, HeadChangeEvt{ From: types.TipSetKey{}, FromHeight: abi.ChainEpoch(i), To: types.TipSetKey{}, diff --git a/journal/nil.go b/journal/nil.go index 0123fe585..5d0c78b05 100644 --- a/journal/nil.go +++ b/journal/nil.go @@ -11,6 +11,6 @@ func NilJournal() Journal { func (n *nilJournal) RegisterEventType(_, _ string) EventType { return EventType{} } -func (n *nilJournal) AddEntry(_ EventType, _ interface{}) {} +func (n *nilJournal) RecordEvent(_ EventType, _ interface{}) {} func (n *nilJournal) Close() error { return nil } diff --git a/journal/sugar.go b/journal/sugar.go index 9ee59f2c7..069434916 100644 --- a/journal/sugar.go +++ b/journal/sugar.go @@ -1,17 +1,17 @@ package journal -// MaybeAddEntry is a convenience function that evaluates if the EventType is -// enabled, and if so, it calls the supplier to create the entry and -// subsequently journal.AddEntry on the provided journal to record it. +// MaybeRecordEvent is a convenience function that evaluates if the EventType is +// enabled, and if so, it calls the supplier to create the event and +// subsequently journal.RecordEvent on the provided journal to record it. // // This is safe to call with a nil Journal, either because the value is nil, // or because a journal obtained through NilJournal() is in use. -func MaybeAddEntry(journal Journal, evtType EventType, supplier func() interface{}) { +func MaybeRecordEvent(journal Journal, evtType EventType, supplier func() interface{}) { if journal == nil || journal == nilj { return } if !evtType.Enabled() { return } - journal.AddEntry(evtType, supplier()) + journal.RecordEvent(evtType, supplier()) } diff --git a/journal/types.go b/journal/types.go index 95349b24e..b1c36b515 100644 --- a/journal/types.go +++ b/journal/types.go @@ -47,18 +47,18 @@ type Journal interface { // entries appropriately. RegisterEventType(system, event string) EventType - // AddEntry adds an entry to this journal. See godocs on the Journal type + // RecordEvent records this event to the journal. See godocs on the Journal type // for more info. - AddEntry(evtType EventType, data interface{}) + RecordEvent(evtType EventType, data interface{}) // Close closes this journal for further writing. Close() error } -// Entry represents a journal entry. +// Event represents a journal entry. // // See godocs on Journal for more information. -type Entry struct { +type Event struct { EventType Timestamp time.Time diff --git a/markets/storageadapter/client.go b/markets/storageadapter/client.go index 1da85fa69..925a0a271 100644 --- a/markets/storageadapter/client.go +++ b/markets/storageadapter/client.go @@ -247,7 +247,7 @@ func (c *ClientNodeAdapter) ValidatePublishedDeal(ctx context.Context, deal stor } dealID := res.IDs[dealIdx] - journal.MaybeAddEntry(c.jrnl, c.evtTypes[evtTypeDealAccepted], func() interface{} { + journal.MaybeRecordEvent(c.jrnl, c.evtTypes[evtTypeDealAccepted], func() interface{} { deal := deal // copy and strip fields we don't want to log to the journal deal.ClientSignature = crypto.Signature{} return ClientDealAcceptedEvt{ID: dealID, Deal: deal, Height: c.cs.GetHeaviestTipSet().Height()} @@ -296,7 +296,7 @@ func (c *ClientNodeAdapter) OnDealSectorCommitted(ctx context.Context, provider log.Infof("Storage deal %d activated at epoch %d", dealId, sd.State.SectorStartEpoch) - journal.MaybeAddEntry(c.jrnl, c.evtTypes[evtTypeDealSectorCommitted], func() interface{} { + journal.MaybeRecordEvent(c.jrnl, c.evtTypes[evtTypeDealSectorCommitted], func() interface{} { return ClientDealSectorCommittedEvt{ID: dealId, State: sd.State, Height: curH} }) diff --git a/markets/storageadapter/provider.go b/markets/storageadapter/provider.go index 2aa9c45df..0b877cf6e 100644 --- a/markets/storageadapter/provider.go +++ b/markets/storageadapter/provider.go @@ -115,7 +115,7 @@ func (n *ProviderNodeAdapter) OnDealComplete(ctx context.Context, deal storagema log.Warnf("New Deal: deal %d", deal.DealID) - journal.MaybeAddEntry(n.jrnl, n.evtTypes[evtTypeDealAccepted], func() interface{} { + journal.MaybeRecordEvent(n.jrnl, n.evtTypes[evtTypeDealAccepted], func() interface{} { deal := deal // copy and strip fields we don't want to log to the journal deal.ClientSignature = crypto.Signature{} return MinerDealAcceptedEvt{ID: deal.DealID, Deal: deal} @@ -287,7 +287,7 @@ func (n *ProviderNodeAdapter) OnDealSectorCommitted(ctx context.Context, provide log.Infof("Storage deal %d activated at epoch %d", dealID, sd.State.SectorStartEpoch) - journal.MaybeAddEntry(n.jrnl, n.evtTypes[evtTypeDealSectorCommitted], func() interface{} { + journal.MaybeRecordEvent(n.jrnl, n.evtTypes[evtTypeDealSectorCommitted], func() interface{} { return MinerDealSectorCommittedEvt{ID: dealID, State: sd.State, Height: curH} }) @@ -397,7 +397,7 @@ func (n *ProviderNodeAdapter) OnDealExpiredOrSlashed(ctx context.Context, dealID // Check if the deal has already expired if sd.Proposal.EndEpoch <= height { onDealExpired(nil) - journal.MaybeAddEntry(n.jrnl, n.evtTypes[evtTypeDealExpired], func() interface{} { + journal.MaybeRecordEvent(n.jrnl, n.evtTypes[evtTypeDealExpired], func() interface{} { return MinerDealExpiredEvt{ID: dealID, State: sd.State, Height: height} }) return true, false, nil @@ -406,7 +406,7 @@ func (n *ProviderNodeAdapter) OnDealExpiredOrSlashed(ctx context.Context, dealID // If there is no deal assume it's already been slashed if sd.State.SectorStartEpoch < 0 { onDealSlashed(height, nil) - journal.MaybeAddEntry(n.jrnl, n.evtTypes[evtTypeDealSlashed], func() interface{} { + journal.MaybeRecordEvent(n.jrnl, n.evtTypes[evtTypeDealSlashed], func() interface{} { return MinerDealSlashedEvt{ID: dealID, State: sd.State, Height: height} }) return true, false, nil @@ -425,7 +425,7 @@ func (n *ProviderNodeAdapter) OnDealExpiredOrSlashed(ctx context.Context, dealID // Check if the deal has already expired if sd.Proposal.EndEpoch <= height { onDealExpired(nil) - journal.MaybeAddEntry(n.jrnl, n.evtTypes[evtTypeDealExpired], func() interface{} { + journal.MaybeRecordEvent(n.jrnl, n.evtTypes[evtTypeDealExpired], func() interface{} { return MinerDealExpiredEvt{ID: dealID, State: sd.State, Height: height} }) return false, nil @@ -451,7 +451,7 @@ func (n *ProviderNodeAdapter) OnDealExpiredOrSlashed(ctx context.Context, dealID // Deal was slashed if deal.To == nil { onDealSlashed(height, nil) - journal.MaybeAddEntry(n.jrnl, n.evtTypes[evtTypeDealSlashed], func() interface{} { + journal.MaybeRecordEvent(n.jrnl, n.evtTypes[evtTypeDealSlashed], func() interface{} { return MinerDealSlashedEvt{ID: dealID, State: sd.State, Height: height} }) return false, nil diff --git a/storage/miner.go b/storage/miner.go index 6f16b9cfe..499509b25 100644 --- a/storage/miner.go +++ b/storage/miner.go @@ -134,7 +134,7 @@ func (m *Miner) Run(ctx context.Context) error { } func (m *Miner) handleSealingNotifications(before, after sealing.SectorInfo) { - journal.MaybeAddEntry(m.jrnl, m.sealingEvtType, func() interface{} { + journal.MaybeRecordEvent(m.jrnl, m.sealingEvtType, func() interface{} { return SealingStateEvt{ SectorNumber: before.SectorNumber, SectorType: before.SectorType, diff --git a/storage/wdpost_run.go b/storage/wdpost_run.go index 191ac5319..c6aedc068 100644 --- a/storage/wdpost_run.go +++ b/storage/wdpost_run.go @@ -27,7 +27,7 @@ import ( var errNoPartitions = errors.New("no partitions") func (s *WindowPoStScheduler) failPost(err error, deadline *miner.DeadlineInfo) { - journal.MaybeAddEntry(s.jrnl, s.wdPoStEvtType, func() interface{} { + journal.MaybeRecordEvent(s.jrnl, s.wdPoStEvtType, func() interface{} { return WindowPoStEvt{ State: "failed", Deadline: s.activeDeadline, @@ -51,7 +51,7 @@ func (s *WindowPoStScheduler) doPost(ctx context.Context, deadline *miner.Deadli s.abort = abort s.activeDeadline = deadline - journal.MaybeAddEntry(s.jrnl, s.wdPoStEvtType, func() interface{} { + journal.MaybeRecordEvent(s.jrnl, s.wdPoStEvtType, func() interface{} { return WindowPoStEvt{ State: "started", Deadline: s.activeDeadline, @@ -82,7 +82,7 @@ func (s *WindowPoStScheduler) doPost(ctx context.Context, deadline *miner.Deadli return } - journal.MaybeAddEntry(s.jrnl, s.wdPoStEvtType, func() interface{} { + journal.MaybeRecordEvent(s.jrnl, s.wdPoStEvtType, func() interface{} { return WindowPoStEvt{ State: "succeeded", Deadline: s.activeDeadline, @@ -148,7 +148,7 @@ func (s *WindowPoStScheduler) checkNextRecoveries(ctx context.Context, dlIdx uin Recoveries: []miner.RecoveryDeclaration{}, } - defer journal.MaybeAddEntry(s.jrnl, s.wdPoStEvtType, func() interface{} { + defer journal.MaybeRecordEvent(s.jrnl, s.wdPoStEvtType, func() interface{} { var mcid cid.Cid if sm != nil { mcid = sm.Cid() @@ -258,7 +258,7 @@ func (s *WindowPoStScheduler) checkNextFaults(ctx context.Context, dlIdx uint64, Faults: []miner.FaultDeclaration{}, } - defer journal.MaybeAddEntry(s.jrnl, s.wdPoStEvtType, func() interface{} { + defer journal.MaybeRecordEvent(s.jrnl, s.wdPoStEvtType, func() interface{} { var mcid cid.Cid if sm != nil { mcid = sm.Cid() @@ -519,7 +519,7 @@ func (s *WindowPoStScheduler) submitPost(ctx context.Context, proof *miner.Submi var sm *types.SignedMessage - defer journal.MaybeAddEntry(s.jrnl, s.wdPoStEvtType, func() interface{} { + defer journal.MaybeRecordEvent(s.jrnl, s.wdPoStEvtType, func() interface{} { var mcid cid.Cid if sm != nil { mcid = sm.Cid() diff --git a/storage/wdpost_sched.go b/storage/wdpost_sched.go index 3bc591bb7..8344097dc 100644 --- a/storage/wdpost_sched.go +++ b/storage/wdpost_sched.go @@ -247,7 +247,7 @@ func (s *WindowPoStScheduler) abortActivePoSt() { if s.abort != nil { s.abort() - journal.MaybeAddEntry(s.jrnl, s.wdPoStEvtType, func() interface{} { + journal.MaybeRecordEvent(s.jrnl, s.wdPoStEvtType, func() interface{} { return WindowPoStEvt{ State: "abort", Deadline: s.activeDeadline, From 443473f8338effeaa3e1f8c0f7005012b558083c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Tue, 21 Jul 2020 17:37:06 +0100 Subject: [PATCH 12/40] fix tests. --- chain/messagepool/messagepool_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/chain/messagepool/messagepool_test.go b/chain/messagepool/messagepool_test.go index 64af26e9a..b1787f8d6 100644 --- a/chain/messagepool/messagepool_test.go +++ b/chain/messagepool/messagepool_test.go @@ -9,6 +9,7 @@ import ( "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/journal" _ "github.com/filecoin-project/lotus/lib/sigs/bls" _ "github.com/filecoin-project/lotus/lib/sigs/secp" "github.com/filecoin-project/specs-actors/actors/crypto" @@ -147,7 +148,7 @@ func TestMessagePool(t *testing.T) { ds := datastore.NewMapDatastore() - mp, err := New(tma, ds, "mptest", nil) + mp, err := New(tma, ds, "mptest", journal.NilJournal()) if err != nil { t.Fatal(err) } @@ -188,7 +189,7 @@ func TestRevertMessages(t *testing.T) { ds := datastore.NewMapDatastore() - mp, err := New(tma, ds, "mptest", nil) + mp, err := New(tma, ds, "mptest", journal.NilJournal()) if err != nil { t.Fatal(err) } From 5074ce5a38986ac517c00fc2c022aa2dcf01dd4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Mon, 10 Aug 2020 15:02:15 +0100 Subject: [PATCH 13/40] move in-mem journal to Project Oni. --- journal/{filesystem.go => fs.go} | 4 +- journal/memory.go | 248 ------------------------------- journal/memory_test.go | 183 ----------------------- journal/sugar.go | 17 --- journal/types.go | 38 ++++- 5 files changed, 33 insertions(+), 457 deletions(-) rename journal/{filesystem.go => fs.go} (97%) delete mode 100644 journal/memory.go delete mode 100644 journal/memory_test.go delete mode 100644 journal/sugar.go diff --git a/journal/filesystem.go b/journal/fs.go similarity index 97% rename from journal/filesystem.go rename to journal/fs.go index 0f953b4e2..096f5f1fd 100644 --- a/journal/filesystem.go +++ b/journal/fs.go @@ -21,7 +21,7 @@ var log = logging.Logger("journal") // fsJournal is a basic journal backed by files on a filesystem. type fsJournal struct { - *eventTypeFactory + EventTypeFactory dir string sizeLimit int64 @@ -44,7 +44,7 @@ func OpenFSJournal(lr repo.LockedRepo, lc fx.Lifecycle, disabled DisabledEvents) } f := &fsJournal{ - eventTypeFactory: newEventTypeFactory(disabled), + EventTypeFactory: NewEventTypeFactory(disabled), dir: dir, sizeLimit: 1 << 30, incoming: make(chan *Event, 32), diff --git a/journal/memory.go b/journal/memory.go deleted file mode 100644 index 6676b9696..000000000 --- a/journal/memory.go +++ /dev/null @@ -1,248 +0,0 @@ -package journal - -import ( - "context" - "sync/atomic" - - "go.uber.org/fx" - - "github.com/filecoin-project/lotus/build" -) - -// Control messages. -type ( - clearCtrl struct{} - addObserverCtrl struct { - observer *observer - replay bool - } - rmObserverCtrl *observer - getEntriesCtrl chan []*Event -) - -type MemJournal struct { - *eventTypeFactory - - entries []*Event - index map[string]map[string][]*Event - observers []observer - - incomingCh chan *Event - controlCh chan interface{} - - state int32 // guarded by atomic; 0=closed, 1=running. - closed chan struct{} -} - -var _ Journal = (*MemJournal)(nil) - -type observer struct { - accept map[EventType]struct{} - ch chan *Event -} - -func (o *observer) dispatch(entry *Event) { - if o.accept == nil { - o.ch <- entry - } - if _, ok := o.accept[entry.EventType]; ok { - o.ch <- entry - } -} - -func NewMemoryJournal(lc fx.Lifecycle, disabled DisabledEvents) *MemJournal { - m := &MemJournal{ - eventTypeFactory: newEventTypeFactory(disabled), - - index: make(map[string]map[string][]*Event, 16), - observers: make([]observer, 0, 16), - incomingCh: make(chan *Event, 256), - controlCh: make(chan interface{}, 16), - state: 1, - closed: make(chan struct{}), - } - - lc.Append(fx.Hook{ - OnStop: func(_ context.Context) error { return m.Close() }, - }) - - go m.process() - - return m -} - -func (m *MemJournal) RecordEvent(evtType EventType, obj interface{}) { - if !evtType.enabled || !evtType.safe { - // tried to record a disabled event type, or used an invalid EventType. - return - } - - entry := &Event{ - EventType: evtType, - Timestamp: build.Clock.Now(), - Data: obj, - } - - select { - case m.incomingCh <- entry: - case <-m.closed: - } -} - -func (m *MemJournal) Close() error { - if !atomic.CompareAndSwapInt32(&m.state, 1, 0) { - // already closed. - return nil - } - close(m.closed) - return nil -} - -func (m *MemJournal) Clear() { - select { - case m.controlCh <- clearCtrl{}: - case <-m.closed: - } -} - -// Observe starts observing events that are recorded in the MemJournal, and -// returns a channel where new events will be sent. When replay is true, all -// entries that have been recorded prior to the observer being registered will -// be replayed. To restrict the event types this observer will sent, use the -// include argument. If no include set is passed, the observer will receive all -// events types. -func (m *MemJournal) Observe(ctx context.Context, replay bool, include ...EventType) <-chan *Event { - var acc map[EventType]struct{} - if include != nil { - acc = make(map[EventType]struct{}, len(include)) - for _, et := range include { - if !et.enabled { - // skip over disabled event type. - continue - } - acc[et] = struct{}{} - } - } - - ch := make(chan *Event, 256) - o := &observer{ - accept: acc, - ch: ch, - } - - // watch the context, and fire the "remove observer" control message upon - // cancellation. - go func() { - <-ctx.Done() - select { - case m.controlCh <- rmObserverCtrl(o): - case <-m.closed: - } - }() - - select { - case m.controlCh <- addObserverCtrl{o, replay}: - case <-m.closed: - // we are already stopped. - close(ch) - } - - return ch -} - -// Entries gets a snapshot of stored entries. -func (m *MemJournal) Entries() []*Event { - ch := make(chan []*Event) - m.controlCh <- getEntriesCtrl(ch) - return <-ch -} - -func (m *MemJournal) process() { - processCtrlMsg := func(message interface{}) { - switch msg := message.(type) { - case addObserverCtrl: - // adding an observer. - m.observers = append(m.observers, *msg.observer) - - if msg.replay { - // replay all existing entries. - for _, e := range m.entries { - msg.observer.dispatch(e) - } - } - case rmObserverCtrl: - // removing an observer; find the observer, close its channel. - // then discard it from our list by replacing it with the last - // observer and reslicing. - for i, o := range m.observers { - if o.ch == msg.ch { - close(o.ch) - m.observers[i] = m.observers[len(m.observers)-1] - m.observers = m.observers[:len(m.observers)-1] - } - } - case clearCtrl: - m.entries = m.entries[0:0] - // carry over system and event names; there are unlikely to change; - // just reslice the entry slices, so we are not thrashing memory. - for _, events := range m.index { - for ev := range events { - events[ev] = events[ev][0:0] - } - } - case getEntriesCtrl: - cpy := make([]*Event, len(m.entries)) - copy(cpy, m.entries) - msg <- cpy - close(msg) - } - } - - processClose := func() { - m.entries = nil - m.index = make(map[string]map[string][]*Event, 16) - for _, o := range m.observers { - close(o.ch) - } - m.observers = nil - } - - for { - // Drain all control messages first! - select { - case msg := <-m.controlCh: - processCtrlMsg(msg) - continue - case <-m.closed: - processClose() - return - default: - } - - // Now consume and pipe messages. - select { - case entry := <-m.incomingCh: - m.entries = append(m.entries, entry) - events := m.index[entry.System] - if events == nil { - events = make(map[string][]*Event, 16) - m.index[entry.System] = events - } - - entries := events[entry.Event] - events[entry.Event] = append(entries, entry) - - for _, o := range m.observers { - o.dispatch(entry) - } - - case msg := <-m.controlCh: - processCtrlMsg(msg) - continue - - case <-m.closed: - processClose() - return - } - } -} diff --git a/journal/memory_test.go b/journal/memory_test.go deleted file mode 100644 index db38085e3..000000000 --- a/journal/memory_test.go +++ /dev/null @@ -1,183 +0,0 @@ -package journal - -import ( - "context" - "fmt" - "testing" - "time" - - "github.com/filecoin-project/lotus/build" - "github.com/filecoin-project/lotus/chain/types" - - "github.com/filecoin-project/specs-actors/actors/abi" - - "github.com/raulk/clock" - "github.com/stretchr/testify/require" - "go.uber.org/fx/fxtest" -) - -func TestMemJournal_AddEntry(t *testing.T) { - lc := fxtest.NewLifecycle(t) - defer lc.RequireStop() - - clk := clock.NewMock() - build.Clock = clk - - journal := NewMemoryJournal(lc, nil) - addEntries(journal, 100) - - require.Eventually(t, func() bool { return len(journal.Entries()) == 100 }, 1*time.Second, 100*time.Millisecond) - - entries := journal.Entries() - cnt := make(map[string]int, 10) - for i, e := range entries { - require.EqualValues(t, "spaceship", e.System) - require.Equal(t, HeadChangeEvt{ - From: types.TipSetKey{}, - FromHeight: abi.ChainEpoch(i), - To: types.TipSetKey{}, - ToHeight: abi.ChainEpoch(i), - RevertCount: i, - ApplyCount: i, - }, e.Data) - require.Equal(t, build.Clock.Now(), e.Timestamp) - cnt[e.Event]++ - } - - // we received 10 entries of each event type. - for _, c := range cnt { - require.Equal(t, 10, c) - } -} - -func TestMemJournal_Close(t *testing.T) { - lc := fxtest.NewLifecycle(t) - defer lc.RequireStop() - - journal := NewMemoryJournal(lc, nil) - addEntries(journal, 100) - - require.Eventually(t, func() bool { return len(journal.Entries()) == 100 }, 1*time.Second, 100*time.Millisecond) - - o1 := journal.Observe(context.TODO(), false) - o2 := journal.Observe(context.TODO(), false) - o3 := journal.Observe(context.TODO(), false) - - time.Sleep(500 * time.Millisecond) - - // Close the journal. - require.NoError(t, journal.Close()) - - time.Sleep(500 * time.Millisecond) - -NextChannel: - for _, ch := range []<-chan *Event{o1, o2, o3} { - for { - select { - case _, more := <-ch: - if more { - // keep consuming - } else { - continue NextChannel - } - default: - t.Fatal("nothing more to consume, and channel is not closed") - } - } - } -} - -func TestMemJournal_Clear(t *testing.T) { - lc := fxtest.NewLifecycle(t) - defer lc.RequireStop() - - journal := NewMemoryJournal(lc, nil) - addEntries(journal, 100) - - require.Eventually(t, func() bool { return len(journal.Entries()) == 100 }, 1*time.Second, 100*time.Millisecond) - - journal.Clear() - require.Empty(t, journal.Entries()) - require.Empty(t, journal.Entries()) - require.Empty(t, journal.Entries()) -} - -func TestMemJournal_Observe(t *testing.T) { - lc := fxtest.NewLifecycle(t) - defer lc.RequireStop() - - journal := NewMemoryJournal(lc, nil) - addEntries(journal, 100) - - require.Eventually(t, func() bool { return len(journal.Entries()) == 100 }, 1*time.Second, 100*time.Millisecond) - - et1 := journal.RegisterEventType("spaceship", "wheezing-1") - et2 := journal.RegisterEventType("spaceship", "wheezing-2") - - o1 := journal.Observe(context.TODO(), false, et1) - o2 := journal.Observe(context.TODO(), true, et1, et2) - o3 := journal.Observe(context.TODO(), true) - - time.Sleep(1 * time.Second) - - require.Len(t, o1, 0) // no replay - require.Len(t, o2, 20) // replay with include set - require.Len(t, o3, 100) // replay with no include set (all entries) - - // add another 100 entries and assert what the observers have seen. - addEntries(journal, 100) - - require.Eventually(t, func() bool { return len(journal.Entries()) == 200 }, 1*time.Second, 100*time.Millisecond) - - // note: we're able to queue items because the observer channel buffer size is 256. - require.Len(t, o1, 10) // should have 0 old entries + 10 new entries - require.Len(t, o2, 40) // should have 20 old entries + 20 new entries - require.Len(t, o3, 200) // should have 100 old entries + 100 new entries -} - -func TestMemJournal_ObserverCancellation(t *testing.T) { - lc := fxtest.NewLifecycle(t) - defer lc.RequireStop() - - journal := NewMemoryJournal(lc, nil) - - ctx, cancel := context.WithCancel(context.TODO()) - o1 := journal.Observe(ctx, false) - o2 := journal.Observe(context.TODO(), false) - addEntries(journal, 100) - - require.Eventually(t, func() bool { return len(journal.Entries()) == 100 }, 1*time.Second, 100*time.Millisecond) - - // all observers have received the 100 entries. - require.Len(t, o1, 100) - require.Len(t, o2, 100) - - // cancel o1's context. - cancel() - time.Sleep(500 * time.Millisecond) - - // add 50 new entries - addEntries(journal, 50) - - require.Eventually(t, func() bool { return len(journal.Entries()) == 150 }, 1*time.Second, 100*time.Millisecond) - - require.Len(t, o1, 100) // has not moved. - require.Len(t, o2, 150) // should have 100 old entries + 50 new entries -} - -func addEntries(journal *MemJournal, count int) { - for i := 0; i < count; i++ { - eventIdx := i % 10 - - // RegisterEventType is not _really_ intended to be used this way (on every write). - et := journal.RegisterEventType("spaceship", fmt.Sprintf("wheezing-%d", eventIdx)) - journal.RecordEvent(et, HeadChangeEvt{ - From: types.TipSetKey{}, - FromHeight: abi.ChainEpoch(i), - To: types.TipSetKey{}, - ToHeight: abi.ChainEpoch(i), - RevertCount: i, - ApplyCount: i, - }) - } -} diff --git a/journal/sugar.go b/journal/sugar.go deleted file mode 100644 index 069434916..000000000 --- a/journal/sugar.go +++ /dev/null @@ -1,17 +0,0 @@ -package journal - -// MaybeRecordEvent is a convenience function that evaluates if the EventType is -// enabled, and if so, it calls the supplier to create the event and -// subsequently journal.RecordEvent on the provided journal to record it. -// -// This is safe to call with a nil Journal, either because the value is nil, -// or because a journal obtained through NilJournal() is in use. -func MaybeRecordEvent(journal Journal, evtType EventType, supplier func() interface{}) { - if journal == nil || journal == nilj { - return - } - if !evtType.Enabled() { - return - } - journal.RecordEvent(evtType, supplier()) -} diff --git a/journal/types.go b/journal/types.go index b1c36b515..29954d9cf 100644 --- a/journal/types.go +++ b/journal/types.go @@ -29,7 +29,17 @@ type EventType struct { // All event types are enabled by default, and specific event types can only // be disabled at Journal construction time. func (et EventType) Enabled() bool { - return et.enabled + return et.safe && et.enabled +} + +// EventTypeFactory is a component that constructs tracked EventType tokens, +// for usage with a Journal. +type EventTypeFactory interface { + // RegisterEventType introduces a new event type to a journal, and + // returns an EventType token that components can later use to check whether + // journalling for that type is enabled/suppressed, and to tag journal + // entries appropriately. + RegisterEventType(system, event string) EventType } // Journal represents an audit trail of system actions. @@ -41,11 +51,7 @@ func (et EventType) Enabled() bool { // For cleanliness and type safety, we recommend to use typed events. See the // *Evt struct types in this package for more info. type Journal interface { - // RegisterEventType introduces a new event type to this journal, and - // returns an EventType token that components can later use to check whether - // journalling for that type is enabled/suppressed, and to tag journal - // entries appropriately. - RegisterEventType(system, event string) EventType + EventTypeFactory // RecordEvent records this event to the journal. See godocs on the Journal type // for more info. @@ -65,6 +71,22 @@ type Event struct { Data interface{} } +// MaybeRecordEvent is a convenience function that evaluates if the EventType is +// enabled, and if so, it calls the supplier to create the event and +// subsequently journal.RecordEvent on the provided journal to record it. +// +// This is safe to call with a nil Journal, either because the value is nil, +// or because a journal obtained through NilJournal() is in use. +func MaybeRecordEvent(journal Journal, evtType EventType, supplier func() interface{}) { + if journal == nil || journal == nilj { + return + } + if !evtType.Enabled() { + return + } + journal.RecordEvent(evtType, supplier()) +} + // eventTypeFactory is an embeddable mixin that takes care of tracking disabled // event types, and returning initialized/safe EventTypes when requested. type eventTypeFactory struct { @@ -73,7 +95,9 @@ type eventTypeFactory struct { m map[string]EventType } -func newEventTypeFactory(disabled DisabledEvents) *eventTypeFactory { +var _ EventTypeFactory = (*eventTypeFactory)(nil) + +func NewEventTypeFactory(disabled DisabledEvents) EventTypeFactory { ret := &eventTypeFactory{ m: make(map[string]EventType, len(disabled)+32), // + extra capacity. } From 5e2c28d7e9e84c77ffde8b0b63178f42e2af0119 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Tue, 11 Aug 2020 13:10:22 +0100 Subject: [PATCH 14/40] add comment. --- markets/storageadapter/client.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/markets/storageadapter/client.go b/markets/storageadapter/client.go index db43c9a56..9186b94c0 100644 --- a/markets/storageadapter/client.go +++ b/markets/storageadapter/client.go @@ -43,7 +43,9 @@ type ClientNodeAdapter struct { fm *market.FundMgr ev *events.Events - jrnl journal.Journal + jrnl journal.Journal + + // index 0 is unused, as it corresponds to evtTypeDealAccepted, a provider-only event. evtTypes [4]journal.EventType } From d53c6f25991630fb085508298c4e3e6d7e9eebef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Tue, 11 Aug 2020 13:22:35 +0100 Subject: [PATCH 15/40] storage-fsm: emit sealing state transition notifications. --- extern/storage-fsm/fsm.go | 8 +++++++- extern/storage-fsm/fsm_test.go | 17 ++++++++++++++++- extern/storage-fsm/sealing.go | 7 ++++++- go.mod | 2 +- go.sum | 6 ++++++ 5 files changed, 36 insertions(+), 4 deletions(-) diff --git a/extern/storage-fsm/fsm.go b/extern/storage-fsm/fsm.go index 25b8f364a..4d6c4b7e0 100644 --- a/extern/storage-fsm/fsm.go +++ b/extern/storage-fsm/fsm.go @@ -165,6 +165,12 @@ func (m *Sealing) plan(events []statemachine.Event, state *SectorInfo) (func(sta state.Log = append(state.Log, l) } + if m.notifee != nil { + defer func(before SectorInfo) { + m.notifee(before, *state) + }(*state) // take safe-ish copy of the before state (except for nested pointers) + } + p := fsmPlanners[state.State] if p == nil { return nil, xerrors.Errorf("planner for state %s not found", state.State) @@ -351,7 +357,7 @@ func on(mut mutator, next SectorState) func() (mutator, SectorState) { } } -func planOne(ts ...func() (mut mutator, next SectorState)) func(events []statemachine.Event, state *SectorInfo) error { +func planOne(ts ...func() (mutator, SectorState)) func(events []statemachine.Event, state *SectorInfo) error { return func(events []statemachine.Event, state *SectorInfo) error { if len(events) != 1 { for _, event := range events { diff --git a/extern/storage-fsm/fsm_test.go b/extern/storage-fsm/fsm_test.go index b1e53133c..4625bd26c 100644 --- a/extern/storage-fsm/fsm_test.go +++ b/extern/storage-fsm/fsm_test.go @@ -25,8 +25,13 @@ type test struct { } func TestHappyPath(t *testing.T) { + var notif []struct{ before, after SectorInfo } m := test{ - s: &Sealing{}, + s: &Sealing{ + notifee: func(before, after SectorInfo) { + notif = append(notif, struct{ before, after SectorInfo }{before, after}) + }, + }, t: t, state: &SectorInfo{State: Packing}, } @@ -57,6 +62,16 @@ 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, 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) + } + if n.after.State != expected[i+1] { + t.Fatalf("expected after state: %s, got: %s", expected[i+1], n.after.State) + } + } } func TestSeedRevert(t *testing.T) { diff --git a/extern/storage-fsm/sealing.go b/extern/storage-fsm/sealing.go index d15255696..76040764f 100644 --- a/extern/storage-fsm/sealing.go +++ b/extern/storage-fsm/sealing.go @@ -51,6 +51,8 @@ type SealingAPI interface { ChainReadObj(context.Context, cid.Cid) ([]byte, error) } +type SectorStateNotifee func(before, after SectorInfo) + type Sealing struct { api SealingAPI events Events @@ -69,6 +71,8 @@ type Sealing struct { toUpgrade map[abi.SectorNumber]struct{} getSealDelay GetSealingDelayFunc + + notifee SectorStateNotifee } type UnsealedSectorMap struct { @@ -83,7 +87,7 @@ type UnsealedSectorInfo struct { pieceSizes []abi.UnpaddedPieceSize } -func New(api SealingAPI, events Events, maddr address.Address, ds datastore.Batching, sealer sectorstorage.SectorManager, sc SectorIDCounter, verif ffiwrapper.Verifier, pcp PreCommitPolicy, gsd GetSealingDelayFunc) *Sealing { +func New(api SealingAPI, events Events, maddr address.Address, ds datastore.Batching, sealer sectorstorage.SectorManager, sc SectorIDCounter, verif ffiwrapper.Verifier, pcp PreCommitPolicy, gsd GetSealingDelayFunc, notifee SectorStateNotifee) *Sealing { s := &Sealing{ api: api, events: events, @@ -100,6 +104,7 @@ func New(api SealingAPI, events Events, maddr address.Address, ds datastore.Batc toUpgrade: map[abi.SectorNumber]struct{}{}, getSealDelay: gsd, + notifee: notifee, } s.sectors = statemachine.New(namespace.Wrap(ds, datastore.NewKey(SectorStorePrefix)), s, SectorInfo{}) diff --git a/go.mod b/go.mod index 90bc30a80..51ca85830 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( github.com/filecoin-project/sector-storage v0.0.0-20200805173933-deec7a2658d4 github.com/filecoin-project/specs-actors v0.8.7-0.20200805174427-9d42fb163883 github.com/filecoin-project/specs-storage v0.1.1-0.20200622113353-88a9704877ea - github.com/filecoin-project/storage-fsm v0.0.0-20200810142921-b9bc6718b0b2 + github.com/filecoin-project/storage-fsm v0.0.0-20200805013058-9d9ea4e6331f 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 3fb0bfc5d..ca9f0df33 100644 --- a/go.sum +++ b/go.sum @@ -40,6 +40,7 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/zstd v1.4.1 h1:3oxKN3wbHibqx897utPC2LTQU4J+IHWWJO+glkAkpFM= github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/GeertJohan/go.incremental v1.0.0 h1:7AH+pY1XUgQE4Y1HcXYaMqAI0m9yrFqo/jt0CW30vsg= github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= github.com/GeertJohan/go.rice v1.0.0 h1:KkI6O9uMaQU3VEKaj01ulavtF7o1fWT7+pk/4voiMLQ= github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= @@ -61,6 +62,7 @@ github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpH github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw= github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= @@ -644,6 +646,7 @@ github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0 github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= @@ -1128,6 +1131,7 @@ github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJE github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/nikkolasg/hexjson v0.0.0-20181101101858-78e39397e00c h1:5bFTChQxSKNwy8ALwOebjekYExl9HTT9urdawqC95tA= github.com/nikkolasg/hexjson v0.0.0-20181101101858-78e39397e00c/go.mod h1:7qN3Y0BvzRUf4LofcoJplQL10lsFDb4PYlePTVwrP28= +github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229 h1:E2B8qYyeSgv5MXpmzZXRNp8IAQ4vjxIjhpAf5hv/tAg= github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -1337,7 +1341,9 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX github.com/urfave/cli/v2 v2.0.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4= github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= From 2ea5abdfb5cbba97d5c935a3ad3f292287e760cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Tue, 11 Aug 2020 13:48:32 +0100 Subject: [PATCH 16/40] wire journal into miner. --- cmd/lotus-storage-miner/init.go | 15 +++++++++++---- journal/fs.go | 13 ++++++------- journal/types.go | 9 +++++++++ miner/journal_events.go | 1 + miner/miner.go | 28 +++++++++++++++++++++------- node/builder.go | 9 ++------- node/modules/services.go | 17 +++++++++++++++++ node/modules/storageminer.go | 4 ++-- 8 files changed, 69 insertions(+), 27 deletions(-) create mode 100644 miner/journal_events.go diff --git a/cmd/lotus-storage-miner/init.go b/cmd/lotus-storage-miner/init.go index 5007a7120..1714bd901 100644 --- a/cmd/lotus-storage-miner/init.go +++ b/cmd/lotus-storage-miner/init.go @@ -24,9 +24,6 @@ import ( "github.com/filecoin-project/go-address" cborutil "github.com/filecoin-project/go-cbor-util" paramfetch "github.com/filecoin-project/go-paramfetch" - sectorstorage "github.com/filecoin-project/sector-storage" - "github.com/filecoin-project/sector-storage/ffiwrapper" - "github.com/filecoin-project/sector-storage/stores" "github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin/market" @@ -34,6 +31,11 @@ import ( "github.com/filecoin-project/specs-actors/actors/builtin/power" crypto2 "github.com/filecoin-project/specs-actors/actors/crypto" + "github.com/filecoin-project/lotus/journal" + sectorstorage "github.com/filecoin-project/sector-storage" + "github.com/filecoin-project/sector-storage/ffiwrapper" + "github.com/filecoin-project/sector-storage/stores" + lapi "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors" @@ -446,7 +448,12 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api lapi.FullNode, return err } - m := miner.NewMiner(api, epp, a, slashfilter.New(mds)) + jrnl, err := journal.OpenFSJournal(lr, journal.DefaultDisabledEvents) + if err != nil { + return fmt.Errorf("failed to open filesystem journal: %w", err) + } + + m := miner.NewMiner(api, epp, a, slashfilter.New(mds), jrnl) { if err := m.Start(ctx); err != nil { return xerrors.Errorf("failed to start up genesis miner: %w", err) diff --git a/journal/fs.go b/journal/fs.go index 096f5f1fd..91b0d1e6d 100644 --- a/journal/fs.go +++ b/journal/fs.go @@ -1,7 +1,6 @@ package journal import ( - "context" "encoding/json" "fmt" "os" @@ -10,7 +9,6 @@ import ( "time" logging "github.com/ipfs/go-log" - "go.uber.org/fx" "golang.org/x/xerrors" "github.com/filecoin-project/lotus/build" @@ -33,11 +31,12 @@ type fsJournal struct { incoming chan *Event closing chan struct{} + closed chan struct{} } // OpenFSJournal constructs a rolling filesystem journal, with a default // per-file size limit of 1GiB. -func OpenFSJournal(lr repo.LockedRepo, lc fx.Lifecycle, disabled DisabledEvents) (Journal, error) { +func OpenFSJournal(lr repo.LockedRepo, disabled DisabledEvents) (Journal, error) { dir := filepath.Join(lr.Path(), "journal") if err := os.MkdirAll(dir, 0755); err != nil { return nil, fmt.Errorf("failed to mk directory %s for file journal: %w", dir, err) @@ -49,16 +48,13 @@ func OpenFSJournal(lr repo.LockedRepo, lc fx.Lifecycle, disabled DisabledEvents) sizeLimit: 1 << 30, incoming: make(chan *Event, 32), closing: make(chan struct{}), + closed: make(chan struct{}), } if err := f.rollJournalFile(); err != nil { return nil, err } - lc.Append(fx.Hook{ - OnStop: func(_ context.Context) error { return f.Close() }, - }) - go f.runLoop() return f, nil @@ -79,6 +75,7 @@ func (f *fsJournal) RecordEvent(evtType EventType, obj interface{}) { func (f *fsJournal) Close() error { close(f.closing) + <-f.closed return nil } @@ -117,6 +114,8 @@ func (f *fsJournal) rollJournalFile() error { } func (f *fsJournal) runLoop() { + defer close(f.closed) + for { select { case je := <-f.incoming: diff --git a/journal/types.go b/journal/types.go index 29954d9cf..6b6d53c08 100644 --- a/journal/types.go +++ b/journal/types.go @@ -5,6 +5,15 @@ import ( "time" ) +var ( + // DefaultDisabledEvents lists the journal events disabled by + // default, usually because they are considered noisy. + DefaultDisabledEvents = DisabledEvents{ + EventType{System: "mpool", Event: "add"}, + EventType{System: "mpool", Event: "remove"}, + } +) + // DisabledEvents is the set of event types whose journaling is suppressed. type DisabledEvents []EventType diff --git a/miner/journal_events.go b/miner/journal_events.go new file mode 100644 index 000000000..ab865910b --- /dev/null +++ b/miner/journal_events.go @@ -0,0 +1 @@ +package miner diff --git a/miner/miner.go b/miner/miner.go index b8bb9e562..091919b6c 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -31,6 +31,11 @@ import ( var log = logging.Logger("miner") +// Journal event types. +const ( + evtTypeBlockMined = iota +) + // returns a callback reporting whether we mined a blocks in this round type waitFunc func(ctx context.Context, baseTime uint64) (func(bool, error), abi.ChainEpoch, error) @@ -42,7 +47,7 @@ func randTimeOffset(width time.Duration) time.Duration { return val - (width / 2) } -func NewMiner(api api.FullNode, epp gen.WinningPoStProver, addr address.Address, sf *slashfilter.SlashFilter) *Miner { +func NewMiner(api api.FullNode, epp gen.WinningPoStProver, addr address.Address, sf *slashfilter.SlashFilter, jrnl journal.Journal) *Miner { arc, err := lru.NewARC(10000) if err != nil { panic(err) @@ -66,6 +71,10 @@ func NewMiner(api api.FullNode, epp gen.WinningPoStProver, addr address.Address, sf: sf, minedBlockHeights: arc, + jrnl: jrnl, + evtTypes: [...]journal.EventType{ + evtTypeBlockMined: jrnl.RegisterEventType("miner", "block_mined"), + }, } } @@ -85,6 +94,9 @@ type Miner struct { sf *slashfilter.SlashFilter minedBlockHeights *lru.ARCCache + + jrnl journal.Journal + evtTypes [1]journal.EventType } func (m *Miner) Address() address.Address { @@ -213,12 +225,14 @@ func (m *Miner) mine(ctx context.Context) { onDone(b != nil, nil) if b != nil { - journal.Add("blockMined", map[string]interface{}{ - "parents": base.TipSet.Cids(), - "nulls": base.NullRounds, - "epoch": b.Header.Height, - "timestamp": b.Header.Timestamp, - "cid": b.Header.Cid(), + journal.MaybeRecordEvent(m.jrnl, m.evtTypes[evtTypeBlockMined], func() interface{} { + return map[string]interface{}{ + "parents": base.TipSet.Cids(), + "nulls": base.NullRounds, + "epoch": b.Header.Height, + "timestamp": b.Header.Timestamp, + "cid": b.Header.Cid(), + } }) btime := time.Unix(int64(b.Header.Timestamp), 0) diff --git a/node/builder.go b/node/builder.go index 86ef23192..580aec3df 100644 --- a/node/builder.go +++ b/node/builder.go @@ -156,13 +156,8 @@ func defaults() []Option { Override(new(record.Validator), modules.RecordValidator), Override(new(dtypes.Bootstrapper), dtypes.Bootstrapper(false)), Override(new(dtypes.ShutdownChan), make(chan struct{})), - Override(new(journal.Journal), journal.OpenFSJournal), - - // By default, disable noisy mpool events; keep only mpool:repub on. - Override(new(journal.DisabledEvents), journal.DisabledEvents{ - journal.EventType{System: "mpool", Event: "add"}, - journal.EventType{System: "mpool", Event: "remove"}, - }), + Override(new(journal.Journal), modules.OpenFilesystemJournal), + Override(new(journal.DisabledEvents), journal.DefaultDisabledEvents), Override(InitJournalKey, func(j journal.Journal) { /* forces the creation of the journal at startup */ }), // Filecoin modules diff --git a/node/modules/services.go b/node/modules/services.go index 0d148ffb4..def286913 100644 --- a/node/modules/services.go +++ b/node/modules/services.go @@ -1,6 +1,8 @@ package modules import ( + "context" + "github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore/namespace" eventbus "github.com/libp2p/go-eventbus" @@ -22,10 +24,12 @@ import ( "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/sub" + "github.com/filecoin-project/lotus/journal" "github.com/filecoin-project/lotus/lib/peermgr" "github.com/filecoin-project/lotus/node/hello" "github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/helpers" + "github.com/filecoin-project/lotus/node/repo" ) func RunHello(mctx helpers.MetricsCtx, lc fx.Lifecycle, h host.Host, svc *hello.Service) error { @@ -141,3 +145,16 @@ func RandomBeacon(p RandomBeaconParams, _ dtypes.AfterGenesisSet) (beacon.Random //return beacon.NewMockBeacon(build.BlockDelaySecs * time.Second) return drand.NewDrandBeacon(gen.Timestamp, build.BlockDelaySecs, p.PubSub, p.DrandConfig) } + +func OpenFilesystemJournal(lr repo.LockedRepo, lc fx.Lifecycle, disabled journal.DisabledEvents) (journal.Journal, error) { + jrnl, err := journal.OpenFSJournal(lr, disabled) + if err != nil { + return nil, err + } + + lc.Append(fx.Hook{ + OnStop: func(_ context.Context) error { return jrnl.Close() }, + }) + + return jrnl, err +} diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index a06e44198..fc7458f8f 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -340,13 +340,13 @@ func StagingGraphsync(mctx helpers.MetricsCtx, lc fx.Lifecycle, ibs dtypes.Stagi return gs } -func SetupBlockProducer(lc fx.Lifecycle, ds dtypes.MetadataDS, api lapi.FullNode, epp gen.WinningPoStProver, sf *slashfilter.SlashFilter) (*miner.Miner, error) { +func SetupBlockProducer(lc fx.Lifecycle, ds dtypes.MetadataDS, api lapi.FullNode, epp gen.WinningPoStProver, sf *slashfilter.SlashFilter, jrnl journal.Journal) (*miner.Miner, error) { minerAddr, err := minerAddrFromDS(ds) if err != nil { return nil, err } - m := miner.NewMiner(api, epp, minerAddr, sf) + m := miner.NewMiner(api, epp, minerAddr, sf, jrnl) lc.Append(fx.Hook{ OnStart: func(ctx context.Context) error { From b534ab9d3c8aa8f4a4f86e91cd089465701118ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Tue, 11 Aug 2020 14:28:00 +0100 Subject: [PATCH 17/40] panic recovery in MaybeRecordEvent; handle nil current tipsets in wdpost. --- journal/fs.go | 3 --- journal/types.go | 16 ++++++++++++++++ miner/journal_events.go | 1 - storage/wdpost_run.go | 36 ++++++++++++------------------------ storage/wdpost_sched.go | 21 +++++++++++++++------ 5 files changed, 43 insertions(+), 34 deletions(-) delete mode 100644 miner/journal_events.go diff --git a/journal/fs.go b/journal/fs.go index 91b0d1e6d..73a2fff43 100644 --- a/journal/fs.go +++ b/journal/fs.go @@ -8,15 +8,12 @@ import ( "sync" "time" - logging "github.com/ipfs/go-log" "golang.org/x/xerrors" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/node/repo" ) -var log = logging.Logger("journal") - // fsJournal is a basic journal backed by files on a filesystem. type fsJournal struct { EventTypeFactory diff --git a/journal/types.go b/journal/types.go index 6b6d53c08..6183e6cfa 100644 --- a/journal/types.go +++ b/journal/types.go @@ -3,8 +3,12 @@ package journal import ( "sync" "time" + + logging "github.com/ipfs/go-log" ) +var log = logging.Logger("journal") + var ( // DefaultDisabledEvents lists the journal events disabled by // default, usually because they are considered noisy. @@ -30,6 +34,10 @@ type EventType struct { safe bool } +func (et EventType) String() string { + return et.System + ":" + et.Event +} + // Enabled returns whether this event type is enabled in the journaling // subsystem. Users are advised to check this before actually attempting to // add a journal entry, as it helps bypass object construction for events that @@ -84,9 +92,17 @@ type Event struct { // enabled, and if so, it calls the supplier to create the event and // subsequently journal.RecordEvent on the provided journal to record it. // +// It also recovers from panics raised when calling the supplier function. +// // This is safe to call with a nil Journal, either because the value is nil, // or because a journal obtained through NilJournal() is in use. func MaybeRecordEvent(journal Journal, evtType EventType, supplier func() interface{}) { + defer func() { + if r := recover(); r != nil { + log.Warnf("recovered from panic while recording journal event; type=%s, err=%v", evtType, r) + } + }() + if journal == nil || journal == nilj { return } diff --git a/miner/journal_events.go b/miner/journal_events.go deleted file mode 100644 index ab865910b..000000000 --- a/miner/journal_events.go +++ /dev/null @@ -1 +0,0 @@ -package miner diff --git a/storage/wdpost_run.go b/storage/wdpost_run.go index 6750042cf..0ec4ac1f6 100644 --- a/storage/wdpost_run.go +++ b/storage/wdpost_run.go @@ -27,13 +27,11 @@ var errNoPartitions = errors.New("no partitions") func (s *WindowPoStScheduler) failPost(err error, deadline *miner.DeadlineInfo) { journal.MaybeRecordEvent(s.jrnl, s.wdPoStEvtType, func() interface{} { - return WindowPoStEvt{ + return s.enrichWithTipset(WindowPoStEvt{ State: "failed", Deadline: s.activeDeadline, - Height: s.cur.Height(), - TipSet: s.cur.Cids(), Error: err, - } + }) }) log.Errorf("TODO") @@ -51,12 +49,10 @@ func (s *WindowPoStScheduler) doPost(ctx context.Context, deadline *miner.Deadli s.activeDeadline = deadline journal.MaybeRecordEvent(s.jrnl, s.wdPoStEvtType, func() interface{} { - return WindowPoStEvt{ + return s.enrichWithTipset(WindowPoStEvt{ State: "started", Deadline: s.activeDeadline, - Height: s.cur.Height(), - TipSet: s.cur.Cids(), - } + }) }) go func() { @@ -82,12 +78,10 @@ func (s *WindowPoStScheduler) doPost(ctx context.Context, deadline *miner.Deadli } journal.MaybeRecordEvent(s.jrnl, s.wdPoStEvtType, func() interface{} { - return WindowPoStEvt{ + return s.enrichWithTipset(WindowPoStEvt{ State: "succeeded", Deadline: s.activeDeadline, - Height: s.cur.Height(), - TipSet: s.cur.Cids(), - } + }) }) }() } @@ -153,16 +147,14 @@ func (s *WindowPoStScheduler) checkNextRecoveries(ctx context.Context, dlIdx uin mcid = sm.Cid() } - return WindowPoStEvt{ + return s.enrichWithTipset(WindowPoStEvt{ State: "recoveries_processed", Deadline: s.activeDeadline, - Height: s.cur.Height(), - TipSet: s.cur.Cids(), Recoveries: &WindowPoStEvt_Recoveries{ Declarations: params.Recoveries, MessageCID: mcid, }, - } + }) }) for partIdx, partition := range partitions { @@ -260,16 +252,14 @@ func (s *WindowPoStScheduler) checkNextFaults(ctx context.Context, dlIdx uint64, if sm != nil { mcid = sm.Cid() } - return WindowPoStEvt{ + return s.enrichWithTipset(WindowPoStEvt{ State: "faults_processed", Deadline: s.activeDeadline, - Height: s.cur.Height(), - TipSet: s.cur.Cids(), Faults: &WindowPoStEvt_Faults{ Declarations: params.Faults, MessageCID: mcid, }, - } + }) }) for partIdx, partition := range partitions { @@ -517,16 +507,14 @@ func (s *WindowPoStScheduler) submitPost(ctx context.Context, proof *miner.Submi mcid = sm.Cid() } - return WindowPoStEvt{ + return s.enrichWithTipset(WindowPoStEvt{ State: "proofs_processed", Deadline: s.activeDeadline, - Height: s.cur.Height(), - TipSet: s.cur.Cids(), Proofs: &WindowPoStEvt_Proofs{ Partitions: proof.Partitions, MessageCID: mcid, }, - } + }) }) enc, aerr := actors.SerializeParams(proof) diff --git a/storage/wdpost_sched.go b/storage/wdpost_sched.go index 8344097dc..2c55b93ef 100644 --- a/storage/wdpost_sched.go +++ b/storage/wdpost_sched.go @@ -140,12 +140,13 @@ func (s *WindowPoStScheduler) Run(ctx context.Context) { log.Errorf("expected first notif to have len = 1") continue } - if changes[0].Type != store.HCCurrent { + chg := changes[0] + if chg.Type != store.HCCurrent { log.Errorf("expected first notif to tell current ts") continue } - if err := s.update(ctx, changes[0].Val); err != nil { + if err := s.update(ctx, chg.Val); err != nil { log.Errorf("%+v", err) } @@ -248,12 +249,10 @@ func (s *WindowPoStScheduler) abortActivePoSt() { s.abort() journal.MaybeRecordEvent(s.jrnl, s.wdPoStEvtType, func() interface{} { - return WindowPoStEvt{ + return s.enrichWithTipset(WindowPoStEvt{ State: "abort", Deadline: s.activeDeadline, - Height: s.cur.Height(), - TipSet: s.cur.Cids(), - } + }) }) log.Warnf("Aborting Window PoSt (Deadline: %+v)", s.activeDeadline) @@ -262,3 +261,13 @@ func (s *WindowPoStScheduler) abortActivePoSt() { s.activeDeadline = nil s.abort = nil } + +// enrichWithTipset enriches a WindowPoStEvt with tipset information, +// if available. +func (s *WindowPoStScheduler) enrichWithTipset(evt WindowPoStEvt) WindowPoStEvt { + if s.cur != nil { + evt.Height = s.cur.Height() + evt.TipSet = s.cur.Cids() + } + return evt +} From 8f19fff1ecb770d4108a692be47829b91e4ba8e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Tue, 11 Aug 2020 14:47:02 +0100 Subject: [PATCH 18/40] fix tests. --- chain/messagepool/messagepool_test.go | 2 +- chain/messagepool/selection_test.go | 4 +++- chain/store/index_test.go | 3 ++- chain/store/store_test.go | 5 +++-- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/chain/messagepool/messagepool_test.go b/chain/messagepool/messagepool_test.go index 1dcc6a233..06541d7e5 100644 --- a/chain/messagepool/messagepool_test.go +++ b/chain/messagepool/messagepool_test.go @@ -271,7 +271,7 @@ func TestPruningSimple(t *testing.T) { ds := datastore.NewMapDatastore() - mp, err := New(tma, ds, "mptest") + mp, err := New(tma, ds, "mptest", journal.NilJournal()) if err != nil { t.Fatal(err) } diff --git a/chain/messagepool/selection_test.go b/chain/messagepool/selection_test.go index 177c62dc2..91337d63c 100644 --- a/chain/messagepool/selection_test.go +++ b/chain/messagepool/selection_test.go @@ -10,6 +10,8 @@ import ( "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/journal" + "github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/crypto" "github.com/ipfs/go-datastore" @@ -42,7 +44,7 @@ func makeTestMessage(w *wallet.Wallet, from, to address.Address, nonce uint64, g func makeTestMpool() (*MessagePool, *testMpoolAPI) { tma := newTestMpoolAPI() ds := datastore.NewMapDatastore() - mp, err := New(tma, ds, "test") + mp, err := New(tma, ds, "test", journal.NilJournal()) if err != nil { panic(err) } diff --git a/chain/store/index_test.go b/chain/store/index_test.go index 9443b4c07..2a0fdc2d1 100644 --- a/chain/store/index_test.go +++ b/chain/store/index_test.go @@ -8,6 +8,7 @@ import ( "github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types/mock" + "github.com/filecoin-project/lotus/journal" "github.com/filecoin-project/lotus/lib/blockstore" "github.com/filecoin-project/specs-actors/actors/abi" datastore "github.com/ipfs/go-datastore" @@ -31,7 +32,7 @@ func TestIndexSeeks(t *testing.T) { ctx := context.TODO() nbs := blockstore.NewTemporarySync() - cs := store.NewChainStore(nbs, syncds.MutexWrap(datastore.NewMapDatastore()), nil) + cs := store.NewChainStore(nbs, syncds.MutexWrap(datastore.NewMapDatastore()), nil, journal.NilJournal()) _, err = cs.Import(bytes.NewReader(gencar)) if err != nil { diff --git a/chain/store/store_test.go b/chain/store/store_test.go index 3267feccd..56a78330a 100644 --- a/chain/store/store_test.go +++ b/chain/store/store_test.go @@ -17,6 +17,7 @@ import ( "github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/store" "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/node/repo" ) @@ -67,7 +68,7 @@ func BenchmarkGetRandomness(b *testing.B) { bs := blockstore.NewBlockstore(bds) - cs := store.NewChainStore(bs, mds, nil) + cs := store.NewChainStore(bs, mds, nil, journal.NilJournal()) b.ResetTimer() @@ -101,7 +102,7 @@ func TestChainExportImport(t *testing.T) { } nbs := blockstore.NewTemporary() - cs := store.NewChainStore(nbs, datastore.NewMapDatastore(), nil) + cs := store.NewChainStore(nbs, datastore.NewMapDatastore(), nil, journal.NilJournal()) root, err := cs.Import(buf) if err != nil { From 200b0f72cc4a9b5d78085b24e9b69f139296764d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Tue, 11 Aug 2020 15:06:13 +0100 Subject: [PATCH 19/40] mpool/repub: only record in journal if actually repubbing. --- chain/messagepool/messagepool.go | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index c87a02b95..19856b9f7 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -371,17 +371,19 @@ func (mp *MessagePool) runLoop() { log.Errorf("errors while republishing: %+v", errout) } - journal.MaybeRecordEvent(mp.jrnl, mp.evtTypes[evtTypeMpoolRepub], func() interface{} { - msgs := make([]MessagePoolEvt_Message, 0, len(outputMsgs)) - for _, m := range outputMsgs { - msgs = append(msgs, MessagePoolEvt_Message{Message: m.Message, CID: m.Cid()}) - } - return MessagePoolEvt{ - Action: "repub", - Messages: msgs, - Error: errout, - } - }) + if len(outputMsgs) > 0 { + journal.MaybeRecordEvent(mp.jrnl, mp.evtTypes[evtTypeMpoolRepub], func() interface{} { + msgs := make([]MessagePoolEvt_Message, 0, len(outputMsgs)) + for _, m := range outputMsgs { + msgs = append(msgs, MessagePoolEvt_Message{Message: m.Message, CID: m.Cid()}) + } + return MessagePoolEvt{ + Action: "repub", + Messages: msgs, + Error: errout, + } + }) + } case <-mp.pruneTrigger: if err := mp.pruneExcessMessages(); err != nil { From cc859d3948c0f4a1c01e4a3cd6ea2284afd66927 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Tue, 11 Aug 2020 16:30:54 +0100 Subject: [PATCH 20/40] journal: wdpost: record proofs_processed even if no eligible partitions. --- storage/wdpost_run.go | 44 ++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/storage/wdpost_run.go b/storage/wdpost_run.go index 0ec4ac1f6..c448fb223 100644 --- a/storage/wdpost_run.go +++ b/storage/wdpost_run.go @@ -61,16 +61,34 @@ func (s *WindowPoStScheduler) doPost(ctx context.Context, deadline *miner.Deadli ctx, span := trace.StartSpan(ctx, "WindowPoStScheduler.doPost") defer span.End() + // recordEvent records a successful proofs_processed event in the + // journal, even if it was a noop (no partitions). + recordEvent := func(partitions []miner.PoStPartition, mcid cid.Cid) { + journal.MaybeRecordEvent(s.jrnl, s.wdPoStEvtType, func() interface{} { + return s.enrichWithTipset(WindowPoStEvt{ + State: "proofs_processed", + Deadline: s.activeDeadline, + Proofs: &WindowPoStEvt_Proofs{ + Partitions: partitions, + MessageCID: mcid, + }, + }) + }) + } + proof, err := s.runPost(ctx, *deadline, ts) switch err { case errNoPartitions: + recordEvent(nil, cid.Undef) return case nil: - if err := s.submitPost(ctx, proof); err != nil { + sm, err := s.submitPost(ctx, proof) + if err != nil { log.Errorf("submitPost failed: %+v", err) s.failPost(err, deadline) return } + recordEvent(proof.Partitions, sm.Cid()) default: log.Errorf("runPost failed: %+v", err) s.failPost(err, deadline) @@ -495,31 +513,15 @@ func (s *WindowPoStScheduler) sectorInfo(ctx context.Context, deadlineSectors *a return sbsi, nil } -func (s *WindowPoStScheduler) submitPost(ctx context.Context, proof *miner.SubmitWindowedPoStParams) error { +func (s *WindowPoStScheduler) submitPost(ctx context.Context, proof *miner.SubmitWindowedPoStParams) (*types.SignedMessage, error) { ctx, span := trace.StartSpan(ctx, "storage.commitPost") defer span.End() var sm *types.SignedMessage - defer journal.MaybeRecordEvent(s.jrnl, s.wdPoStEvtType, func() interface{} { - var mcid cid.Cid - if sm != nil { - mcid = sm.Cid() - } - - return s.enrichWithTipset(WindowPoStEvt{ - State: "proofs_processed", - Deadline: s.activeDeadline, - Proofs: &WindowPoStEvt_Proofs{ - Partitions: proof.Partitions, - MessageCID: mcid, - }, - }) - }) - enc, aerr := actors.SerializeParams(proof) if aerr != nil { - return xerrors.Errorf("could not serialize submit post parameters: %w", aerr) + return nil, xerrors.Errorf("could not serialize submit post parameters: %w", aerr) } msg := &types.Message{ @@ -534,7 +536,7 @@ func (s *WindowPoStScheduler) submitPost(ctx context.Context, proof *miner.Submi var err error sm, err = s.api.MpoolPushMessage(ctx, msg) if err != nil { - return xerrors.Errorf("pushing message to mpool: %w", err) + return nil, xerrors.Errorf("pushing message to mpool: %w", err) } log.Infof("Submitted window post: %s", sm.Cid()) @@ -553,5 +555,5 @@ func (s *WindowPoStScheduler) submitPost(ctx context.Context, proof *miner.Submi log.Errorf("Submitting window post %s failed: exit %d", sm.Cid(), rec.Receipt.ExitCode) }() - return nil + return sm, nil } From 4e1ef09751ab8d937c16d7012a977cad93d3c492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Wed, 26 Aug 2020 16:09:37 +0100 Subject: [PATCH 21/40] make journal a global var. --- chain/gen/gen.go | 3 +- chain/gen/genesis/genesis.go | 3 +- chain/messagepool/messagepool.go | 15 +++-- chain/messagepool/messagepool_test.go | 18 +++--- chain/messagepool/selection_test.go | 11 ++-- chain/store/index_test.go | 12 ++-- chain/store/store.go | 8 +-- chain/store/store_test.go | 4 +- chain/validation/applier.go | 2 +- cmd/lotus-bench/import.go | 2 +- cmd/lotus-storage-miner/init.go | 7 ++- cmd/lotus/daemon.go | 7 +-- go.sum | 17 +++++ journal/fs.go | 28 ++++++--- journal/global.go | 9 +++ journal/nil.go | 2 +- journal/registry.go | 57 +++++++++++++++++ journal/types.go | 89 +++------------------------ markets/storageadapter/client.go | 15 ++--- markets/storageadapter/provider.go | 24 ++++---- miner/miner.go | 8 +-- node/builder.go | 10 ++- node/modules/chain.go | 9 ++- node/modules/storageminer.go | 14 ++--- storage/miner.go | 8 +-- storage/wdpost_run.go | 12 ++-- storage/wdpost_sched.go | 8 +-- 27 files changed, 202 insertions(+), 200 deletions(-) create mode 100644 journal/global.go create mode 100644 journal/registry.go diff --git a/chain/gen/gen.go b/chain/gen/gen.go index a58c34764..d4851a933 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -35,7 +35,6 @@ import ( "github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/lotus/cmd/lotus-seed/seed" "github.com/filecoin-project/lotus/genesis" - "github.com/filecoin-project/lotus/journal" "github.com/filecoin-project/lotus/lib/blockstore" "github.com/filecoin-project/lotus/lib/sigs" "github.com/filecoin-project/lotus/node/repo" @@ -221,7 +220,7 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) { return nil, xerrors.Errorf("make genesis block failed: %w", err) } - cs := store.NewChainStore(bs, ds, sys, journal.NilJournal()) + cs := store.NewChainStore(bs, ds, sys) genfb := &types.FullBlock{Header: genb.Genesis} gents := store.NewFullTipSet([]*types.FullBlock{genfb}) diff --git a/chain/gen/genesis/genesis.go b/chain/gen/genesis/genesis.go index 16f8d5307..1731d780a 100644 --- a/chain/gen/genesis/genesis.go +++ b/chain/gen/genesis/genesis.go @@ -27,7 +27,6 @@ import ( "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/genesis" - "github.com/filecoin-project/lotus/journal" bstore "github.com/filecoin-project/lotus/lib/blockstore" "github.com/filecoin-project/lotus/lib/sigs" ) @@ -398,7 +397,7 @@ func MakeGenesisBlock(ctx context.Context, bs bstore.Blockstore, sys vm.SyscallB } // temp chainstore - cs := store.NewChainStore(bs, datastore.NewMapDatastore(), sys, journal.NilJournal()) + cs := store.NewChainStore(bs, datastore.NewMapDatastore(), sys) // Verify PreSealed Data stateroot, err = VerifyPreSealedData(ctx, cs, stateroot, template, keyIDs) diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index 19856b9f7..ab23af856 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -234,7 +234,7 @@ func (mpp *mpoolProvider) ChainComputeBaseFee(ctx context.Context, ts *types.Tip return baseFee, nil } -func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName, jrnl journal.Journal) (*MessagePool, error) { +func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName) (*MessagePool, error) { cache, _ := lru.New2Q(build.BlsSignatureCacheSize) verifcache, _ := lru.New2Q(build.VerifSigCacheSize) @@ -263,11 +263,10 @@ func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName, jrnl jo cfg: cfg, rbfNum: types.NewInt(uint64((cfg.ReplaceByFeeRatio - 1) * RbfDenom)), rbfDenom: types.NewInt(RbfDenom), - jrnl: jrnl, evtTypes: [...]journal.EventType{ - evtTypeMpoolAdd: jrnl.RegisterEventType("mpool", "add"), - evtTypeMpoolRemove: jrnl.RegisterEventType("mpool", "remove"), - evtTypeMpoolRepub: jrnl.RegisterEventType("mpool", "repub"), + evtTypeMpoolAdd: journal.J.RegisterEventType("mpool", "add"), + evtTypeMpoolRemove: journal.J.RegisterEventType("mpool", "remove"), + evtTypeMpoolRepub: journal.J.RegisterEventType("mpool", "repub"), }, } @@ -372,7 +371,7 @@ func (mp *MessagePool) runLoop() { } if len(outputMsgs) > 0 { - journal.MaybeRecordEvent(mp.jrnl, mp.evtTypes[evtTypeMpoolRepub], func() interface{} { + journal.J.RecordEvent(mp.evtTypes[evtTypeMpoolRepub], func() interface{} { msgs := make([]MessagePoolEvt_Message, 0, len(outputMsgs)) for _, m := range outputMsgs { msgs = append(msgs, MessagePoolEvt_Message{Message: m.Message, CID: m.Cid()}) @@ -584,7 +583,7 @@ func (mp *MessagePool) addLocked(m *types.SignedMessage) error { Message: m, }, localUpdates) - journal.MaybeRecordEvent(mp.jrnl, mp.evtTypes[evtTypeMpoolAdd], func() interface{} { + journal.J.RecordEvent(mp.evtTypes[evtTypeMpoolAdd], func() interface{} { return MessagePoolEvt{ Action: "add", Messages: []MessagePoolEvt_Message{{Message: m.Message, CID: m.Cid()}}, @@ -732,7 +731,7 @@ func (mp *MessagePool) remove(from address.Address, nonce uint64) { Message: m, }, localUpdates) - journal.MaybeRecordEvent(mp.jrnl, mp.evtTypes[evtTypeMpoolRemove], func() interface{} { + journal.J.RecordEvent(mp.evtTypes[evtTypeMpoolRemove], func() interface{} { return MessagePoolEvt{ Action: "remove", Messages: []MessagePoolEvt_Message{{Message: m.Message, CID: m.Cid()}}} diff --git a/chain/messagepool/messagepool_test.go b/chain/messagepool/messagepool_test.go index 06541d7e5..a16f61c48 100644 --- a/chain/messagepool/messagepool_test.go +++ b/chain/messagepool/messagepool_test.go @@ -6,17 +6,17 @@ import ( "testing" "github.com/filecoin-project/go-address" - "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/journal" - _ "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/filecoin-project/specs-actors/actors/crypto" "github.com/ipfs/go-cid" "github.com/ipfs/go-datastore" logging "github.com/ipfs/go-log/v2" + + "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" ) func init() { @@ -174,7 +174,7 @@ func TestMessagePool(t *testing.T) { ds := datastore.NewMapDatastore() - mp, err := New(tma, ds, "mptest", journal.NilJournal()) + mp, err := New(tma, ds, "mptest") if err != nil { t.Fatal(err) } @@ -215,7 +215,7 @@ func TestRevertMessages(t *testing.T) { ds := datastore.NewMapDatastore() - mp, err := New(tma, ds, "mptest", journal.NilJournal()) + mp, err := New(tma, ds, "mptest") if err != nil { t.Fatal(err) } @@ -271,7 +271,7 @@ func TestPruningSimple(t *testing.T) { ds := datastore.NewMapDatastore() - mp, err := New(tma, ds, "mptest", journal.NilJournal()) + mp, err := New(tma, ds, "mptest") if err != nil { t.Fatal(err) } diff --git a/chain/messagepool/selection_test.go b/chain/messagepool/selection_test.go index 91337d63c..af3f88807 100644 --- a/chain/messagepool/selection_test.go +++ b/chain/messagepool/selection_test.go @@ -5,16 +5,15 @@ import ( "testing" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/specs-actors/actors/builtin" + "github.com/filecoin-project/specs-actors/actors/crypto" + "github.com/ipfs/go-datastore" + "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/lotus/journal" - - "github.com/filecoin-project/specs-actors/actors/builtin" - "github.com/filecoin-project/specs-actors/actors/crypto" - "github.com/ipfs/go-datastore" _ "github.com/filecoin-project/lotus/lib/sigs/bls" _ "github.com/filecoin-project/lotus/lib/sigs/secp" @@ -44,7 +43,7 @@ func makeTestMessage(w *wallet.Wallet, from, to address.Address, nonce uint64, g func makeTestMpool() (*MessagePool, *testMpoolAPI) { tma := newTestMpoolAPI() ds := datastore.NewMapDatastore() - mp, err := New(tma, ds, "test", journal.NilJournal()) + mp, err := New(tma, ds, "test") if err != nil { panic(err) } diff --git a/chain/store/index_test.go b/chain/store/index_test.go index 2a0fdc2d1..38cad96dd 100644 --- a/chain/store/index_test.go +++ b/chain/store/index_test.go @@ -5,15 +5,15 @@ import ( "context" "testing" + "github.com/filecoin-project/specs-actors/actors/abi" + "github.com/ipfs/go-datastore" + syncds "github.com/ipfs/go-datastore/sync" + "github.com/stretchr/testify/assert" + "github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types/mock" - "github.com/filecoin-project/lotus/journal" "github.com/filecoin-project/lotus/lib/blockstore" - "github.com/filecoin-project/specs-actors/actors/abi" - datastore "github.com/ipfs/go-datastore" - syncds "github.com/ipfs/go-datastore/sync" - "github.com/stretchr/testify/assert" ) func TestIndexSeeks(t *testing.T) { @@ -32,7 +32,7 @@ func TestIndexSeeks(t *testing.T) { ctx := context.TODO() nbs := blockstore.NewTemporarySync() - cs := store.NewChainStore(nbs, syncds.MutexWrap(datastore.NewMapDatastore()), nil, journal.NilJournal()) + cs := store.NewChainStore(nbs, syncds.MutexWrap(datastore.NewMapDatastore()), nil) _, err = cs.Import(bytes.NewReader(gencar)) if err != nil { diff --git a/chain/store/store.go b/chain/store/store.go index 198f18756..053da258b 100644 --- a/chain/store/store.go +++ b/chain/store/store.go @@ -96,11 +96,10 @@ type ChainStore struct { vmcalls vm.SyscallBuilder - journal journal.Journal evtTypes [1]journal.EventType } -func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls vm.SyscallBuilder, jrnl journal.Journal) *ChainStore { +func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls vm.SyscallBuilder) *ChainStore { c, _ := lru.NewARC(2048) tsc, _ := lru.NewARC(4096) cs := &ChainStore{ @@ -111,11 +110,10 @@ func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls vm.SyscallB mmCache: c, tsCache: tsc, vmcalls: vmcalls, - journal: jrnl, } cs.evtTypes = [1]journal.EventType{ - evtTypeHeadChange: jrnl.RegisterEventType("sync", "head_change"), + evtTypeHeadChange: journal.J.RegisterEventType("sync", "head_change"), } ci := NewChainIndex(cs.LoadTipSet) @@ -344,7 +342,7 @@ func (cs *ChainStore) reorgWorker(ctx context.Context, initialNotifees []ReorgNo continue } - journal.MaybeRecordEvent(cs.journal, cs.evtTypes[evtTypeHeadChange], func() interface{} { + journal.J.RecordEvent(cs.evtTypes[evtTypeHeadChange], func() interface{} { return HeadChangeEvt{ From: r.old.Key(), FromHeight: r.old.Height(), diff --git a/chain/store/store_test.go b/chain/store/store_test.go index 56a78330a..e52a77570 100644 --- a/chain/store/store_test.go +++ b/chain/store/store_test.go @@ -68,7 +68,7 @@ func BenchmarkGetRandomness(b *testing.B) { bs := blockstore.NewBlockstore(bds) - cs := store.NewChainStore(bs, mds, nil, journal.NilJournal()) + cs := store.NewChainStore(bs, mds, nil) b.ResetTimer() @@ -102,7 +102,7 @@ func TestChainExportImport(t *testing.T) { } nbs := blockstore.NewTemporary() - cs := store.NewChainStore(nbs, datastore.NewMapDatastore(), nil, journal.NilJournal()) + cs := store.NewChainStore(nbs, datastore.NewMapDatastore(), nil) root, err := cs.Import(buf) if err != nil { diff --git a/chain/validation/applier.go b/chain/validation/applier.go index 9b688b8f0..c67a91c1a 100644 --- a/chain/validation/applier.go +++ b/chain/validation/applier.go @@ -69,7 +69,7 @@ func (a *Applier) ApplySignedMessage(epoch abi.ChainEpoch, msg *vtypes.SignedMes } func (a *Applier) ApplyTipSetMessages(epoch abi.ChainEpoch, blocks []vtypes.BlockMessagesInfo, rnd vstate.RandomnessSource) (vtypes.ApplyTipSetResult, error) { - cs := store.NewChainStore(a.stateWrapper.bs, a.stateWrapper.ds, a.syscalls, journal.NilJournal()) + cs := store.NewChainStore(a.stateWrapper.bs, a.stateWrapper.ds, a.syscalls) sm := stmgr.NewStateManager(cs) var bms []stmgr.BlockMessages diff --git a/cmd/lotus-bench/import.go b/cmd/lotus-bench/import.go index 03035880d..c7f687eb7 100644 --- a/cmd/lotus-bench/import.go +++ b/cmd/lotus-bench/import.go @@ -87,7 +87,7 @@ var importBenchCmd = &cli.Command{ } bs = cbs ds := datastore.NewMapDatastore() - cs := store.NewChainStore(bs, ds, vm.Syscalls(ffiwrapper.ProofVerifier), journal.NilJournal()) + cs := store.NewChainStore(bs, ds, vm.Syscalls(ffiwrapper.ProofVerifier)) stm := stmgr.NewStateManager(cs) prof, err := os.Create("import-bench.prof") diff --git a/cmd/lotus-storage-miner/init.go b/cmd/lotus-storage-miner/init.go index 1714bd901..fc1e417ce 100644 --- a/cmd/lotus-storage-miner/init.go +++ b/cmd/lotus-storage-miner/init.go @@ -448,12 +448,13 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api lapi.FullNode, return err } - jrnl, err := journal.OpenFSJournal(lr, journal.DefaultDisabledEvents) - if err != nil { + if jrnl, err := journal.OpenFSJournal(lr, journal.DefaultDisabledEvents); err == nil { + journal.J = jrnl + } else { return fmt.Errorf("failed to open filesystem journal: %w", err) } - m := miner.NewMiner(api, epp, a, slashfilter.New(mds), jrnl) + m := miner.NewMiner(api, epp, a, slashfilter.New(mds)) { if err := m.Start(ctx); err != nil { return xerrors.Errorf("failed to start up genesis miner: %w", err) diff --git a/cmd/lotus/daemon.go b/cmd/lotus/daemon.go index dc5168d69..52e8976c7 100644 --- a/cmd/lotus/daemon.go +++ b/cmd/lotus/daemon.go @@ -12,9 +12,6 @@ import ( "runtime/pprof" "strings" - "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/lotus/journal" - paramfetch "github.com/filecoin-project/go-paramfetch" "github.com/mitchellh/go-homedir" "github.com/multiformats/go-multiaddr" @@ -25,6 +22,8 @@ import ( "go.opencensus.io/tag" "golang.org/x/xerrors" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/stmgr" @@ -338,7 +337,7 @@ func ImportChain(r repo.Repo, fname string) error { bs := blockstore.NewBlockstore(ds) - cst := store.NewChainStore(bs, mds, vm.Syscalls(ffiwrapper.ProofVerifier), journal.NilJournal()) + cst := store.NewChainStore(bs, mds, vm.Syscalls(ffiwrapper.ProofVerifier)) log.Info("importing chain from file...") ts, err := cst.Import(fi) diff --git a/go.sum b/go.sum index ca9f0df33..37703fd02 100644 --- a/go.sum +++ b/go.sum @@ -1230,6 +1230,7 @@ github.com/prometheus/procfs v0.1.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/raulk/clock v1.1.0 h1:dpb29+UKMbLqiU/jqIJptgLR1nn23HLgMY0sTCDza5Y= github.com/raulk/clock v1.1.0/go.mod h1:3MpVxdZ/ODBQDxbN+kzshf5OSZwPjtMDx6BBXBmOeY0= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -1327,6 +1328,7 @@ github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFd github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e/go.mod h1:XDKHRm5ThF8YJjx001LtgelzsoaEcvnA7lVWz9EeX3g= +github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/uber/jaeger-client-go v2.15.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.23.1+incompatible h1:uArBYHQR0HqLFFAypI7RsWTzPSj/bDpmZZuQjMLSg1A= @@ -1395,11 +1397,14 @@ 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/go.mod h1:h/1PEBwj7Ym/8kOuMWvO2ujZ6Lt+TMbySEXNhjjR87I= +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= github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542 h1:oWgZJmC1DorFZDpfMfWg7xk29yEOZiXmo/wZl+utTI8= 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.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 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= @@ -1482,6 +1487,8 @@ golang.org/x/crypto v0.0.0-20200427165652-729f1e841bcc/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 h1:vEg9joUBmeBcK9iSJftGNf3coIG4HqZElCPehJsfAYM= 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/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= @@ -1515,6 +1522,7 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180524181706-dfa909b99c79/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1557,6 +1565,8 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200519113804-d87ec0cfa476/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM= golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1695,6 +1705,7 @@ golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200318150045-ba25ddc85566/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4 h1:kDtqNkeBrZb8B+atrj50B5XLHpzXXqcCdZPP/ApQ5NY= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200711155855-7342f9734a7d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= @@ -1808,6 +1819,7 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= @@ -1825,6 +1837,11 @@ howett.net/plist v0.0.0-20181124034731-591f970eefbb h1:jhnBjNi9UFpfpl8YZhA9CrOqp howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0= launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= +modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= +modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= +modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= +modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/journal/fs.go b/journal/fs.go index 73a2fff43..7d5203556 100644 --- a/journal/fs.go +++ b/journal/fs.go @@ -16,7 +16,7 @@ import ( // fsJournal is a basic journal backed by files on a filesystem. type fsJournal struct { - EventTypeFactory + EventTypeRegistry dir string sizeLimit int64 @@ -40,12 +40,12 @@ func OpenFSJournal(lr repo.LockedRepo, disabled DisabledEvents) (Journal, error) } f := &fsJournal{ - EventTypeFactory: NewEventTypeFactory(disabled), - dir: dir, - sizeLimit: 1 << 30, - incoming: make(chan *Event, 32), - closing: make(chan struct{}), - closed: make(chan struct{}), + EventTypeRegistry: NewEventTypeRegistry(disabled), + dir: dir, + sizeLimit: 1 << 30, + incoming: make(chan *Event, 32), + closing: make(chan struct{}), + closed: make(chan struct{}), } if err := f.rollJournalFile(); err != nil { @@ -57,11 +57,21 @@ func OpenFSJournal(lr repo.LockedRepo, disabled DisabledEvents) (Journal, error) return f, nil } -func (f *fsJournal) RecordEvent(evtType EventType, obj interface{}) { +func (f *fsJournal) RecordEvent(evtType EventType, supplier func() interface{}) { + defer func() { + if r := recover(); r != nil { + log.Warnf("recovered from panic while recording journal event; type=%s, err=%v", evtType, r) + } + }() + + if !evtType.Enabled() { + return + } + je := &Event{ EventType: evtType, Timestamp: build.Clock.Now(), - Data: obj, + Data: supplier(), } select { case f.incoming <- je: diff --git a/journal/global.go b/journal/global.go new file mode 100644 index 000000000..b4d0e0a1b --- /dev/null +++ b/journal/global.go @@ -0,0 +1,9 @@ +package journal + +var ( + // J is a globally accessible Journal. It starts being NilJournal, and early + // during the Lotus initialization routine, it is reset to whichever Journal + // is configured (by default, the filesystem journal). Components can safely + // record in the journal by calling: journal.J.RecordEvent(...). + J Journal = NilJournal() // nolint +) diff --git a/journal/nil.go b/journal/nil.go index 5d0c78b05..fa72fa373 100644 --- a/journal/nil.go +++ b/journal/nil.go @@ -11,6 +11,6 @@ func NilJournal() Journal { func (n *nilJournal) RegisterEventType(_, _ string) EventType { return EventType{} } -func (n *nilJournal) RecordEvent(_ EventType, _ interface{}) {} +func (n *nilJournal) RecordEvent(_ EventType, _ func() interface{}) {} func (n *nilJournal) Close() error { return nil } diff --git a/journal/registry.go b/journal/registry.go new file mode 100644 index 000000000..6ab5b5fb1 --- /dev/null +++ b/journal/registry.go @@ -0,0 +1,57 @@ +package journal + +import "sync" + +// EventTypeRegistry is a component that constructs tracked EventType tokens, +// for usage with a Journal. +type EventTypeRegistry interface { + + // RegisterEventType introduces a new event type to a journal, and + // returns an EventType token that components can later use to check whether + // journalling for that type is enabled/suppressed, and to tag journal + // entries appropriately. + RegisterEventType(system, event string) EventType +} + +// eventTypeRegistry is an embeddable mixin that takes care of tracking disabled +// event types, and returning initialized/safe EventTypes when requested. +type eventTypeRegistry struct { + sync.Mutex + + m map[string]EventType +} + +var _ EventTypeRegistry = (*eventTypeRegistry)(nil) + +func NewEventTypeRegistry(disabled DisabledEvents) EventTypeRegistry { + ret := &eventTypeRegistry{ + m: make(map[string]EventType, len(disabled)+32), // + extra capacity. + } + + for _, et := range disabled { + et.enabled, et.safe = false, true + ret.m[et.System+":"+et.Event] = et + } + + return ret +} + +func (d *eventTypeRegistry) RegisterEventType(system, event string) EventType { + d.Lock() + defer d.Unlock() + + key := system + ":" + event + if et, ok := d.m[key]; ok { + return et + } + + et := EventType{ + System: system, + Event: event, + enabled: true, + safe: true, + } + + d.m[key] = et + return et +} diff --git a/journal/types.go b/journal/types.go index 6183e6cfa..c81fb8c89 100644 --- a/journal/types.go +++ b/journal/types.go @@ -1,7 +1,6 @@ package journal import ( - "sync" "time" logging "github.com/ipfs/go-log" @@ -49,16 +48,6 @@ func (et EventType) Enabled() bool { return et.safe && et.enabled } -// EventTypeFactory is a component that constructs tracked EventType tokens, -// for usage with a Journal. -type EventTypeFactory interface { - // RegisterEventType introduces a new event type to a journal, and - // returns an EventType token that components can later use to check whether - // journalling for that type is enabled/suppressed, and to tag journal - // entries appropriately. - RegisterEventType(system, event string) EventType -} - // Journal represents an audit trail of system actions. // // Every entry is tagged with a timestamp, a system name, and an event name. @@ -68,11 +57,14 @@ type EventTypeFactory interface { // For cleanliness and type safety, we recommend to use typed events. See the // *Evt struct types in this package for more info. type Journal interface { - EventTypeFactory + EventTypeRegistry - // RecordEvent records this event to the journal. See godocs on the Journal type - // for more info. - RecordEvent(evtType EventType, data interface{}) + // RecordEvent records this event to the journal, if and only if the + // EventType is enabled. If so, it calls the supplier function to obtain + // the payload to record. + // + // Implementations MUST recover from panics raised by the supplier function. + RecordEvent(evtType EventType, supplier func() interface{}) // Close closes this journal for further writing. Close() error @@ -87,70 +79,3 @@ type Event struct { Timestamp time.Time Data interface{} } - -// MaybeRecordEvent is a convenience function that evaluates if the EventType is -// enabled, and if so, it calls the supplier to create the event and -// subsequently journal.RecordEvent on the provided journal to record it. -// -// It also recovers from panics raised when calling the supplier function. -// -// This is safe to call with a nil Journal, either because the value is nil, -// or because a journal obtained through NilJournal() is in use. -func MaybeRecordEvent(journal Journal, evtType EventType, supplier func() interface{}) { - defer func() { - if r := recover(); r != nil { - log.Warnf("recovered from panic while recording journal event; type=%s, err=%v", evtType, r) - } - }() - - if journal == nil || journal == nilj { - return - } - if !evtType.Enabled() { - return - } - journal.RecordEvent(evtType, supplier()) -} - -// eventTypeFactory is an embeddable mixin that takes care of tracking disabled -// event types, and returning initialized/safe EventTypes when requested. -type eventTypeFactory struct { - sync.Mutex - - m map[string]EventType -} - -var _ EventTypeFactory = (*eventTypeFactory)(nil) - -func NewEventTypeFactory(disabled DisabledEvents) EventTypeFactory { - ret := &eventTypeFactory{ - m: make(map[string]EventType, len(disabled)+32), // + extra capacity. - } - - for _, et := range disabled { - et.enabled, et.safe = false, true - ret.m[et.System+":"+et.Event] = et - } - - return ret -} - -func (d *eventTypeFactory) RegisterEventType(system, event string) EventType { - d.Lock() - defer d.Unlock() - - key := system + ":" + event - if et, ok := d.m[key]; ok { - return et - } - - et := EventType{ - System: system, - Event: event, - enabled: true, - safe: true, - } - - d.m[key] = et - return et -} diff --git a/markets/storageadapter/client.go b/markets/storageadapter/client.go index 9186b94c0..761a4aa74 100644 --- a/markets/storageadapter/client.go +++ b/markets/storageadapter/client.go @@ -43,8 +43,6 @@ type ClientNodeAdapter struct { fm *market.FundMgr ev *events.Events - jrnl journal.Journal - // index 0 is unused, as it corresponds to evtTypeDealAccepted, a provider-only event. evtTypes [4]journal.EventType } @@ -54,7 +52,7 @@ 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, jrnl journal.Journal) storagemarket.StorageClientNode { +func NewClientNodeAdapter(state full.StateAPI, chain full.ChainAPI, mpool full.MpoolAPI, sm *stmgr.StateManager, cs *store.ChainStore, fm *market.FundMgr) storagemarket.StorageClientNode { return &ClientNodeAdapter{ StateAPI: state, ChainAPI: chain, @@ -65,11 +63,10 @@ func NewClientNodeAdapter(state full.StateAPI, chain full.ChainAPI, mpool full.M fm: fm, ev: events.NewEvents(context.TODO(), &clientApi{chain, state}), - jrnl: jrnl, evtTypes: [...]journal.EventType{ - evtTypeDealSectorCommitted: jrnl.RegisterEventType("markets:storage:client", "deal_sector_committed"), - evtTypeDealExpired: jrnl.RegisterEventType("markets:storage:client", "deal_expired"), - evtTypeDealSlashed: jrnl.RegisterEventType("markets:storage:client", "deal_slashed"), + evtTypeDealSectorCommitted: journal.J.RegisterEventType("markets:storage:client", "deal_sector_committed"), + evtTypeDealExpired: journal.J.RegisterEventType("markets:storage:client", "deal_expired"), + evtTypeDealSlashed: journal.J.RegisterEventType("markets:storage:client", "deal_slashed"), }, } } @@ -236,7 +233,7 @@ func (c *ClientNodeAdapter) ValidatePublishedDeal(ctx context.Context, deal stor } dealID := res.IDs[dealIdx] - journal.MaybeRecordEvent(c.jrnl, c.evtTypes[evtTypeDealAccepted], func() interface{} { + journal.J.RecordEvent(c.evtTypes[evtTypeDealAccepted], func() interface{} { deal := deal // copy and strip fields we don't want to log to the journal deal.ClientSignature = crypto.Signature{} return ClientDealAcceptedEvt{ID: dealID, Deal: deal, Height: c.cs.GetHeaviestTipSet().Height()} @@ -294,7 +291,7 @@ func (c *ClientNodeAdapter) OnDealSectorCommitted(ctx context.Context, provider log.Infof("Storage deal %d activated at epoch %d", dealId, sd.State.SectorStartEpoch) - journal.MaybeRecordEvent(c.jrnl, c.evtTypes[evtTypeDealSectorCommitted], func() interface{} { + journal.J.RecordEvent(c.evtTypes[evtTypeDealSectorCommitted], func() interface{} { return ClientDealSectorCommittedEvt{ID: dealId, State: sd.State, Height: curH} }) diff --git a/markets/storageadapter/provider.go b/markets/storageadapter/provider.go index 8e31939df..d772a36a8 100644 --- a/markets/storageadapter/provider.go +++ b/markets/storageadapter/provider.go @@ -47,23 +47,21 @@ type ProviderNodeAdapter struct { secb *sectorblocks.SectorBlocks ev *events.Events - jrnl journal.Journal evtTypes [4]journal.EventType } -func NewProviderNodeAdapter(dag dtypes.StagingDAG, secb *sectorblocks.SectorBlocks, full api.FullNode, jrnl journal.Journal) storagemarket.StorageProviderNode { +func NewProviderNodeAdapter(dag dtypes.StagingDAG, secb *sectorblocks.SectorBlocks, full api.FullNode) storagemarket.StorageProviderNode { return &ProviderNodeAdapter{ FullNode: full, dag: dag, secb: secb, ev: events.NewEvents(context.TODO(), full), - jrnl: jrnl, evtTypes: [...]journal.EventType{ - evtTypeDealAccepted: jrnl.RegisterEventType("markets:storage:provider", "deal_complete"), - evtTypeDealSectorCommitted: jrnl.RegisterEventType("markets:storage:provider", "deal_sector_committed"), - evtTypeDealExpired: jrnl.RegisterEventType("markets:storage:provider", "deal_expired"), - evtTypeDealSlashed: jrnl.RegisterEventType("markets:storage:provider", "deal_slashed"), + evtTypeDealAccepted: journal.J.RegisterEventType("markets:storage:provider", "deal_complete"), + evtTypeDealSectorCommitted: journal.J.RegisterEventType("markets:storage:provider", "deal_sector_committed"), + evtTypeDealExpired: journal.J.RegisterEventType("markets:storage:provider", "deal_expired"), + evtTypeDealSlashed: journal.J.RegisterEventType("markets:storage:provider", "deal_slashed"), }, } } @@ -113,7 +111,7 @@ func (n *ProviderNodeAdapter) OnDealComplete(ctx context.Context, deal storagema log.Warnf("New Deal: deal %d", deal.DealID) - journal.MaybeRecordEvent(n.jrnl, n.evtTypes[evtTypeDealAccepted], func() interface{} { + journal.J.RecordEvent(n.evtTypes[evtTypeDealAccepted], func() interface{} { deal := deal // copy and strip fields we don't want to log to the journal deal.ClientSignature = crypto.Signature{} return MinerDealAcceptedEvt{ID: deal.DealID, Deal: deal} @@ -297,7 +295,7 @@ func (n *ProviderNodeAdapter) OnDealSectorCommitted(ctx context.Context, provide log.Infof("Storage deal %d activated at epoch %d", dealID, sd.State.SectorStartEpoch) - journal.MaybeRecordEvent(n.jrnl, n.evtTypes[evtTypeDealSectorCommitted], func() interface{} { + journal.J.RecordEvent(n.evtTypes[evtTypeDealSectorCommitted], func() interface{} { return MinerDealSectorCommittedEvt{ID: dealID, State: sd.State, Height: curH} }) @@ -407,7 +405,7 @@ func (n *ProviderNodeAdapter) OnDealExpiredOrSlashed(ctx context.Context, dealID // Check if the deal has already expired if sd.Proposal.EndEpoch <= height { onDealExpired(nil) - journal.MaybeRecordEvent(n.jrnl, n.evtTypes[evtTypeDealExpired], func() interface{} { + journal.J.RecordEvent(n.evtTypes[evtTypeDealExpired], func() interface{} { return MinerDealExpiredEvt{ID: dealID, State: sd.State, Height: height} }) return true, false, nil @@ -416,7 +414,7 @@ func (n *ProviderNodeAdapter) OnDealExpiredOrSlashed(ctx context.Context, dealID // If there is no deal assume it's already been slashed if sd.State.SectorStartEpoch < 0 { onDealSlashed(height, nil) - journal.MaybeRecordEvent(n.jrnl, n.evtTypes[evtTypeDealSlashed], func() interface{} { + journal.J.RecordEvent(n.evtTypes[evtTypeDealSlashed], func() interface{} { return MinerDealSlashedEvt{ID: dealID, State: sd.State, Height: height} }) return true, false, nil @@ -435,7 +433,7 @@ func (n *ProviderNodeAdapter) OnDealExpiredOrSlashed(ctx context.Context, dealID // Check if the deal has already expired if sd.Proposal.EndEpoch <= height { onDealExpired(nil) - journal.MaybeRecordEvent(n.jrnl, n.evtTypes[evtTypeDealExpired], func() interface{} { + journal.J.RecordEvent(n.evtTypes[evtTypeDealExpired], func() interface{} { return MinerDealExpiredEvt{ID: dealID, State: sd.State, Height: height} }) return false, nil @@ -461,7 +459,7 @@ func (n *ProviderNodeAdapter) OnDealExpiredOrSlashed(ctx context.Context, dealID // Deal was slashed if deal.To == nil { onDealSlashed(height, nil) - journal.MaybeRecordEvent(n.jrnl, n.evtTypes[evtTypeDealSlashed], func() interface{} { + journal.J.RecordEvent(n.evtTypes[evtTypeDealSlashed], func() interface{} { return MinerDealSlashedEvt{ID: dealID, State: sd.State, Height: height} }) return false, nil diff --git a/miner/miner.go b/miner/miner.go index 091919b6c..bf1874f53 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -47,7 +47,7 @@ func randTimeOffset(width time.Duration) time.Duration { return val - (width / 2) } -func NewMiner(api api.FullNode, epp gen.WinningPoStProver, addr address.Address, sf *slashfilter.SlashFilter, jrnl journal.Journal) *Miner { +func NewMiner(api api.FullNode, epp gen.WinningPoStProver, addr address.Address, sf *slashfilter.SlashFilter) *Miner { arc, err := lru.NewARC(10000) if err != nil { panic(err) @@ -71,9 +71,8 @@ func NewMiner(api api.FullNode, epp gen.WinningPoStProver, addr address.Address, sf: sf, minedBlockHeights: arc, - jrnl: jrnl, evtTypes: [...]journal.EventType{ - evtTypeBlockMined: jrnl.RegisterEventType("miner", "block_mined"), + evtTypeBlockMined: journal.J.RegisterEventType("miner", "block_mined"), }, } } @@ -95,7 +94,6 @@ type Miner struct { sf *slashfilter.SlashFilter minedBlockHeights *lru.ARCCache - jrnl journal.Journal evtTypes [1]journal.EventType } @@ -225,7 +223,7 @@ func (m *Miner) mine(ctx context.Context) { onDone(b != nil, nil) if b != nil { - journal.MaybeRecordEvent(m.jrnl, m.evtTypes[evtTypeBlockMined], func() interface{} { + journal.J.RecordEvent(m.evtTypes[evtTypeBlockMined], func() interface{} { return map[string]interface{}{ "parents": base.TipSet.Cids(), "nulls": base.NullRounds, diff --git a/node/builder.go b/node/builder.go index 580aec3df..000099a43 100644 --- a/node/builder.go +++ b/node/builder.go @@ -152,14 +152,18 @@ type Settings struct { func defaults() []Option { return []Option{ + // global system journal. + Override(new(journal.DisabledEvents), journal.DefaultDisabledEvents), + Override(new(journal.Journal), modules.OpenFilesystemJournal), + Override(InitJournalKey, func(j journal.Journal) { + journal.J = j // eagerly sets the global journal through fx.Invoke. + }), + Override(new(helpers.MetricsCtx), context.Background), Override(new(record.Validator), modules.RecordValidator), Override(new(dtypes.Bootstrapper), dtypes.Bootstrapper(false)), Override(new(dtypes.ShutdownChan), make(chan struct{})), - Override(new(journal.Journal), modules.OpenFilesystemJournal), - Override(new(journal.DisabledEvents), journal.DefaultDisabledEvents), - Override(InitJournalKey, func(j journal.Journal) { /* forces the creation of the journal at startup */ }), // Filecoin modules } diff --git a/node/modules/chain.go b/node/modules/chain.go index 7ad4786ca..904c9f23b 100644 --- a/node/modules/chain.go +++ b/node/modules/chain.go @@ -26,7 +26,6 @@ import ( "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/vm" - "github.com/filecoin-project/lotus/journal" "github.com/filecoin-project/lotus/lib/blockstore" "github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/helpers" @@ -48,9 +47,9 @@ func ChainExchange(mctx helpers.MetricsCtx, lc fx.Lifecycle, host host.Host, rt return exch } -func MessagePool(lc fx.Lifecycle, sm *stmgr.StateManager, ps *pubsub.PubSub, ds dtypes.MetadataDS, nn dtypes.NetworkName, jrnl journal.Journal) (*messagepool.MessagePool, error) { +func MessagePool(lc fx.Lifecycle, sm *stmgr.StateManager, ps *pubsub.PubSub, ds dtypes.MetadataDS, nn dtypes.NetworkName) (*messagepool.MessagePool, error) { mpp := messagepool.NewProvider(sm, ps) - mp, err := messagepool.New(mpp, ds, nn, jrnl) + mp, err := messagepool.New(mpp, ds, nn) if err != nil { return nil, xerrors.Errorf("constructing mpool: %w", err) } @@ -85,8 +84,8 @@ func ChainBlockservice(bs dtypes.ChainBlockstore, rem dtypes.ChainExchange) dtyp return blockservice.New(bs, rem) } -func ChainStore(lc fx.Lifecycle, bs dtypes.ChainBlockstore, ds dtypes.MetadataDS, syscalls vm.SyscallBuilder, journal journal.Journal) *store.ChainStore { - chain := store.NewChainStore(bs, ds, syscalls, journal) +func ChainStore(lc fx.Lifecycle, bs dtypes.ChainBlockstore, ds dtypes.MetadataDS, syscalls vm.SyscallBuilder) *store.ChainStore { + chain := store.NewChainStore(bs, ds, syscalls) if err := chain.Load(); err != nil { log.Warnf("loading chain state from disk: %s", err) diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index fc7458f8f..85ffeb9cc 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -44,11 +44,11 @@ import ( paramfetch "github.com/filecoin-project/go-paramfetch" "github.com/filecoin-project/go-statestore" "github.com/filecoin-project/go-storedcounter" - "github.com/filecoin-project/lotus/journal" + "github.com/filecoin-project/specs-actors/actors/abi" + sectorstorage "github.com/filecoin-project/sector-storage" "github.com/filecoin-project/sector-storage/ffiwrapper" "github.com/filecoin-project/sector-storage/stores" - "github.com/filecoin-project/specs-actors/actors/abi" sealing "github.com/filecoin-project/storage-fsm" lapi "github.com/filecoin-project/lotus/api" @@ -155,7 +155,6 @@ type StorageMinerParams struct { SectorIDCounter sealing.SectorIDCounter Verifier ffiwrapper.Verifier GetSealingDelayFn dtypes.GetSealingDelayFunc - Journal journal.Journal } func StorageMiner(params StorageMinerParams) (*storage.Miner, error) { @@ -169,7 +168,6 @@ func StorageMiner(params StorageMinerParams) (*storage.Miner, error) { sc = params.SectorIDCounter verif = params.Verifier gsd = params.GetSealingDelayFn - jrnl = params.Journal ) maddr, err := minerAddrFromDS(ds) if err != nil { @@ -188,12 +186,12 @@ func StorageMiner(params StorageMinerParams) (*storage.Miner, error) { return nil, err } - fps, err := storage.NewWindowedPoStScheduler(api, sealer, sealer, maddr, worker, jrnl) + fps, err := storage.NewWindowedPoStScheduler(api, sealer, sealer, maddr, worker) if err != nil { return nil, err } - sm, err := storage.NewMiner(api, maddr, worker, h, ds, sealer, sc, verif, gsd, jrnl) + sm, err := storage.NewMiner(api, maddr, worker, h, ds, sealer, sc, verif, gsd) if err != nil { return nil, err } @@ -340,13 +338,13 @@ func StagingGraphsync(mctx helpers.MetricsCtx, lc fx.Lifecycle, ibs dtypes.Stagi return gs } -func SetupBlockProducer(lc fx.Lifecycle, ds dtypes.MetadataDS, api lapi.FullNode, epp gen.WinningPoStProver, sf *slashfilter.SlashFilter, jrnl journal.Journal) (*miner.Miner, error) { +func SetupBlockProducer(lc fx.Lifecycle, ds dtypes.MetadataDS, api lapi.FullNode, epp gen.WinningPoStProver, sf *slashfilter.SlashFilter) (*miner.Miner, error) { minerAddr, err := minerAddrFromDS(ds) if err != nil { return nil, err } - m := miner.NewMiner(api, epp, minerAddr, sf, jrnl) + m := miner.NewMiner(api, epp, minerAddr, sf) lc.Append(fx.Hook{ OnStart: func(ctx context.Context) error { diff --git a/storage/miner.go b/storage/miner.go index 2c37e8c4a..b09ee2fc4 100644 --- a/storage/miner.go +++ b/storage/miner.go @@ -45,7 +45,6 @@ type Miner struct { getSealDelay dtypes.GetSealingDelayFunc sealing *sealing.Sealing - jrnl journal.Journal sealingEvtType journal.EventType } @@ -94,7 +93,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.GetSealingDelayFunc, jrnl journal.Journal) (*Miner, 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.GetSealingDelayFunc) (*Miner, error) { m := &Miner{ api: api, h: h, @@ -107,8 +106,7 @@ func NewMiner(api storageMinerApi, maddr, worker address.Address, h host.Host, d worker: worker, getSealDelay: gsd, - jrnl: jrnl, - sealingEvtType: jrnl.RegisterEventType("storage", "sealing_states"), + sealingEvtType: journal.J.RegisterEventType("storage", "sealing_states"), } return m, nil @@ -135,7 +133,7 @@ func (m *Miner) Run(ctx context.Context) error { } func (m *Miner) handleSealingNotifications(before, after sealing.SectorInfo) { - journal.MaybeRecordEvent(m.jrnl, m.sealingEvtType, func() interface{} { + journal.J.RecordEvent(m.sealingEvtType, func() interface{} { return SealingStateEvt{ SectorNumber: before.SectorNumber, SectorType: before.SectorType, diff --git a/storage/wdpost_run.go b/storage/wdpost_run.go index c448fb223..7fff0b916 100644 --- a/storage/wdpost_run.go +++ b/storage/wdpost_run.go @@ -26,7 +26,7 @@ import ( var errNoPartitions = errors.New("no partitions") func (s *WindowPoStScheduler) failPost(err error, deadline *miner.DeadlineInfo) { - journal.MaybeRecordEvent(s.jrnl, s.wdPoStEvtType, func() interface{} { + journal.J.RecordEvent(s.wdPoStEvtType, func() interface{} { return s.enrichWithTipset(WindowPoStEvt{ State: "failed", Deadline: s.activeDeadline, @@ -48,7 +48,7 @@ func (s *WindowPoStScheduler) doPost(ctx context.Context, deadline *miner.Deadli s.abort = abort s.activeDeadline = deadline - journal.MaybeRecordEvent(s.jrnl, s.wdPoStEvtType, func() interface{} { + journal.J.RecordEvent(s.wdPoStEvtType, func() interface{} { return s.enrichWithTipset(WindowPoStEvt{ State: "started", Deadline: s.activeDeadline, @@ -64,7 +64,7 @@ func (s *WindowPoStScheduler) doPost(ctx context.Context, deadline *miner.Deadli // recordEvent records a successful proofs_processed event in the // journal, even if it was a noop (no partitions). recordEvent := func(partitions []miner.PoStPartition, mcid cid.Cid) { - journal.MaybeRecordEvent(s.jrnl, s.wdPoStEvtType, func() interface{} { + journal.J.RecordEvent(s.wdPoStEvtType, func() interface{} { return s.enrichWithTipset(WindowPoStEvt{ State: "proofs_processed", Deadline: s.activeDeadline, @@ -95,7 +95,7 @@ func (s *WindowPoStScheduler) doPost(ctx context.Context, deadline *miner.Deadli return } - journal.MaybeRecordEvent(s.jrnl, s.wdPoStEvtType, func() interface{} { + journal.J.RecordEvent(s.wdPoStEvtType, func() interface{} { return s.enrichWithTipset(WindowPoStEvt{ State: "succeeded", Deadline: s.activeDeadline, @@ -159,7 +159,7 @@ func (s *WindowPoStScheduler) checkNextRecoveries(ctx context.Context, dlIdx uin Recoveries: []miner.RecoveryDeclaration{}, } - defer journal.MaybeRecordEvent(s.jrnl, s.wdPoStEvtType, func() interface{} { + defer journal.J.RecordEvent(s.wdPoStEvtType, func() interface{} { var mcid cid.Cid if sm != nil { mcid = sm.Cid() @@ -265,7 +265,7 @@ func (s *WindowPoStScheduler) checkNextFaults(ctx context.Context, dlIdx uint64, Faults: []miner.FaultDeclaration{}, } - defer journal.MaybeRecordEvent(s.jrnl, s.wdPoStEvtType, func() interface{} { + defer journal.J.RecordEvent(s.wdPoStEvtType, func() interface{} { var mcid cid.Cid if sm != nil { mcid = sm.Cid() diff --git a/storage/wdpost_sched.go b/storage/wdpost_sched.go index 2c55b93ef..c73d320f3 100644 --- a/storage/wdpost_sched.go +++ b/storage/wdpost_sched.go @@ -66,14 +66,13 @@ type WindowPoStScheduler struct { activeDeadline *miner.DeadlineInfo abort context.CancelFunc - jrnl journal.Journal wdPoStEvtType journal.EventType // failed abi.ChainEpoch // eps // failLk sync.Mutex } -func NewWindowedPoStScheduler(api storageMinerApi, sb storage.Prover, ft sectorstorage.FaultTracker, actor address.Address, worker address.Address, jrnl journal.Journal) (*WindowPoStScheduler, error) { +func NewWindowedPoStScheduler(api storageMinerApi, sb storage.Prover, ft sectorstorage.FaultTracker, actor address.Address, worker 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) @@ -93,8 +92,7 @@ func NewWindowedPoStScheduler(api storageMinerApi, sb storage.Prover, ft sectors actor: actor, worker: worker, - jrnl: jrnl, - wdPoStEvtType: jrnl.RegisterEventType("storage", "wdpost"), + wdPoStEvtType: journal.J.RegisterEventType("storage", "wdpost"), }, nil } @@ -248,7 +246,7 @@ func (s *WindowPoStScheduler) abortActivePoSt() { if s.abort != nil { s.abort() - journal.MaybeRecordEvent(s.jrnl, s.wdPoStEvtType, func() interface{} { + journal.J.RecordEvent(s.wdPoStEvtType, func() interface{} { return s.enrichWithTipset(WindowPoStEvt{ State: "abort", Deadline: s.activeDeadline, From cb8e105a948aaeea1bdd2e989821a1403b573cea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Wed, 26 Aug 2020 16:44:06 +0100 Subject: [PATCH 22/40] reduce diff noise. --- chain/messagepool/messagepool_test.go | 5 ----- chain/messagepool/repub.go | 1 - chain/messagepool/selection_test.go | 2 -- chain/store/index_test.go | 9 ++++----- cmd/lotus-storage-miner/init.go | 2 -- cmd/lotus/daemon.go | 4 ++-- 6 files changed, 6 insertions(+), 17 deletions(-) diff --git a/chain/messagepool/messagepool_test.go b/chain/messagepool/messagepool_test.go index d5caf7428..316c86d87 100644 --- a/chain/messagepool/messagepool_test.go +++ b/chain/messagepool/messagepool_test.go @@ -7,22 +7,17 @@ import ( "testing" "github.com/filecoin-project/go-address" - "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/filecoin-project/specs-actors/actors/crypto" "github.com/ipfs/go-cid" "github.com/ipfs/go-datastore" logging "github.com/ipfs/go-log/v2" - - _ "github.com/filecoin-project/lotus/lib/sigs/bls" - _ "github.com/filecoin-project/lotus/lib/sigs/secp" ) func init() { diff --git a/chain/messagepool/repub.go b/chain/messagepool/repub.go index 1fbd66d86..5095821fb 100644 --- a/chain/messagepool/repub.go +++ b/chain/messagepool/repub.go @@ -11,7 +11,6 @@ import ( "github.com/filecoin-project/lotus/chain/messagepool/gasguess" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/journal" - "github.com/ipfs/go-cid" ) diff --git a/chain/messagepool/selection_test.go b/chain/messagepool/selection_test.go index 98c82e324..2d17f7115 100644 --- a/chain/messagepool/selection_test.go +++ b/chain/messagepool/selection_test.go @@ -8,13 +8,11 @@ import ( "testing" "github.com/filecoin-project/go-address" - "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/specs-actors/actors/crypto" "github.com/ipfs/go-cid" diff --git a/chain/store/index_test.go b/chain/store/index_test.go index 0a7fc3559..5c49c6791 100644 --- a/chain/store/index_test.go +++ b/chain/store/index_test.go @@ -5,15 +5,14 @@ import ( "context" "testing" - "github.com/filecoin-project/specs-actors/actors/abi" - "github.com/ipfs/go-datastore" - syncds "github.com/ipfs/go-datastore/sync" - "github.com/stretchr/testify/assert" - "github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types/mock" "github.com/filecoin-project/lotus/lib/blockstore" + "github.com/filecoin-project/specs-actors/actors/abi" + datastore "github.com/ipfs/go-datastore" + syncds "github.com/ipfs/go-datastore/sync" + "github.com/stretchr/testify/assert" ) func TestIndexSeeks(t *testing.T) { diff --git a/cmd/lotus-storage-miner/init.go b/cmd/lotus-storage-miner/init.go index 57f9c072f..e33030e4e 100644 --- a/cmd/lotus-storage-miner/init.go +++ b/cmd/lotus-storage-miner/init.go @@ -26,11 +26,9 @@ import ( "github.com/filecoin-project/go-address" cborutil "github.com/filecoin-project/go-cbor-util" paramfetch "github.com/filecoin-project/go-paramfetch" - 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/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin/market" diff --git a/cmd/lotus/daemon.go b/cmd/lotus/daemon.go index b697cda26..848596944 100644 --- a/cmd/lotus/daemon.go +++ b/cmd/lotus/daemon.go @@ -12,6 +12,8 @@ import ( "runtime/pprof" "strings" + "github.com/filecoin-project/lotus/chain/types" + paramfetch "github.com/filecoin-project/go-paramfetch" "github.com/mitchellh/go-homedir" "github.com/multiformats/go-multiaddr" @@ -22,8 +24,6 @@ import ( "go.opencensus.io/tag" "golang.org/x/xerrors" - "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/stmgr" From 0b6a182a44d8860ddb580f82f0e4fa7cd059ec18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Wed, 2 Sep 2020 19:15:07 +0100 Subject: [PATCH 23/40] move InitJournalKey to the top; add godcs on invoke order. --- node/builder.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/node/builder.go b/node/builder.go index 670702fff..bd9bc5005 100644 --- a/node/builder.go +++ b/node/builder.go @@ -91,11 +91,16 @@ var ( type invoke int +// Invokes are called in the order they are defined. //nolint:golint const ( + // InitJournal at position 0 initializes the journal global var as soon as + // the system starts, so that it's available for all other components. + InitJournalKey = invoke(iota) + // libp2p - PstoreAddSelfKeysKey = invoke(iota) + PstoreAddSelfKeysKey StartListeningKey BootstrapKey @@ -123,7 +128,6 @@ const ( HeadMetricsKey SettlePaymentChannelsKey RunPeerTaggerKey - InitJournalKey SetApiEndpointKey From ac152abc75419c785f1da1a4ddec61d7015d4c39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Wed, 2 Sep 2020 19:15:25 +0100 Subject: [PATCH 24/40] shuffle code to journal wdpost events. --- storage/wdpost_run.go | 125 ++++++++++++++++++++++-------------------- 1 file changed, 66 insertions(+), 59 deletions(-) diff --git a/storage/wdpost_run.go b/storage/wdpost_run.go index cde31d135..83861a6d8 100644 --- a/storage/wdpost_run.go +++ b/storage/wdpost_run.go @@ -151,41 +151,24 @@ func (s *WindowPoStScheduler) checkSectors(ctx context.Context, check abi.BitFie return sbf, nil } -func (s *WindowPoStScheduler) checkNextRecoveries(ctx context.Context, dlIdx uint64, partitions []*miner.Partition) error { +func (s *WindowPoStScheduler) checkNextRecoveries(ctx context.Context, dlIdx uint64, partitions []*miner.Partition) ([]miner.RecoveryDeclaration, *types.SignedMessage, error) { ctx, span := trace.StartSpan(ctx, "storage.checkNextRecoveries") defer span.End() - var sm *types.SignedMessage faulty := uint64(0) params := &miner.DeclareFaultsRecoveredParams{ Recoveries: []miner.RecoveryDeclaration{}, } - defer journal.J.RecordEvent(s.wdPoStEvtType, func() interface{} { - var mcid cid.Cid - if sm != nil { - mcid = sm.Cid() - } - - return s.enrichWithTipset(WindowPoStEvt{ - State: "recoveries_processed", - Deadline: s.activeDeadline, - Recoveries: &WindowPoStEvt_Recoveries{ - Declarations: params.Recoveries, - MessageCID: mcid, - }, - }) - }) - for partIdx, partition := range partitions { unrecovered, err := bitfield.SubtractBitField(partition.Faults, partition.Recoveries) if err != nil { - return xerrors.Errorf("subtracting recovered set from fault set: %w", err) + return nil, nil, xerrors.Errorf("subtracting recovered set from fault set: %w", err) } uc, err := unrecovered.Count() if err != nil { - return xerrors.Errorf("counting unrecovered sectors: %w", err) + return nil, nil, xerrors.Errorf("counting unrecovered sectors: %w", err) } if uc == 0 { @@ -196,13 +179,13 @@ func (s *WindowPoStScheduler) checkNextRecoveries(ctx context.Context, dlIdx uin recovered, err := s.checkSectors(ctx, unrecovered) if err != nil { - return xerrors.Errorf("checking unrecovered sectors: %w", err) + return nil, nil, xerrors.Errorf("checking unrecovered sectors: %w", err) } // if all sectors failed to recover, don't declare recoveries recoveredCount, err := recovered.Count() if err != nil { - return xerrors.Errorf("counting recovered sectors: %w", err) + return nil, nil, xerrors.Errorf("counting recovered sectors: %w", err) } if recoveredCount == 0 { @@ -216,17 +199,18 @@ func (s *WindowPoStScheduler) checkNextRecoveries(ctx context.Context, dlIdx uin }) } - if len(params.Recoveries) == 0 { + recoveries := params.Recoveries + if len(recoveries) == 0 { if faulty != 0 { log.Warnw("No recoveries to declare", "deadline", dlIdx, "faulty", faulty) } - return nil + return recoveries, nil, nil } enc, aerr := actors.SerializeParams(params) if aerr != nil { - return xerrors.Errorf("could not serialize declare recoveries parameters: %w", aerr) + return recoveries, nil, xerrors.Errorf("could not serialize declare recoveries parameters: %w", aerr) } msg := &types.Message{ @@ -241,67 +225,51 @@ func (s *WindowPoStScheduler) checkNextRecoveries(ctx context.Context, dlIdx uin sm, err := s.api.MpoolPushMessage(ctx, msg, &api.MessageSendSpec{MaxFee: abi.TokenAmount(s.feeCfg.MaxWindowPoStGasFee)}) if err != nil { - return xerrors.Errorf("pushing message to mpool: %w", err) + return recoveries, sm, xerrors.Errorf("pushing message to mpool: %w", err) } log.Warnw("declare faults recovered Message CID", "cid", sm.Cid()) rec, err := s.api.StateWaitMsg(context.TODO(), sm.Cid(), build.MessageConfidence) if err != nil { - return xerrors.Errorf("declare faults recovered wait error: %w", err) + return recoveries, sm, xerrors.Errorf("declare faults recovered wait error: %w", err) } if rec.Receipt.ExitCode != 0 { - return xerrors.Errorf("declare faults recovered wait non-0 exit code: %d", rec.Receipt.ExitCode) + return recoveries, sm, xerrors.Errorf("declare faults recovered wait non-0 exit code: %d", rec.Receipt.ExitCode) } - return nil + return recoveries, sm, nil } -func (s *WindowPoStScheduler) checkNextFaults(ctx context.Context, dlIdx uint64, partitions []*miner.Partition) error { +func (s *WindowPoStScheduler) checkNextFaults(ctx context.Context, dlIdx uint64, partitions []*miner.Partition) ([]miner.FaultDeclaration, *types.SignedMessage, error) { ctx, span := trace.StartSpan(ctx, "storage.checkNextFaults") defer span.End() - var sm *types.SignedMessage bad := uint64(0) params := &miner.DeclareFaultsParams{ Faults: []miner.FaultDeclaration{}, } - defer journal.J.RecordEvent(s.wdPoStEvtType, func() interface{} { - var mcid cid.Cid - if sm != nil { - mcid = sm.Cid() - } - return s.enrichWithTipset(WindowPoStEvt{ - State: "faults_processed", - Deadline: s.activeDeadline, - Faults: &WindowPoStEvt_Faults{ - Declarations: params.Faults, - MessageCID: mcid, - }, - }) - }) - for partIdx, partition := range partitions { toCheck, err := partition.ActiveSectors() if err != nil { - return xerrors.Errorf("getting active sectors: %w", err) + return nil, nil, xerrors.Errorf("getting active sectors: %w", err) } good, err := s.checkSectors(ctx, toCheck) if err != nil { - return xerrors.Errorf("checking sectors: %w", err) + return nil, nil, xerrors.Errorf("checking sectors: %w", err) } faulty, err := bitfield.SubtractBitField(toCheck, good) if err != nil { - return xerrors.Errorf("calculating faulty sector set: %w", err) + return nil, nil, xerrors.Errorf("calculating faulty sector set: %w", err) } c, err := faulty.Count() if err != nil { - return xerrors.Errorf("counting faulty sectors: %w", err) + return nil, nil, xerrors.Errorf("counting faulty sectors: %w", err) } if c == 0 { @@ -317,15 +285,16 @@ func (s *WindowPoStScheduler) checkNextFaults(ctx context.Context, dlIdx uint64, }) } - if len(params.Faults) == 0 { - return nil + faults := params.Faults + if len(faults) == 0 { + return faults, nil, nil } log.Errorw("DETECTED FAULTY SECTORS, declaring faults", "count", bad) enc, aerr := actors.SerializeParams(params) if aerr != nil { - return xerrors.Errorf("could not serialize declare faults parameters: %w", aerr) + return faults, nil, xerrors.Errorf("could not serialize declare faults parameters: %w", aerr) } msg := &types.Message{ @@ -340,21 +309,21 @@ func (s *WindowPoStScheduler) checkNextFaults(ctx context.Context, dlIdx uint64, sm, err := s.api.MpoolPushMessage(ctx, msg, spec) if err != nil { - return xerrors.Errorf("pushing message to mpool: %w", err) + return faults, sm, xerrors.Errorf("pushing message to mpool: %w", err) } log.Warnw("declare faults Message CID", "cid", sm.Cid()) rec, err := s.api.StateWaitMsg(context.TODO(), sm.Cid(), build.MessageConfidence) if err != nil { - return xerrors.Errorf("declare faults wait error: %w", err) + return faults, sm, xerrors.Errorf("declare faults wait error: %w", err) } if rec.Receipt.ExitCode != 0 { - return xerrors.Errorf("declare faults wait non-0 exit code: %d", rec.Receipt.ExitCode) + return faults, sm, xerrors.Errorf("declare faults wait non-0 exit code: %d", rec.Receipt.ExitCode) } - return nil + return faults, sm, nil } func (s *WindowPoStScheduler) runPost(ctx context.Context, di miner.DeadlineInfo, ts *types.TipSet) (*miner.SubmitWindowedPoStParams, error) { @@ -374,15 +343,53 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di miner.DeadlineInfo return } - if err := s.checkNextRecoveries(context.TODO(), declDeadline, partitions); err != nil { + var ( + sigmsg *types.SignedMessage + recoveries []miner.RecoveryDeclaration + faults []miner.FaultDeclaration + + // optionalCid returns the CID of the message, or cid.Undef is the + // message is nil. We don't need the argument (could capture the + // pointer), but it's clearer and purer like that. + optionalCid = func(sigmsg *types.SignedMessage) cid.Cid { + if sigmsg == nil { + return cid.Undef + } + return sigmsg.Cid() + } + ) + + if recoveries, sigmsg, err = s.checkNextRecoveries(context.TODO(), declDeadline, partitions); err != nil { // TODO: This is potentially quite bad, but not even trying to post when this fails is objectively worse log.Errorf("checking sector recoveries: %v", err) } - if err := s.checkNextFaults(context.TODO(), declDeadline, partitions); err != nil { + journal.J.RecordEvent(s.wdPoStEvtType, func() interface{} { + return s.enrichWithTipset(WindowPoStEvt{ + State: "recoveries_processed", + Deadline: s.activeDeadline, + Recoveries: &WindowPoStEvt_Recoveries{ + Declarations: recoveries, + MessageCID: optionalCid(sigmsg), + }, + }) + }) + + if faults, sigmsg, err = s.checkNextFaults(context.TODO(), declDeadline, partitions); err != nil { // TODO: This is also potentially really bad, but we try to post anyways log.Errorf("checking sector faults: %v", err) } + + journal.J.RecordEvent(s.wdPoStEvtType, func() interface{} { + return s.enrichWithTipset(WindowPoStEvt{ + State: "faults_processed", + Deadline: s.activeDeadline, + Faults: &WindowPoStEvt_Faults{ + Declarations: faults, + MessageCID: optionalCid(sigmsg), + }, + }) + }) }() buf := new(bytes.Buffer) From f046af337ae2f7391d6b0b288137d95a0620148f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Wed, 2 Sep 2020 19:45:25 +0100 Subject: [PATCH 25/40] split wdpost event into finer-grained ones. --- storage/wdpost_journal.go | 74 +++++++++++++++++++++++++++++++++ storage/wdpost_run.go | 86 ++++++++++++++++++--------------------- storage/wdpost_sched.go | 65 ++++++++++------------------- 3 files changed, 135 insertions(+), 90 deletions(-) create mode 100644 storage/wdpost_journal.go diff --git a/storage/wdpost_journal.go b/storage/wdpost_journal.go new file mode 100644 index 000000000..04bca895c --- /dev/null +++ b/storage/wdpost_journal.go @@ -0,0 +1,74 @@ +package storage + +import ( + "github.com/filecoin-project/specs-actors/actors/abi" + "github.com/filecoin-project/specs-actors/actors/builtin/miner" + + "github.com/ipfs/go-cid" +) + +// SchedulerState defines the possible states in which the scheduler could be, +// for the purposes of journalling. +type SchedulerState string + +const ( + // SchedulerStateStarted gets recorded when a WdPoSt cycle for an + // epoch begins. + SchedulerStateStarted = SchedulerState("started") + // SchedulerStateAborted gets recorded when a WdPoSt cycle for an + // epoch is aborted, normally because of a chain reorg or advancement. + SchedulerStateAborted = SchedulerState("aborted") + // SchedulerStateFaulted gets recorded when a WdPoSt cycle for an + // epoch terminates abnormally, in which case the error is also recorded. + SchedulerStateFaulted = SchedulerState("faulted") + // SchedulerStateSucceeded gets recorded when a WdPoSt cycle for an + // epoch ends successfully. + SchedulerStateSucceeded = SchedulerState("succeeded") +) + +// Journal event types. +const ( + evtTypeWdPoStScheduler = iota + evtTypeWdPoStProofs + evtTypeWdPoStRecoveries + evtTypeWdPoStFaults +) + +// evtCommon is a common set of attributes for Windowed PoSt journal events. +type evtCommon struct { + Deadline *miner.DeadlineInfo + Height abi.ChainEpoch + TipSet []cid.Cid + Error error `json:",omitempty"` +} + +// WdPoStSchedulerEvt is the journal event that gets recorded on scheduler +// actions. +type WdPoStSchedulerEvt struct { + evtCommon + State SchedulerState +} + +// WdPoStProofsProcessedEvt is the journal event that gets recorded when +// Windowed PoSt proofs have been processed. +type WdPoStProofsProcessedEvt struct { + evtCommon + Partitions []miner.PoStPartition + MessageCID cid.Cid `json:",omitempty"` +} + +// WdPoStRecoveriesProcessedEvt is the journal event that gets recorded when +// Windowed PoSt recoveries have been processed. +type WdPoStRecoveriesProcessedEvt struct { + evtCommon + Declarations []miner.RecoveryDeclaration + MessageCID cid.Cid `json:",omitempty"` +} + +// WdPoStFaultsProcessedEvt is the journal event that gets recorded when +// Windowed PoSt faults have been processed. +type WdPoStFaultsProcessedEvt struct { + evtCommon + Declarations []miner.FaultDeclaration + MessageCID cid.Cid `json:",omitempty"` +} diff --git a/storage/wdpost_run.go b/storage/wdpost_run.go index 83861a6d8..1ae454295 100644 --- a/storage/wdpost_run.go +++ b/storage/wdpost_run.go @@ -28,12 +28,11 @@ import ( var errNoPartitions = errors.New("no partitions") func (s *WindowPoStScheduler) failPost(err error, deadline *miner.DeadlineInfo) { - journal.J.RecordEvent(s.wdPoStEvtType, func() interface{} { - return s.enrichWithTipset(WindowPoStEvt{ - State: "failed", - Deadline: s.activeDeadline, - Error: err, - }) + journal.J.RecordEvent(s.evtTypes[evtTypeWdPoStScheduler], func() interface{} { + return WdPoStSchedulerEvt{ + evtCommon: s.getEvtCommon(err), + State: SchedulerStateFaulted, + } }) log.Errorf("TODO") @@ -50,11 +49,11 @@ func (s *WindowPoStScheduler) doPost(ctx context.Context, deadline *miner.Deadli s.abort = abort s.activeDeadline = deadline - journal.J.RecordEvent(s.wdPoStEvtType, func() interface{} { - return s.enrichWithTipset(WindowPoStEvt{ - State: "started", - Deadline: s.activeDeadline, - }) + journal.J.RecordEvent(s.evtTypes[evtTypeWdPoStScheduler], func() interface{} { + return WdPoStSchedulerEvt{ + evtCommon: s.getEvtCommon(nil), + State: SchedulerStateStarted, + } }) go func() { @@ -63,25 +62,22 @@ func (s *WindowPoStScheduler) doPost(ctx context.Context, deadline *miner.Deadli ctx, span := trace.StartSpan(ctx, "WindowPoStScheduler.doPost") defer span.End() - // recordEvent records a successful proofs_processed event in the + // recordProofsEvent records a successful proofs_processed event in the // journal, even if it was a noop (no partitions). - recordEvent := func(partitions []miner.PoStPartition, mcid cid.Cid) { - journal.J.RecordEvent(s.wdPoStEvtType, func() interface{} { - return s.enrichWithTipset(WindowPoStEvt{ - State: "proofs_processed", - Deadline: s.activeDeadline, - Proofs: &WindowPoStEvt_Proofs{ - Partitions: partitions, - MessageCID: mcid, - }, - }) + recordProofsEvent := func(partitions []miner.PoStPartition, mcid cid.Cid) { + journal.J.RecordEvent(s.evtTypes[evtTypeWdPoStProofs], func() interface{} { + return &WdPoStProofsProcessedEvt{ + evtCommon: s.getEvtCommon(nil), + Partitions: partitions, + MessageCID: mcid, + } }) } proof, err := s.runPost(ctx, *deadline, ts) switch err { case errNoPartitions: - recordEvent(nil, cid.Undef) + recordProofsEvent(nil, cid.Undef) return case nil: sm, err := s.submitPost(ctx, proof) @@ -90,18 +86,18 @@ func (s *WindowPoStScheduler) doPost(ctx context.Context, deadline *miner.Deadli s.failPost(err, deadline) return } - recordEvent(proof.Partitions, sm.Cid()) + recordProofsEvent(proof.Partitions, sm.Cid()) default: log.Errorf("runPost failed: %+v", err) s.failPost(err, deadline) return } - journal.J.RecordEvent(s.wdPoStEvtType, func() interface{} { - return s.enrichWithTipset(WindowPoStEvt{ - State: "succeeded", - Deadline: s.activeDeadline, - }) + journal.J.RecordEvent(s.evtTypes[evtTypeWdPoStScheduler], func() interface{} { + return WdPoStSchedulerEvt{ + evtCommon: s.getEvtCommon(nil), + State: SchedulerStateSucceeded, + } }) }() } @@ -364,15 +360,14 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di miner.DeadlineInfo log.Errorf("checking sector recoveries: %v", err) } - journal.J.RecordEvent(s.wdPoStEvtType, func() interface{} { - return s.enrichWithTipset(WindowPoStEvt{ - State: "recoveries_processed", - Deadline: s.activeDeadline, - Recoveries: &WindowPoStEvt_Recoveries{ - Declarations: recoveries, - MessageCID: optionalCid(sigmsg), - }, - }) + journal.J.RecordEvent(s.evtTypes[evtTypeWdPoStRecoveries], func() interface{} { + j := WdPoStRecoveriesProcessedEvt{ + evtCommon: s.getEvtCommon(err), + Declarations: recoveries, + MessageCID: optionalCid(sigmsg), + } + j.Error = err + return j }) if faults, sigmsg, err = s.checkNextFaults(context.TODO(), declDeadline, partitions); err != nil { @@ -380,15 +375,12 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di miner.DeadlineInfo log.Errorf("checking sector faults: %v", err) } - journal.J.RecordEvent(s.wdPoStEvtType, func() interface{} { - return s.enrichWithTipset(WindowPoStEvt{ - State: "faults_processed", - Deadline: s.activeDeadline, - Faults: &WindowPoStEvt_Faults{ - Declarations: faults, - MessageCID: optionalCid(sigmsg), - }, - }) + journal.J.RecordEvent(s.evtTypes[evtTypeWdPoStFaults], func() interface{} { + return WdPoStFaultsProcessedEvt{ + evtCommon: s.getEvtCommon(err), + Declarations: faults, + MessageCID: optionalCid(sigmsg), + } }) }() diff --git a/storage/wdpost_sched.go b/storage/wdpost_sched.go index 1b2303dc0..d2b8279a0 100644 --- a/storage/wdpost_sched.go +++ b/storage/wdpost_sched.go @@ -19,39 +19,11 @@ import ( "github.com/filecoin-project/lotus/journal" "github.com/filecoin-project/lotus/node/config" - "github.com/ipfs/go-cid" "go.opencensus.io/trace" ) const StartConfidence = 4 // TODO: config -type WindowPoStEvt struct { - State string - Deadline *miner.DeadlineInfo - Height abi.ChainEpoch - TipSet []cid.Cid - Error error `json:",omitempty"` - - Proofs *WindowPoStEvt_Proofs `json:",omitempty"` - Recoveries *WindowPoStEvt_Recoveries `json:",omitempty"` - Faults *WindowPoStEvt_Faults `json:",omitempty"` -} - -type WindowPoStEvt_Proofs struct { - Partitions []miner.PoStPartition - MessageCID cid.Cid `json:",omitempty"` -} - -type WindowPoStEvt_Recoveries struct { - Declarations []miner.RecoveryDeclaration - MessageCID cid.Cid `json:",omitempty"` -} - -type WindowPoStEvt_Faults struct { - Declarations []miner.FaultDeclaration - MessageCID cid.Cid `json:",omitempty"` -} - type WindowPoStScheduler struct { api storageMinerApi feeCfg config.MinerFeeConfig @@ -69,7 +41,7 @@ type WindowPoStScheduler struct { activeDeadline *miner.DeadlineInfo abort context.CancelFunc - wdPoStEvtType journal.EventType + evtTypes [4]journal.EventType // failed abi.ChainEpoch // eps // failLk sync.Mutex @@ -94,9 +66,14 @@ func NewWindowedPoStScheduler(api storageMinerApi, fc config.MinerFeeConfig, sb proofType: rt, partitionSectors: mi.WindowPoStPartitionSectors, - actor: actor, - worker: worker, - wdPoStEvtType: journal.J.RegisterEventType("storage", "wdpost"), + actor: actor, + worker: worker, + evtTypes: [...]journal.EventType{ + evtTypeWdPoStScheduler: journal.J.RegisterEventType("wdpost", "scheduler"), + evtTypeWdPoStProofs: journal.J.RegisterEventType("wdpost", "proofs_processed"), + evtTypeWdPoStRecoveries: journal.J.RegisterEventType("wdpost", "recoveries_processed"), + evtTypeWdPoStFaults: journal.J.RegisterEventType("wdpost", "faults_processed"), + }, }, nil } @@ -253,11 +230,11 @@ func (s *WindowPoStScheduler) abortActivePoSt() { if s.abort != nil { s.abort() - journal.J.RecordEvent(s.wdPoStEvtType, func() interface{} { - return s.enrichWithTipset(WindowPoStEvt{ - State: "abort", - Deadline: s.activeDeadline, - }) + journal.J.RecordEvent(s.evtTypes[evtTypeWdPoStScheduler], func() interface{} { + return WdPoStSchedulerEvt{ + evtCommon: s.getEvtCommon(nil), + State: SchedulerStateAborted, + } }) log.Warnf("Aborting Window PoSt (Deadline: %+v)", s.activeDeadline) @@ -267,12 +244,14 @@ func (s *WindowPoStScheduler) abortActivePoSt() { s.abort = nil } -// enrichWithTipset enriches a WindowPoStEvt with tipset information, -// if available. -func (s *WindowPoStScheduler) enrichWithTipset(evt WindowPoStEvt) WindowPoStEvt { +// getEvtCommon populates and returns common attributes from state, for a +// WdPoSt journal event. +func (s *WindowPoStScheduler) getEvtCommon(err error) evtCommon { + c := evtCommon{Error: err} if s.cur != nil { - evt.Height = s.cur.Height() - evt.TipSet = s.cur.Cids() + c.Deadline = s.activeDeadline + c.Height = s.cur.Height() + c.TipSet = s.cur.Cids() } - return evt + return c } From fd04a195449a2620555b60925eeeb94464a622d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Wed, 2 Sep 2020 19:46:57 +0100 Subject: [PATCH 26/40] go mod tidy. --- go.sum | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/go.sum b/go.sum index b35a642a5..24c3cedc7 100644 --- a/go.sum +++ b/go.sum @@ -1278,6 +1278,7 @@ github.com/prometheus/procfs v0.1.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/raulk/clock v1.1.0 h1:dpb29+UKMbLqiU/jqIJptgLR1nn23HLgMY0sTCDza5Y= github.com/raulk/clock v1.1.0/go.mod h1:3MpVxdZ/ODBQDxbN+kzshf5OSZwPjtMDx6BBXBmOeY0= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= @@ -1293,8 +1294,10 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sercand/kuberesolver v2.1.0+incompatible/go.mod h1:lWF3GL0xptCB/vCiJPl/ZshwPsX/n4Y7u0CW9E7aQIQ= +github.com/sercand/kuberesolver v2.4.0+incompatible h1:WE2OlRf6wjLxHwNkkFLQGaZcVLEXjMjBPjjEU5vksH8= github.com/sercand/kuberesolver v2.4.0+incompatible/go.mod h1:lWF3GL0xptCB/vCiJPl/ZshwPsX/n4Y7u0CW9E7aQIQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/shirou/gopsutil v2.18.12+incompatible h1:1eaJvGomDnH74/5cF4CTmTbLHAriGFsTZppLXDX93OM= github.com/shirou/gopsutil v2.18.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= @@ -1323,13 +1326,16 @@ github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5k github.com/siebenmann/go-kstat v0.0.0-20160321171754-d34789b79745/go.mod h1:G81aIFAMS9ECrwBYR9YxhlPjWgrItd+Kje78O6+uqm8= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= +github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w= github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa/go.mod h1:2RVY1rIf+2J2o/IM9+vPq9RzmHDSseB7FoXiSNIUsoU= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -1338,6 +1344,7 @@ github.com/soundcloud/go-runit v0.0.0-20150630195641-06ad41a06c4a/go.mod h1:LeFC github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= +github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= @@ -1356,6 +1363,7 @@ github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3 github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -1370,11 +1378,14 @@ github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFd github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e/go.mod h1:XDKHRm5ThF8YJjx001LtgelzsoaEcvnA7lVWz9EeX3g= +github.com/tj/go-spin v1.1.0 h1:lhdWZsvImxvZ3q1C5OIB7d72DuOwP4O2NdBg9PyzNds= github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/uber/jaeger-client-go v2.15.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= +github.com/uber/jaeger-client-go v2.23.1+incompatible h1:uArBYHQR0HqLFFAypI7RsWTzPSj/bDpmZZuQjMLSg1A= github.com/uber/jaeger-client-go v2.23.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v1.5.1-0.20181102163054-1fc5c315e03c/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= +github.com/uber/jaeger-lib v2.2.0+incompatible h1:MxZXOiR2JuoANZ3J6DE/U0kSFv/eJ/GfSYVCjK7dyaw= github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= @@ -1392,10 +1403,14 @@ github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMI github.com/wangjia184/sortedset v0.0.0-20160527075905-f5d03557ba30/go.mod h1:YkocrP2K2tcw938x9gCOmT5G5eCD6jsTz0SZuyAqwIE= github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/warpfork/go-wish v0.0.0-20190328234359-8b3e70f8e830/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= +github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a h1:G++j5e0OC488te356JvdhaM8YS6nMsjLAYF7JxCv07w= github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= +github.com/weaveworks/common v0.0.0-20200512154658-384f10054ec5 h1:EYxr08r8x6r/5fLEAMMkida1BVgxVXE4LfZv/XV+znU= github.com/weaveworks/common v0.0.0-20200512154658-384f10054ec5/go.mod h1:c98fKi5B9u8OsKGiWHLRKus6ToQ1Tubeow44ECO1uxY= +github.com/weaveworks/promrus v1.2.0 h1:jOLf6pe6/vss4qGHjXmGz4oDJQA+AOCqEL3FvvZGz7M= github.com/weaveworks/promrus v1.2.0/go.mod h1:SaE82+OJ91yqjrE1rsvBWVzNZKcHYFtMUyS1+Ogs/KA= github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc/go.mod h1:r45hJU7yEoA81k6MWNhpMj/kms0n14dkzkxYHoB96UM= +github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba h1:X4n8JG2e2biEZZXdBKt9HX7DN3bYGFUqljqqy0DqgnY= github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba/go.mod h1:CHQnYnQUEPydYCwuy8lmTHfGmdw9TKrhWV0xLx8l0oM= github.com/whyrusleeping/cbor-gen v0.0.0-20191212224538-d370462a7e8a/go.mod h1:xdlJQaiqipF0HW+Mzpg7XRM3fWbGvfgFlcppuvlkIvY= github.com/whyrusleeping/cbor-gen v0.0.0-20191216205031-b047b6acb3c0/go.mod h1:xdlJQaiqipF0HW+Mzpg7XRM3fWbGvfgFlcppuvlkIvY= @@ -1435,20 +1450,27 @@ 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/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= +github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542 h1:oWgZJmC1DorFZDpfMfWg7xk29yEOZiXmo/wZl+utTI8= 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.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +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= +go.dedis.ch/kyber/v3 v3.0.9 h1:i0ZbOQocHUjfFasBiUql5zVeC7u/vahFd96DFA8UOWk= go.dedis.ch/kyber/v3 v3.0.9/go.mod h1:rhNjUUg6ahf8HEg5HUvVBYoWY4boAafX8tYxX+PS+qg= go.dedis.ch/protobuf v1.0.5/go.mod h1:eIV4wicvi6JK0q/QnfIEGeSFNG0ZeB24kzut5+HaRLo= go.dedis.ch/protobuf v1.0.7/go.mod h1:pv5ysfkDX/EawiPqcW3ikOxsL5t+BqnV6xHSmE79KI4= +go.dedis.ch/protobuf v1.0.11 h1:FTYVIEzY/bfl37lu3pR4lIj+F9Vp1jE8oh91VmxKgLo= go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYrJ4= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg= go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= @@ -1471,12 +1493,14 @@ go.uber.org/dig v1.8.0 h1:1rR6hnL/bu1EVcjnRDN5kx1vbIjEJDTGhSQ2B3ddpcI= go.uber.org/dig v1.8.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= go.uber.org/fx v1.9.0 h1:7OAz8ucp35AU8eydejpYG7QrbE8rLKzGhHbZlJi5LYY= go.uber.org/fx v1.9.0/go.mod h1:mFdUyAUuJ3w4jAckiKSKbldsxy1ojpAMJ+dVZg5Y0Aw= +go.uber.org/goleak v1.0.0 h1:qsup4IcBdlmsnGfqyLl4Ntn3C2XCCuKAE7DwHpScyUo= go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= @@ -1528,6 +1552,7 @@ golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -1541,6 +1566,7 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= @@ -1549,6 +1575,7 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180524181706-dfa909b99c79/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1733,6 +1760,7 @@ golang.org/x/tools v0.0.0-20200216192241-b320d3a0f5a2/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200318150045-ba25ddc85566/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200711155855-7342f9734a7d h1:F3OmlXCzYtG9YE6tXDnUOlJBzVzHF8EcmZ1yTJlcgIk= golang.org/x/tools v0.0.0-20200711155855-7342f9734a7d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1824,6 +1852,7 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj 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= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk= @@ -1835,6 +1864,7 @@ gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= @@ -1844,9 +1874,11 @@ gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1855,14 +1887,21 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= howett.net/plist v0.0.0-20181124034731-591f970eefbb h1:jhnBjNi9UFpfpl8YZhA9CrOqpnJdvzuiHsl/dnxl11M= howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= +modernc.org/cc v1.0.0 h1:nPibNuDEx6tvYrUAtvDTTw98rx5juGsa5zuDnKwEEQQ= modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= +modernc.org/golex v1.0.0 h1:wWpDlbK8ejRfSyi0frMyhilD3JBvtcx2AdGDnU+JtsE= modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= +modernc.org/mathutil v1.1.1 h1:FeylZSVX8S+58VsyJlkEj2bcpdytmp9MmDKZkKx8OIE= modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/strutil v1.1.0 h1:+1/yCzZxY2pZwwrsbH+4T7BQMoLQ9QiBshRC9eicYsc= modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= +modernc.org/xc v1.0.0 h1:7ccXrupWZIS3twbUGrtKmHS2DXY6xegFua+6O3xgAFU= modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= From 4554c4bda93da2246d2af1b73427d98b5b0f283b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Wed, 2 Sep 2020 19:54:13 +0100 Subject: [PATCH 27/40] fix lotus-bench stale import. --- cmd/lotus-bench/import.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/lotus-bench/import.go b/cmd/lotus-bench/import.go index 29a5cb91b..7400cd92e 100644 --- a/cmd/lotus-bench/import.go +++ b/cmd/lotus-bench/import.go @@ -21,7 +21,6 @@ import ( "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/vm" - "github.com/filecoin-project/lotus/journal" "github.com/filecoin-project/lotus/lib/blockstore" _ "github.com/filecoin-project/lotus/lib/sigs/bls" _ "github.com/filecoin-project/lotus/lib/sigs/secp" From 97ff90f8fa061ff408bdc1f884067f36f656c19f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Thu, 3 Sep 2020 15:51:26 +0100 Subject: [PATCH 28/40] fix imports. --- chain/store/store_test.go | 1 - chain/validation/applier.go | 1 - 2 files changed, 2 deletions(-) diff --git a/chain/store/store_test.go b/chain/store/store_test.go index c7be48b9c..42de4c19d 100644 --- a/chain/store/store_test.go +++ b/chain/store/store_test.go @@ -17,7 +17,6 @@ import ( "github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/store" "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/node/repo" ) diff --git a/chain/validation/applier.go b/chain/validation/applier.go index 9bf32962f..ac2fccf85 100644 --- a/chain/validation/applier.go +++ b/chain/validation/applier.go @@ -19,7 +19,6 @@ import ( "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/vm" - "github.com/filecoin-project/lotus/journal" ) // Applier applies messages to state trees and storage. From d46f684bb8dffbe712fe66e363b7ceff50580805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Fri, 4 Sep 2020 00:05:44 +0100 Subject: [PATCH 29/40] fix test following merge. --- extern/storage-sealing/fsm_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/storage-sealing/fsm_test.go b/extern/storage-sealing/fsm_test.go index 7fad643c6..35797c5c9 100644 --- a/extern/storage-sealing/fsm_test.go +++ b/extern/storage-sealing/fsm_test.go @@ -73,7 +73,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, CommitWait, FinalizeSector, Proving} + expected := []SectorState{Packing, 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) From 905168e72e2c194ca724071bd3482bd75e1727d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Fri, 4 Sep 2020 10:54:56 +0100 Subject: [PATCH 30/40] fix lint errors. --- chain/messagepool/messagepool.go | 9 ++++----- chain/messagepool/repub.go | 4 ++-- journal/fs.go | 1 - 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index a7f134e12..75573539b 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -89,11 +89,11 @@ const ( // MessagePoolEvt is the journal entry for message pool events. type MessagePoolEvt struct { Action string - Messages []MessagePoolEvt_Message + Messages []MessagePoolEvtMessage Error error `json:",omitempty"` } -type MessagePoolEvt_Message struct { +type MessagePoolEvtMessage struct { types.Message CID cid.Cid @@ -145,7 +145,6 @@ type MessagePool struct { sigValCache *lru.TwoQueueCache - jrnl journal.Journal evtTypes [3]journal.EventType } @@ -561,7 +560,7 @@ func (mp *MessagePool) addLocked(m *types.SignedMessage, limit bool) error { journal.J.RecordEvent(mp.evtTypes[evtTypeMpoolAdd], func() interface{} { return MessagePoolEvt{ Action: "add", - Messages: []MessagePoolEvt_Message{{Message: m.Message, CID: m.Cid()}}, + Messages: []MessagePoolEvtMessage{{Message: m.Message, CID: m.Cid()}}, } }) @@ -725,7 +724,7 @@ func (mp *MessagePool) remove(from address.Address, nonce uint64) { journal.J.RecordEvent(mp.evtTypes[evtTypeMpoolRemove], func() interface{} { return MessagePoolEvt{ Action: "remove", - Messages: []MessagePoolEvt_Message{{Message: m.Message, CID: m.Cid()}}} + Messages: []MessagePoolEvtMessage{{Message: m.Message, CID: m.Cid()}}} }) mp.currentSize-- diff --git a/chain/messagepool/repub.go b/chain/messagepool/repub.go index 9b94ee61b..f23659eea 100644 --- a/chain/messagepool/repub.go +++ b/chain/messagepool/repub.go @@ -136,9 +136,9 @@ func (mp *MessagePool) republishPendingMessages() error { if len(msgs) > 0 { journal.J.RecordEvent(mp.evtTypes[evtTypeMpoolRepub], func() interface{} { - msgs := make([]MessagePoolEvt_Message, 0, len(msgs)) + msgs := make([]MessagePoolEvtMessage, 0, len(msgs)) for _, m := range msgs { - msgs = append(msgs, MessagePoolEvt_Message{Message: m.Message, CID: m.Cid()}) + msgs = append(msgs, MessagePoolEvtMessage{Message: m.Message, CID: m.Cid()}) } return MessagePoolEvt{ Action: "repub", diff --git a/journal/fs.go b/journal/fs.go index 83dd986bf..340705f07 100644 --- a/journal/fs.go +++ b/journal/fs.go @@ -22,7 +22,6 @@ type fsJournal struct { dir string sizeLimit int64 - lk sync.Mutex fi *os.File fSize int64 From 0a4c473a7cb0aad8d51525974ed591a5124f8e2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Fri, 4 Sep 2020 12:14:27 +0100 Subject: [PATCH 31/40] fix dangling import. --- journal/fs.go | 1 - 1 file changed, 1 deletion(-) diff --git a/journal/fs.go b/journal/fs.go index 340705f07..57774d3aa 100644 --- a/journal/fs.go +++ b/journal/fs.go @@ -5,7 +5,6 @@ import ( "fmt" "os" "path/filepath" - "sync" "golang.org/x/xerrors" From 6e7de3c8d922b4b75db0ba1f80f2c676c4b36e4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=C2=B7Gou?= Date: Fri, 11 Sep 2020 16:52:48 +0800 Subject: [PATCH 32/40] optimize definition of state_heights In the same parentstateroot, the one with the smallest height should be selected --- cmd/lotus-chainwatch/syncer/sync.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/lotus-chainwatch/syncer/sync.go b/cmd/lotus-chainwatch/syncer/sync.go index 52a36fc9e..306cf8b3e 100644 --- a/cmd/lotus-chainwatch/syncer/sync.go +++ b/cmd/lotus-chainwatch/syncer/sync.go @@ -136,7 +136,8 @@ create unique index if not exists block_cid_uindex on blocks (cid,height); create materialized view if not exists state_heights - as select distinct height, parentstateroot from blocks; + as select b.parentstateroot, min(b.height) height + from blocks b group by b.parentstateroot; create index if not exists state_heights_height_index on state_heights (height); From e45a7749b0d03c98fef4dd160edefff89306fe42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=C2=B7Gou?= Date: Mon, 14 Sep 2020 16:20:01 +0800 Subject: [PATCH 33/40] Update sync.go --- cmd/lotus-chainwatch/syncer/sync.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/lotus-chainwatch/syncer/sync.go b/cmd/lotus-chainwatch/syncer/sync.go index 306cf8b3e..19ceddda9 100644 --- a/cmd/lotus-chainwatch/syncer/sync.go +++ b/cmd/lotus-chainwatch/syncer/sync.go @@ -5,6 +5,7 @@ import ( "context" "database/sql" "fmt" + cid "github.com/ipfs/go-cid/_rsrch/cidiface" "sync" "time" @@ -136,7 +137,7 @@ create unique index if not exists block_cid_uindex on blocks (cid,height); create materialized view if not exists state_heights - as select b.parentstateroot, min(b.height) height + as select min(b.height) height, b.parentstateroot from blocks b group by b.parentstateroot; create index if not exists state_heights_height_index From 747b34c2c89d83b91bdb45d279e58c4329aa181a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=C2=B7Gou?= Date: Mon, 14 Sep 2020 18:00:17 +0800 Subject: [PATCH 34/40] Update sync.go --- cmd/lotus-chainwatch/syncer/sync.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/lotus-chainwatch/syncer/sync.go b/cmd/lotus-chainwatch/syncer/sync.go index 19ceddda9..609b71088 100644 --- a/cmd/lotus-chainwatch/syncer/sync.go +++ b/cmd/lotus-chainwatch/syncer/sync.go @@ -5,7 +5,6 @@ import ( "context" "database/sql" "fmt" - cid "github.com/ipfs/go-cid/_rsrch/cidiface" "sync" "time" From 05aa5f2d385c85ff8cdf9ffd8ce20149d446ea85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Mon, 14 Sep 2020 13:01:03 +0100 Subject: [PATCH 35/40] allow customizing disabled journal events + tests. --- journal/registry_test.go | 49 ++++++++++++++++++++++++++++++++++++++++ journal/types.go | 21 +++++++++++++++++ node/builder.go | 15 +++++++++++- 3 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 journal/registry_test.go diff --git a/journal/registry_test.go b/journal/registry_test.go new file mode 100644 index 000000000..9d2085c12 --- /dev/null +++ b/journal/registry_test.go @@ -0,0 +1,49 @@ +package journal + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestDisabledEvents(t *testing.T) { + req := require.New(t) + + test := func(dis DisabledEvents) func(*testing.T) { + return func(t *testing.T) { + registry := NewEventTypeRegistry(dis) + + reg1 := registry.RegisterEventType("system1", "disabled1") + reg2 := registry.RegisterEventType("system2", "disabled2") + + req.False(reg1.Enabled()) + req.False(reg2.Enabled()) + req.True(reg1.safe) + req.True(reg2.safe) + + reg3 := registry.RegisterEventType("system3", "enabled3") + req.True(reg3.Enabled()) + req.True(reg3.safe) + } + } + + t.Run("direct", test(DisabledEvents{ + EventType{System: "system1", Event: "disabled1"}, + EventType{System: "system2", Event: "disabled2"}, + })) + + dis, err := ParseDisabledEvents("system1:disabled1,system2:disabled2") + req.NoError(err) + + t.Run("parsed", test(dis)) + + dis, err = ParseDisabledEvents(" system1:disabled1 , system2:disabled2 ") + req.NoError(err) + + t.Run("parsed_spaces", test(dis)) +} + +func TestParseDisableEvents(t *testing.T) { + _, err := ParseDisabledEvents("system1:disabled1:failed,system2:disabled2") + require.Error(t, err) +} diff --git a/journal/types.go b/journal/types.go index c81fb8c89..56c7d4bc0 100644 --- a/journal/types.go +++ b/journal/types.go @@ -1,6 +1,8 @@ package journal import ( + "fmt" + "strings" "time" logging "github.com/ipfs/go-log" @@ -20,6 +22,25 @@ var ( // DisabledEvents is the set of event types whose journaling is suppressed. type DisabledEvents []EventType +// ParseDisabledEvents parses a string of the form: "system1:event1,system2:event2[,...]" +// into a DisabledEvents object, returning an error if the string failed to parse. +// +// It sanitizes strings via strings.TrimSpace. +func ParseDisabledEvents(s string) (DisabledEvents, error) { + s = strings.TrimSpace(s) // sanitize + evts := strings.Split(s, ",") + ret := make(DisabledEvents, 0, len(evts)) + for _, evt := range evts { + evt = strings.TrimSpace(evt) // sanitize + s := strings.Split(evt, ":") + if len(s) != 2 { + return nil, fmt.Errorf("invalid event type: %s", s) + } + ret = append(ret, EventType{System: s[0], Event: s[1]}) + } + return ret, nil +} + // EventType represents the signature of an event. type EventType struct { System string diff --git a/node/builder.go b/node/builder.go index 08c48d408..028c9212e 100644 --- a/node/builder.go +++ b/node/builder.go @@ -3,6 +3,7 @@ package node import ( "context" "errors" + "os" "time" logging "github.com/ipfs/go-log" @@ -68,6 +69,10 @@ import ( "github.com/filecoin-project/lotus/storage/sectorblocks" ) +// EnvJournalDisabledEvents is the environment variable through which disabled +// journal events can be customized. +const EnvJournalDisabledEvents = "LOTUS_JOURNAL_DISABLED_EVENTS" + //nolint:deadcode,varcheck var log = logging.Logger("builder") @@ -157,7 +162,15 @@ type Settings struct { func defaults() []Option { return []Option{ // global system journal. - Override(new(journal.DisabledEvents), journal.DefaultDisabledEvents), + Override(new(journal.DisabledEvents), func() journal.DisabledEvents { + if env, ok := os.LookupEnv(EnvJournalDisabledEvents); ok { + if ret, err := journal.ParseDisabledEvents(env); err == nil { + return ret + } + } + // fallback if env variable is not set, or if it failed to parse. + return journal.DefaultDisabledEvents + }), Override(new(journal.Journal), modules.OpenFilesystemJournal), Override(InitJournalKey, func(j journal.Journal) { journal.J = j // eagerly sets the global journal through fx.Invoke. From 09e9d6d7781a221b842d34fd43f49e172f387419 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Mon, 14 Sep 2020 16:20:01 +0100 Subject: [PATCH 36/40] deal journal events: wire into markets subscriptions. --- markets/loggers/journal.go | 76 ++++++++++++++++++++++++ markets/storageadapter/client.go | 23 +------ markets/storageadapter/journal_events.go | 64 -------------------- markets/storageadapter/provider.go | 45 ++------------ node/modules/client.go | 9 +++ node/modules/storageminer.go | 9 +++ 6 files changed, 99 insertions(+), 127 deletions(-) create mode 100644 markets/loggers/journal.go delete mode 100644 markets/storageadapter/journal_events.go diff --git a/markets/loggers/journal.go b/markets/loggers/journal.go new file mode 100644 index 000000000..12948fe7b --- /dev/null +++ b/markets/loggers/journal.go @@ -0,0 +1,76 @@ +package marketevents + +import ( + "github.com/filecoin-project/go-fil-markets/retrievalmarket" + "github.com/filecoin-project/go-fil-markets/storagemarket" + + "github.com/filecoin-project/lotus/journal" +) + +type StorageClientEvt struct { + Event string + Deal storagemarket.ClientDeal +} + +type StorageProviderEvt struct { + Event string + Deal storagemarket.MinerDeal +} + +type RetrievalClientEvt struct { + Event string + Deal retrievalmarket.ClientDealState +} + +type RetrievalProviderEvt struct { + Event string + Deal retrievalmarket.ProviderDealState +} + +// StorageClientJournaler records journal events from the storage client. +func StorageClientJournaler(evtType journal.EventType) func(event storagemarket.ClientEvent, deal storagemarket.ClientDeal) { + return func(event storagemarket.ClientEvent, deal storagemarket.ClientDeal) { + journal.J.RecordEvent(evtType, func() interface{} { + return StorageClientEvt{ + Event: storagemarket.ClientEvents[event], + Deal: deal, + } + }) + } +} + +// StorageProviderJournaler records journal events from the storage provider. +func StorageProviderJournaler(evtType journal.EventType) func(event storagemarket.ProviderEvent, deal storagemarket.MinerDeal) { + return func(event storagemarket.ProviderEvent, deal storagemarket.MinerDeal) { + journal.J.RecordEvent(evtType, func() interface{} { + return StorageProviderEvt{ + Event: storagemarket.ProviderEvents[event], + Deal: deal, + } + }) + } +} + +// RetrievalClientJournaler records journal events from the retrieval client. +func RetrievalClientJournaler(evtType journal.EventType) func(event retrievalmarket.ClientEvent, deal retrievalmarket.ClientDealState) { + return func(event retrievalmarket.ClientEvent, deal retrievalmarket.ClientDealState) { + journal.J.RecordEvent(evtType, func() interface{} { + return RetrievalClientEvt{ + Event: retrievalmarket.ClientEvents[event], + Deal: deal, + } + }) + } +} + +// RetrievalProviderJournaler records journal events from the retrieval provider. +func RetrievalProviderJournaler(evtType journal.EventType) func(event retrievalmarket.ProviderEvent, deal retrievalmarket.ProviderDealState) { + return func(event retrievalmarket.ProviderEvent, deal retrievalmarket.ProviderDealState) { + journal.J.RecordEvent(evtType, func() interface{} { + return RetrievalProviderEvt{ + Event: retrievalmarket.ProviderEvents[event], + Deal: deal, + } + }) + } +} diff --git a/markets/storageadapter/client.go b/markets/storageadapter/client.go index f66fd3ef9..4168792da 100644 --- a/markets/storageadapter/client.go +++ b/markets/storageadapter/client.go @@ -24,7 +24,6 @@ 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/journal" "github.com/filecoin-project/lotus/lib/sigs" "github.com/filecoin-project/lotus/markets/utils" "github.com/filecoin-project/lotus/node/impl/full" @@ -43,9 +42,6 @@ type ClientNodeAdapter struct { cs *store.ChainStore fm *market.FundMgr ev *events.Events - - // index 0 is unused, as it corresponds to evtTypeDealAccepted, a provider-only event. - evtTypes [4]journal.EventType } type clientApi struct { @@ -63,12 +59,6 @@ func NewClientNodeAdapter(state full.StateAPI, chain full.ChainAPI, mpool full.M cs: cs, fm: fm, ev: events.NewEvents(context.TODO(), &clientApi{chain, state}), - - evtTypes: [...]journal.EventType{ - evtTypeDealSectorCommitted: journal.J.RegisterEventType("markets:storage:client", "deal_sector_committed"), - evtTypeDealExpired: journal.J.RegisterEventType("markets:storage:client", "deal_expired"), - evtTypeDealSlashed: journal.J.RegisterEventType("markets:storage:client", "deal_slashed"), - }, } } @@ -233,14 +223,7 @@ func (c *ClientNodeAdapter) ValidatePublishedDeal(ctx context.Context, deal stor return 0, err } - dealID := res.IDs[dealIdx] - journal.J.RecordEvent(c.evtTypes[evtTypeDealAccepted], func() interface{} { - deal := deal // copy and strip fields we don't want to log to the journal - deal.ClientSignature = crypto.Signature{} - return ClientDealAcceptedEvt{ID: dealID, Deal: deal, Height: c.cs.GetHeaviestTipSet().Height()} - }) - - return dealID, nil + return res.IDs[dealIdx], nil } const clientOverestimation = 2 @@ -294,10 +277,6 @@ func (c *ClientNodeAdapter) OnDealSectorCommitted(ctx context.Context, provider log.Infof("Storage deal %d activated at epoch %d", dealId, sd.State.SectorStartEpoch) - journal.J.RecordEvent(c.evtTypes[evtTypeDealSectorCommitted], func() interface{} { - return ClientDealSectorCommittedEvt{ID: dealId, State: sd.State, Height: curH} - }) - cb(nil) return false, nil diff --git a/markets/storageadapter/journal_events.go b/markets/storageadapter/journal_events.go deleted file mode 100644 index b74c50301..000000000 --- a/markets/storageadapter/journal_events.go +++ /dev/null @@ -1,64 +0,0 @@ -package storageadapter - -import ( - "github.com/filecoin-project/go-fil-markets/storagemarket" - "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/specs-actors/actors/builtin/market" -) - -// Journal entry types emitted from this module. -const ( - evtTypeDealAccepted = iota - evtTypeDealSectorCommitted - evtTypeDealExpired - evtTypeDealSlashed -) - -type ClientDealAcceptedEvt struct { - ID abi.DealID - Deal storagemarket.ClientDeal - Height abi.ChainEpoch -} - -type ClientDealSectorCommittedEvt struct { - ID abi.DealID - State market.DealState - Height abi.ChainEpoch -} - -type ClientDealExpiredEvt struct { - ID abi.DealID - State market.DealState - Height abi.ChainEpoch -} - -type ClientDealSlashedEvt struct { - ID abi.DealID - State market.DealState - Height abi.ChainEpoch -} - -type MinerDealAcceptedEvt struct { - ID abi.DealID - Deal storagemarket.MinerDeal - State market.DealState - Height abi.ChainEpoch -} - -type MinerDealSectorCommittedEvt struct { - ID abi.DealID - State market.DealState - Height abi.ChainEpoch -} - -type MinerDealExpiredEvt struct { - ID abi.DealID - State market.DealState - Height abi.ChainEpoch -} - -type MinerDealSlashedEvt struct { - ID abi.DealID - State market.DealState - Height abi.ChainEpoch -} diff --git a/markets/storageadapter/provider.go b/markets/storageadapter/provider.go index 5b8ead5be..7af1808c1 100644 --- a/markets/storageadapter/provider.go +++ b/markets/storageadapter/provider.go @@ -30,7 +30,6 @@ import ( "github.com/filecoin-project/lotus/chain/events/state" "github.com/filecoin-project/lotus/chain/types" sealing "github.com/filecoin-project/lotus/extern/storage-sealing" - "github.com/filecoin-project/lotus/journal" "github.com/filecoin-project/lotus/lib/sigs" "github.com/filecoin-project/lotus/markets/utils" "github.com/filecoin-project/lotus/node/modules/dtypes" @@ -49,8 +48,6 @@ type ProviderNodeAdapter struct { secb *sectorblocks.SectorBlocks ev *events.Events - - evtTypes [4]journal.EventType } func NewProviderNodeAdapter(dag dtypes.StagingDAG, secb *sectorblocks.SectorBlocks, full api.FullNode) storagemarket.StorageProviderNode { @@ -59,13 +56,6 @@ func NewProviderNodeAdapter(dag dtypes.StagingDAG, secb *sectorblocks.SectorBloc dag: dag, secb: secb, ev: events.NewEvents(context.TODO(), full), - - evtTypes: [...]journal.EventType{ - evtTypeDealAccepted: journal.J.RegisterEventType("markets:storage:provider", "deal_complete"), - evtTypeDealSectorCommitted: journal.J.RegisterEventType("markets:storage:provider", "deal_sector_committed"), - evtTypeDealExpired: journal.J.RegisterEventType("markets:storage:provider", "deal_expired"), - evtTypeDealSlashed: journal.J.RegisterEventType("markets:storage:provider", "deal_slashed"), - }, } } @@ -132,15 +122,8 @@ func (n *ProviderNodeAdapter) OnDealComplete(ctx context.Context, deal storagema if err != nil { return nil, xerrors.Errorf("AddPiece failed: %s", err) } - log.Warnf("New Deal: deal %d", deal.DealID) - journal.J.RecordEvent(n.evtTypes[evtTypeDealAccepted], func() interface{} { - deal := deal // copy and strip fields we don't want to log to the journal - deal.ClientSignature = crypto.Signature{} - return MinerDealAcceptedEvt{ID: deal.DealID, Deal: deal} - }) - return &storagemarket.PackingResult{ SectorNumber: p, Offset: offset, @@ -319,10 +302,6 @@ func (n *ProviderNodeAdapter) OnDealSectorCommitted(ctx context.Context, provide log.Infof("Storage deal %d activated at epoch %d", dealID, sd.State.SectorStartEpoch) - journal.J.RecordEvent(n.evtTypes[evtTypeDealSectorCommitted], func() interface{} { - return MinerDealSectorCommittedEvt{ID: dealID, State: sd.State, Height: curH} - }) - cb(nil) return false, nil @@ -429,23 +408,15 @@ func (n *ProviderNodeAdapter) OnDealExpiredOrSlashed(ctx context.Context, dealID return false, true, nil } - height := ts.Height() - // Check if the deal has already expired - if sd.Proposal.EndEpoch <= height { + if sd.Proposal.EndEpoch <= ts.Height() { onDealExpired(nil) - journal.J.RecordEvent(n.evtTypes[evtTypeDealExpired], func() interface{} { - return MinerDealExpiredEvt{ID: dealID, State: sd.State, Height: height} - }) return true, false, nil } // If there is no deal assume it's already been slashed if sd.State.SectorStartEpoch < 0 { - onDealSlashed(height, nil) - journal.J.RecordEvent(n.evtTypes[evtTypeDealSlashed], func() interface{} { - return MinerDealSlashedEvt{ID: dealID, State: sd.State, Height: height} - }) + onDealSlashed(ts.Height(), nil) return true, false, nil } @@ -457,14 +428,9 @@ func (n *ProviderNodeAdapter) OnDealExpiredOrSlashed(ctx context.Context, dealID // Called when there was a match against the state change we're looking for // and the chain has advanced to the confidence height stateChanged := func(ts *types.TipSet, ts2 *types.TipSet, states events.StateChange, h abi.ChainEpoch) (more bool, err error) { - height := ts2.Height() - // Check if the deal has already expired - if sd.Proposal.EndEpoch <= height { + if sd.Proposal.EndEpoch <= ts2.Height() { onDealExpired(nil) - journal.J.RecordEvent(n.evtTypes[evtTypeDealExpired], func() interface{} { - return MinerDealExpiredEvt{ID: dealID, State: sd.State, Height: height} - }) return false, nil } @@ -487,10 +453,7 @@ func (n *ProviderNodeAdapter) OnDealExpiredOrSlashed(ctx context.Context, dealID // Deal was slashed if deal.To == nil { - onDealSlashed(height, nil) - journal.J.RecordEvent(n.evtTypes[evtTypeDealSlashed], func() interface{} { - return MinerDealSlashedEvt{ID: dealID, State: sd.State, Height: height} - }) + onDealSlashed(ts2.Height(), nil) return false, nil } diff --git a/node/modules/client.go b/node/modules/client.go index 63633c0e3..7d1ac942e 100644 --- a/node/modules/client.go +++ b/node/modules/client.go @@ -26,6 +26,7 @@ import ( "github.com/ipfs/go-datastore/namespace" "github.com/libp2p/go-libp2p-core/host" + "github.com/filecoin-project/lotus/journal" "github.com/filecoin-project/lotus/lib/blockstore" marketevents "github.com/filecoin-project/lotus/markets/loggers" "github.com/filecoin-project/lotus/markets/retrievaladapter" @@ -119,6 +120,10 @@ func StorageClient(lc fx.Lifecycle, h host.Host, ibs dtypes.ClientBlockstore, md lc.Append(fx.Hook{ OnStart: func(ctx context.Context) error { c.SubscribeToEvents(marketevents.StorageClientLogger) + + evtType := journal.J.RegisterEventType("markets/storage/client", "state_change") + c.SubscribeToEvents(marketevents.StorageClientJournaler(evtType)) + return c.Start(ctx) }, OnStop: func(context.Context) error { @@ -140,6 +145,10 @@ func RetrievalClient(lc fx.Lifecycle, h host.Host, mds dtypes.ClientMultiDstore, lc.Append(fx.Hook{ OnStart: func(ctx context.Context) error { client.SubscribeToEvents(marketevents.RetrievalClientLogger) + + evtType := journal.J.RegisterEventType("markets/retrieval/client", "state_change") + client.SubscribeToEvents(marketevents.RetrievalClientJournaler(evtType)) + return nil }, }) diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 5f00fffc0..eb512da07 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -49,6 +49,7 @@ 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" lapi "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" @@ -213,6 +214,10 @@ func HandleRetrieval(host host.Host, lc fx.Lifecycle, m retrievalmarket.Retrieva lc.Append(fx.Hook{ OnStart: func(context.Context) error { m.SubscribeToEvents(marketevents.RetrievalProviderLogger) + + evtType := journal.J.RegisterEventType("markets/retrieval/provider", "state_change") + m.SubscribeToEvents(marketevents.RetrievalProviderJournaler(evtType)) + return m.Start() }, OnStop: func(context.Context) error { @@ -227,6 +232,10 @@ func HandleDeals(mctx helpers.MetricsCtx, lc fx.Lifecycle, host host.Host, h sto lc.Append(fx.Hook{ OnStart: func(context.Context) error { h.SubscribeToEvents(marketevents.StorageProviderLogger) + + evtType := journal.J.RegisterEventType("markets/storage/provider", "state_change") + h.SubscribeToEvents(marketevents.StorageProviderJournaler(evtType)) + return h.Start(ctx) }, OnStop: func(context.Context) error { From 954ff325034abd98c73a87b67330c9ea9b9af4fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Mon, 14 Sep 2020 19:01:35 +0100 Subject: [PATCH 37/40] fix transitive api dependency on ffi. --- markets/{loggers => }/journal.go | 2 +- node/modules/client.go | 5 +++-- node/modules/storageminer.go | 5 +++-- 3 files changed, 7 insertions(+), 5 deletions(-) rename markets/{loggers => }/journal.go (99%) diff --git a/markets/loggers/journal.go b/markets/journal.go similarity index 99% rename from markets/loggers/journal.go rename to markets/journal.go index 12948fe7b..a73d28011 100644 --- a/markets/loggers/journal.go +++ b/markets/journal.go @@ -1,4 +1,4 @@ -package marketevents +package markets import ( "github.com/filecoin-project/go-fil-markets/retrievalmarket" diff --git a/node/modules/client.go b/node/modules/client.go index 7d1ac942e..6aa3cbb0e 100644 --- a/node/modules/client.go +++ b/node/modules/client.go @@ -28,6 +28,7 @@ import ( "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/node/impl/full" @@ -122,7 +123,7 @@ func StorageClient(lc fx.Lifecycle, h host.Host, ibs dtypes.ClientBlockstore, md c.SubscribeToEvents(marketevents.StorageClientLogger) evtType := journal.J.RegisterEventType("markets/storage/client", "state_change") - c.SubscribeToEvents(marketevents.StorageClientJournaler(evtType)) + c.SubscribeToEvents(markets.StorageClientJournaler(evtType)) return c.Start(ctx) }, @@ -147,7 +148,7 @@ func RetrievalClient(lc fx.Lifecycle, h host.Host, mds dtypes.ClientMultiDstore, client.SubscribeToEvents(marketevents.RetrievalClientLogger) evtType := journal.J.RegisterEventType("markets/retrieval/client", "state_change") - client.SubscribeToEvents(marketevents.RetrievalClientJournaler(evtType)) + client.SubscribeToEvents(markets.RetrievalClientJournaler(evtType)) return nil }, diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index eb512da07..9a94a56a5 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -50,6 +50,7 @@ import ( 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" @@ -216,7 +217,7 @@ func HandleRetrieval(host host.Host, lc fx.Lifecycle, m retrievalmarket.Retrieva m.SubscribeToEvents(marketevents.RetrievalProviderLogger) evtType := journal.J.RegisterEventType("markets/retrieval/provider", "state_change") - m.SubscribeToEvents(marketevents.RetrievalProviderJournaler(evtType)) + m.SubscribeToEvents(markets.RetrievalProviderJournaler(evtType)) return m.Start() }, @@ -234,7 +235,7 @@ func HandleDeals(mctx helpers.MetricsCtx, lc fx.Lifecycle, host host.Host, h sto h.SubscribeToEvents(marketevents.StorageProviderLogger) evtType := journal.J.RegisterEventType("markets/storage/provider", "state_change") - h.SubscribeToEvents(marketevents.StorageProviderJournaler(evtType)) + h.SubscribeToEvents(markets.StorageProviderJournaler(evtType)) return h.Start(ctx) }, From 8a05fe86d6e6504004aae927f2e27dd02a4c6159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 14 Sep 2020 20:33:54 +0200 Subject: [PATCH 38/40] wdpost: Skip sectors correctly --- storage/wdpost_run.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/storage/wdpost_run.go b/storage/wdpost_run.go index 8f15c4796..08a7437a9 100644 --- a/storage/wdpost_run.go +++ b/storage/wdpost_run.go @@ -430,16 +430,16 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di dline.Info, ts *ty return nil, xerrors.Errorf("adding recoveries to set of sectors to prove: %w", err) } - toProve, err = bitfield.SubtractBitField(toProve, postSkipped) - if err != nil { - return nil, xerrors.Errorf("toProve - postSkipped: %w", err) - } - good, err := s.checkSectors(ctx, toProve) if err != nil { return nil, xerrors.Errorf("checking sectors to skip: %w", err) } + good, err = bitfield.SubtractBitField(good, postSkipped) + if err != nil { + return nil, xerrors.Errorf("toProve - postSkipped: %w", err) + } + skipped, err := bitfield.SubtractBitField(toProve, good) if err != nil { return nil, xerrors.Errorf("toProve - good: %w", err) From 32eeb96ce72aff598c15f16699d4916936069c32 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 14 Sep 2020 12:41:55 -0700 Subject: [PATCH 39/40] Update to specs-actors 0.9.9 This patch changes the runtime interfaces, to make it possible to abstract over them. --- chain/stmgr/forks_test.go | 6 +- chain/vm/invoker.go | 2 +- chain/vm/runtime.go | 124 ++++++++++++++------------------ chain/vm/runtime_test.go | 2 +- chain/vm/vm.go | 8 +-- conformance/chaos/actor.go | 16 ++--- conformance/chaos/actor_test.go | 6 +- go.mod | 4 +- go.sum | 8 +-- 9 files changed, 78 insertions(+), 98 deletions(-) diff --git a/chain/stmgr/forks_test.go b/chain/stmgr/forks_test.go index e96d3f316..2fc11b3d7 100644 --- a/chain/stmgr/forks_test.go +++ b/chain/stmgr/forks_test.go @@ -74,8 +74,8 @@ func (ta *testActor) Exports() []interface{} { func (ta *testActor) Constructor(rt runtime.Runtime, params *abi.EmptyValue) *abi.EmptyValue { rt.ValidateImmediateCallerAcceptAny() - rt.State().Create(&testActorState{11}) - fmt.Println("NEW ACTOR ADDRESS IS: ", rt.Message().Receiver()) + rt.StateCreate(&testActorState{11}) + fmt.Println("NEW ACTOR ADDRESS IS: ", rt.Receiver()) return abi.Empty } @@ -83,7 +83,7 @@ func (ta *testActor) Constructor(rt runtime.Runtime, params *abi.EmptyValue) *ab func (ta *testActor) TestMethod(rt runtime.Runtime, params *abi.EmptyValue) *abi.EmptyValue { rt.ValidateImmediateCallerAcceptAny() var st testActorState - rt.State().Readonly(&st) + rt.StateReadonly(&st) if rt.CurrEpoch() > testForkHeight { if st.HasUpgraded != 55 { diff --git a/chain/vm/invoker.go b/chain/vm/invoker.go index c9d22cd4c..1a9a2090a 100644 --- a/chain/vm/invoker.go +++ b/chain/vm/invoker.go @@ -64,7 +64,7 @@ func (inv *Invoker) Invoke(codeCid cid.Cid, rt runtime.Runtime, method abi.Metho code, ok := inv.builtInCode[codeCid] if !ok { - log.Errorf("no code for actor %s (Addr: %s)", codeCid, rt.Message().Receiver()) + log.Errorf("no code for actor %s (Addr: %s)", codeCid, rt.Receiver()) return nil, aerrors.Newf(exitcode.SysErrorIllegalActor, "no code for actor %s(%d)(%s)", codeCid, method, hex.EncodeToString(params)) } if method >= abi.MethodNum(len(code)) || code[method] == nil { diff --git a/chain/vm/runtime.go b/chain/vm/runtime.go index 7e9dd894b..d3757f458 100644 --- a/chain/vm/runtime.go +++ b/chain/vm/runtime.go @@ -8,7 +8,9 @@ import ( gruntime "runtime" "time" + "github.com/filecoin-project/go-state-types/cbor" "github.com/filecoin-project/go-state-types/network" + rtt "github.com/filecoin-project/go-state-types/rt" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" @@ -16,11 +18,9 @@ import ( "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/specs-actors/actors/builtin" - "github.com/filecoin-project/specs-actors/actors/runtime" - vmr "github.com/filecoin-project/specs-actors/actors/runtime" + rt0 "github.com/filecoin-project/specs-actors/actors/runtime" "github.com/ipfs/go-cid" - cbor "github.com/ipfs/go-ipld-cbor" - cbg "github.com/whyrusleeping/cbor-gen" + ipldcbor "github.com/ipfs/go-ipld-cbor" "go.opencensus.io/trace" "golang.org/x/xerrors" @@ -31,20 +31,20 @@ import ( ) type Runtime struct { + types.Message + rt0.Syscalls + ctx context.Context vm *VM state *state.StateTree - vmsg vmr.Message height abi.ChainEpoch - cst cbor.IpldStore + cst ipldcbor.IpldStore pricelist Pricelist gasAvailable int64 gasUsed int64 - sys runtime.Syscalls - // address that started invoke chain origin address.Address originNonce uint64 @@ -85,11 +85,11 @@ type notFoundErr interface { IsNotFound() bool } -func (rt *Runtime) Get(c cid.Cid, o vmr.CBORUnmarshaler) bool { +func (rt *Runtime) StoreGet(c cid.Cid, o cbor.Unmarshaler) bool { if err := rt.cst.Get(context.TODO(), c, o); err != nil { var nfe notFoundErr if xerrors.As(err, &nfe) && nfe.IsNotFound() { - if xerrors.As(err, new(cbor.SerializationError)) { + if xerrors.As(err, new(ipldcbor.SerializationError)) { panic(aerrors.Newf(exitcode.ErrSerialization, "failed to unmarshal cbor object %s", err)) } return false @@ -100,10 +100,10 @@ func (rt *Runtime) Get(c cid.Cid, o vmr.CBORUnmarshaler) bool { return true } -func (rt *Runtime) Put(x vmr.CBORMarshaler) cid.Cid { +func (rt *Runtime) StorePut(x cbor.Marshaler) cid.Cid { c, err := rt.cst.Put(context.TODO(), x) if err != nil { - if xerrors.As(err, new(cbor.SerializationError)) { + if xerrors.As(err, new(ipldcbor.SerializationError)) { panic(aerrors.Newf(exitcode.ErrSerialization, "failed to marshal cbor object %s", err)) } panic(aerrors.Fatalf("failed to put cbor object: %s", err)) @@ -111,7 +111,7 @@ func (rt *Runtime) Put(x vmr.CBORMarshaler) cid.Cid { return c } -var _ vmr.Runtime = (*Runtime)(nil) +var _ rt0.Runtime = (*Runtime)(nil) func (rt *Runtime) shimCall(f func() interface{}) (rval []byte, aerr aerrors.ActorError) { defer func() { @@ -139,7 +139,7 @@ func (rt *Runtime) shimCall(f func() interface{}) (rval []byte, aerr aerrors.Act return ret, nil case *abi.EmptyValue: return nil, nil - case cbg.CBORMarshaler: + case cbor.Marshaler: buf := new(bytes.Buffer) if err := ret.MarshalCBOR(buf); err != nil { return nil, aerrors.Absorb(err, 2, "failed to marshal response to cbor") @@ -152,17 +152,13 @@ func (rt *Runtime) shimCall(f func() interface{}) (rval []byte, aerr aerrors.Act } } -func (rt *Runtime) Message() vmr.Message { - return rt.vmsg -} - func (rt *Runtime) ValidateImmediateCallerAcceptAny() { rt.abortIfAlreadyValidated() return } func (rt *Runtime) CurrentBalance() abi.TokenAmount { - b, err := rt.GetBalance(rt.Message().Receiver()) + b, err := rt.GetBalance(rt.Receiver()) if err != nil { rt.Abortf(err.RetCode(), "get current balance: %v", err) } @@ -198,10 +194,6 @@ func (rt *Runtime) GetRandomnessFromBeacon(personalization crypto.DomainSeparati return res } -func (rt *Runtime) Store() vmr.Store { - return rt -} - func (rt *Runtime) NewActorAddress() address.Address { var b bytes.Buffer oa, _ := ResolveToKeyAddr(rt.vm.cstate, rt.vm.cst, rt.origin) @@ -258,7 +250,7 @@ func (rt *Runtime) CreateActor(codeID cid.Cid, address address.Address) { // May only be called by the actor itself. func (rt *Runtime) DeleteActor(beneficiary address.Address) { rt.chargeGas(rt.Pricelist().OnDeleteActor()) - act, err := rt.state.GetActor(rt.Message().Receiver()) + act, err := rt.state.GetActor(rt.Receiver()) if err != nil { if xerrors.Is(err, types.ErrActorNotFound) { rt.Abortf(exitcode.SysErrorIllegalActor, "failed to load actor in delete actor: %s", err) @@ -267,36 +259,32 @@ func (rt *Runtime) DeleteActor(beneficiary address.Address) { } if !act.Balance.IsZero() { // Transfer the executing actor's balance to the beneficiary - if err := rt.vm.transfer(rt.Message().Receiver(), beneficiary, act.Balance); err != nil { + if err := rt.vm.transfer(rt.Receiver(), beneficiary, act.Balance); err != nil { panic(aerrors.Fatalf("failed to transfer balance to beneficiary actor: %s", err)) } } // Delete the executing actor - if err := rt.state.DeleteActor(rt.Message().Receiver()); err != nil { + if err := rt.state.DeleteActor(rt.Receiver()); err != nil { panic(aerrors.Fatalf("failed to delete actor: %s", err)) } _ = rt.chargeGasSafe(gasOnActorExec) } -func (rt *Runtime) Syscalls() vmr.Syscalls { - return rt.sys -} - -func (rt *Runtime) StartSpan(name string) vmr.TraceSpan { +func (rt *Runtime) StartSpan(name string) func() { panic("implement me") } func (rt *Runtime) ValidateImmediateCallerIs(as ...address.Address) { rt.abortIfAlreadyValidated() - imm := rt.Message().Caller() + imm := rt.Caller() for _, a := range as { if imm == a { return } } - rt.Abortf(exitcode.SysErrForbidden, "caller %s is not one of %s", rt.Message().Caller(), as) + rt.Abortf(exitcode.SysErrForbidden, "caller %s is not one of %s", rt.Caller(), as) } func (rt *Runtime) Context() context.Context { @@ -314,7 +302,7 @@ func (rt *Runtime) AbortStateMsg(msg string) { func (rt *Runtime) ValidateImmediateCallerType(ts ...cid.Cid) { rt.abortIfAlreadyValidated() - callerCid, ok := rt.GetActorCodeCID(rt.Message().Caller()) + callerCid, ok := rt.GetActorCodeCID(rt.Caller()) if !ok { panic(aerrors.Fatalf("failed to lookup code cid for caller")) } @@ -334,11 +322,11 @@ type dumbWrapperType struct { val []byte } -func (dwt *dumbWrapperType) Into(um vmr.CBORUnmarshaler) error { +func (dwt *dumbWrapperType) Into(um cbor.Unmarshaler) error { return um.UnmarshalCBOR(bytes.NewReader(dwt.val)) } -func (rt *Runtime) Send(to address.Address, method abi.MethodNum, m vmr.CBORMarshaler, value abi.TokenAmount) (vmr.SendReturn, exitcode.ExitCode) { +func (rt *Runtime) Send(to address.Address, method abi.MethodNum, m cbor.Marshaler, value abi.TokenAmount, out cbor.Er) exitcode.ExitCode { if !rt.allowInternal { rt.Abortf(exitcode.SysErrorIllegalActor, "runtime.Send() is currently disallowed") } @@ -351,16 +339,20 @@ func (rt *Runtime) Send(to address.Address, method abi.MethodNum, m vmr.CBORMars params = buf.Bytes() } - ret, err := rt.internalSend(rt.Message().Receiver(), to, method, value, params) + ret, err := rt.internalSend(rt.Receiver(), to, method, value, params) if err != nil { if err.IsFatal() { panic(err) } log.Warnf("vmctx send failed: to: %s, method: %d: ret: %d, err: %s", to, method, ret, err) - return &dumbWrapperType{nil}, err.RetCode() + return err.RetCode() } _ = rt.chargeGasSafe(gasOnActorExec) - return &dumbWrapperType{ret}, 0 + + if err := out.UnmarshalCBOR(bytes.NewReader(ret)); err != nil { + rt.Abortf(exitcode.ErrSerialization, "failed to unmarshal return value: %s", err) + } + return 0 } func (rt *Runtime) internalSend(from, to address.Address, method abi.MethodNum, value types.BigInt, params []byte) ([]byte, aerrors.ActorError) { @@ -404,49 +396,41 @@ func (rt *Runtime) internalSend(from, to address.Address, method abi.MethodNum, return ret, errSend } -func (rt *Runtime) State() vmr.StateHandle { - return &shimStateHandle{rt: rt} -} - -type shimStateHandle struct { - rt *Runtime -} - -func (ssh *shimStateHandle) Create(obj vmr.CBORMarshaler) { - c := ssh.rt.Put(obj) - err := ssh.rt.stateCommit(EmptyObjectCid, c) +func (rt *Runtime) StateCreate(obj cbor.Marshaler) { + c := rt.StorePut(obj) + err := rt.stateCommit(EmptyObjectCid, c) if err != nil { panic(fmt.Errorf("failed to commit state after creating object: %w", err)) } } -func (ssh *shimStateHandle) Readonly(obj vmr.CBORUnmarshaler) { - act, err := ssh.rt.state.GetActor(ssh.rt.Message().Receiver()) +func (rt *Runtime) StateReadonly(obj cbor.Unmarshaler) { + act, err := rt.state.GetActor(rt.Receiver()) if err != nil { - ssh.rt.Abortf(exitcode.SysErrorIllegalArgument, "failed to get actor for Readonly state: %s", err) + rt.Abortf(exitcode.SysErrorIllegalArgument, "failed to get actor for Readonly state: %s", err) } - ssh.rt.Get(act.Head, obj) + rt.StoreGet(act.Head, obj) } -func (ssh *shimStateHandle) Transaction(obj vmr.CBORer, f func()) { +func (rt *Runtime) StateTransaction(obj cbor.Er, f func()) { if obj == nil { - ssh.rt.Abortf(exitcode.SysErrorIllegalActor, "Must not pass nil to Transaction()") + rt.Abortf(exitcode.SysErrorIllegalActor, "Must not pass nil to Transaction()") } - act, err := ssh.rt.state.GetActor(ssh.rt.Message().Receiver()) + act, err := rt.state.GetActor(rt.Receiver()) if err != nil { - ssh.rt.Abortf(exitcode.SysErrorIllegalActor, "failed to get actor for Transaction: %s", err) + rt.Abortf(exitcode.SysErrorIllegalActor, "failed to get actor for Transaction: %s", err) } baseState := act.Head - ssh.rt.Get(baseState, obj) + rt.StoreGet(baseState, obj) - ssh.rt.allowInternal = false + rt.allowInternal = false f() - ssh.rt.allowInternal = true + rt.allowInternal = true - c := ssh.rt.Put(obj) + c := rt.StorePut(obj) - err = ssh.rt.stateCommit(baseState, c) + err = rt.stateCommit(baseState, c) if err != nil { panic(fmt.Errorf("failed to commit state after transaction: %w", err)) } @@ -466,7 +450,7 @@ func (rt *Runtime) GetBalance(a address.Address) (types.BigInt, aerrors.ActorErr func (rt *Runtime) stateCommit(oldh, newh cid.Cid) aerrors.ActorError { // TODO: we can make this more efficient in the future... - act, err := rt.state.GetActor(rt.Message().Receiver()) + act, err := rt.state.GetActor(rt.Receiver()) if err != nil { return aerrors.Escalate(err, "failed to get actor to commit state") } @@ -477,7 +461,7 @@ func (rt *Runtime) stateCommit(oldh, newh cid.Cid) aerrors.ActorError { act.Head = newh - if err := rt.state.SetActor(rt.Message().Receiver(), act); err != nil { + if err := rt.state.SetActor(rt.Receiver(), act); err != nil { return aerrors.Fatalf("failed to set actor in commit state: %s", err) } @@ -572,15 +556,15 @@ func (rt *Runtime) abortIfAlreadyValidated() { rt.callerValidated = true } -func (rt *Runtime) Log(level vmr.LogLevel, msg string, args ...interface{}) { +func (rt *Runtime) Log(level rtt.LogLevel, msg string, args ...interface{}) { switch level { - case vmr.DEBUG: + case rtt.DEBUG: actorLog.Debugf(msg, args...) - case vmr.INFO: + case rtt.INFO: actorLog.Infof(msg, args...) - case vmr.WARN: + case rtt.WARN: actorLog.Warnf(msg, args...) - case vmr.ERROR: + case rtt.ERROR: actorLog.Errorf(msg, args...) } } diff --git a/chain/vm/runtime_test.go b/chain/vm/runtime_test.go index 2f9704394..c22a8b615 100644 --- a/chain/vm/runtime_test.go +++ b/chain/vm/runtime_test.go @@ -42,6 +42,6 @@ func TestRuntimePutErrors(t *testing.T) { cst: cbor.NewCborStore(nil), } - rt.Put(&NotAVeryGoodMarshaler{}) + rt.StorePut(&NotAVeryGoodMarshaler{}) t.Error("expected panic") } diff --git a/chain/vm/vm.go b/chain/vm/vm.go index e389a3531..c9acc8658 100644 --- a/chain/vm/vm.go +++ b/chain/vm/vm.go @@ -116,7 +116,7 @@ func (vm *VM) makeRuntime(ctx context.Context, msg *types.Message, origin addres Blocks: &gasChargingBlocks{rt.chargeGasFunc(2), rt.pricelist, vm.cst.Blocks}, Atlas: vm.cst.Atlas, } - rt.sys = pricedSyscalls{ + rt.Syscalls = pricedSyscalls{ under: vm.Syscalls(ctx, vm.cstate, rt.cst), chargeGas: rt.chargeGasFunc(1), pl: rt.pricelist, @@ -128,7 +128,7 @@ func (vm *VM) makeRuntime(ctx context.Context, msg *types.Message, origin addres rt.Abortf(exitcode.SysErrInvalidReceiver, "resolve msg.From address failed") } vmm.From = resF - rt.vmsg = &vmm + rt.Message = vmm return rt } @@ -700,9 +700,9 @@ func (vm *VM) Invoke(act *types.Actor, rt *Runtime, method abi.MethodNum, params defer span.End() if span.IsRecordingEvents() { span.AddAttributes( - trace.StringAttribute("to", rt.Message().Receiver().String()), + trace.StringAttribute("to", rt.Receiver().String()), trace.Int64Attribute("method", int64(method)), - trace.StringAttribute("value", rt.Message().ValueReceived().String()), + trace.StringAttribute("value", rt.ValueReceived().String()), ) } diff --git a/conformance/chaos/actor.go b/conformance/chaos/actor.go index b9a181ba7..daff26694 100644 --- a/conformance/chaos/actor.go +++ b/conformance/chaos/actor.go @@ -100,18 +100,14 @@ type SendReturn struct { // passed parameters. func (a Actor) Send(rt runtime.Runtime, args *SendArgs) *SendReturn { rt.ValidateImmediateCallerAcceptAny() - ret, code := rt.Send( + var out runtime.CBORBytes + code := rt.Send( args.To, args.Method, runtime.CBORBytes(args.Params), args.Value, + &out, ) - var out runtime.CBORBytes - if ret != nil { - if err := ret.Into(&out); err != nil { - rt.Abortf(exitcode.ErrIllegalState, "failed to unmarshal send return: %v", err) - } - } return &SendReturn{ Return: out, Code: code, @@ -217,14 +213,14 @@ func (a Actor) MutateState(rt runtime.Runtime, args *MutateStateArgs) *abi.Empty var st State switch args.Branch { case MutateInTransaction: - rt.State().Transaction(&st, func() { + rt.StateTransaction(&st, func() { st.Value = args.Value }) case MutateReadonly: - rt.State().Readonly(&st) + rt.StateReadonly(&st) st.Value = args.Value case MutateAfterTransaction: - rt.State().Transaction(&st, func() { + rt.StateTransaction(&st, func() { st.Value = args.Value + "-in" }) st.Value = args.Value diff --git a/conformance/chaos/actor_test.go b/conformance/chaos/actor_test.go index a08267022..67ced2899 100644 --- a/conformance/chaos/actor_test.go +++ b/conformance/chaos/actor_test.go @@ -46,7 +46,7 @@ func TestMutateStateInTransaction(t *testing.T) { var a Actor rt.ExpectValidateCallerAny() - rt.Create(&State{}) + rt.StateCreate(&State{}) val := "__mutstat test" rt.Call(a.MutateState, &MutateStateArgs{ @@ -72,7 +72,7 @@ func TestMutateStateAfterTransaction(t *testing.T) { var a Actor rt.ExpectValidateCallerAny() - rt.Create(&State{}) + rt.StateCreate(&State{}) val := "__mutstat test" rt.Call(a.MutateState, &MutateStateArgs{ @@ -99,7 +99,7 @@ func TestMutateStateReadonly(t *testing.T) { var a Actor rt.ExpectValidateCallerAny() - rt.Create(&State{}) + rt.StateCreate(&State{}) val := "__mutstat test" rt.Call(a.MutateState, &MutateStateArgs{ diff --git a/go.mod b/go.mod index 4cedea65f..5470e226a 100644 --- a/go.mod +++ b/go.mod @@ -32,11 +32,11 @@ 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-20200909080127-001afaca718c + github.com/filecoin-project/go-state-types v0.0.0-20200911004822-964d6c679cfc github.com/filecoin-project/go-statemachine v0.0.0-20200813232949-df9b130df370 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.8 + github.com/filecoin-project/specs-actors v0.9.9 github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796 github.com/filecoin-project/test-vectors/schema v0.0.1 github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1 diff --git a/go.sum b/go.sum index 215eec431..5e479db82 100644 --- a/go.sum +++ b/go.sum @@ -241,8 +241,8 @@ github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261/g 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-20200909080127-001afaca718c h1:HHRMFpU8OrODDUja5NmGWNBAVGoSy4MRjxgZa+a0qIw= -github.com/filecoin-project/go-state-types v0.0.0-20200909080127-001afaca718c/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I= +github.com/filecoin-project/go-state-types v0.0.0-20200911004822-964d6c679cfc h1:1vr/LoqGq5m5g37Q3sNSAjfwF1uJY0zmiHcvnxY6hik= +github.com/filecoin-project/go-state-types v0.0.0-20200911004822-964d6c679cfc/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-20200813232949-df9b130df370 h1:Jbburj7Ih2iaJ/o5Q9A+EAeTabME6YII7FLi9SKUf5c= github.com/filecoin-project/go-statemachine v0.0.0-20200813232949-df9b130df370/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= @@ -252,8 +252,8 @@ github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b 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.8 h1:45fnx/BsseFL3CtvSoR6CszFY26TFtsh9AHwCW2vkg8= -github.com/filecoin-project/specs-actors v0.9.8/go.mod h1:xFObDoWPySBNTNBrGXVVrutmgSZH/mMo46Q1bec/0hw= +github.com/filecoin-project/specs-actors v0.9.9 h1:hc1iCks6dv7mpGQXcbYU3hL1WfBRZaVTYE4x2d1l2yw= +github.com/filecoin-project/specs-actors v0.9.9/go.mod h1:czlvLQGEX0fjLLfdNHD7xLymy6L3n7aQzRWzsYGf+ys= 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.1 h1:5fNF76nl4qolEvcIsjc0kUADlTMVHO73tW4kXXPnsus= From 9804310cc8243dc34e2944fc4ee839fbf3251c2c Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 14 Sep 2020 13:31:03 -0700 Subject: [PATCH 40/40] Update specs-actors to 0.9.10 Moves the Keyer type (and helpers) into go-state-types. --- chain/events/state/diff_adt.go | 3 ++- chain/events/state/diff_adt_test.go | 33 +++++++++++++------------ chain/events/state/predicates.go | 8 +++--- chain/gen/genesis/t01_init.go | 9 ++++--- chain/state/statetree.go | 7 +++--- chain/stmgr/utils.go | 4 +-- chain/sync.go | 2 +- cli/chain.go | 2 +- cmd/lotus-chainwatch/processor/miner.go | 2 +- cmd/lotus-shed/verifreg.go | 3 ++- go.mod | 2 +- go.sum | 4 +-- node/impl/full/chain.go | 4 +-- node/impl/full/state.go | 6 ++--- storage/adapter_storage_miner.go | 2 +- 15 files changed, 48 insertions(+), 43 deletions(-) diff --git a/chain/events/state/diff_adt.go b/chain/events/state/diff_adt.go index 39d7e8556..519c61c2d 100644 --- a/chain/events/state/diff_adt.go +++ b/chain/events/state/diff_adt.go @@ -3,6 +3,7 @@ package state import ( "bytes" + "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/specs-actors/actors/util/adt" typegen "github.com/whyrusleeping/cbor-gen" ) @@ -69,7 +70,7 @@ func DiffAdtArray(preArr, curArr *adt.Array, out AdtArrayDiff) error { // Modify should be called when a value is modified in the map // Remove should be called when a value is removed from the map type AdtMapDiff interface { - AsKey(key string) (adt.Keyer, error) + AsKey(key string) (abi.Keyer, error) Add(key string, val *typegen.Deferred) error Modify(key string, from, to *typegen.Deferred) error Remove(key string, val *typegen.Deferred) error diff --git a/chain/events/state/diff_adt_test.go b/chain/events/state/diff_adt_test.go index 56a03bf33..55926afb9 100644 --- a/chain/events/state/diff_adt_test.go +++ b/chain/events/state/diff_adt_test.go @@ -11,6 +11,7 @@ import ( cbornode "github.com/ipfs/go-ipld-cbor" typegen "github.com/whyrusleeping/cbor-gen" + "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/specs-actors/actors/runtime" "github.com/filecoin-project/specs-actors/actors/util/adt" @@ -78,21 +79,21 @@ func TestDiffAdtMap(t *testing.T) { mapA := adt.MakeEmptyMap(ctxstoreA) mapB := adt.MakeEmptyMap(ctxstoreB) - require.NoError(t, mapA.Put(adt.UIntKey(0), runtime.CBORBytes([]byte{0}))) // delete + require.NoError(t, mapA.Put(abi.UIntKey(0), runtime.CBORBytes([]byte{0}))) // delete - require.NoError(t, mapA.Put(adt.UIntKey(1), runtime.CBORBytes([]byte{0}))) // modify - require.NoError(t, mapB.Put(adt.UIntKey(1), runtime.CBORBytes([]byte{1}))) + 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(adt.UIntKey(2), runtime.CBORBytes([]byte{1}))) // delete + require.NoError(t, mapA.Put(abi.UIntKey(2), runtime.CBORBytes([]byte{1}))) // delete - require.NoError(t, mapA.Put(adt.UIntKey(3), runtime.CBORBytes([]byte{0}))) // noop - require.NoError(t, mapB.Put(adt.UIntKey(3), runtime.CBORBytes([]byte{0}))) + 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(adt.UIntKey(4), runtime.CBORBytes([]byte{0}))) // modify - require.NoError(t, mapB.Put(adt.UIntKey(4), runtime.CBORBytes([]byte{6}))) + 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, mapB.Put(adt.UIntKey(5), runtime.CBORBytes{8})) // add - require.NoError(t, mapB.Put(adt.UIntKey(6), runtime.CBORBytes{9})) // add + require.NoError(t, mapB.Put(abi.UIntKey(5), runtime.CBORBytes{8})) // add + require.NoError(t, mapB.Put(abi.UIntKey(6), runtime.CBORBytes{9})) // add changes := new(TestDiffMap) @@ -134,12 +135,12 @@ type TestDiffMap struct { var _ AdtMapDiff = &TestDiffMap{} -func (t *TestDiffMap) AsKey(key string) (adt.Keyer, error) { - k, err := adt.ParseUIntKey(key) +func (t *TestDiffMap) AsKey(key string) (abi.Keyer, error) { + k, err := abi.ParseUIntKey(key) if err != nil { return nil, err } - return adt.UIntKey(k), nil + return abi.UIntKey(k), nil } func (t *TestDiffMap) Add(key string, val *typegen.Deferred) error { @@ -148,7 +149,7 @@ func (t *TestDiffMap) Add(key string, val *typegen.Deferred) error { if err != nil { return err } - k, err := adt.ParseUIntKey(key) + k, err := abi.ParseUIntKey(key) if err != nil { return err } @@ -172,7 +173,7 @@ func (t *TestDiffMap) Modify(key string, from, to *typegen.Deferred) error { return err } - k, err := adt.ParseUIntKey(key) + k, err := abi.ParseUIntKey(key) if err != nil { return err } @@ -198,7 +199,7 @@ func (t *TestDiffMap) Remove(key string, val *typegen.Deferred) error { if err != nil { return err } - k, err := adt.ParseUIntKey(key) + k, err := abi.ParseUIntKey(key) if err != nil { return err } diff --git a/chain/events/state/predicates.go b/chain/events/state/predicates.go index b30e69b48..0858793d8 100644 --- a/chain/events/state/predicates.go +++ b/chain/events/state/predicates.go @@ -537,8 +537,8 @@ type MinerPreCommitChanges struct { Removed []miner.SectorPreCommitOnChainInfo } -func (m *MinerPreCommitChanges) AsKey(key string) (adt.Keyer, error) { - sector, err := adt.ParseUIntKey(key) +func (m *MinerPreCommitChanges) AsKey(key string) (abi.Keyer, error) { + sector, err := abi.ParseUIntKey(key) if err != nil { return nil, err } @@ -662,12 +662,12 @@ type AddressChange struct { type DiffInitActorStateFunc func(ctx context.Context, oldState *init_.State, newState *init_.State) (changed bool, user UserData, err error) -func (i *InitActorAddressChanges) AsKey(key string) (adt.Keyer, error) { +func (i *InitActorAddressChanges) AsKey(key string) (abi.Keyer, error) { addr, err := address.NewFromBytes([]byte(key)) if err != nil { return nil, err } - return adt.AddrKey(addr), nil + return abi.AddrKey(addr), nil } func (i *InitActorAddressChanges) Add(key string, val *typegen.Deferred) error { diff --git a/chain/gen/genesis/t01_init.go b/chain/gen/genesis/t01_init.go index 1686102fe..667079a6d 100644 --- a/chain/gen/genesis/t01_init.go +++ b/chain/gen/genesis/t01_init.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/util/adt" @@ -50,7 +51,7 @@ func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesi fmt.Printf("init set %s t0%d\n", e, counter) value := cbg.CborInt(counter) - if err := amap.Put(adt.AddrKey(e), &value); err != nil { + if err := amap.Put(abi.AddrKey(e), &value); err != nil { return 0, nil, nil, err } counter = counter + 1 @@ -77,7 +78,7 @@ func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesi fmt.Printf("init set %s t0%d\n", ainfo.Owner, counter) value := cbg.CborInt(counter) - if err := amap.Put(adt.AddrKey(ainfo.Owner), &value); err != nil { + if err := amap.Put(abi.AddrKey(ainfo.Owner), &value); err != nil { return 0, nil, nil, err } counter = counter + 1 @@ -95,7 +96,7 @@ func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesi return 0, nil, nil, xerrors.Errorf("unmarshaling account meta: %w", err) } value := cbg.CborInt(80) - if err := amap.Put(adt.AddrKey(ainfo.Owner), &value); err != nil { + if err := amap.Put(abi.AddrKey(ainfo.Owner), &value); err != nil { return 0, nil, nil, err } } else if rootVerifier.Type == genesis.TMultisig { @@ -110,7 +111,7 @@ func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesi fmt.Printf("init set %s t0%d\n", e, counter) value := cbg.CborInt(counter) - if err := amap.Put(adt.AddrKey(e), &value); err != nil { + if err := amap.Put(abi.AddrKey(e), &value); err != nil { return 0, nil, nil, err } counter = counter + 1 diff --git a/chain/state/statetree.go b/chain/state/statetree.go index c083f1817..445f3765a 100644 --- a/chain/state/statetree.go +++ b/chain/state/statetree.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/specs-actors/actors/builtin" init_ "github.com/filecoin-project/specs-actors/actors/builtin/init" @@ -209,7 +210,7 @@ func (st *StateTree) GetActor(addr address.Address) (*types.Actor, error) { } var act types.Actor - if found, err := st.root.Get(adt.AddrKey(addr), &act); err != nil { + if found, err := st.root.Get(abi.AddrKey(addr), &act); err != nil { return nil, xerrors.Errorf("hamt find failed: %w", err) } else if !found { return nil, types.ErrActorNotFound @@ -254,11 +255,11 @@ func (st *StateTree) Flush(ctx context.Context) (cid.Cid, error) { for addr, sto := range st.snaps.layers[0].actors { if sto.Delete { - if err := st.root.Delete(adt.AddrKey(addr)); err != nil { + if err := st.root.Delete(abi.AddrKey(addr)); err != nil { return cid.Undef, err } } else { - if err := st.root.Put(adt.AddrKey(addr), &sto.Act); err != nil { + if err := st.root.Put(abi.AddrKey(addr), &sto.Act); err != nil { return cid.Undef, err } } diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index f77ec20ff..27b71f358 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -120,7 +120,7 @@ func GetPowerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr addres } var claim power.Claim - if _, err := cm.Get(adt.AddrKey(maddr), &claim); err != nil { + if _, err := cm.Get(abi.AddrKey(maddr), &claim); err != nil { return power.Claim{}, power.Claim{}, err } @@ -312,7 +312,7 @@ func GetMinerSlashed(ctx context.Context, sm *StateManager, ts *types.TipSet, ma return false, err } - ok, err := claims.Get(power.AddrKey(maddr), nil) + ok, err := claims.Get(abi.AddrKey(maddr), nil) if err != nil { return false, err } diff --git a/chain/sync.go b/chain/sync.go index 9864600dd..bb3e50bdb 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -648,7 +648,7 @@ func (syncer *Syncer) minerIsValid(ctx context.Context, maddr address.Address, b } var claim power.Claim - exist, err := cm.Get(adt.AddrKey(maddr), &claim) + exist, err := cm.Get(abi.AddrKey(maddr), &claim) if err != nil { return err } diff --git a/cli/chain.go b/cli/chain.go index 36288c7d7..278a8e29b 100644 --- a/cli/chain.go +++ b/cli/chain.go @@ -659,7 +659,7 @@ func handleHamtEpoch(ctx context.Context, api api.FullNode, r cid.Cid) error { } return mp.ForEach(nil, func(key string) error { - ik, err := adt.ParseIntKey(key) + ik, err := abi.ParseIntKey(key) if err != nil { return err } diff --git a/cmd/lotus-chainwatch/processor/miner.go b/cmd/lotus-chainwatch/processor/miner.go index e063db19f..71d881927 100644 --- a/cmd/lotus-chainwatch/processor/miner.go +++ b/cmd/lotus-chainwatch/processor/miner.go @@ -221,7 +221,7 @@ func (p *Processor) processMiners(ctx context.Context, minerTips map[types.TipSe var claim power.Claim // get miner claim from power actors claim map and store if found, else the miner had no claim at // this tipset - found, err := minersClaims.Get(adt.AddrKey(act.addr), &claim) + found, err := minersClaims.Get(abi.AddrKey(act.addr), &claim) if err != nil { return nil, err } diff --git a/cmd/lotus-shed/verifreg.go b/cmd/lotus-shed/verifreg.go index 6e24dc0b6..9f475261d 100644 --- a/cmd/lotus-shed/verifreg.go +++ b/cmd/lotus-shed/verifreg.go @@ -7,6 +7,7 @@ import ( "golang.org/x/xerrors" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin/verifreg" "github.com/filecoin-project/specs-actors/actors/util/adt" @@ -336,7 +337,7 @@ var verifRegCheckVerifierCmd = &cli.Command{ } var dcap verifreg.DataCap - if found, err := vh.Get(adt.AddrKey(vaddr), &dcap); err != nil { + if found, err := vh.Get(abi.AddrKey(vaddr), &dcap); err != nil { return err } else if !found { return fmt.Errorf("not found") diff --git a/go.mod b/go.mod index 5470e226a..65c2addb8 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/filecoin-project/go-statemachine v0.0.0-20200813232949-df9b130df370 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.9 + github.com/filecoin-project/specs-actors v0.9.10 github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796 github.com/filecoin-project/test-vectors/schema v0.0.1 github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1 diff --git a/go.sum b/go.sum index 5e479db82..77b556fb2 100644 --- a/go.sum +++ b/go.sum @@ -252,8 +252,8 @@ github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b 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.9 h1:hc1iCks6dv7mpGQXcbYU3hL1WfBRZaVTYE4x2d1l2yw= -github.com/filecoin-project/specs-actors v0.9.9/go.mod h1:czlvLQGEX0fjLLfdNHD7xLymy6L3n7aQzRWzsYGf+ys= +github.com/filecoin-project/specs-actors v0.9.10 h1:gU0TrRhgkCsBEOP42sGDE7RQuR0Cov9hJhBqq+RJmjU= +github.com/filecoin-project/specs-actors v0.9.10/go.mod h1:czlvLQGEX0fjLLfdNHD7xLymy6L3n7aQzRWzsYGf+ys= 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.1 h1:5fNF76nl4qolEvcIsjc0kUADlTMVHO73tW4kXXPnsus= diff --git a/node/impl/full/chain.go b/node/impl/full/chain.go index ad2c2944c..0d6f923d8 100644 --- a/node/impl/full/chain.go +++ b/node/impl/full/chain.go @@ -300,7 +300,7 @@ func resolveOnce(bs blockstore.Blockstore) func(ctx context.Context, ds ipld.Nod return nil, nil, xerrors.Errorf("parsing int64: %w", err) } - ik := adt.IntKey(i) + ik := abi.IntKey(i) names[0] = "@H:" + ik.Key() } @@ -311,7 +311,7 @@ func resolveOnce(bs blockstore.Blockstore) func(ctx context.Context, ds ipld.Nod return nil, nil, xerrors.Errorf("parsing uint64: %w", err) } - ik := adt.UIntKey(i) + ik := abi.UIntKey(i) names[0] = "@H:" + ik.Key() } diff --git a/node/impl/full/state.go b/node/impl/full/state.go index e183fafa4..e82086053 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -509,7 +509,7 @@ func (a *StateAPI) StateMarketParticipants(ctx context.Context, tsk types.TipSet return err } - if found, err := locked.Get(adt.AddrKey(a), &lk); err != nil { + if found, err := locked.Get(abi.AddrKey(a), &lk); err != nil { return err } else if !found { return fmt.Errorf("locked funds not found") @@ -604,7 +604,7 @@ func (a *StateAPI) StateChangedActors(ctx context.Context, old cid.Cid, new cid. return xerrors.Errorf("address in state tree was not valid: %w", err) } - found, err := oh.Get(adt.AddrKey(addr), &ocval) + found, err := oh.Get(abi.AddrKey(addr), &ocval) if err != nil { return err } @@ -1150,7 +1150,7 @@ func (a *StateAPI) StateVerifiedClientStatus(ctx context.Context, addr address.A } var dcap verifreg.DataCap - if found, err := vh.Get(adt.AddrKey(aid), &dcap); err != nil { + if found, err := vh.Get(abi.AddrKey(aid), &dcap); err != nil { return nil, err } else if !found { return nil, nil diff --git a/storage/adapter_storage_miner.go b/storage/adapter_storage_miner.go index 2869e48e5..f7431299d 100644 --- a/storage/adapter_storage_miner.go +++ b/storage/adapter_storage_miner.go @@ -195,7 +195,7 @@ func (s SealingAPIAdapter) StateSectorPreCommitInfo(ctx context.Context, maddr a } var pci miner.SectorPreCommitOnChainInfo - ok, err := precommits.Get(adt.UIntKey(uint64(sectorNumber)), &pci) + ok, err := precommits.Get(abi.UIntKey(uint64(sectorNumber)), &pci) if err != nil { return nil, err }