github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/cmd/abigen/main.go (about) 1 // Copyright 2016 The go-simplechain Authors 2 // This file is part of go-simplechain. 3 // 4 // go-simplechain is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // go-simplechain is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-simplechain. If not, see <http://www.gnu.org/licenses/>. 16 17 package main 18 19 import ( 20 "encoding/json" 21 "fmt" 22 "io/ioutil" 23 "os" 24 "regexp" 25 "strings" 26 27 "github.com/bigzoro/my_simplechain/accounts/abi/bind" 28 "github.com/bigzoro/my_simplechain/cmd/utils" 29 "github.com/bigzoro/my_simplechain/common/compiler" 30 "github.com/bigzoro/my_simplechain/crypto" 31 "github.com/bigzoro/my_simplechain/log" 32 "gopkg.in/urfave/cli.v1" 33 ) 34 35 var ( 36 // Git SHA1 commit hash of the release (set via linker flags) 37 gitCommit = "" 38 gitDate = "" 39 40 app *cli.App 41 42 // Flags needed by abigen 43 abiFlag = cli.StringFlag{ 44 Name: "abi", 45 Usage: "Path to the Ethereum contract ABI json to bind, - for STDIN", 46 } 47 binFlag = cli.StringFlag{ 48 Name: "bin", 49 Usage: "Path to the Ethereum contract bytecode (generate deploy method)", 50 } 51 typeFlag = cli.StringFlag{ 52 Name: "type", 53 Usage: "Struct name for the binding (default = package name)", 54 } 55 jsonFlag = cli.StringFlag{ 56 Name: "combined-json", 57 Usage: "Path to the combined-json file generated by compiler", 58 } 59 solFlag = cli.StringFlag{ 60 Name: "sol", 61 Usage: "Path to the Ethereum contract Solidity source to build and bind", 62 } 63 solcFlag = cli.StringFlag{ 64 Name: "solc", 65 Usage: "Solidity compiler to use if source builds are requested", 66 Value: "solc", 67 } 68 vyFlag = cli.StringFlag{ 69 Name: "vy", 70 Usage: "Path to the Ethereum contract Vyper source to build and bind", 71 } 72 vyperFlag = cli.StringFlag{ 73 Name: "vyper", 74 Usage: "Vyper compiler to use if source builds are requested", 75 Value: "vyper", 76 } 77 excFlag = cli.StringFlag{ 78 Name: "exc", 79 Usage: "Comma separated types to exclude from binding", 80 } 81 pkgFlag = cli.StringFlag{ 82 Name: "pkg", 83 Usage: "Package name to generate the binding into", 84 } 85 outFlag = cli.StringFlag{ 86 Name: "out", 87 Usage: "Output file for the generated binding (default = stdout)", 88 } 89 langFlag = cli.StringFlag{ 90 Name: "lang", 91 Usage: "Destination language for the bindings (go, java, objc)", 92 Value: "go", 93 } 94 aliasFlag = cli.StringFlag{ 95 Name: "alias", 96 Usage: "Comma separated aliases for function and event renaming, e.g. foo=bar", 97 } 98 ) 99 100 func init() { 101 app = utils.NewApp(gitCommit, gitDate, "ethereum checkpoint helper tool") 102 app.Flags = []cli.Flag{ 103 abiFlag, 104 binFlag, 105 typeFlag, 106 jsonFlag, 107 solFlag, 108 solcFlag, 109 vyFlag, 110 vyperFlag, 111 excFlag, 112 pkgFlag, 113 outFlag, 114 langFlag, 115 aliasFlag, 116 } 117 app.Action = utils.MigrateFlags(abigen) 118 cli.CommandHelpTemplate = utils.OriginCommandHelpTemplate 119 } 120 121 func abigen(c *cli.Context) error { 122 utils.CheckExclusive(c, abiFlag, jsonFlag, solFlag, vyFlag) // Only one source can be selected. 123 if c.GlobalString(pkgFlag.Name) == "" { 124 utils.Fatalf("No destination package specified (--pkg)") 125 } 126 var lang bind.Lang 127 switch c.GlobalString(langFlag.Name) { 128 case "go": 129 lang = bind.LangGo 130 case "java": 131 lang = bind.LangJava 132 case "objc": 133 lang = bind.LangObjC 134 utils.Fatalf("Objc binding generation is uncompleted") 135 default: 136 utils.Fatalf("Unsupported destination language \"%s\" (--lang)", c.GlobalString(langFlag.Name)) 137 } 138 // If the entire solidity code was specified, build and bind based on that 139 var ( 140 abis []string 141 bins []string 142 types []string 143 sigs []map[string]string 144 libs = make(map[string]string) 145 aliases = make(map[string]string) 146 ) 147 if c.GlobalString(abiFlag.Name) != "" { 148 // Load up the ABI, optional bytecode and type name from the parameters 149 var ( 150 abi []byte 151 err error 152 ) 153 input := c.GlobalString(abiFlag.Name) 154 if input == "-" { 155 abi, err = ioutil.ReadAll(os.Stdin) 156 } else { 157 abi, err = ioutil.ReadFile(input) 158 } 159 if err != nil { 160 utils.Fatalf("Failed to read input ABI: %v", err) 161 } 162 abis = append(abis, string(abi)) 163 164 var bin []byte 165 if binFile := c.GlobalString(binFlag.Name); binFile != "" { 166 if bin, err = ioutil.ReadFile(binFile); err != nil { 167 utils.Fatalf("Failed to read input bytecode: %v", err) 168 } 169 if strings.Contains(string(bin), "//") { 170 utils.Fatalf("Contract has additional library references, please use other mode(e.g. --combined-json) to catch library infos") 171 } 172 } 173 bins = append(bins, string(bin)) 174 175 kind := c.GlobalString(typeFlag.Name) 176 if kind == "" { 177 kind = c.GlobalString(pkgFlag.Name) 178 } 179 types = append(types, kind) 180 } else { 181 // Generate the list of types to exclude from binding 182 exclude := make(map[string]bool) 183 for _, kind := range strings.Split(c.GlobalString(excFlag.Name), ",") { 184 exclude[strings.ToLower(kind)] = true 185 } 186 var err error 187 var contracts map[string]*compiler.Contract 188 189 switch { 190 case c.GlobalIsSet(solFlag.Name): 191 contracts, err = compiler.CompileSolidity(c.GlobalString(solcFlag.Name), c.GlobalString(solFlag.Name)) 192 if err != nil { 193 utils.Fatalf("Failed to build Solidity contract: %v", err) 194 } 195 case c.GlobalIsSet(vyFlag.Name): 196 contracts, err = compiler.CompileVyper(c.GlobalString(vyperFlag.Name), c.GlobalString(vyFlag.Name)) 197 if err != nil { 198 utils.Fatalf("Failed to build Vyper contract: %v", err) 199 } 200 case c.GlobalIsSet(jsonFlag.Name): 201 jsonOutput, err := ioutil.ReadFile(c.GlobalString(jsonFlag.Name)) 202 if err != nil { 203 utils.Fatalf("Failed to read combined-json from compiler: %v", err) 204 } 205 contracts, err = compiler.ParseCombinedJSON(jsonOutput, "", "", "", "") 206 if err != nil { 207 utils.Fatalf("Failed to read contract information from json output: %v", err) 208 } 209 } 210 // Gather all non-excluded contract for binding 211 for name, contract := range contracts { 212 if exclude[strings.ToLower(name)] { 213 continue 214 } 215 abi, err := json.Marshal(contract.Info.AbiDefinition) // Flatten the compiler parse 216 if err != nil { 217 utils.Fatalf("Failed to parse ABIs from compiler output: %v", err) 218 } 219 abis = append(abis, string(abi)) 220 bins = append(bins, contract.Code) 221 sigs = append(sigs, contract.Hashes) 222 nameParts := strings.Split(name, ":") 223 types = append(types, nameParts[len(nameParts)-1]) 224 225 libPattern := crypto.Keccak256Hash([]byte(name)).String()[2:36] 226 libs[libPattern] = nameParts[len(nameParts)-1] 227 } 228 } 229 // Extract all aliases from the flags 230 if c.GlobalIsSet(aliasFlag.Name) { 231 // We support multi-versions for aliasing 232 // e.g. 233 // foo=bar,foo2=bar2 234 // foo:bar,foo2:bar2 235 re := regexp.MustCompile(`(?:(\w+)[:=](\w+))`) 236 submatches := re.FindAllStringSubmatch(c.GlobalString(aliasFlag.Name), -1) 237 for _, match := range submatches { 238 aliases[match[1]] = match[2] 239 } 240 } 241 // Generate the contract binding 242 code, err := bind.Bind(types, abis, bins, sigs, c.GlobalString(pkgFlag.Name), lang, libs, aliases) 243 if err != nil { 244 utils.Fatalf("Failed to generate ABI binding: %v", err) 245 } 246 // Either flush it out to a file or display on the standard output 247 if !c.GlobalIsSet(outFlag.Name) { 248 fmt.Printf("%s\n", code) 249 return nil 250 } 251 if err := ioutil.WriteFile(c.GlobalString(outFlag.Name), []byte(code), 0600); err != nil { 252 utils.Fatalf("Failed to write ABI binding: %v", err) 253 } 254 return nil 255 } 256 257 func main() { 258 log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) 259 260 if err := app.Run(os.Args); err != nil { 261 fmt.Fprintln(os.Stderr, err) 262 os.Exit(1) 263 } 264 }