From 5e38ed7d8684a447cf958b1c050bdc309f463255 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Thu, 5 Jan 2017 20:22:52 +0100 Subject: [PATCH] common/compiler: remove workaround for solc 0.3.5 stdin bug The crash when compiling stdin was fixed in solc 0.3.6 (released 2016-08-10). While here, simplify the test so it runs with any solc version. Fixes #3484. The byte code was different for each run because recent solc embeds the swarm hash of contract metadata into the code. When compiling from stdin the name in the metadata is constant. --- common/compiler/solidity.go | 30 ++++++++++-------------------- common/compiler/solidity_test.go | 28 ++++++++++++---------------- 2 files changed, 22 insertions(+), 36 deletions(-) diff --git a/common/compiler/solidity.go b/common/compiler/solidity.go index b682107d9c..b0ca9bd75a 100644 --- a/common/compiler/solidity.go +++ b/common/compiler/solidity.go @@ -22,9 +22,7 @@ import ( "encoding/json" "errors" "fmt" - "io" "io/ioutil" - "os" "os/exec" "regexp" "strings" @@ -96,27 +94,16 @@ func CompileSolidityString(solc, source string) (map[string]*Contract, error) { if solc == "" { solc = "solc" } - // Write source to a temporary file. Compiling stdin used to be supported - // but seems to produce an exception with solc 0.3.5. - infile, err := ioutil.TempFile("", "geth-compile-solidity") - if err != nil { - return nil, err - } - defer os.Remove(infile.Name()) - if _, err := io.WriteString(infile, source); err != nil { - return nil, err - } - if err := infile.Close(); err != nil { - return nil, err - } - - return CompileSolidity(solc, infile.Name()) + args := append(solcParams, "--") + cmd := exec.Command(solc, append(args, "-")...) + cmd.Stdin = strings.NewReader(source) + return runsolc(cmd, source) } // CompileSolidity compiles all given Solidity source files. func CompileSolidity(solc string, sourcefiles ...string) (map[string]*Contract, error) { if len(sourcefiles) == 0 { - return nil, errors.New("solc: no source ") + return nil, errors.New("solc: no source files") } source, err := slurpFiles(sourcefiles) if err != nil { @@ -125,10 +112,13 @@ func CompileSolidity(solc string, sourcefiles ...string) (map[string]*Contract, if solc == "" { solc = "solc" } - - var stderr, stdout bytes.Buffer args := append(solcParams, "--") cmd := exec.Command(solc, append(args, sourcefiles...)...) + return runsolc(cmd, source) +} + +func runsolc(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 { diff --git a/common/compiler/solidity_test.go b/common/compiler/solidity_test.go index e4d96bd018..8ba9e55d05 100644 --- a/common/compiler/solidity_test.go +++ b/common/compiler/solidity_test.go @@ -20,6 +20,7 @@ import ( "encoding/json" "io/ioutil" "os" + "os/exec" "path" "testing" @@ -27,8 +28,7 @@ import ( ) const ( - supportedSolcVersion = "0.3.5" - testSource = ` + testSource = ` contract test { /// @notice Will multiply ` + "`a`" + ` by 7. function multiply(uint a) returns(uint d) { @@ -36,23 +36,18 @@ contract test { } } ` - testCode = "0x6060604052602a8060106000396000f3606060405260e060020a6000350463c6888fa18114601a575b005b6007600435026060908152602090f3" testInfo = `{"source":"\ncontract test {\n /// @notice Will multiply ` + "`a`" + ` by 7.\n function multiply(uint a) returns(uint d) {\n return a * 7;\n }\n}\n","language":"Solidity","languageVersion":"0.1.1","compilerVersion":"0.1.1","compilerOptions":"--binary file --json-abi file --natspec-user file --natspec-dev file --add-std 1","abiDefinition":[{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"type":"function"}],"userDoc":{"methods":{"multiply(uint256)":{"notice":"Will multiply ` + "`a`" + ` by 7."}}},"developerDoc":{"methods":{}}}` ) -func skipUnsupported(t *testing.T) { - sol, err := SolidityVersion("") - if err != nil { +func skipWithoutSolc(t *testing.T) { + if _, err := exec.LookPath("solc"); err != nil { t.Skip(err) - return - } - if sol.Version != supportedSolcVersion { - t.Skipf("unsupported version of solc found (%v, expect %v)", sol.Version, supportedSolcVersion) } } func TestCompiler(t *testing.T) { - skipUnsupported(t) + skipWithoutSolc(t) + contracts, err := CompileSolidityString("", testSource) if err != nil { t.Fatalf("error compiling source. result %v: %v", contracts, err) @@ -64,19 +59,20 @@ func TestCompiler(t *testing.T) { if !ok { t.Fatal("info for contract 'test' not present in result") } - if c.Code != testCode { - t.Errorf("wrong code: expected\n%s, got\n%s", testCode, c.Code) + if c.Code == "" { + t.Error("empty code") } if c.Info.Source != testSource { t.Error("wrong source") } - if c.Info.CompilerVersion != supportedSolcVersion { - t.Errorf("wrong version: expected %q, got %q", supportedSolcVersion, c.Info.CompilerVersion) + if c.Info.CompilerVersion == "" { + t.Error("empty version") } } func TestCompileError(t *testing.T) { - skipUnsupported(t) + skipWithoutSolc(t) + contracts, err := CompileSolidityString("", testSource[4:]) if err == nil { t.Errorf("error expected compiling source. got none. result %v", contracts)