Browse Source

multiple contract source for solidity compiler: returns contract array if multiple contracts. fixes #1023

zelig 10 years ago
parent
commit
b0ae84aa0d
6 changed files with 91 additions and 74 deletions
  1. 3 3
      cmd/geth/js_test.go
  2. 55 52
      common/compiler/solidity.go
  3. 10 6
      common/compiler/solidity_test.go
  4. 2 3
      rpc/api.go
  5. 14 10
      rpc/api_test.go
  6. 7 0
      xeth/xeth.go

+ 3 - 3
cmd/geth/js_test.go

@@ -234,7 +234,7 @@ func TestSignature(t *testing.T) {
 
 	// This is a very preliminary test, lacking actual signature verification
 	if err != nil {
-		t.Errorf("Error runnig js: %v", err)
+		t.Errorf("Error running js: %v", err)
 		return
 	}
 	output := val.String()
@@ -297,7 +297,7 @@ func TestContract(t *testing.T) {
 			t.Errorf("%v", err)
 		}
 	} else {
-		checkEvalJSON(t, repl, `contract = eth.compile.solidity(source)`, string(contractInfo))
+		checkEvalJSON(t, repl, `contract = eth.compile.solidity(source).test`, string(contractInfo))
 	}
 
 	checkEvalJSON(t, repl, `contract.code`, `"0x605880600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b603d6004803590602001506047565b8060005260206000f35b60006007820290506053565b91905056"`)
@@ -310,7 +310,7 @@ func TestContract(t *testing.T) {
 
 	callSetup := `abiDef = JSON.parse('[{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"type":"function"}]');
 Multiply7 = eth.contract(abiDef);
-multiply7 = new Multiply7(contractaddress);
+multiply7 = Multiply7.at(contractaddress);
 `
 	// time.Sleep(1500 * time.Millisecond)
 	_, err = repl.re.Run(callSetup)

+ 55 - 52
common/compiler/solidity.go

@@ -92,7 +92,7 @@ func (sol *Solidity) Version() string {
 	return sol.version
 }
 
-func (sol *Solidity) Compile(source string) (contract *Contract, err error) {
+func (sol *Solidity) Compile(source string) (contracts map[string]*Contract, err error) {
 
 	if len(source) == 0 {
 		err = fmt.Errorf("empty source")
@@ -123,58 +123,61 @@ func (sol *Solidity) Compile(source string) (contract *Contract, err error) {
 		err = fmt.Errorf("solc error: missing code output")
 		return
 	}
-	if len(matches) > 1 {
-		err = fmt.Errorf("multi-contract sources are not supported")
-		return
-	}
-	_, file := filepath.Split(matches[0])
-	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")
 
-	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)
-	if err != nil {
-		err = fmt.Errorf("error reading compiler output for userDoc: %v", err)
-		return
-	}
-	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 developerDoc interface{}
-	err = json.Unmarshal(developerDocJson, &developerDoc)
-
-	contract = &Contract{
-		Code: "0x" + string(code),
-		Info: ContractInfo{
-			Source:          source,
-			Language:        "Solidity",
-			LanguageVersion: languageVersion,
-			CompilerVersion: sol.version,
-			AbiDefinition:   abiDefinition,
-			UserDoc:         userDoc,
-			DeveloperDoc:    developerDoc,
-		},
+	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
+		}
+		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 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 developerDoc interface{}
+		err = json.Unmarshal(developerDocJson, &developerDoc)
+
+		contract := &Contract{
+			Code: "0x" + string(code),
+			Info: ContractInfo{
+				Source:          source,
+				Language:        "Solidity",
+				LanguageVersion: languageVersion,
+				CompilerVersion: sol.version,
+				AbiDefinition:   abiDefinition,
+				UserDoc:         userDoc,
+				DeveloperDoc:    developerDoc,
+			},
+		}
+
+		contracts[base] = contract
 	}
 
 	return

+ 10 - 6
common/compiler/solidity_test.go

@@ -33,14 +33,18 @@ func TestCompiler(t *testing.T) {
 	} else if sol.Version() != solcVersion {
 		t.Logf("WARNING: a newer version of solc found (%v, expect %v)", sol.Version(), solcVersion)
 	}
-	contract, err := sol.Compile(source)
+	contracts, err := sol.Compile(source)
 	if err != nil {
-		t.Errorf("error compiling source. result %v: %v", contract, err)
+		t.Errorf("error compiling source. result %v: %v", contracts, err)
 		return
 	}
 
-	if contract.Code != code {
-		t.Errorf("wrong code, expected\n%s, got\n%s", code, contract.Code)
+	if len(contracts) != 1 {
+		t.Errorf("one contract expected, got\n%s", len(contracts))
+	}
+
+	if contracts["test"].Code != code {
+		t.Errorf("wrong code, expected\n%s, got\n%s", code, contracts["test"].Code)
 	}
 
 }
@@ -52,9 +56,9 @@ func TestCompileError(t *testing.T) {
 	} else if sol.Version() != solcVersion {
 		t.Logf("WARNING: a newer version of solc found (%v, expect %v)", sol.Version(), solcVersion)
 	}
-	contract, err := sol.Compile(source[2:])
+	contracts, err := sol.Compile(source[2:])
 	if err == nil {
-		t.Errorf("error expected compiling source. got none. result %v", contract)
+		t.Errorf("error expected compiling source. got none. result %v", contracts)
 		return
 	}
 }

+ 2 - 3
rpc/api.go

@@ -355,12 +355,11 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
 			return err
 		}
 
