-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial draft solc functionality impl (no binaries so far)
- Loading branch information
1 parent
ecb504b
commit dd4158b
Showing
7 changed files
with
416 additions
and
0 deletions.
There are no files selected for viewing
34 changes: 34 additions & 0 deletions
34
ethereumj-core/src/main/java/org/ethereum/solidity/compiler/CompilationResult.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package org.ethereum.solidity.compiler; | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import org.codehaus.jackson.annotate.JsonIgnoreProperties; | ||
import org.codehaus.jackson.annotate.JsonProperty; | ||
|
||
import java.io.IOException; | ||
import java.util.Map; | ||
|
||
@JsonIgnoreProperties(ignoreUnknown = true) | ||
public class CompilationResult { | ||
|
||
public Map<String, ContractMetadata> contracts; | ||
public String version; | ||
|
||
public static CompilationResult parse(String rawJson) throws IOException { | ||
return new ObjectMapper().readValue(rawJson, CompilationResult.class); | ||
} | ||
|
||
@JsonIgnoreProperties(ignoreUnknown = true) | ||
public static class ContractMetadata { | ||
public String abi; | ||
public String bin; | ||
public String solInterface; | ||
|
||
public String getInterface() { | ||
return solInterface; | ||
} | ||
|
||
public void setInterface(String solInterface) { | ||
this.solInterface = solInterface; | ||
} | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
ethereumj-core/src/main/java/org/ethereum/solidity/compiler/ContractException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package org.ethereum.solidity.compiler; | ||
|
||
public class ContractException extends RuntimeException { | ||
|
||
public ContractException(String message) { | ||
super(message); | ||
} | ||
|
||
public static ContractException permissionError(String msg, Object... args) { | ||
return error("contract permission error", msg, args); | ||
} | ||
|
||
public static ContractException compilationError(String msg, Object... args) { | ||
return error("contract compilation error", msg, args); | ||
} | ||
|
||
public static ContractException validationError(String msg, Object... args) { | ||
return error("contract validation error", msg, args); | ||
} | ||
|
||
public static ContractException assembleError(String msg, Object... args) { | ||
return error("contract assemble error", msg, args); | ||
} | ||
|
||
private static ContractException error(String title, String message, Object... args) { | ||
return new ContractException(title + ": " + String.format(message, args)); | ||
} | ||
} |
65 changes: 65 additions & 0 deletions
65
ethereumj-core/src/main/java/org/ethereum/solidity/compiler/Solc.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package org.ethereum.solidity.compiler; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.nio.file.Files; | ||
import java.nio.file.StandardCopyOption; | ||
import java.util.Scanner; | ||
|
||
/** | ||
* Created by Anton Nashatyrev on 03.03.2016. | ||
*/ | ||
public class Solc { | ||
|
||
public static final Solc INSTANCE = new Solc(); | ||
|
||
private File solc = null; | ||
|
||
private Solc() { | ||
try { | ||
init(); | ||
} catch (IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
private void init() throws IOException { | ||
File tmpDir = new File(System.getProperty("java.io.tmpdir")); | ||
|
||
InputStream is = getClass().getResourceAsStream("/bin/" + getOS() + "/file.list"); | ||
Scanner scanner = new Scanner(is); | ||
while (scanner.hasNext()) { | ||
String s = scanner.next(); | ||
File targetFile = new File(tmpDir, s); | ||
if (!targetFile.canRead()) { | ||
InputStream fis = getClass().getResourceAsStream("/bin/" + getOS() + "/" + s); | ||
Files.copy(fis, targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING); | ||
} | ||
if (solc == null) { | ||
// first file in the list denotes executable | ||
solc = targetFile; | ||
solc.setExecutable(true); | ||
} | ||
targetFile.deleteOnExit(); | ||
} | ||
|
||
} | ||
|
||
private static String getOS() { | ||
String osName = System.getProperty("os.name").toLowerCase(); | ||
if (osName.contains("win")) { | ||
return "win"; | ||
} else if (osName.contains("linux")) { | ||
return "linux"; | ||
} else if (osName.contains("mac")) { | ||
return "mac"; | ||
} else { | ||
throw new RuntimeException("Can't find solc compiler for unrecognized OS: " + osName); | ||
} | ||
} | ||
|
||
public File getExecutable() { | ||
return solc; | ||
} | ||
} |
121 changes: 121 additions & 0 deletions
121
ethereumj-core/src/main/java/org/ethereum/solidity/compiler/SolidityCompiler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package org.ethereum.solidity.compiler; | ||
|
||
import com.google.common.base.Joiner; | ||
import com.google.common.base.Strings; | ||
|
||
import java.io.*; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
import static org.apache.commons.lang3.StringUtils.isNotBlank; | ||
|
||
public class SolidityCompiler { | ||
|
||
public enum Options { | ||
AST("ast"), | ||
BIN("bin"), | ||
INTERFACE("interface"), | ||
ABI("abi"); | ||
|
||
private String name; | ||
|
||
Options(String name) { | ||
this.name = name; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return name; | ||
} | ||
} | ||
|
||
public static class Result { | ||
public String errors; | ||
public String output; | ||
|
||
public Result(String errors, String output) { | ||
this.errors = errors; | ||
this.output = output; | ||
} | ||
|
||
public boolean isFailed() { | ||
return isNotBlank(errors); | ||
} | ||
} | ||
|
||
private static class ParallelReader extends Thread { | ||
|
||
private InputStream stream; | ||
private StringBuilder content = new StringBuilder(); | ||
|
||
ParallelReader(InputStream stream) { | ||
this.stream = stream; | ||
} | ||
|
||
public String getContent() { | ||
return content.toString(); | ||
} | ||
|
||
public void run() { | ||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream));) { | ||
String line; | ||
while ((line = reader.readLine()) != null) { | ||
content.append(line).append("\n"); | ||
} | ||
} catch (IOException ioe) { | ||
ioe.printStackTrace(); | ||
} | ||
} | ||
} | ||
|
||
private static String readStream(InputStream stream) throws IOException { | ||
StringBuilder result = new StringBuilder(); | ||
|
||
try (BufferedReader reader =new BufferedReader(new InputStreamReader(stream))) { | ||
String line; | ||
while ((line = reader.readLine()) != null) { | ||
result.append(line).append("\n"); | ||
} | ||
} | ||
|
||
return result.toString(); | ||
} | ||
|
||
public static Result compile(byte[] source, boolean combinedJson, Options... options) throws IOException { | ||
List<String> commandParts = new ArrayList<>(); | ||
commandParts.add(Solc.INSTANCE.getExecutable().getCanonicalPath()); | ||
if (combinedJson) { | ||
commandParts.add("--combined-json"); | ||
commandParts.add(Joiner.on(',').join(options)); | ||
} else { | ||
for (Options option : options) { | ||
commandParts.add("--" + option.getName()); | ||
} | ||
} | ||
|
||
Process process = new ProcessBuilder(commandParts) | ||
.directory(Solc.INSTANCE.getExecutable().getParentFile()) | ||
.start(); | ||
|
||
try (BufferedOutputStream stream = new BufferedOutputStream(process.getOutputStream())) { | ||
stream.write(source); | ||
} | ||
|
||
ParallelReader error = new ParallelReader(process.getErrorStream()); | ||
ParallelReader output = new ParallelReader(process.getInputStream()); | ||
error.start(); | ||
output.start(); | ||
|
||
try { | ||
process.waitFor(); | ||
} catch (InterruptedException e) { | ||
throw new RuntimeException(e); | ||
} | ||
|
||
return new Result(error.getContent(), output.getContent()); | ||
} | ||
} |
90 changes: 90 additions & 0 deletions
90
ethereumj-core/src/main/java/org/ethereum/solidity/compiler/SourceArtifact.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package org.ethereum.solidity.compiler; | ||
|
||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.util.*; | ||
|
||
import static java.lang.String.format; | ||
import static java.util.Arrays.asList; | ||
import static java.util.Collections.emptyList; | ||
import static org.apache.commons.collections4.CollectionUtils.disjunction; | ||
import static org.apache.commons.collections4.CollectionUtils.isNotEmpty; | ||
import static org.apache.commons.lang3.StringUtils.substringsBetween; | ||
import static org.ethereum.solidity.compiler.ContractException.assembleError; | ||
|
||
public class SourceArtifact { | ||
|
||
private String name; | ||
private List<String> dependencies; | ||
private String source; | ||
|
||
private final Set<SourceArtifact> injectedDependencies = new HashSet<>(); | ||
private final Set<SourceArtifact> dependentArtifacts = new HashSet<>(); | ||
|
||
public SourceArtifact(String name, String source) { | ||
this.name = name; | ||
this.dependencies = extractDependencies(source); | ||
this.source = source.replaceAll("import\\s\"\\.*?\\.sol\";", ""); | ||
} | ||
|
||
public SourceArtifact(File f) { | ||
|
||
} | ||
|
||
private static List<String> extractDependencies(String source) { | ||
String[] deps = substringsBetween(source, "import \"", "\";"); | ||
return deps == null ? Collections.<String>emptyList() : asList(deps); | ||
} | ||
|
||
// public SourceArtifact(MultipartFile srcFile) throws IOException { | ||
// this(srcFile.getOriginalFilename(), new String(srcFile.getBytes(), "UTF-8")); | ||
// } | ||
|
||
public void injectDependency(SourceArtifact srcArtifact) { | ||
injectedDependencies.add(srcArtifact); | ||
srcArtifact.addDependentArtifact(this); | ||
} | ||
|
||
private void addDependentArtifact(SourceArtifact srcArtifact) { | ||
dependentArtifacts.add(srcArtifact); | ||
} | ||
|
||
public boolean hasDependentArtifacts() { | ||
return !dependentArtifacts.isEmpty(); | ||
} | ||
|
||
private Collection<String> getUnresolvedDependencies() { | ||
Set<String> ret = new HashSet<>(); | ||
for (SourceArtifact injectedDependency : injectedDependencies) { | ||
ret.add(injectedDependency.getName()); | ||
} | ||
|
||
return disjunction(dependencies, ret); | ||
} | ||
|
||
public String plainSource() { | ||
Collection<String> unresolvedDeps = getUnresolvedDependencies(); | ||
if (isNotEmpty(unresolvedDeps)) { | ||
throw assembleError("Followed dependencies aren't resolved: %s", unresolvedDeps); | ||
} | ||
|
||
String result = this.source; | ||
for (SourceArtifact dependencyArtifact : injectedDependencies) { | ||
String importDefinition = format("import \"%s\";", dependencyArtifact.getName()); | ||
String dependencySrc = format("// %s\n%s", importDefinition, dependencyArtifact.plainSource()); | ||
|
||
result = result.replace(importDefinition, dependencySrc); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
public List<String> getDependencies() { | ||
return dependencies; | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
ethereumj-core/src/main/java/org/ethereum/solidity/compiler/Sources.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package org.ethereum.solidity.compiler; | ||
|
||
import java.io.File; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
import static org.ethereum.solidity.compiler.ContractException.assembleError; | ||
|
||
public class Sources { | ||
|
||
private final Map<String, SourceArtifact> artifacts = new HashMap<>(); | ||
private String targetArtifact; | ||
|
||
public Sources(File[] files) { | ||
for (File file : files) { | ||
artifacts.put(file.getName(), new SourceArtifact(file)); | ||
} | ||
} | ||
|
||
public void resolveDependencies() { | ||
for (String srcName : artifacts.keySet()) { | ||
SourceArtifact src = artifacts.get(srcName); | ||
for (String dep : src.getDependencies()) { | ||
SourceArtifact depArtifact = artifacts.get(dep); | ||
if (depArtifact == null) { | ||
throw assembleError("can't resolve dependency: dependency '%s' not found.", dep); | ||
} | ||
src.injectDependency(depArtifact); | ||
}; | ||
} | ||
|
||
for (SourceArtifact artifact : artifacts.values()) { | ||
if (!artifact.hasDependentArtifacts()) { | ||
targetArtifact = artifact.getName(); | ||
} | ||
} | ||
} | ||
|
||
public String plainSource() { | ||
return artifacts.get(targetArtifact).plainSource(); | ||
} | ||
} |
Oops, something went wrong.