-
Notifications
You must be signed in to change notification settings - Fork 467
/
Copy pathloader.go
95 lines (81 loc) · 3.08 KB
/
loader.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
package dispatch
import (
"github.com/filecoin-project/go-state-types/exitcode"
rtt "github.com/filecoin-project/go-state-types/rt"
rt5 "github.com/filecoin-project/specs-actors/v5/actors/runtime"
"github.com/ipfs/go-cid"
xerrors "github.com/pkg/errors"
"github.com/filecoin-project/venus/pkg/specactors"
vmr "github.com/filecoin-project/venus/pkg/vm/runtime"
)
// CodeLoader allows you to load an actor's code based on its id an epoch.
type CodeLoader struct {
actors map[cid.Cid]ActorInfo
}
type ActorInfo struct {
vmActor rtt.VMActor
// TODO: consider making this a network version range?
predicate ActorPredicate
}
// GetActorImpl returns executable code for an actor by code cid at a specific protocol version
func (cl CodeLoader) GetActorImpl(code cid.Cid, rt vmr.Runtime) (Dispatcher, *ExcuteError) {
//todo version check
actor, ok := cl.actors[code]
if !ok {
return nil, NewExcuteError(exitcode.SysErrorIllegalActor, "Actor code not found. code: %s", code)
}
if err := actor.predicate(rt, actor.vmActor); err != nil {
return nil, NewExcuteError(exitcode.SysErrorIllegalActor, "unsupport actor. code: %s", code)
}
return &actorDispatcher{code: code, actor: actor.vmActor}, nil
}
// GetActorImpl returns executable code for an actor by code cid at a specific protocol version
func (cl CodeLoader) GetUnsafeActorImpl(code cid.Cid) (Dispatcher, error) {
//todo version check
actor, ok := cl.actors[code]
if !ok {
return nil, xerrors.Errorf("unable to get actorv for code %s", code)
}
return &actorDispatcher{code: code, actor: actor.vmActor}, nil
}
// CodeLoaderBuilder helps you build a CodeLoader.
type CodeLoaderBuilder struct {
actors map[cid.Cid]ActorInfo
}
// NewBuilder creates a builder to generate a builtin.Actor data structure
func NewBuilder() *CodeLoaderBuilder {
return &CodeLoaderBuilder{actors: map[cid.Cid]ActorInfo{}}
}
// Add lets you add an actor dispatch table for a given version.
func (b *CodeLoaderBuilder) Add(predict ActorPredicate, actor Actor) *CodeLoaderBuilder {
if predict == nil {
predict = func(vmr.Runtime, rtt.VMActor) error { return nil }
}
b.actors[actor.Code()] = ActorInfo{
vmActor: actor,
predicate: predict,
}
return b
}
// Add lets you add an actor dispatch table for a given version.
func (b *CodeLoaderBuilder) AddMany(predict ActorPredicate, actors ...rt5.VMActor) *CodeLoaderBuilder {
for _, actor := range actors {
b.Add(predict, actor)
}
return b
}
// Build builds the code loader.
func (b *CodeLoaderBuilder) Build() CodeLoader {
return CodeLoader{actors: b.actors}
}
// An ActorPredicate returns an error if the given actor is not valid for the given runtime environment (e.g., chain height, version, etc.).
type ActorPredicate func(vmr.Runtime, rtt.VMActor) error
func ActorsVersionPredicate(ver specactors.Version) ActorPredicate {
return func(rt vmr.Runtime, v rtt.VMActor) error {
nver := specactors.VersionForNetwork(rt.NtwkVersion())
if nver != ver {
return xerrors.Errorf("actor %s is a version %d actor; chain only supports actor version %d at height %d", v.Code(), ver, nver, rt.CurrentEpoch())
}
return nil
}
}