github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/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 19:16:30</date> 10 //</624450059311779840> 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 method, exist := abi.Methods[name] 59 if !exist { 60 return nil, fmt.Errorf("method '%s' not found", name) 61 } 62 arguments, err := method.Inputs.Pack(args...) 63 if err != nil { 64 return nil, err 65 } 66 //如果不是构造函数,也打包方法ID并返回 67 return append(method.Id(), arguments...), nil 68 } 69 70 //根据ABI规范以V为单位解包输出 71 func (abi ABI) Unpack(v interface{}, name string, output []byte) (err error) { 72 if len(output) == 0 { 73 return fmt.Errorf("abi: unmarshalling empty output") 74 } 75 //既然不能命名与契约和事件的冲突, 76 //我们需要决定是调用方法还是调用事件 77 if method, ok := abi.Methods[name]; ok { 78 if len(output)%32 != 0 { 79 return fmt.Errorf("abi: improperly formatted output: %s - Bytes: [%+v]", string(output), output) 80 } 81 return method.Outputs.Unpack(v, output) 82 } else if event, ok := abi.Events[name]; ok { 83 return event.Inputs.Unpack(v, output) 84 } 85 return fmt.Errorf("abi: could not locate named method or event") 86 } 87 88 //unmashaljson实现json.unmasheler接口 89 func (abi *ABI) UnmarshalJSON(data []byte) error { 90 var fields []struct { 91 Type string 92 Name string 93 Constant bool 94 Anonymous bool 95 Inputs []Argument 96 Outputs []Argument 97 } 98 99 if err := json.Unmarshal(data, &fields); err != nil { 100 return err 101 } 102 103 abi.Methods = make(map[string]Method) 104 abi.Events = make(map[string]Event) 105 for _, field := range fields { 106 switch field.Type { 107 case "constructor": 108 abi.Constructor = Method{ 109 Inputs: field.Inputs, 110 } 111 //空默认为根据ABI规范的功能 112 case "function", "": 113 abi.Methods[field.Name] = Method{ 114 Name: field.Name, 115 Const: field.Constant, 116 Inputs: field.Inputs, 117 Outputs: field.Outputs, 118 } 119 case "event": 120 abi.Events[field.Name] = Event{ 121 Name: field.Name, 122 Anonymous: field.Anonymous, 123 Inputs: field.Inputs, 124 } 125 } 126 } 127 128 return nil 129 } 130 131 //method by id按4字节的ID查找方法 132 //如果未找到,则返回nil 133 func (abi *ABI) MethodById(sigdata []byte) (*Method, error) { 134 if len(sigdata) < 4 { 135 return nil, fmt.Errorf("data too short (% bytes) for abi method lookup", len(sigdata)) 136 } 137 for _, method := range abi.Methods { 138 if bytes.Equal(method.Id(), sigdata[:4]) { 139 return &method, nil 140 } 141 } 142 return nil, fmt.Errorf("no method with id: %#x", sigdata[:4]) 143 } 144