diff --git a/cmd/abigen/main.go b/cmd/abigen/main.go index dcee50199b..132dec9f75 100644 --- a/cmd/abigen/main.go +++ b/cmd/abigen/main.go @@ -17,124 +17,124 @@ package main import ( - "encoding/json" - "flag" - "fmt" - "io/ioutil" - "os" - "strings" + "encoding/json" + "flag" + "fmt" + "io/ioutil" + "os" + "strings" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common/compiler" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common/compiler" ) 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)") + 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)") - 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") + 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") - 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") + 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") - 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)") + 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)") ) func main() { - // Parse and ensure all needed inputs are specified - flag.Parse() + // Parse and ensure all needed inputs are specified + flag.Parse() - 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) - } - var lang bind.Lang - switch *langFlag { - case "go": - lang = bind.LangGo - case "java": - lang = bind.LangJava - case "objc": - lang = bind.LangObjC - default: - fmt.Printf("Unsupported destination language \"%s\" (--lang)\n", *langFlag) - os.Exit(-1) - } - // If the entire solidity code was specified, build and bind based on that - var ( - abis []string - bins []string - types []string - ) - if *solFlag != "" || *vyFlag != "" || (*abiFlag == "-" && *pkgFlag == "") { - // Generate the list of types to exclude from binding - exclude := make(map[string]bool) - for _, kind := range strings.Split(*excFlag, ",") { - exclude[strings.ToLower(kind)] = true - } + 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) + } + var lang bind.Lang + switch *langFlag { + case "go": + lang = bind.LangGo + case "java": + lang = bind.LangJava + case "objc": + lang = bind.LangObjC + default: + fmt.Printf("Unsupported destination language \"%s\" (--lang)\n", *langFlag) + os.Exit(-1) + } + // If the entire solidity code was specified, build and bind based on that + var ( + abis []string + bins []string + types []string + ) + if *solFlag != "" || *vyFlag != "" || (*abiFlag == "-" && *pkgFlag == "") { + // Generate the list of types to exclude from binding + exclude := make(map[string]bool) + for _, kind := range strings.Split(*excFlag, ",") { + exclude[strings.ToLower(kind)] = true + } - var contracts map[string]*compiler.Contract - var err error - if *solFlag != "" { - contracts, err = compiler.CompileSolidity(*solcFlag, *solFlag) - if err != nil { - fmt.Printf("Failed to build Solidity contract: %v\n", err) - os.Exit(-1) - } - } else if *vyFlag != "" { - contracts, err = compiler.CompileVyper(*vyperFlag, *vyFlag) - if err != nil { - fmt.Printf("Failed to build Vyper contract: %v\n", err) - os.Exit(-1) - } - } else { - contracts, err = contractsFromStdin() - if err != nil { - fmt.Printf("Failed to read input ABIs from STDIN: %v\n", err) - os.Exit(-1) - } - } - // Gather all non-excluded contract for binding - for name, contract := range contracts { - if exclude[strings.ToLower(name)] { - continue - } - abi, _ := json.Marshal(contract.Info.AbiDefinition) // Flatten the compiler parse - abis = append(abis, string(abi)) - bins = append(bins, contract.Code) + var contracts map[string]*compiler.Contract + var err error + if *solFlag != "" { + contracts, err = compiler.CompileSolidity(*solcFlag, *solFlag) + if err != nil { + fmt.Printf("Failed to build Solidity contract: %v\n", err) + os.Exit(-1) + } + } else if *vyFlag != "" { + contracts, err = compiler.CompileVyper(*vyperFlag, *vyFlag) + if err != nil { + fmt.Printf("Failed to build Vyper contract: %v\n", err) + os.Exit(-1) + } + } else { + contracts, err = contractsFromStdin() + if err != nil { + fmt.Printf("Failed to read input ABIs from STDIN: %v\n", err) + os.Exit(-1) + } + } + // Gather all non-excluded contract for binding + for name, contract := range contracts { + if exclude[strings.ToLower(name)] { + continue + } + abi, _ := json.Marshal(contract.Info.AbiDefinition) // Flatten the compiler parse + abis = append(abis, string(abi)) + bins = append(bins, contract.Code) - nameParts := strings.Split(name, ":") - types = append(types, nameParts[len(nameParts)-1]) - } - } else { - // Otherwise load up the ABI, optional bytecode and type name from the parameters - var abi []byte - var err error - if *abiFlag == "-" { - abi, err = ioutil.ReadAll(os.Stdin) - } else { - 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)) + nameParts := strings.Split(name, ":") + types = append(types, nameParts[len(nameParts)-1]) + } + } else { + // Otherwise load up the ABI, optional bytecode and type name from the parameters + var abi []byte + var err error + if *abiFlag == "-" { + abi, err = ioutil.ReadAll(os.Stdin) + } else { + 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 != "" { @@ -145,33 +145,34 @@ func main() { } 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, *pkgFlag, lang) - if err != nil { - fmt.Printf("Failed to generate ABI binding: %v\n", err) - os.Exit(-1) - } - // Either flush it out to a file or display on the standard output - if *outFlag == "" { - fmt.Printf("%s\n", code) - return - } - if err := ioutil.WriteFile(*outFlag, []byte(code), 0600); err != nil { - fmt.Printf("Failed to write ABI binding: %v\n", err) - os.Exit(-1) - } + kind := *typFlag + if kind == "" { + kind = *pkgFlag + } + types = append(types, kind) + } + // Generate the contract binding + fmt.Printf("%+v", abis) + code, err := bind.Bind(types, abis, bins, *pkgFlag, lang) + if err != nil { + fmt.Printf("Failed to generate ABI binding: %v\n", err) + os.Exit(-1) + } + // Either flush it out to a file or display on the standard output + if *outFlag == "" { + fmt.Printf("%s\n", code) + return + } + if err := ioutil.WriteFile(*outFlag, []byte(code), 0600); err != nil { + fmt.Printf("Failed to write ABI binding: %v\n", err) + os.Exit(-1) + } } func contractsFromStdin() (map[string]*compiler.Contract, error) { - bytes, err := ioutil.ReadAll(os.Stdin) - if err != nil { - return nil, err - } - return compiler.ParseCombinedJSON(bytes, "", "", "", "") + bytes, err := ioutil.ReadAll(os.Stdin) + if err != nil { + return nil, err + } + return compiler.ParseCombinedJSON(bytes, "", "", "", "") } diff --git a/common/compiler/helpers.go b/common/compiler/helpers.go index 3ac4ba828d..59e650a2c3 100644 --- a/common/compiler/helpers.go +++ b/common/compiler/helpers.go @@ -18,18 +18,18 @@ package compiler import ( - "bytes" - "io/ioutil" - "regexp" + "bytes" + "io/ioutil" + "regexp" ) var versionRegexp = regexp.MustCompile(`([0-9]+)\.([0-9]+)\.([0-9]+)`) // Contract contains information about a compiled contract, alongside its code and runtime code. type Contract struct { - Code string `json:"code"` - RuntimeCode string `json:"runtime-code"` - Info ContractInfo `json:"info"` + Code string `json:"code"` + RuntimeCode string `json:"runtime-code"` + Info ContractInfo `json:"info"` } // ContractInfo contains information about a compiled contract, including access @@ -38,27 +38,27 @@ type Contract struct { // Depending on the source, language version, compiler version, and compiler // options will provide information about how the contract was compiled. type ContractInfo struct { - Source string `json:"source"` - Language string `json:"language"` - LanguageVersion string `json:"languageVersion"` - CompilerVersion string `json:"compilerVersion"` - CompilerOptions string `json:"compilerOptions"` - SrcMap interface{} `json:"srcMap"` - SrcMapRuntime string `json:"srcMapRuntime"` - AbiDefinition interface{} `json:"abiDefinition"` - UserDoc interface{} `json:"userDoc"` - DeveloperDoc interface{} `json:"developerDoc"` - Metadata string `json:"metadata"` + Source string `json:"source"` + Language string `json:"language"` + LanguageVersion string `json:"languageVersion"` + CompilerVersion string `json:"compilerVersion"` + CompilerOptions string `json:"compilerOptions"` + SrcMap interface{} `json:"srcMap"` + SrcMapRuntime string `json:"srcMapRuntime"` + AbiDefinition interface{} `json:"abiDefinition"` + UserDoc interface{} `json:"userDoc"` + DeveloperDoc interface{} `json:"developerDoc"` + Metadata string `json:"metadata"` } func slurpFiles(files []string) (string, error) { - var concat bytes.Buffer - for _, file := range files { - content, err := ioutil.ReadFile(file) - if err != nil { - return "", err - } - concat.Write(content) - } - return concat.String(), nil -} \ No newline at end of file + var concat bytes.Buffer + for _, file := range files { + content, err := ioutil.ReadFile(file) + if err != nil { + return "", err + } + concat.Write(content) + } + return concat.String(), nil +} diff --git a/common/compiler/vyper.go b/common/compiler/vyper.go index eb9317db50..7f0455925f 100644 --- a/common/compiler/vyper.go +++ b/common/compiler/vyper.go @@ -18,84 +18,84 @@ package compiler import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "os/exec" - "strconv" - "strings" + "bytes" + "encoding/json" + "errors" + "fmt" + "os/exec" + "strconv" + "strings" ) // Vyper contains information about the vyper compiler. type Vyper struct { - Path, Version, FullVersion string - Major, Minor, Patch int + Path, Version, FullVersion string + Major, Minor, Patch int } func (s *Vyper) makeArgs() []string { - p := []string{ - "-f", "combined_json", - } - return p + p := []string{ + "-f", "combined_json", + } + return p } // VyperVersion runs vyper and parses its version output. func VyperVersion(vyper string) (*Vyper, error) { - if vyper == "" { - vyper = "vyper" - } - var out bytes.Buffer - cmd := exec.Command(vyper, "--version") - cmd.Stdout = &out - err := cmd.Run() - if err != nil { - return nil, err - } - matches := versionRegexp.FindStringSubmatch(out.String()) - if len(matches) != 4 { - return nil, fmt.Errorf("can't parse vyper version %q", out.String()) - } - s := &Vyper{Path: cmd.Path, FullVersion: out.String(), Version: matches[0]} - if s.Major, err = strconv.Atoi(matches[1]); err != nil { - return nil, err - } - if s.Minor, err = strconv.Atoi(matches[2]); err != nil { - return nil, err - } - if s.Patch, err = strconv.Atoi(matches[3]); err != nil { - return nil, err - } - return s, nil + if vyper == "" { + vyper = "vyper" + } + var out bytes.Buffer + cmd := exec.Command(vyper, "--version") + cmd.Stdout = &out + err := cmd.Run() + if err != nil { + return nil, err + } + matches := versionRegexp.FindStringSubmatch(out.String()) + if len(matches) != 4 { + return nil, fmt.Errorf("can't parse vyper version %q", out.String()) + } + s := &Vyper{Path: cmd.Path, FullVersion: out.String(), Version: matches[0]} + if s.Major, err = strconv.Atoi(matches[1]); err != nil { + return nil, err + } + if s.Minor, err = strconv.Atoi(matches[2]); err != nil { + return nil, err + } + if s.Patch, err = strconv.Atoi(matches[3]); err != nil { + return nil, err + } + return s, nil } // CompileVyper compiles all given Vyper source files. func CompileVyper(vyper string, sourcefiles ...string) (map[string]*Contract, error) { - if len(sourcefiles) == 0 { - return nil, errors.New("vyper: no source files") - } - source, err := slurpFiles(sourcefiles) - if err != nil { - return nil, err - } - s, err := VyperVersion(vyper) - if err != nil { - return nil, err - } - args := s.makeArgs() - cmd := exec.Command(s.Path, append(args, sourcefiles...)...) - return s.run(cmd, source) + if len(sourcefiles) == 0 { + return nil, errors.New("vyper: no source files") + } + source, err := slurpFiles(sourcefiles) + if err != nil { + return nil, err + } + s, err := VyperVersion(vyper) + if err != nil { + return nil, err + } + args := s.makeArgs() + cmd := exec.Command(s.Path, append(args, sourcefiles...)...) + return s.run(cmd, source) } func (s *Vyper) run(cmd *exec.Cmd, source string) (map[string]*Contract, error) { - var stderr, stdout bytes.Buffer - cmd.Stderr = &stderr - cmd.Stdout = &stdout - if err := cmd.Run(); err != nil { - return nil, fmt.Errorf("vyper: %v\n%s", err, stderr.Bytes()) - } + var stderr, stdout bytes.Buffer + cmd.Stderr = &stderr + cmd.Stdout = &stdout + if err := cmd.Run(); err != nil { + return nil, fmt.Errorf("vyper: %v\n%s", err, stderr.Bytes()) + } - return ParseVyperJSON(stdout.Bytes(), source, s.Version, s.Version, strings.Join(s.makeArgs(), " ")) + return ParseVyperJSON(stdout.Bytes(), source, s.Version, s.Version, strings.Join(s.makeArgs(), " ")) } // ParseVyperJSON takes the direct output of a vyper --f combined_json run and @@ -108,37 +108,37 @@ func (s *Vyper) run(cmd *exec.Cmd, source string) (map[string]*Contract, error) // Returns an error if the JSON is malformed or missing data, or if the JSON // embedded within the JSON is malformed. func ParseVyperJSON(combinedJSON []byte, source string, languageVersion string, compilerVersion string, compilerOptions string) (map[string]*Contract, error) { - var output map[string]interface{} - if err := json.Unmarshal(combinedJSON, &output); err != nil { - return nil, err - } + var output map[string]interface{} + if err := json.Unmarshal(combinedJSON, &output); err != nil { + return nil, err + } - // Compilation succeeded, assemble and return the contracts. - contracts := make(map[string]*Contract) - for name, info := range output { - // Parse the individual compilation results. - if name == "version" { - continue - } - c := info.(map[string]interface{}) + // Compilation succeeded, assemble and return the contracts. + contracts := make(map[string]*Contract) + for name, info := range output { + // Parse the individual compilation results. + if name == "version" { + continue + } + c := info.(map[string]interface{}) - contracts[name] = &Contract{ - Code: c["bytecode"].(string), - RuntimeCode: c["bytecode_runtime"].(string), - Info: ContractInfo{ - Source: source, - Language: "Vyper", - LanguageVersion: languageVersion, - CompilerVersion: compilerVersion, - CompilerOptions: compilerOptions, - SrcMap: c["source_map"], - SrcMapRuntime: "", - AbiDefinition: c["abi"], - UserDoc: "", - DeveloperDoc: "", - Metadata: "", - }, - } - } - return contracts, nil + contracts[name] = &Contract{ + Code: c["bytecode"].(string), + RuntimeCode: c["bytecode_runtime"].(string), + Info: ContractInfo{ + Source: source, + Language: "Vyper", + LanguageVersion: languageVersion, + CompilerVersion: compilerVersion, + CompilerOptions: compilerOptions, + SrcMap: c["source_map"], + SrcMapRuntime: "", + AbiDefinition: c["abi"], + UserDoc: "", + DeveloperDoc: "", + Metadata: "", + }, + } + } + return contracts, nil } diff --git a/common/compiler/vyper_test.go b/common/compiler/vyper_test.go index 2c1049ccf7..68480ef5ca 100644 --- a/common/compiler/vyper_test.go +++ b/common/compiler/vyper_test.go @@ -17,52 +17,55 @@ package compiler import ( - "os/exec" - "testing" + "os/exec" + "testing" ) func skipWithoutVyper(t *testing.T) { - if _, err := exec.LookPath("vyper"); err != nil { - t.Skip(err) - } + if _, err := exec.LookPath("vyper"); err != nil { + t.Skip(err) + } } func TestVyperCompiler(t *testing.T) { - skipWithoutVyper(t) + skipWithoutVyper(t) - testSource := []string{"test.v.py"} - source, err := slurpFiles(testSource) - contracts, err := CompileVyper("", testSource...) - if err != nil { - t.Fatalf("error compiling test.v.py. result %v: %v", contracts, err) - } - if len(contracts) != 1 { - t.Errorf("one contract expected, got %d", len(contracts)) - } - c, ok := contracts["test.v.py"] - if !ok { - c, ok = contracts[":test"] - if !ok { - t.Fatal("info for contract 'test.v.py' not present in result") - } - } - if c.Code == "" { - t.Error("empty code") - } - if c.Info.Source != source { - t.Error("wrong source") - } - if c.Info.CompilerVersion == "" { - t.Error("empty version") - } + testSource := []string{"test.v.py"} + source, err := slurpFiles(testSource) + if err != nil { + t.Error("couldn't read test files") + } + contracts, err := CompileVyper("", testSource...) + if err != nil { + t.Fatalf("error compiling test.v.py. result %v: %v", contracts, err) + } + if len(contracts) != 1 { + t.Errorf("one contract expected, got %d", len(contracts)) + } + c, ok := contracts["test.v.py"] + if !ok { + c, ok = contracts[":test"] + if !ok { + t.Fatal("info for contract 'test.v.py' not present in result") + } + } + if c.Code == "" { + t.Error("empty code") + } + if c.Info.Source != source { + t.Error("wrong source") + } + if c.Info.CompilerVersion == "" { + t.Error("empty version") + } } func TestVyperCompileError(t *testing.T) { - skipWithoutVyper(t) + skipWithoutVyper(t) - contracts, err := CompileVyper("", "test_bad.v.py") - if err == nil { - t.Errorf("error expected compiling test_bad.v.py. got none. result %v", contracts) - } - t.Logf("error: %v", err) + contracts, err := CompileVyper("", "test_bad.v.py") + if err == nil { + t.Errorf("error expected compiling test_bad.v.py. got none. result %v", contracts) + } + t.Logf("error: %v", err) }