feat: stmgr: skip tipset execution when possible
This commit is contained in:
parent
9d994dac9e
commit
92bca485b6
@ -8,6 +8,7 @@ import (
|
|||||||
"go.opencensus.io/trace"
|
"go.opencensus.io/trace"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
|
"github.com/filecoin-project/lotus/chain/store"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -52,6 +53,12 @@ func (sm *StateManager) TipSetState(ctx context.Context, ts *types.TipSet) (st c
|
|||||||
|
|
||||||
sm.stlk.Unlock()
|
sm.stlk.Unlock()
|
||||||
|
|
||||||
|
// First, try to find the tipset in the current chain. If found, we can avoid re-executing
|
||||||
|
// it.
|
||||||
|
if st, rec, found := tryLookupTipsetState(ctx, sm.cs, ts); found {
|
||||||
|
return st, rec, nil
|
||||||
|
}
|
||||||
|
|
||||||
st, rec, err = sm.tsExec.ExecuteTipSet(ctx, sm, ts, sm.tsExecMonitor, false)
|
st, rec, err = sm.tsExec.ExecuteTipSet(ctx, sm, ts, sm.tsExecMonitor, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, cid.Undef, err
|
return cid.Undef, cid.Undef, err
|
||||||
@ -60,6 +67,51 @@ func (sm *StateManager) TipSetState(ctx context.Context, ts *types.TipSet) (st c
|
|||||||
return st, rec, nil
|
return st, rec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try to lookup a state & receipt CID for a given tipset by walking the chain instead of executing
|
||||||
|
// it. This will only successfully return the state/receipt CIDs if they're found in the state
|
||||||
|
// store.
|
||||||
|
//
|
||||||
|
// NOTE: This _won't_ recursively walk the receipt/state trees. It assumes that having the root
|
||||||
|
// implies having the rest of the tree. However, lotus generally makes that assumption anyways.
|
||||||
|
func tryLookupTipsetState(ctx context.Context, cs *store.ChainStore, ts *types.TipSet) (cid.Cid, cid.Cid, bool) {
|
||||||
|
nextTs, err := cs.GetTipsetByHeight(ctx, ts.Height()+1, nil, false)
|
||||||
|
if err != nil {
|
||||||
|
// Nothing to see here. The requested height may be beyond the current head.
|
||||||
|
return cid.Undef, cid.Undef, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we're on the correct fork.
|
||||||
|
if nextTs.Parents() != ts.Key() {
|
||||||
|
// Also nothing to see here. This just means that the requested tipset is on a
|
||||||
|
// different fork.
|
||||||
|
return cid.Undef, cid.Undef, false
|
||||||
|
}
|
||||||
|
|
||||||
|
stateCid := nextTs.ParentState()
|
||||||
|
receiptCid := nextTs.ParentMessageReceipts()
|
||||||
|
|
||||||
|
// Make sure we have the parent state.
|
||||||
|
if hasState, err := cs.StateBlockstore().Has(ctx, stateCid); err != nil {
|
||||||
|
log.Errorw("failed to lookup state-root in blockstore", "cid", stateCid, "error", err)
|
||||||
|
return cid.Undef, cid.Undef, false
|
||||||
|
} else if !hasState {
|
||||||
|
// We have the chain but don't have the state. It looks like we need to try
|
||||||
|
// executing?
|
||||||
|
return cid.Undef, cid.Undef, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we have the receipts.
|
||||||
|
if hasReceipts, err := cs.ChainBlockstore().Has(ctx, receiptCid); err != nil {
|
||||||
|
log.Errorw("failed to lookup receipts in blockstore", "cid", receiptCid, "error", err)
|
||||||
|
return cid.Undef, cid.Undef, false
|
||||||
|
} else if !hasReceipts {
|
||||||
|
// If we don't have the receipts, re-execute and try again.
|
||||||
|
return cid.Undef, cid.Undef, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return stateCid, receiptCid, true
|
||||||
|
}
|
||||||
|
|
||||||
func (sm *StateManager) ExecutionTraceWithMonitor(ctx context.Context, ts *types.TipSet, em ExecMonitor) (cid.Cid, error) {
|
func (sm *StateManager) ExecutionTraceWithMonitor(ctx context.Context, ts *types.TipSet, em ExecMonitor) (cid.Cid, error) {
|
||||||
st, _, err := sm.tsExec.ExecuteTipSet(ctx, sm, ts, em, true)
|
st, _, err := sm.tsExec.ExecuteTipSet(ctx, sm, ts, em, true)
|
||||||
return st, err
|
return st, err
|
||||||
|
@ -234,6 +234,10 @@ func (ts *TipSet) MinTicketBlock() *BlockHeader {
|
|||||||
return min
|
return min
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ts *TipSet) ParentMessageReceipts() cid.Cid {
|
||||||
|
return ts.blks[0].ParentMessageReceipts
|
||||||
|
}
|
||||||
|
|
||||||
func (ts *TipSet) ParentState() cid.Cid {
|
func (ts *TipSet) ParentState() cid.Cid {
|
||||||
return ts.blks[0].ParentStateRoot
|
return ts.blks[0].ParentStateRoot
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user