-		contract, err := solc.Compile(args.Source)
+		contracts, err := solc.Compile(args.Source)
 		if err != nil {
 			return err
 		}
-		contract.Code = newHexData(contract.Code).String()
-		*reply = contract
+		*reply = contracts
 
 	case "eth_newFilter":
 		args := new(BlockFilterArgs)

+ 14 - 10
rpc/api_test.go

@@ -2,14 +2,11 @@ package rpc
 
 import (
 	"encoding/json"
-	// "sync"
-	"testing"
-	// "time"
-	// "fmt"
-	"io/ioutil"
 	"strconv"
+	"testing"
 
 	"github.com/ethereum/go-ethereum/common/compiler"
+	"github.com/ethereum/go-ethereum/eth"
 	"github.com/ethereum/go-ethereum/xeth"
 )
 
@@ -58,7 +55,7 @@ func TestCompileSolidity(t *testing.T) {
 	expLanguageVersion := "0"
 	expSource := source
 
-	api := NewEthereumApi(&xeth.XEth{})
+	api := NewEthereumApi(xeth.NewTest(&eth.Ethereum{}, nil))
 
 	var req RpcRequest
 	json.Unmarshal([]byte(jsonstr), &req)
@@ -73,12 +70,18 @@ func TestCompileSolidity(t *testing.T) {
 		t.Errorf("expected no error, got %v", err)
 	}
 
-	var contract = compiler.Contract{}
-	err = json.Unmarshal(respjson, &contract)
+	var contracts = make(map[string]*compiler.Contract)
+	err = json.Unmarshal(respjson, &contracts)
 	if err != nil {
 		t.Errorf("expected no error, got %v", err)
 	}
 
+	if len(contracts) != 1 {
+		t.Errorf("expected one contract, got %v", len(contracts))
+	}
+
+	contract := contracts["test"]
+
 	if contract.Code != expCode {
 		t.Errorf("Expected \n%s got \n%s", expCode, contract.Code)
 	}
@@ -86,12 +89,15 @@ func TestCompileSolidity(t *testing.T) {
 	if strconv.Quote(contract.Info.Source) != `"`+expSource+`"` {
 		t.Errorf("Expected \n'%s' got \n'%s'", expSource, strconv.Quote(contract.Info.Source))
 	}
+
 	if contract.Info.Language != expLanguage {
 		t.Errorf("Expected %s got %s", expLanguage, contract.Info.Language)
 	}
+
 	if contract.Info.LanguageVersion != expLanguageVersion {
 		t.Errorf("Expected %s got %s", expLanguageVersion, contract.Info.LanguageVersion)
 	}
+
 	if contract.Info.CompilerVersion != expCompilerVersion {
 		t.Errorf("Expected %s got %s", expCompilerVersion, contract.Info.CompilerVersion)
 	}
@@ -114,8 +120,6 @@ func TestCompileSolidity(t *testing.T) {
 	if string(abidef) != expAbiDefinition {
 		t.Errorf("Expected \n'%s' got \n'%s'", expAbiDefinition, string(abidef))
 	}
-	ioutil.WriteFile("/tmp/abidef", []byte(string(abidef)), 0700)
-	ioutil.WriteFile("/tmp/expabidef", []byte(expAbiDefinition), 0700)
 
 	if string(userdoc) != expUserDoc {
 		t.Errorf("Expected \n'%s' got \n'%s'", expUserDoc, string(userdoc))

+ 7 - 0
xeth/xeth.go

@@ -69,6 +69,13 @@ type XEth struct {
 	agent *miner.RemoteAgent
 }
 
+func NewTest(eth *eth.Ethereum, frontend Frontend) *XEth {
+	return &XEth{
+		backend:  eth,
+		frontend: frontend,
+	}
+}
+
 // New creates an XEth that uses the given frontend.
 // If a nil Frontend is provided, a default frontend which
 // confirms all transactions will be used.