-
Notifications
You must be signed in to change notification settings - Fork 3
/
evm.go
137 lines (121 loc) · 3.44 KB
/
evm.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
package evm
import (
"strings"
"github.com/33cn/externaldb/db"
pabi "github.com/33cn/plugin/plugin/dapp/evm/executor/abi"
pcom "github.com/33cn/plugin/plugin/dapp/evm/executor/vm/common"
)
var funcConverts = make(map[string]FuncConvert)
var eventHandlers = make(map[string]EventHandle)
var initDBs = make([]InitDB, 0)
type FuncConvert func(*Convert, int, EVM) ([]db.Record, error)
type InitDB func(cli db.DBCreator) error
type EventHandle func(*Convert, int, EVM) ([]db.Record, error)
func RegisterFuncConvert(name string, convert FuncConvert) {
name = UpperFirstLetter(name)
if _, ok := funcConverts[name]; ok {
panic("double register function convert:" + name)
}
funcConverts[name] = convert
}
func GetFuncConvert(name string) (FuncConvert, bool) {
name = UpperFirstLetter(name)
fc, ok := funcConverts[name]
return fc, ok
}
func UpperFirstLetter(name string) string {
if len(name) > 0 {
name = strings.ToTitle(name[:1]) + name[1:]
}
return name
}
func RegisterEventHandle(name string, convert EventHandle) {
if _, ok := eventHandlers[name]; ok {
panic("double register function convert:" + name)
}
eventHandlers[name] = convert
}
func GetEventHandle(name string) (EventHandle, bool) {
fc, ok := eventHandlers[name]
return fc, ok
}
func RegisterInitDB(initDB InitDB) {
initDBs = append(initDBs, initDB)
}
func UnpackEvent(data []byte, topics []pcom.Hash, abi *pabi.ABI) (name string, ans map[string]interface{}, err error) {
if len(topics) <= 0 || abi == nil {
return
}
ans = make(map[string]interface{})
// non index arguments
log.Info("UnpackEventData", "data", len(data))
evt, arg, err := UnpackEventData(data, topics[0], abi)
if err != nil {
return
}
name = evt.Name
log.Info("UnpackEventData", "name parsed", name)
nonIndexed := evt.Inputs.NonIndexed()
for i, v := range arg {
ans[nonIndexed[i].Name] = v
if nonIndexed[i].Type.T == pabi.AddressTy {
if addr, ok := v.(pcom.Hash160Address); ok {
ans[nonIndexed[i].Name] = db.Hash160AddressToString(addr)
}
}
}
// index arguments
as := make(pabi.Arguments, 0)
for _, a := range evt.Inputs {
if a.Indexed {
as = append(as, a)
}
}
err = pabi.ParseTopicsIntoMap(ans, as, topics[1:])
if err != nil {
return
}
for k, v := range ans {
if addr, ok := v.(pcom.Hash160Address); ok {
ans[k] = db.Hash160AddressToString(addr)
}
}
return
}
// UnpackEventData use abi and topic unpack event data
func UnpackEventData(data []byte, topic pcom.Hash, abi *pabi.ABI) (event *pabi.Event, args []interface{}, err error) {
event, err = abi.EventByID(topic)
if err != nil {
log.Error("not found by topic")
return
}
args, err = event.Inputs.UnpackValues(data)
return
}
func UnpackParam(data []byte, abi *pabi.ABI) (args map[string]interface{}, err error) {
method, arg, err := UnpackParamData(data, abi)
if err != nil {
return
}
args = make(map[string]interface{})
args["call_func_name"] = method.Name
nonIndexed := method.Inputs.NonIndexed()
for i, v := range arg {
args[method.Inputs[i].Name] = v
if nonIndexed[i].Type.T == pabi.AddressTy {
if addr, ok := v.(pcom.Hash160Address); ok {
args[nonIndexed[i].Name] = db.Hash160AddressToString(addr)
}
}
}
return
}
// UnpackParamData 通过abi解析调用方法和输入参数
func UnpackParamData(data []byte, abi *pabi.ABI) (method *pabi.Method, args []interface{}, err error) {
method, err = abi.MethodByID(data[:4])
if err != nil {
return
}
args, err = method.Inputs.UnpackValues(data[4:])
return
}