diff --git a/ethereumj-core/build.gradle b/ethereumj-core/build.gradle index f2d0886d4b..854658be38 100644 --- a/ethereumj-core/build.gradle +++ b/ethereumj-core/build.gradle @@ -121,7 +121,7 @@ dependencies { compile "org.ethereum:leveldbjni-all:1.18.3" // native leveldb components - compile "org.ethereum:solcJ-all:0.4.8" // Solidity Compiler win/mac/linux binaries + compile "org.ethereum:solcJ-all:0.4.19" // Solidity Compiler win/mac/linux binaries compile "com.cedarsoftware:java-util:1.8.0" // for deep equals compile "org.javassist:javassist:3.15.0-GA" diff --git a/ethereumj-core/src/main/java/org/ethereum/core/CallTransaction.java b/ethereumj-core/src/main/java/org/ethereum/core/CallTransaction.java index 6375f31a17..260efb8e1b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/CallTransaction.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/CallTransaction.java @@ -86,6 +86,13 @@ public String getType() { } } + public enum StateMutabilityType { + pure, + view, + nonpayable, + payable + } + public enum FunctionType { constructor, function, @@ -101,6 +108,7 @@ public static class Function { public Param[] inputs = new Param[0]; public Param[] outputs = new Param[0]; public FunctionType type; + public StateMutabilityType stateMutability; private Function() {} diff --git a/ethereumj-core/src/main/java/org/ethereum/samples/CreateContractSample.java b/ethereumj-core/src/main/java/org/ethereum/samples/CreateContractSample.java index 9ad6bbd028..5e51e6bab0 100644 --- a/ethereumj-core/src/main/java/org/ethereum/samples/CreateContractSample.java +++ b/ethereumj-core/src/main/java/org/ethereum/samples/CreateContractSample.java @@ -75,10 +75,10 @@ public void onBlock(Block block, List receipts) { throw new RuntimeException("Contract compilation failed:\n" + result.errors); } CompilationResult res = CompilationResult.parse(result.output); - if (res.contracts.isEmpty()) { + if (res.getContracts().isEmpty()) { throw new RuntimeException("Compilation failed, no contracts returned:\n" + result.errors); } - CompilationResult.ContractMetadata metadata = res.contracts.values().iterator().next(); + CompilationResult.ContractMetadata metadata = res.getContracts().iterator().next(); if (metadata.bin == null || metadata.bin.isEmpty()) { throw new RuntimeException("Compilation failed, no binary returned:\n" + result.errors); } diff --git a/ethereumj-core/src/main/java/org/ethereum/samples/EventListenerSample.java b/ethereumj-core/src/main/java/org/ethereum/samples/EventListenerSample.java index 4b70110afc..8ba0e397c4 100644 --- a/ethereumj-core/src/main/java/org/ethereum/samples/EventListenerSample.java +++ b/ethereumj-core/src/main/java/org/ethereum/samples/EventListenerSample.java @@ -343,10 +343,10 @@ private CompilationResult.ContractMetadata compileContract() throws IOException throw new RuntimeException("Contract compilation failed:\n" + result.errors); } CompilationResult res = CompilationResult.parse(result.output); - if (res.contracts.isEmpty()) { + if (res.getContracts().isEmpty()) { throw new RuntimeException("Compilation failed, no contracts returned:\n" + result.errors); } - CompilationResult.ContractMetadata metadata = res.contracts.values().iterator().next(); + CompilationResult.ContractMetadata metadata = res.getContracts().iterator().next(); if (metadata.bin == null || metadata.bin.isEmpty()) { throw new RuntimeException("Compilation failed, no binary returned:\n" + result.errors); } diff --git a/ethereumj-core/src/main/java/org/ethereum/solidity/compiler/CompilationResult.java b/ethereumj-core/src/main/java/org/ethereum/solidity/compiler/CompilationResult.java index 02b7bca3ef..c5dd28453c 100644 --- a/ethereumj-core/src/main/java/org/ethereum/solidity/compiler/CompilationResult.java +++ b/ethereumj-core/src/main/java/org/ethereum/solidity/compiler/CompilationResult.java @@ -17,20 +17,26 @@ */ package org.ethereum.solidity.compiler; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; import java.util.Collections; +import java.util.List; import java.util.Map; @JsonIgnoreProperties(ignoreUnknown = true) public class CompilationResult { - public Map contracts; - public String version; + @JsonProperty("contracts") private Map contracts; + @JsonProperty("version") public String version; - public static CompilationResult parse(String rawJson) throws IOException { + @JsonIgnore public static CompilationResult parse(String rawJson) throws IOException { if(rawJson == null || rawJson.isEmpty()){ CompilationResult empty = new CompilationResult(); empty.contracts = Collections.emptyMap(); @@ -42,6 +48,73 @@ public static CompilationResult parse(String rawJson) throws IOException { } } + /** + * @return the contract's path given this compilation result contains exactly one contract + */ + @JsonIgnore public Path getContractPath() { + if (contracts.size() > 1) { + throw new UnsupportedOperationException("Source contains more than 1 contact. Please specify the contract name. Available keys (" + getContractKeys() + ")."); + } else { + String key = contracts.keySet().iterator().next(); + return Paths.get(key.substring(0, key.lastIndexOf(':'))); + } + } + + /** + * @return the contract's name given this compilation result contains exactly one contract + */ + @JsonIgnore public String getContractName() { + if (contracts.size() > 1) { + throw new UnsupportedOperationException("Source contains more than 1 contact. Please specify the contract name. Available keys (" + getContractKeys() + ")."); + } else { + String key = contracts.keySet().iterator().next(); + return key.substring(key.lastIndexOf(':') + 1); + } + } + + /** + * @param contractName The contract name + * @return the first contract found for a given contract name; use {@link #getContract(Path, String)} if this compilation result contains more than one contract with the same name + */ + @JsonIgnore public ContractMetadata getContract(String contractName) { + if (contractName == null && contracts.size() == 1) { + return contracts.values().iterator().next(); + } else if (contractName == null || contractName.isEmpty()) { + throw new UnsupportedOperationException("Source contains more than 1 contact. Please specify the contract name. Available keys (" + getContractKeys() + ")."); + } + for (Map.Entry entry : contracts.entrySet()) { + String key = entry.getKey(); + String name = key.substring(key.lastIndexOf(':') + 1); + if (contractName.equals(name)) { + return entry.getValue(); + } + } + throw new UnsupportedOperationException("No contract found with name '" + contractName + "'. Please specify a valid contract name. Available keys (" + getContractKeys() + ")."); + } + + /** + * @param contractPath The contract path + * @param contractName The contract name + * @return the contract with key {@code contractPath:contractName} if it exists; {@code null} otherwise + */ + @JsonIgnore public ContractMetadata getContract(Path contractPath, String contractName) { + return contracts.get(contractPath.toAbsolutePath().toString() + ':' + contractName); + } + + /** + * @return all contracts from this compilation result + */ + @JsonIgnore public List getContracts() { + return new ArrayList<>(contracts.values()); + } + + /** + * @return all keys from this compilation result + */ + @JsonIgnore public List getContractKeys() { + return new ArrayList<>(contracts.keySet()); + } + @JsonIgnoreProperties(ignoreUnknown = true) public static class ContractMetadata { public String abi; diff --git a/ethereumj-core/src/main/java/org/ethereum/solidity/compiler/SolidityCompiler.java b/ethereumj-core/src/main/java/org/ethereum/solidity/compiler/SolidityCompiler.java index 6b67723279..303a97ace6 100644 --- a/ethereumj-core/src/main/java/org/ethereum/solidity/compiler/SolidityCompiler.java +++ b/ethereumj-core/src/main/java/org/ethereum/solidity/compiler/SolidityCompiler.java @@ -17,15 +17,24 @@ */ package org.ethereum.solidity.compiler; -import com.google.common.base.Joiner; import org.ethereum.config.SystemProperties; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.io.*; +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Serializable; +import java.nio.file.Path; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import static java.util.stream.Collectors.toList; + @Component public class SolidityCompiler { @@ -38,30 +47,106 @@ public SolidityCompiler(SystemProperties config) { solc = new Solc(config); } - public static Result compile(File sourceDirectory, boolean combinedJson, Options... options) throws IOException { + public static Result compile(File sourceDirectory, boolean combinedJson, Option... options) throws IOException { return getInstance().compileSrc(sourceDirectory, false, combinedJson, options); } - public enum Options { + /** + * This class is mainly here for backwards compatibility; however we are now reusing it making it the solely public + * interface listing all the supported options. + */ + public static final class Options { + public static final OutputOption AST = OutputOption.AST; + public static final OutputOption BIN = OutputOption.BIN; + public static final OutputOption INTERFACE = OutputOption.INTERFACE; + public static final OutputOption ABI = OutputOption.ABI; + public static final OutputOption METADATA = OutputOption.METADATA; + public static final OutputOption ASTJSON = OutputOption.ASTJSON; + + private static final NameOnlyOption OPTIMIZE = NameOnlyOption.OPTIMIZE; + private static final NameOnlyOption VERSION = NameOnlyOption.VERSION; + + private static class CombinedJson extends ListOption { + private CombinedJson(List values) { + super("combined-json", values); + } + } + public static class AllowPaths extends ListOption { + public AllowPaths(List values) { + super("allow-paths", values); + } + } + } + + public interface Option extends Serializable { + String getValue(); + String getName(); + } + + private static class ListOption implements Option { + private String name; + private List values; + + private ListOption(String name, List values) { + this.name = name; + this.values = values; + } + + @Override public String getValue() { + StringBuilder result = new StringBuilder(); + for (Object value : values) { + if (OutputOption.class.isAssignableFrom(value.getClass())) { + result.append((result.length() == 0) ? ((OutputOption) value).getName() : ',' + ((OutputOption) value).getName()); + } else if (Path.class.isAssignableFrom(value.getClass())) { + result.append((result.length() == 0) ? ((Path) value).toAbsolutePath().toString() : ',' + ((Path) value).toAbsolutePath().toString()); + } else if (File.class.isAssignableFrom(value.getClass())) { + result.append((result.length() == 0) ? ((File) value).getAbsolutePath() : ',' + ((File) value).getAbsolutePath()); + } else if (String.class.isAssignableFrom(value.getClass())) { + result.append((result.length() == 0) ? value : "," + value); + } else { + throw new UnsupportedOperationException("Unexpected type, value '" + value + "' cannot be retrieved."); + } + } + return result.toString(); + } + @Override public String getName() { return name; } + @Override public String toString() { return name; } + } + + private enum NameOnlyOption implements Option { + OPTIMIZE("optimize"), + VERSION("version"); + + private String name; + + NameOnlyOption(String name) { + this.name = name; + } + + @Override public String getValue() { return ""; } + @Override public String getName() { return name; } + @Override public String toString() { + return name; + } + } + + private enum OutputOption implements Option { AST("ast"), BIN("bin"), INTERFACE("interface"), ABI("abi"), - METADATA("metadata"), + METADATA("metadata"), ASTJSON("ast-json"); private String name; - Options(String name) { + OutputOption(String name) { this.name = name; } - public String getName() { - return name; - } - - @Override - public String toString() { + @Override public String getValue() { return ""; } + @Override public String getName() { return name; } + @Override public String toString() { return name; } } @@ -69,7 +154,7 @@ public String toString() { public static class Result { public String errors; public String output; - private boolean success = false; + private boolean success; public Result(String errors, String output, boolean success) { this.errors = errors; @@ -125,11 +210,11 @@ public void run() { } } - public static Result compile(byte[] source, boolean combinedJson, Options... options) throws IOException { + public static Result compile(byte[] source, boolean combinedJson, Option... options) throws IOException { return getInstance().compileSrc(source, false, combinedJson, options); } - public Result compileSrc(File source, boolean optimize, boolean combinedJson, Options... options) throws IOException { + public Result compileSrc(File source, boolean optimize, boolean combinedJson, Option... options) throws IOException { List commandParts = prepareCommandOptions(optimize, combinedJson, options); commandParts.add(source.getAbsolutePath()); @@ -156,24 +241,33 @@ public Result compileSrc(File source, boolean optimize, boolean combinedJson, Op return new Result(error.getContent(), output.getContent(), success); } - private List prepareCommandOptions(boolean optimize, boolean combinedJson, Options[] options) throws IOException { + private List prepareCommandOptions(boolean optimize, boolean combinedJson, Option... options) throws IOException { List commandParts = new ArrayList<>(); commandParts.add(solc.getExecutable().getCanonicalPath()); if (optimize) { - commandParts.add("--optimize"); + commandParts.add("--" + Options.OPTIMIZE.getName()); } if (combinedJson) { - commandParts.add("--combined-json"); - commandParts.add(Joiner.on(',').join(options)); + Option combinedJsonOption = new Options.CombinedJson(getElementsOf(OutputOption.class, options)); + commandParts.add("--" + combinedJsonOption.getName()); + commandParts.add(combinedJsonOption.getValue()); } else { - for (Options option : options) { + for (Option option : getElementsOf(OutputOption.class, options)) { commandParts.add("--" + option.getName()); } } + for (Option option : getElementsOf(ListOption.class, options)) { + commandParts.add("--" + option.getName()); + commandParts.add(option.getValue()); + } return commandParts; } - public Result compileSrc(byte[] source, boolean optimize, boolean combinedJson, Options... options) throws IOException { + private static List getElementsOf(Class clazz, Option... options) { + return Arrays.stream(options).filter(clazz::isInstance).map(clazz::cast).collect(toList()); + } + + public Result compileSrc(byte[] source, boolean optimize, boolean combinedJson, Option... options) throws IOException { List commandParts = prepareCommandOptions(optimize, combinedJson, options); ProcessBuilder processBuilder = new ProcessBuilder(commandParts) @@ -205,7 +299,7 @@ public Result compileSrc(byte[] source, boolean optimize, boolean combinedJson, public static String runGetVersionOutput() throws IOException { List commandParts = new ArrayList<>(); commandParts.add(getInstance().solc.getExecutable().getCanonicalPath()); - commandParts.add("--version"); + commandParts.add("--" + Options.VERSION.getName()); ProcessBuilder processBuilder = new ProcessBuilder(commandParts) .directory(getInstance().solc.getExecutable().getParentFile()); @@ -231,12 +325,10 @@ public static String runGetVersionOutput() throws IOException { throw new RuntimeException("Problem getting solc version: " + error.getContent()); } - - public static SolidityCompiler getInstance() { if (INSTANCE == null) { INSTANCE = new SolidityCompiler(SystemProperties.getDefault()); } return INSTANCE; } -} +} \ No newline at end of file diff --git a/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java index 3cd49ed270..7965727824 100644 --- a/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java @@ -381,11 +381,7 @@ private SolidityContractImpl createContract(String soliditySrc, String contractN private SolidityContractImpl createContractFromJson(String contractName, String json) throws IOException { CompilationResult result = CompilationResult.parse(json); if (contractName == null) { - if (result.contracts.size() > 1) { - throw new RuntimeException("Source contains more than 1 contact (" + result.contracts.keySet() + "). Please specify the contract name"); - } else { - contractName = result.contracts.keySet().iterator().next(); - } + contractName = result.getContractName(); } return createContract(contractName, result); @@ -397,10 +393,10 @@ private SolidityContractImpl createContractFromJson(String contractName, String * @return */ private SolidityContractImpl createContract(String contractName, CompilationResult result) { - ContractMetadata cMetaData = result.contracts.get(contractName); + ContractMetadata cMetaData = result.getContract(contractName); SolidityContractImpl contract = createContract(cMetaData); - for (CompilationResult.ContractMetadata metadata : result.contracts.values()) { + for (CompilationResult.ContractMetadata metadata : result.getContracts()) { contract.addRelatedContract(metadata.abi); } return contract; diff --git a/ethereumj-core/src/test/java/org/ethereum/core/ImportLightTest.java b/ethereumj-core/src/test/java/org/ethereum/core/ImportLightTest.java index e9dba75d36..d77774d7a6 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/ImportLightTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/ImportLightTest.java @@ -19,13 +19,11 @@ import org.ethereum.config.CommonConfig; import org.ethereum.config.SystemProperties; -import org.ethereum.config.blockchain.FrontierConfig; import org.ethereum.core.genesis.GenesisLoader; import org.ethereum.crypto.ECKey; import org.ethereum.crypto.HashUtil; import org.ethereum.datasource.inmem.HashMapDB; import org.ethereum.datasource.NoDeleteSource; -import org.ethereum.db.ByteArrayWrapper; import org.ethereum.db.IndexedBlockStore; import org.ethereum.db.RepositoryRoot; import org.ethereum.listener.EthereumListenerAdapter; @@ -514,7 +512,7 @@ public void operateNotExistingContractTest() throws IOException, InterruptedExce // checking balance of not existed address should take // less that gas limit - Assert.assertEquals(21508, spent); + Assert.assertEquals(21532, spent); } { @@ -831,7 +829,7 @@ public void ecRecoverTest() throws Exception { " mstore(0x120, v)" + " mstore(0x140, r)" + " mstore(0x160, s)" + - " callcode(0x50000, 0x01, 0x0, 0x100, 0x80, 0x200, 0x220)" + // call ecrecover + " let ret := callcode(0x50000, 0x01, 0x0, 0x100, 0x80, 0x200, 0x220)" + // call ecrecover " return(0x200, 0x20)" + " }" + " }" + diff --git a/ethereumj-core/src/test/java/org/ethereum/core/TransactionTest.java b/ethereumj-core/src/test/java/org/ethereum/core/TransactionTest.java index 79b89ebd28..a7ae74faf1 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/TransactionTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/TransactionTest.java @@ -576,14 +576,14 @@ public void multiSuicideTest() throws IOException, InterruptedException { ECKey sender = ECKey.fromPrivate(Hex.decode("3ec771c31cac8c0dba77a69e503765701d3c2bb62435888d4ffa38fed60c445c")).compress(); System.out.println("address: " + Hex.toHexString(sender.getAddress())); - if (cres.contracts.get("PsychoKiller") != null) { + if (cres.getContract("PsychoKiller") != null) { Transaction tx = createTx(blockchain, sender, new byte[0], - Hex.decode(cres.contracts.get("PsychoKiller").bin)); + Hex.decode(cres.getContract("PsychoKiller").bin)); executeTransaction(blockchain, tx); byte[] contractAddress = tx.getContractAddress(); - CallTransaction.Contract contract1 = new CallTransaction.Contract(cres.contracts.get("PsychoKiller").abi); + CallTransaction.Contract contract1 = new CallTransaction.Contract(cres.getContract("PsychoKiller").abi); byte[] callData = contract1.getByName("multipleHomocide").encode(); Transaction tx1 = createTx(blockchain, sender, contractAddress, callData, 0l); @@ -662,7 +662,7 @@ public void receiptErrorTest() throws Exception { contract.getBytes(), true, SolidityCompiler.Options.ABI, SolidityCompiler.Options.BIN); System.out.println(res.errors); CompilationResult cres = CompilationResult.parse(res.output); - Transaction tx = createTx(blockchain, sender, new byte[0], Hex.decode(cres.contracts.get("GasConsumer").bin), 0); + Transaction tx = createTx(blockchain, sender, new byte[0], Hex.decode(cres.getContract("GasConsumer").bin), 0); TransactionReceipt receipt = executeTransaction(blockchain, tx).getReceipt(); receipt = new TransactionReceipt(receipt.getEncoded()); diff --git a/ethereumj-core/src/test/java/org/ethereum/solidity/CompilerTest.java b/ethereumj-core/src/test/java/org/ethereum/solidity/CompilerTest.java index 475c4843a6..535ae4e273 100644 --- a/ethereumj-core/src/test/java/org/ethereum/solidity/CompilerTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/solidity/CompilerTest.java @@ -23,8 +23,10 @@ import org.junit.Assert; import org.junit.Test; -import java.io.File; import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; import static org.ethereum.solidity.compiler.SolidityCompiler.Options.*; import static org.hamcrest.MatcherAssert.assertThat; @@ -66,8 +68,8 @@ public void simpleTest() throws IOException { System.out.println("Out: '" + res.output + "'"); System.out.println("Err: '" + res.errors + "'"); CompilationResult result = CompilationResult.parse(res.output); - if (result.contracts.get("a") != null) - System.out.println(result.contracts.get("a").bin); + if (result.getContract("a") != null) + System.out.println(result.getContract("a").bin); else Assert.fail(); } @@ -86,27 +88,91 @@ public void defaultFuncTest() throws IOException { System.out.println("Err: '" + res.errors + "'"); CompilationResult result = CompilationResult.parse(res.output); - CompilationResult.ContractMetadata a = result.contracts.get("a"); + CompilationResult.ContractMetadata a = result.getContract("a"); CallTransaction.Contract contract = new CallTransaction.Contract(a.abi); - System.out.printf(contract.functions[0].toString()); + System.out.print(contract.functions[0].toString()); } @Test public void compileFilesTest() throws IOException { - File source = new File("src/test/resources/solidity/file1.sol"); + Path source = Paths.get("src","test","resources","solidity","file1.sol"); - SolidityCompiler.Result res = SolidityCompiler.compile( - source, true, ABI, BIN, INTERFACE, METADATA); + SolidityCompiler.Result res = SolidityCompiler.compile(source.toFile(), true, ABI, BIN, INTERFACE, METADATA); + System.out.println("Out: '" + res.output + "'"); + System.out.println("Err: '" + res.errors + "'"); + CompilationResult result = CompilationResult.parse(res.output); + + Assert.assertEquals("test1", result.getContractName()); + Assert.assertEquals(source.toAbsolutePath(), result.getContractPath()); + + CompilationResult.ContractMetadata a = result.getContract(source, "test1"); + CallTransaction.Contract contract = new CallTransaction.Contract(a.abi); + System.out.print(contract.functions[0].toString()); + } + + @Test public void compileFilesWithImportTest() throws IOException { + + Path source = Paths.get("src","test","resources","solidity","file2.sol"); + + SolidityCompiler.Result res = SolidityCompiler.compile(source.toFile(), true, ABI, BIN, INTERFACE, METADATA); + System.out.println("Out: '" + res.output + "'"); + System.out.println("Err: '" + res.errors + "'"); + CompilationResult result = CompilationResult.parse(res.output); + + CompilationResult.ContractMetadata a = result.getContract(source, "test2"); + CallTransaction.Contract contract = new CallTransaction.Contract(a.abi); + System.out.print(contract.functions[0].toString()); + } + + @Test public void compileFilesWithImportFromParentFileTest() throws IOException { + + Path source = Paths.get("src","test","resources","solidity","foo","file3.sol"); + + SolidityCompiler.Option allowPathsOption = new SolidityCompiler.Options.AllowPaths(Collections.singletonList(source.getParent().getParent().toFile())); + SolidityCompiler.Result res = SolidityCompiler.compile(source.toFile(), true, ABI, BIN, INTERFACE, METADATA, allowPathsOption); System.out.println("Out: '" + res.output + "'"); System.out.println("Err: '" + res.errors + "'"); CompilationResult result = CompilationResult.parse(res.output); - CompilationResult.ContractMetadata a = result.contracts.get("test1"); + Assert.assertEquals(2, result.getContractKeys().size()); + Assert.assertEquals(result.getContract("test3"), result.getContract(source,"test3")); + Assert.assertNotNull(result.getContract("test1")); + + CompilationResult.ContractMetadata a = result.getContract(source, "test3"); CallTransaction.Contract contract = new CallTransaction.Contract(a.abi); - System.out.printf(contract.functions[0].toString()); + System.out.print(contract.functions[0].toString()); } + @Test public void compileFilesWithImportFromParentStringTest() throws IOException { + + Path source = Paths.get("src","test","resources","solidity","foo","file3.sol"); + + SolidityCompiler.Option allowPathsOption = new SolidityCompiler.Options.AllowPaths(Collections.singletonList(source.getParent().getParent().toAbsolutePath().toString())); + SolidityCompiler.Result res = SolidityCompiler.compile(source.toFile(), true, ABI, BIN, INTERFACE, METADATA, allowPathsOption); + System.out.println("Out: '" + res.output + "'"); + System.out.println("Err: '" + res.errors + "'"); + CompilationResult result = CompilationResult.parse(res.output); + + CompilationResult.ContractMetadata a = result.getContract(source, "test3"); + CallTransaction.Contract contract = new CallTransaction.Contract(a.abi); + System.out.print(contract.functions[0].toString()); + } + + @Test public void compileFilesWithImportFromParentPathTest() throws IOException { + + Path source = Paths.get("src","test","resources","solidity","foo","file3.sol"); + + SolidityCompiler.Option allowPathsOption = new SolidityCompiler.Options.AllowPaths(Collections.singletonList(source.getParent().getParent())); + SolidityCompiler.Result res = SolidityCompiler.compile(source.toFile(), true, ABI, BIN, INTERFACE, METADATA, allowPathsOption); + System.out.println("Out: '" + res.output + "'"); + System.out.println("Err: '" + res.errors + "'"); + CompilationResult result = CompilationResult.parse(res.output); + + CompilationResult.ContractMetadata a = result.getContract("test3"); + CallTransaction.Contract contract = new CallTransaction.Contract(a.abi); + System.out.print(contract.functions[0].toString()); + } public static void main(String[] args) throws Exception { new CompilerTest().simpleTest(); diff --git a/ethereumj-core/src/test/resources/solidity/file2.sol b/ethereumj-core/src/test/resources/solidity/file2.sol index 8d038be125..30c992be3a 100644 --- a/ethereumj-core/src/test/resources/solidity/file2.sol +++ b/ethereumj-core/src/test/resources/solidity/file2.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.7; -import "file1.sol"; +import "./file1.sol"; -contract test2{ +contract test2 is test1 { } diff --git a/ethereumj-core/src/test/resources/solidity/foo/file3.sol b/ethereumj-core/src/test/resources/solidity/foo/file3.sol new file mode 100644 index 0000000000..ffde182d57 --- /dev/null +++ b/ethereumj-core/src/test/resources/solidity/foo/file3.sol @@ -0,0 +1,6 @@ +pragma solidity ^0.4.7; + +import "../file1.sol"; + +contract test3 is test1 { +}