|
|
@@ -18,63 +18,129 @@ package main
|
|
|
|
|
|
import (
|
|
|
"encoding/json"
|
|
|
- "flag"
|
|
|
"fmt"
|
|
|
"io/ioutil"
|
|
|
"os"
|
|
|
"strings"
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
|
|
+ "github.com/ethereum/go-ethereum/cmd/utils"
|
|
|
"github.com/ethereum/go-ethereum/common/compiler"
|
|
|
"github.com/ethereum/go-ethereum/crypto"
|
|
|
+ "github.com/ethereum/go-ethereum/log"
|
|
|
+ "gopkg.in/urfave/cli.v1"
|
|
|
)
|
|
|
|
|
|
-var (
|
|
|
- abiFlag = flag.String("abi", "", "Path to the Ethereum contract ABI json to bind, - for STDIN")
|
|
|
- binFlag = flag.String("bin", "", "Path to the Ethereum contract bytecode (generate deploy method)")
|
|
|
- typFlag = flag.String("type", "", "Struct name for the binding (default = package name)")
|
|
|
+const (
|
|
|
+ commandHelperTemplate = `{{.Name}}{{if .Subcommands}} command{{end}}{{if .Flags}} [command options]{{end}} [arguments...]
|
|
|
+{{if .Description}}{{.Description}}
|
|
|
+{{end}}{{if .Subcommands}}
|
|
|
+SUBCOMMANDS:
|
|
|
+ {{range .Subcommands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
|
|
|
+ {{end}}{{end}}{{if .Flags}}
|
|
|
+OPTIONS:
|
|
|
+{{range $.Flags}}{{"\t"}}{{.}}
|
|
|
+{{end}}
|
|
|
+{{end}}`
|
|
|
+)
|
|
|
|
|
|
- solFlag = flag.String("sol", "", "Path to the Ethereum contract Solidity source to build and bind")
|
|
|
- solcFlag = flag.String("solc", "solc", "Solidity compiler to use if source builds are requested")
|
|
|
- excFlag = flag.String("exc", "", "Comma separated types to exclude from binding")
|
|
|
+var (
|
|
|
+ // Git SHA1 commit hash of the release (set via linker flags)
|
|
|
+ gitCommit = ""
|
|
|
+ gitDate = ""
|
|
|
|
|
|
- vyFlag = flag.String("vy", "", "Path to the Ethereum contract Vyper source to build and bind")
|
|
|
- vyperFlag = flag.String("vyper", "vyper", "Vyper compiler to use if source builds are requested")
|
|
|
+ app *cli.App
|
|
|
|
|
|
- pkgFlag = flag.String("pkg", "", "Package name to generate the binding into")
|
|
|
- outFlag = flag.String("out", "", "Output file for the generated binding (default = stdout)")
|
|
|
- langFlag = flag.String("lang", "go", "Destination language for the bindings (go, java, objc)")
|
|
|
+ // Flags needed by abigen
|
|
|
+ abiFlag = cli.StringFlag{
|
|
|
+ Name: "abi",
|
|
|
+ Usage: "Path to the Ethereum contract ABI json to bind, - for STDIN",
|
|
|
+ }
|
|
|
+ binFlag = cli.StringFlag{
|
|
|
+ Name: "bin",
|
|
|
+ Usage: "Path to the Ethereum contract bytecode (generate deploy method)",
|
|
|
+ }
|
|
|
+ typeFlag = cli.StringFlag{
|
|
|
+ Name: "type",
|
|
|
+ Usage: "Struct name for the binding (default = package name)",
|
|
|
+ }
|
|
|
+ jsonFlag = cli.StringFlag{
|
|
|
+ Name: "combined-json",
|
|
|
+ Usage: "Path to the combined-json file generated by compiler",
|
|
|
+ }
|
|
|
+ solFlag = cli.StringFlag{
|
|
|
+ Name: "sol",
|
|
|
+ Usage: "Path to the Ethereum contract Solidity source to build and bind",
|
|
|
+ }
|
|
|
+ solcFlag = cli.StringFlag{
|
|
|
+ Name: "solc",
|
|
|
+ Usage: "Solidity compiler to use if source builds are requested",
|
|
|
+ Value: "solc",
|
|
|
+ }
|
|
|
+ vyFlag = cli.StringFlag{
|
|
|
+ Name: "vy",
|
|
|
+ Usage: "Path to the Ethereum contract Vyper source to build and bind",
|
|
|
+ }
|
|
|
+ vyperFlag = cli.StringFlag{
|
|
|
+ Name: "vyper",
|
|
|
+ Usage: "Vyper compiler to use if source builds are requested",
|
|
|
+ Value: "vyper",
|
|
|
+ }
|
|
|
+ excFlag = cli.StringFlag{
|
|
|
+ Name: "exc",
|
|
|
+ Usage: "Comma separated types to exclude from binding",
|
|
|
+ }
|
|
|
+ pkgFlag = cli.StringFlag{
|
|
|
+ Name: "pkg",
|
|
|
+ Usage: "Package name to generate the binding into",
|
|
|
+ }
|
|
|
+ outFlag = cli.StringFlag{
|
|
|
+ Name: "out",
|
|
|
+ Usage: "Output file for the generated binding (default = stdout)",
|
|
|
+ }
|
|
|
+ langFlag = cli.StringFlag{
|
|
|
+ Name: "lang",
|
|
|
+ Usage: "Destination language for the bindings (go, java, objc)",
|
|
|
+ Value: "go",
|
|
|
+ }
|
|
|
)
|
|
|
|
|
|
-func main() {
|
|
|
- // Parse and ensure all needed inputs are specified
|
|
|
- flag.Parse()
|
|
|
+func init() {
|
|
|
+ app = utils.NewApp(gitCommit, gitDate, "ethereum checkpoint helper tool")
|
|
|
+ app.Flags = []cli.Flag{
|
|
|
+ abiFlag,
|
|
|
+ binFlag,
|
|
|
+ typeFlag,
|
|
|
+ jsonFlag,
|
|
|
+ solFlag,
|
|
|
+ solcFlag,
|
|
|
+ vyFlag,
|
|
|
+ vyperFlag,
|
|
|
+ excFlag,
|
|
|
+ pkgFlag,
|
|
|
+ outFlag,
|
|
|
+ langFlag,
|
|
|
+ }
|
|
|
+ app.Action = utils.MigrateFlags(abigen)
|
|
|
+ cli.CommandHelpTemplate = commandHelperTemplate
|
|
|
+}
|
|
|
|
|
|
- if *abiFlag == "" && *solFlag == "" && *vyFlag == "" {
|
|
|
- fmt.Printf("No contract ABI (--abi), Solidity source (--sol), or Vyper source (--vy) specified\n")
|
|
|
- os.Exit(-1)
|
|
|
- } else if (*abiFlag != "" || *binFlag != "" || *typFlag != "") && (*solFlag != "" || *vyFlag != "") {
|
|
|
- fmt.Printf("Contract ABI (--abi), bytecode (--bin) and type (--type) flags are mutually exclusive with the Solidity (--sol) and Vyper (--vy) flags\n")
|
|
|
- os.Exit(-1)
|
|
|
- } else if *solFlag != "" && *vyFlag != "" {
|
|
|
- fmt.Printf("Solidity (--sol) and Vyper (--vy) flags are mutually exclusive\n")
|
|
|
- os.Exit(-1)
|
|
|
- }
|
|
|
- if *pkgFlag == "" {
|
|
|
- fmt.Printf("No destination package specified (--pkg)\n")
|
|
|
- os.Exit(-1)
|
|
|
+func abigen(c *cli.Context) error {
|
|
|
+ utils.CheckExclusive(c, abiFlag, jsonFlag, solFlag, vyFlag) // Only one source can be selected.
|
|
|
+ if c.GlobalString(pkgFlag.Name) == "" {
|
|
|
+ utils.Fatalf("No destination package specified (--pkg)")
|
|
|
}
|
|
|
var lang bind.Lang
|
|
|
- switch *langFlag {
|
|
|
+ switch c.GlobalString(langFlag.Name) {
|
|
|
case "go":
|
|
|
lang = bind.LangGo
|
|
|
case "java":
|
|
|
lang = bind.LangJava
|
|
|
case "objc":
|
|
|
lang = bind.LangObjC
|
|
|
+ utils.Fatalf("Objc binding generation is uncompleted")
|
|
|
default:
|
|
|
- fmt.Printf("Unsupported destination language \"%s\" (--lang)\n", *langFlag)
|
|
|
- os.Exit(-1)
|
|
|
+ utils.Fatalf("Unsupported destination language \"%s\" (--lang)", c.GlobalString(langFlag.Name))
|
|
|
}
|
|
|
// If the entire solidity code was specified, build and bind based on that
|
|
|
var (
|
|
|
@@ -84,34 +150,67 @@ func main() {
|
|
|
sigs []map[string]string
|
|
|
libs = make(map[string]string)
|
|
|
)
|
|
|
- if *solFlag != "" || *vyFlag != "" || *abiFlag == "-" {
|
|
|
+ if c.GlobalString(abiFlag.Name) != "" {
|
|
|
+ // Load up the ABI, optional bytecode and type name from the parameters
|
|
|
+ var (
|
|
|
+ abi []byte
|
|
|
+ err error
|
|
|
+ )
|
|
|
+ input := c.GlobalString(abiFlag.Name)
|
|
|
+ if input == "-" {
|
|
|
+ abi, err = ioutil.ReadAll(os.Stdin)
|
|
|
+ } else {
|
|
|
+ abi, err = ioutil.ReadFile(input)
|
|
|
+ }
|
|
|
+ if err != nil {
|
|
|
+ utils.Fatalf("Failed to read input ABI: %v", err)
|
|
|
+ }
|
|
|
+ abis = append(abis, string(abi))
|
|
|
+
|
|
|
+ var bin []byte
|
|
|
+ if binFile := c.GlobalString(binFlag.Name); binFile != "" {
|
|
|
+ if bin, err = ioutil.ReadFile(binFile); err != nil {
|
|
|
+ utils.Fatalf("Failed to read input bytecode: %v", err)
|
|
|
+ }
|
|
|
+ if strings.Contains(string(bin), "//") {
|
|
|
+ utils.Fatalf("Contract has additional library references, please use other mode(e.g. --combined-json) to catch library infos")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ bins = append(bins, string(bin))
|
|
|
+
|
|
|
+ kind := c.GlobalString(typeFlag.Name)
|
|
|
+ if kind == "" {
|
|
|
+ kind = c.GlobalString(pkgFlag.Name)
|
|
|
+ }
|
|
|
+ types = append(types, kind)
|
|
|
+ } else {
|
|
|
// Generate the list of types to exclude from binding
|
|
|
exclude := make(map[string]bool)
|
|
|
- for _, kind := range strings.Split(*excFlag, ",") {
|
|
|
+ for _, kind := range strings.Split(c.GlobalString(excFlag.Name), ",") {
|
|
|
exclude[strings.ToLower(kind)] = true
|
|
|
}
|
|
|
-
|
|
|
- var contracts map[string]*compiler.Contract
|
|
|
var err error
|
|
|
+ var contracts map[string]*compiler.Contract
|
|
|
|
|
|
switch {
|
|
|
- case *solFlag != "":
|
|
|
- contracts, err = compiler.CompileSolidity(*solcFlag, *solFlag)
|
|
|
+ case c.GlobalIsSet(solFlag.Name):
|
|
|
+ contracts, err = compiler.CompileSolidity(c.GlobalString(solcFlag.Name), c.GlobalString(solFlag.Name))
|
|
|
+ if err != nil {
|
|
|
+ utils.Fatalf("Failed to build Solidity contract: %v", err)
|
|
|
+ }
|
|
|
+ case c.GlobalIsSet(vyFlag.Name):
|
|
|
+ contracts, err = compiler.CompileVyper(c.GlobalString(vyperFlag.Name), c.GlobalString(vyFlag.Name))
|
|
|
if err != nil {
|
|
|
- fmt.Printf("Failed to build Solidity contract: %v\n", err)
|
|
|
- os.Exit(-1)
|
|
|
+ utils.Fatalf("Failed to build Vyper contract: %v", err)
|
|
|
}
|
|
|
- case *vyFlag != "":
|
|
|
- contracts, err = compiler.CompileVyper(*vyperFlag, *vyFlag)
|
|
|
+ case c.GlobalIsSet(jsonFlag.Name):
|
|
|
+ jsonOutput, err := ioutil.ReadFile(c.GlobalString(jsonFlag.Name))
|
|
|
if err != nil {
|
|
|
- fmt.Printf("Failed to build Vyper contract: %v\n", err)
|
|
|
- os.Exit(-1)
|
|
|
+ utils.Fatalf("Failed to read combined-json from compiler: %v", err)
|
|
|
}
|
|
|
- default:
|
|
|
- contracts, err = contractsFromStdin()
|
|
|
+ contracts, err = compiler.ParseCombinedJSON(jsonOutput, "", "", "", "")
|
|
|
if err != nil {
|
|
|
- fmt.Printf("Failed to read input ABIs from STDIN: %v\n", err)
|
|
|
- os.Exit(-1)
|
|
|
+ utils.Fatalf("Failed to read contract information from json output: %v", err)
|
|
|
}
|
|
|
}
|
|
|
// Gather all non-excluded contract for binding
|
|
|
@@ -121,65 +220,39 @@ func main() {
|
|
|
}
|
|
|
abi, err := json.Marshal(contract.Info.AbiDefinition) // Flatten the compiler parse
|
|
|
if err != nil {
|
|
|
- fmt.Printf("Failed to parse ABIs from compiler output: %v\n", err)
|
|
|
- os.Exit(-1)
|
|
|
+ utils.Fatalf("Failed to parse ABIs from compiler output: %v", err)
|
|
|
}
|
|
|
abis = append(abis, string(abi))
|
|
|
bins = append(bins, contract.Code)
|
|
|
sigs = append(sigs, contract.Hashes)
|
|
|
-
|
|
|
nameParts := strings.Split(name, ":")
|
|
|
types = append(types, nameParts[len(nameParts)-1])
|
|
|
|
|
|
libPattern := crypto.Keccak256Hash([]byte(name)).String()[2:36]
|
|
|
libs[libPattern] = nameParts[len(nameParts)-1]
|
|
|
}
|
|
|
- } else {
|
|
|
- // Otherwise load up the ABI, optional bytecode and type name from the parameters
|
|
|
- abi, err := ioutil.ReadFile(*abiFlag)
|
|
|
-
|
|
|
- if err != nil {
|
|
|
- fmt.Printf("Failed to read input ABI: %v\n", err)
|
|
|
- os.Exit(-1)
|
|
|
- }
|
|
|
- abis = append(abis, string(abi))
|
|
|
-
|
|
|
- var bin []byte
|
|
|
- if *binFlag != "" {
|
|
|
- if bin, err = ioutil.ReadFile(*binFlag); err != nil {
|
|
|
- fmt.Printf("Failed to read input bytecode: %v\n", err)
|
|
|
- os.Exit(-1)
|
|
|
- }
|
|
|
- }
|
|
|
- bins = append(bins, string(bin))
|
|
|
-
|
|
|
- kind := *typFlag
|
|
|
- if kind == "" {
|
|
|
- kind = *pkgFlag
|
|
|
- }
|
|
|
- types = append(types, kind)
|
|
|
}
|
|
|
// Generate the contract binding
|
|
|
- code, err := bind.Bind(types, abis, bins, sigs, *pkgFlag, lang, libs)
|
|
|
+ code, err := bind.Bind(types, abis, bins, sigs, c.GlobalString(pkgFlag.Name), lang, libs)
|
|
|
if err != nil {
|
|
|
- fmt.Printf("Failed to generate ABI binding: %v\n", err)
|
|
|
- os.Exit(-1)
|
|
|
+ utils.Fatalf("Failed to generate ABI binding: %v", err)
|
|
|
}
|
|
|
// Either flush it out to a file or display on the standard output
|
|
|
- if *outFlag == "" {
|
|
|
+ if !c.GlobalIsSet(outFlag.Name) {
|
|
|
fmt.Printf("%s\n", code)
|
|
|
- return
|
|
|
+ return nil
|
|
|
}
|
|
|
- if err := ioutil.WriteFile(*outFlag, []byte(code), 0600); err != nil {
|
|
|
- fmt.Printf("Failed to write ABI binding: %v\n", err)
|
|
|
- os.Exit(-1)
|
|
|
+ if err := ioutil.WriteFile(c.GlobalString(outFlag.Name), []byte(code), 0600); err != nil {
|
|
|
+ utils.Fatalf("Failed to write ABI binding: %v", err)
|
|
|
}
|
|
|
+ return nil
|
|
|
}
|
|
|
|
|
|
-func contractsFromStdin() (map[string]*compiler.Contract, error) {
|
|
|
- bytes, err := ioutil.ReadAll(os.Stdin)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
+func main() {
|
|
|
+ log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
|
|
+
|
|
|
+ if err := app.Run(os.Args); err != nil {
|
|
|
+ fmt.Fprintln(os.Stderr, err)
|
|
|
+ os.Exit(1)
|
|
|
}
|
|
|
- return compiler.ParseCombinedJSON(bytes, "", "", "", "")
|
|
|
}
|