github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/accounts/abi/abi.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 12:09:26</date> 10 //</624342582222131200> 11 12 13 package abi 14 15 import ( 16 "bytes" 17 "encoding/json" 18 "fmt" 19 "io" 20 ) 21 22 //ABI保存有关合同上下文的信息,并提供 23 //可调用方法。它将允许您键入check函数调用和 24 //相应地打包数据。 25 type ABI struct { 26 Constructor Method 27 Methods map[string]Method 28 Events map[string]Event 29 } 30 31 //JSON返回已分析的ABI接口,如果失败则返回错误。 32 func JSON(reader io.Reader) (ABI, error) { 33 dec := json.NewDecoder(reader) 34 35 var abi ABI 36 if err := dec.Decode(&abi); err != nil { 37 return ABI{}, err 38 } 39 40 return abi, nil 41 } 42 43 //打包给定的方法名以符合ABI。方法调用的数据 44 //将由方法“id”、“args0”、“arg1…”组成。阿尔金方法ID由 45 //其中4个字节和参数都是32个字节。 46 //方法ID是从 47 //方法字符串签名。(签名=baz(uint32,string32)) 48 func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) { 49 //获取所请求方法的ABI 50 if name == "" { 51 //构造函数 52 arguments, err := abi.Constructor.Inputs.Pack(args...) 53 if err != nil { 54 return nil, err 55 } 56 return arguments, nil 57 58 } 59 method, exist := abi.Methods[name] 60 if !exist { 61 return nil, fmt.Errorf("method '%s' not found", name) 62 } 63 64 arguments, err := method.Inputs.Pack(args...) 65 if err != nil { 66 return nil, err 67 } 68 //如果不是构造函数,也打包方法ID并返回 69 return append(method.Id(), arguments...), nil 70 } 71 72 //根据ABI规范以V为单位解包输出 73 func (abi ABI) Unpack(v interface{}, name string, output []byte) (err error) { 74 if len(output) == 0 { 75 return fmt.Errorf("abi: unmarshalling empty output") 76 } 77 //既然不能命名与契约和事件的冲突, 78 //我们需要决定是调用方法还是调用事件 79 if method, ok := abi.Methods[name]; ok { 80 if len(output)%32 != 0 { 81 return fmt.Errorf("abi: improperly formatted output") 82 } 83 return method.Outputs.Unpack(v, output) 84 } else if event, ok := abi.Events[name]; ok { 85 return event.Inputs.Unpack(v, output) 86 } 87 return fmt.Errorf("abi: could not locate named method or event") 88 } 89 90 //unmashaljson实现json.unmasheler接口 91 func (abi *ABI) UnmarshalJSON(data []byte) error { 92 var fields []struct { 93 Type string 94 Name string 95 Constant bool 96 Anonymous bool 97 Inputs []Argument 98 Outputs []Argument 99 } 100 101 if err := json.Unmarshal(data, &fields); err != nil { 102 return err 103 } 104 105 abi.Methods = make(map[string]Method) 106 abi.Events = make(map[string]Event) 107 for _, field := range fields { 108 switch field.Type { 109 case "constructor": 110 abi.Constructor = Method{ 111 Inputs: field.Inputs, 112 } 113 //空默认为根据ABI规范的功能 114 case "function", "": 115 abi.Methods[field.Name] = Method{ 116 Name: field.Name, 117 Const: field.Constant, 118 Inputs: field.Inputs, 119 Outputs: field.Outputs, 120 } 121 case "event": 122 abi.Events[field.Name] = Event{ 123 Name: field.Name, 124 Anonymous: field.Anonymous, 125 Inputs: field.Inputs, 126 } 127 } 128 } 129 130 return nil 131 } 132 133 //method by id按4字节的ID查找方法 134 //如果未找到,则返回nil 135 func (abi *ABI) MethodById(sigdata []byte) (*Method, error) { 136 for _, method := range abi.Methods { 137 if bytes.Equal(method.Id(), sigdata[:4]) { 138 return &method, nil 139 } 140 } 141 return nil, fmt.Errorf("no method with id: %#x", sigdata[:4]) 142 } 143