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