common/compiler: fix #1598, expose solidity errors
This commit is contained in:
parent
abce09954b
commit
101418b275
@ -19,6 +19,7 @@ package compiler
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
@ -110,95 +111,82 @@ func (sol *Solidity) Version() string {
|
|||||||
return sol.version
|
return sol.version
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sol *Solidity) Compile(source string) (contracts map[string]*Contract, err error) {
|
// Compile builds and returns all the contracts contained within a source string.
|
||||||
|
func (sol *Solidity) Compile(source string) (map[string]*Contract, error) {
|
||||||
|
// Short circuit if no source code was specified
|
||||||
if len(source) == 0 {
|
if len(source) == 0 {
|
||||||
err = fmt.Errorf("empty source")
|
return nil, errors.New("solc: empty source string")
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
// Create a safe place to dump compilation output
|
||||||
wd, err := ioutil.TempDir("", "solc")
|
wd, err := ioutil.TempDir("", "solc")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil, fmt.Errorf("solc: failed to create temporary build folder: %v", err)
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(wd)
|
defer os.RemoveAll(wd)
|
||||||
|
|
||||||
in := strings.NewReader(source)
|
// Assemble the compiler command, change to the temp folder and capture any errors
|
||||||
var out bytes.Buffer
|
stderr := new(bytes.Buffer)
|
||||||
// cwd set to temp dir
|
|
||||||
cmd := exec.Command(sol.solcPath, params...)
|
cmd := exec.Command(sol.solcPath, params...)
|
||||||
cmd.Dir = wd
|
cmd.Dir = wd
|
||||||
cmd.Stdin = in
|
cmd.Stdin = strings.NewReader(source)
|
||||||
cmd.Stdout = &out
|
cmd.Stderr = stderr
|
||||||
err = cmd.Run()
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("solc error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
return nil, fmt.Errorf("solc: %v\n%s", err, string(stderr.Bytes()))
|
||||||
|
}
|
||||||
|
// Sanity check that something was actually built
|
||||||
matches, _ := filepath.Glob(wd + "/*.binary")
|
matches, _ := filepath.Glob(wd + "/*.binary")
|
||||||
if len(matches) < 1 {
|
if len(matches) < 1 {
|
||||||
err = fmt.Errorf("solc error: missing code output")
|
return nil, fmt.Errorf("solc: no build results found")
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
// Compilation succeeded, assemble and return the contracts
|
||||||
contracts = make(map[string]*Contract)
|
contracts := make(map[string]*Contract)
|
||||||
for _, path := range matches {
|
for _, path := range matches {
|
||||||
_, file := filepath.Split(path)
|
_, file := filepath.Split(path)
|
||||||
base := strings.Split(file, ".")[0]
|
base := strings.Split(file, ".")[0]
|
||||||
|
|
||||||
codeFile := filepath.Join(wd, base+".binary")
|
// Parse the individual compilation results (code binary, ABI definitions, user and dev docs)
|
||||||
abiDefinitionFile := filepath.Join(wd, base+".abi")
|
var binary []byte
|
||||||
userDocFile := filepath.Join(wd, base+".docuser")
|
if binary, err = ioutil.ReadFile(filepath.Join(wd, base+".binary")); err != nil {
|
||||||
developerDocFile := filepath.Join(wd, base+".docdev")
|
return nil, fmt.Errorf("solc: error reading compiler output for code: %v", err)
|
||||||
|
|
||||||
var code, abiDefinitionJson, userDocJson, developerDocJson []byte
|
|
||||||
code, err = ioutil.ReadFile(codeFile)
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("error reading compiler output for code: %v", err)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
abiDefinitionJson, err = ioutil.ReadFile(abiDefinitionFile)
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("error reading compiler output for abiDefinition: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var abiDefinition interface{}
|
|
||||||
err = json.Unmarshal(abiDefinitionJson, &abiDefinition)
|
|
||||||
|
|
||||||
userDocJson, err = ioutil.ReadFile(userDocFile)
|
var abi interface{}
|
||||||
if err != nil {
|
if blob, err := ioutil.ReadFile(filepath.Join(wd, base+".abi")); err != nil {
|
||||||
err = fmt.Errorf("error reading compiler output for userDoc: %v", err)
|
return nil, fmt.Errorf("solc: error reading abi definition: %v", err)
|
||||||
return
|
} else if err = json.Unmarshal(blob, &abi); err != nil {
|
||||||
|
return nil, fmt.Errorf("solc: error parsing abi definition: %v", err)
|
||||||
}
|
}
|
||||||
var userDoc interface{}
|
|
||||||
err = json.Unmarshal(userDocJson, &userDoc)
|
|
||||||
|
|
||||||
developerDocJson, err = ioutil.ReadFile(developerDocFile)
|
var userdoc interface{}
|
||||||
if err != nil {
|
if blob, err := ioutil.ReadFile(filepath.Join(wd, base+".docuser")); err != nil {
|
||||||
err = fmt.Errorf("error reading compiler output for developerDoc: %v", err)
|
return nil, fmt.Errorf("solc: error reading user doc: %v", err)
|
||||||
return
|
} else if err = json.Unmarshal(blob, &userdoc); err != nil {
|
||||||
|
return nil, fmt.Errorf("solc: error parsing user doc: %v", err)
|
||||||
}
|
}
|
||||||
var developerDoc interface{}
|
|
||||||
err = json.Unmarshal(developerDocJson, &developerDoc)
|
|
||||||
|
|
||||||
contract := &Contract{
|
var devdoc interface{}
|
||||||
Code: "0x" + string(code),
|
if blob, err := ioutil.ReadFile(filepath.Join(wd, base+".docdev")); err != nil {
|
||||||
|
return nil, fmt.Errorf("solc: error reading dev doc: %v", err)
|
||||||
|
} else if err = json.Unmarshal(blob, &devdoc); err != nil {
|
||||||
|
return nil, fmt.Errorf("solc: error parsing dev doc: %v", err)
|
||||||
|
}
|
||||||
|
// Assemble the final contract
|
||||||
|
contracts[base] = &Contract{
|
||||||
|
Code: "0x" + string(binary),
|
||||||
Info: ContractInfo{
|
Info: ContractInfo{
|
||||||
Source: source,
|
Source: source,
|
||||||
Language: "Solidity",
|
Language: "Solidity",
|
||||||
LanguageVersion: languageVersion,
|
LanguageVersion: languageVersion,
|
||||||
CompilerVersion: sol.version,
|
CompilerVersion: sol.version,
|
||||||
AbiDefinition: abiDefinition,
|
AbiDefinition: abi,
|
||||||
UserDoc: userDoc,
|
UserDoc: userdoc,
|
||||||
DeveloperDoc: developerDoc,
|
DeveloperDoc: devdoc,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
contracts[base] = contract
|
|
||||||
}
|
}
|
||||||
|
return contracts, nil
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func SaveInfo(info *ContractInfo, filename string) (contenthash common.Hash, err error) {
|
func SaveInfo(info *ContractInfo, filename string) (contenthash common.Hash, err error) {
|
||||||
|
Loading…
Reference in New Issue
Block a user