github.com/c2s/go-ethereum@v1.9.7/cmd/abigen/main.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum 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-ethereum 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-ethereum. 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 "strings" 25 26 "github.com/ethereum/go-ethereum/accounts/abi/bind" 27 "github.com/ethereum/go-ethereum/cmd/utils" 28 "github.com/ethereum/go-ethereum/common/compiler" 29 "github.com/ethereum/go-ethereum/crypto" 30 "github.com/ethereum/go-ethereum/log" 31 "gopkg.in/urfave/cli.v1" 32 ) 33 34 const ( 35 commandHelperTemplate = `{{.Name}}{{if .Subcommands}} command{{end}}{{if .Flags}} [command options]{{end}} [arguments...] 36 {{if .Description}}{{.Description}} 37 {{end}}{{if .Subcommands}} 38 SUBCOMMANDS: 39 {{range .Subcommands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} 40 {{end}}{{end}}{{if .Flags}} 41 OPTIONS: 42 {{range $.Flags}}{{"\t"}}{{.}} 43 {{end}} 44 {{end}}` 45 ) 46 47 var ( 48 // Git SHA1 commit hash of the release (set via linker flags) 49 gitCommit = "" 50 gitDate = "" 51 52 app *cli.App 53 54 // Flags needed by abigen 55 abiFlag = cli.StringFlag{ 56 Name: "abi", 57 Usage: "Path to the Ethereum contract ABI json to bind, - for STDIN", 58 } 59 binFlag = cli.StringFlag{ 60 Name: "bin", 61 Usage: "Path to the Ethereum contract bytecode (generate deploy method)", 62 } 63 typeFlag = cli.StringFlag{ 64 Name: "type", 65 Usage: "Struct name for the binding (default = package name)", 66 } 67 jsonFlag = cli.StringFlag{ 68 Name: "combined-json", 69 Usage: "Path to the combined-json file generated by compiler", 70 } 71 solFlag = cli.StringFlag{ 72 Name: "sol", 73 Usage: "Path to the Ethereum contract Solidity source to build and bind", 74 } 75 solcFlag = cli.StringFlag{ 76 Name: "solc", 77 Usage: "Solidity compiler to use if source builds are requested", 78 Value: "solc", 79 } 80 vyFlag = cli.StringFlag{ 81 Name: "vy", 82 Usage: "Path to the Ethereum contract Vyper source to build and bind", 83 } 84 vyperFlag = cli.StringFlag{ 85 Name: "vyper", 86 Usage: "Vyper compiler to use if source builds are requested", 87 Value: "vyper", 88 } 89 excFlag = cli.StringFlag{ 90 Name: "exc", 91 Usage: "Comma separated types to exclude from binding", 92 } 93 pkgFlag = cli.StringFlag{ 94 Name: "pkg", 95 Usage: "Package name to generate the binding into", 96 } 97 outFlag = cli.StringFlag{ 98 Name: "out", 99 Usage: "Output file for the generated binding (default = stdout)", 100 } 101 langFlag = cli.StringFlag{ 102 Name: "lang", 103 Usage: "Destination language for the bindings (go, java, objc)", 104 Value: "go", 105 } 106 ) 107 108 func init() { 109 app = utils.NewApp(gitCommit, gitDate, "ethereum checkpoint helper tool") 110 app.Flags = []cli.Flag{ 111 abiFlag, 112 binFlag, 113 typeFlag, 114 jsonFlag, 115 solFlag, 116 solcFlag, 117 vyFlag, 118 vyperFlag, 119 excFlag, 120 pkgFlag, 121 outFlag, 122 langFlag, 123 } 124 app.Action = utils.MigrateFlags(abigen) 125 cli.CommandHelpTemplate = commandHelperTemplate 126 } 127 128 func abigen(c *cli.Context) error { 129 utils.CheckExclusive(c, abiFlag, jsonFlag, solFlag, vyFlag) // Only one source can be selected. 130 if c.GlobalString(pkgFlag.Name) == "" { 131 utils.Fatalf("No destination package specified (--pkg)") 132 } 133 var lang bind.Lang 134 switch c.GlobalString(langFlag.Name) { 135 case "go": 136 lang = bind.LangGo 137 case "java": 138 lang = bind.LangJava 139 case "objc": 140 lang = bind.LangObjC 141 utils.Fatalf("Objc binding generation is uncompleted") 142 default: 143 utils.Fatalf("Unsupported destination language \"%s\" (--lang)", c.GlobalString(langFlag.Name)) 144 } 145 // If the entire solidity code was specified, build and bind based on that 146 var ( 147 abis []string 148 bins []string 149 types []string 150 sigs []map[string]string 151 libs = make(map[string]string) 152 ) 153 if c.GlobalString(abiFlag.Name) != "" { 154 // Load up the ABI, optional bytecode and type name from the parameters 155 var ( 156 abi []byte 157 err error 158 ) 159 input := c.GlobalString(abiFlag.Name) 160 if input == "-" { 161 abi, err = ioutil.ReadAll(os.Stdin) 162 } else { 163 abi, err = ioutil.ReadFile(input) 164 } 165 if err != nil { 166 utils.Fatalf("Failed to read input ABI: %v", err) 167 } 168 abis = append(abis, string(abi)) 169 170 var bin []byte 171 if binFile := c.GlobalString(binFlag.Name); binFile != "" { 172 if bin, err = ioutil.ReadFile(binFile); err != nil { 173 utils.Fatalf("Failed to read input bytecode: %v", err) 174 } 175 if strings.Contains(string(bin), "//") { 176 utils.Fatalf("Contract has additional library references, please use other mode(e.g. --combined-json) to catch library infos") 177 } 178 } 179 bins = append(bins, string(bin)) 180 181 kind := c.GlobalString(typeFlag.Name) 182 if kind == "" { 183 kind = c.GlobalString(pkgFlag.Name) 184 } 185 types = append(types, kind) 186 } else { 187 // Generate the list of types to exclude from binding 188 exclude := make(map[string]bool) 189 for _, kind := range strings.Split(c.GlobalString(excFlag.Name), ",") { 190 exclude[strings.ToLower(kind)] = true 191 } 192 var err error 193 var contracts map[string]*compiler.Contract 194 195 switch { 196 case c.GlobalIsSet(solFlag.Name): 197 contracts, err = compiler.CompileSolidity(c.GlobalString(solcFlag.Name), c.GlobalString(solFlag.Name)) 198 if err != nil { 199 utils.Fatalf("Failed to build Solidity contract: %v", err) 200 } 201 case c.GlobalIsSet(vyFlag.Name): 202 contracts, err = compiler.CompileVyper(c.GlobalString(vyperFlag.Name), c.GlobalString(vyFlag.Name)) 203 if err != nil { 204 utils.Fatalf("Failed to build Vyper contract: %v", err) 205 } 206 case c.GlobalIsSet(jsonFlag.Name): 207 jsonOutput, err := ioutil.ReadFile(c.GlobalString(jsonFlag.Name)) 208 if err != nil { 209 utils.Fatalf("Failed to read combined-json from compiler: %v", err) 210 } 211 contracts, err = compiler.ParseCombinedJSON(jsonOutput, "", "", "", "") 212 if err != nil { 213 utils.Fatalf("Failed to read contract information from json output: %v", err) 214 } 215 } 216 // Gather all non-excluded contract for binding 217 for name, contract := range contracts { 218 if exclude[strings.ToLower(name)] { 219 continue 220 } 221 abi, err := json.Marshal(contract.Info.AbiDefinition) // Flatten the compiler parse 222 if err != nil { 223 utils.Fatalf("Failed to parse ABIs from compiler output: %v", err) 224 } 225 abis = append(abis, string(abi)) 226 bins = append(bins, contract.Code) 227 sigs = append(sigs, contract.Hashes) 228 nameParts := strings.Split(name, ":") 229 types = append(types, nameParts[len(nameParts)-1]) 230 231 libPattern := crypto.Keccak256Hash([]byte(name)).String()[2:36] 232 libs[libPattern] = nameParts[len(nameParts)-1] 233 } 234 } 235 // Generate the contract binding 236 code, err := bind.Bind(types, abis, bins, sigs, c.GlobalString(pkgFlag.Name), lang, libs) 237 if err != nil { 238 utils.Fatalf("Failed to generate ABI binding: %v", err) 239 } 240 // Either flush it out to a file or display on the standard output 241 if !c.GlobalIsSet(outFlag.Name) { 242 fmt.Printf("%s\n", code) 243 return nil 244 } 245 if err := ioutil.WriteFile(c.GlobalString(outFlag.Name), []byte(code), 0600); err != nil { 246 utils.Fatalf("Failed to write ABI binding: %v", err) 247 } 248 return nil 249 } 250 251 func main() { 252 log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) 253 254 if err := app.Run(os.Args); err != nil { 255 fmt.Fprintln(os.Stderr, err) 256 os.Exit(1) 257 } 258 }