-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
read.go
155 lines (124 loc) · 4.03 KB
/
read.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
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)
})
}
}