156 lines
4.0 KiB
Go
156 lines
4.0 KiB
Go
|
package stmgr
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"reflect"
|
||
|
|
||
|
"golang.org/x/xerrors"
|
||
|
|
||
|
"github.com/ipfs/go-cid"
|
||
|
cbor "github.com/ipfs/go-ipld-cbor"
|
||
|
|
||
|
"github.com/filecoin-project/go-address"
|
||
|
"github.com/filecoin-project/lotus/chain/state"
|
||
|
"github.com/filecoin-project/lotus/chain/types"
|
||
|
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
||
|
"github.com/filecoin-project/specs-actors/actors/util/adt"
|
||
|
)
|
||
|
|
||
|
type StateTreeCB func(state *state.StateTree) error
|
||
|
|
||
|
func (sm *StateManager) WithParentStateTsk(tsk types.TipSetKey, cb StateTreeCB) error {
|
||
|
ts, err := sm.cs.GetTipSetFromKey(tsk)
|
||
|
if err != nil {
|
||
|
return xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||
|
}
|
||
|
|
||
|
cst := cbor.NewCborStore(sm.cs.Blockstore())
|
||
|
state, err := state.LoadStateTree(cst, sm.parentState(ts))
|
||
|
if err != nil {
|
||
|
return xerrors.Errorf("load state tree: %w", err)
|
||
|
}
|
||
|
|
||
|
return cb(state)
|
||
|
}
|
||
|
|
||
|
func (sm *StateManager) WithParentState(ts *types.TipSet, cb StateTreeCB) error {
|
||
|
cst := cbor.NewCborStore(sm.cs.Blockstore())
|
||
|
state, err := state.LoadStateTree(cst, sm.parentState(ts))
|
||
|
if err != nil {
|
||
|
return xerrors.Errorf("load state tree: %w", err)
|
||
|
}
|
||
|
|
||
|
return cb(state)
|
||
|
}
|
||
|
|
||
|
func (sm *StateManager) WithStateTree(st cid.Cid, cb StateTreeCB) error {
|
||
|
cst := cbor.NewCborStore(sm.cs.Blockstore())
|
||
|
state, err := state.LoadStateTree(cst, st)
|
||
|
if err != nil {
|
||
|
return xerrors.Errorf("load state tree: %w", err)
|
||
|
}
|
||
|
|
||
|
return cb(state)
|
||
|
}
|
||
|
|
||
|
type ActorCB func(act *types.Actor) error
|
||
|
|
||
|
func GetActor(out *types.Actor) ActorCB {
|
||
|
return func(act *types.Actor) error {
|
||
|
*out = *act
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (sm *StateManager) WithActor(addr address.Address, cb ActorCB) StateTreeCB {
|
||
|
return func(state *state.StateTree) error {
|
||
|
act, err := state.GetActor(addr)
|
||
|
if err != nil {
|
||
|
return xerrors.Errorf("get actor: %w", err)
|
||
|
}
|
||
|
|
||
|
return cb(act)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// WithActorState usage:
|
||
|
// Option 1: WithActorState(ctx, idAddr, func(store adt.Store, st *ActorStateType) error {...})
|
||
|
// Option 2: WithActorState(ctx, idAddr, actorStatePtr)
|
||
|
func (sm *StateManager) WithActorState(ctx context.Context, out interface{}) ActorCB {
|
||
|
return func(act *types.Actor) error {
|
||
|
store := sm.cs.Store(ctx)
|
||
|
|
||
|
outCallback := reflect.TypeOf(out).Kind() == reflect.Func
|
||
|
|
||
|
var st reflect.Value
|
||
|
if outCallback {
|
||
|
st = reflect.New(reflect.TypeOf(out).In(1).Elem())
|
||
|
} else {
|
||
|
st = reflect.ValueOf(out)
|
||
|
}
|
||
|
if err := store.Get(ctx, act.Head, st.Interface()); err != nil {
|
||
|
return xerrors.Errorf("read actor head: %w", err)
|
||
|
}
|
||
|
|
||
|
if outCallback {
|
||
|
out := reflect.ValueOf(out).Call([]reflect.Value{reflect.ValueOf(store), st})
|
||
|
if !out[0].IsNil() && out[0].Interface().(error) != nil {
|
||
|
return out[0].Interface().(error)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type DeadlinesCB func(store adt.Store, deadlines *miner.Deadlines) error
|
||
|
|
||
|
func (sm *StateManager) WithDeadlines(cb DeadlinesCB) func(store adt.Store, mas *miner.State) error {
|
||
|
return func(store adt.Store, mas *miner.State) error {
|
||
|
deadlines, err := mas.LoadDeadlines(store)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return cb(store, deadlines)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type DeadlineCB func(store adt.Store, idx uint64, deadline *miner.Deadline) error
|
||
|
|
||
|
func (sm *StateManager) WithDeadline(idx uint64, cb DeadlineCB) DeadlinesCB {
|
||
|
return func(store adt.Store, deadlines *miner.Deadlines) error {
|
||
|
d, err := deadlines.LoadDeadline(store, idx)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return cb(store, idx, d)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (sm *StateManager) WithEachDeadline(cb DeadlineCB) DeadlinesCB {
|
||
|
return func(store adt.Store, deadlines *miner.Deadlines) error {
|
||
|
return deadlines.ForEach(store, func(dlIdx uint64, dl *miner.Deadline) error {
|
||
|
return cb(store, dlIdx, dl)
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type PartitionCB func(store adt.Store, idx uint64, partition *miner.Partition) error
|
||
|
|
||
|
func (sm *StateManager) WithEachPartition(cb PartitionCB) DeadlineCB {
|
||
|
return func(store adt.Store, idx uint64, deadline *miner.Deadline) error {
|
||
|
parts, err := deadline.PartitionsArray(store)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
var partition miner.Partition
|
||
|
return parts.ForEach(&partition, func(i int64) error {
|
||
|
p := partition
|
||
|
return cb(store, uint64(i), &p)
|
||
|
})
|
||
|
}
|
||
|
}
|