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