/* | |
* Copyright (c) Robert Bosch GmbH. All rights reserved. | |
*/ | |
package org.eclipse.blockchain.core; | |
import java.io.BufferedReader; | |
import java.io.BufferedWriter; | |
import java.io.File; | |
import java.io.FileOutputStream; | |
import java.io.FileReader; | |
import java.io.FileWriter; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.io.InputStreamReader; | |
import java.io.PrintWriter; | |
import java.util.Enumeration; | |
import java.util.HashMap; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.StringJoiner; | |
import java.util.zip.ZipEntry; | |
import java.util.zip.ZipFile; | |
import org.apache.commons.io.FileUtils; | |
import org.eclipse.blockchain.core.log.EthereumLogService; | |
import org.eclipse.core.resources.IResource; | |
import org.eclipse.core.resources.ResourcesPlugin; | |
import org.eclipse.core.runtime.FileLocator; | |
import org.eclipse.core.runtime.Platform; | |
import org.eclipse.core.runtime.preferences.InstanceScope; | |
import org.eclipse.osgi.internal.loader.EquinoxClassLoader; | |
import org.eclipse.osgi.internal.loader.classpath.ClasspathEntry; | |
import org.eclipse.osgi.util.NLS; | |
import org.eclipse.swt.widgets.Display; | |
import org.osgi.framework.Bundle; | |
import com.fasterxml.jackson.databind.ObjectMapper; | |
/** | |
* Code inside this class is just a prototype so it could contain duplicate/in-efficient code and maybe unwanted code | |
* SOLDITY COMPILATION IS TESTED WITH SOLC-0.5.4 version as of NOW | |
* | |
* @author ADG5COB | |
*/ | |
public class CoreCommandExecutor { | |
private Process gethServer = null; | |
/** | |
* As of now only one Geth server instance is considered so everything related to geth is maintained as member | |
* variables | |
*/ | |
private String gethIPC = ""; | |
private String gethDataDirectory = ""; | |
private Map<String, String> gethOptions = null; | |
private final String solcCommand = "solc-path solidity-file --bin --abi --optimize -o output-directory"; | |
private final String web3jCommand = | |
"web3j-path solidity generate -a=abi-path -b=bin-path -o=output-directory -p=com.bosch"; | |
private final Map<String, SolidityABI[]> solidityABIMap = new HashMap<>(); | |
private static CoreCommandExecutor instance; | |
private String gethServerStartError = ""; | |
/** | |
* This instance is used to handle functionality related to geth and solidity | |
* | |
* @return - CorecommandExecutor instance | |
*/ | |
public static CoreCommandExecutor getInstance() { | |
if (instance == null) { | |
instance = new CoreCommandExecutor(); | |
} | |
return instance; | |
} | |
String getGethServerStartError() { | |
return this.gethServerStartError; | |
} | |
/** | |
* To start/stop mining process | |
* | |
* @param start - if true mining will start/ if false mining will stop | |
* @throws IOException - | |
* @throws InterruptedException - | |
*/ | |
public void mine(final boolean start) throws IOException, InterruptedException { | |
Process miner = Runtime.getRuntime().exec("cmd"); | |
StringJoiner inputStream = new StringJoiner(System.lineSeparator()); | |
StringJoiner errorStream = new StringJoiner(System.lineSeparator()); | |
cmdRead(miner, inputStream); | |
cmdReadError(miner, errorStream); | |
PrintWriter writer = new PrintWriter(miner.getOutputStream()); | |
if (start) { | |
writer.println("geth attach " + this.gethIPC.replace("\\\\", "\\")); | |
writer.println("miner.start(3)"); | |
writer.close(); | |
miner.waitFor(); | |
miner.destroy(); | |
} | |
else { | |
writer.println("geth attach " + this.gethIPC.replace("\\\\", "\\")); | |
writer.println("miner.stop()"); | |
writer.close(); | |
miner.waitFor(); | |
miner.destroy(); | |
} | |
} | |
private void transferArtifactsFromTempToOutput(final String tempLocation, final String outputLocation, | |
final String solName) | |
throws IOException { | |
// ABI file | |
File abiTempFile = new File(tempLocation + File.separator + solName + ".abi"); | |
File abiFile = new File(outputLocation + File.separator + solName + ".abi"); | |
abiFile.createNewFile(); | |
FileUtils.copyFile(abiTempFile, abiFile); | |
// BIN file | |
File binTempFile = new File(tempLocation + File.separator + solName + ".bin"); | |
File binFile = new File(outputLocation + File.separator + solName + ".bin"); | |
abiFile.createNewFile(); | |
FileUtils.copyFile(binTempFile, binFile); | |
} | |
/** | |
* Some osgi internal API are accessed in this method to retrieve the classpath content of this plugin. It won't be | |
* changed until problems pop-up | |
* | |
* @param projectName - | |
* @param solidityFiles - | |
* @param outputDir - | |
* @return - | |
* @throws IOException - | |
* @throws InterruptedException - | |
* @throws ClassNotFoundException - | |
*/ | |
public String solidityCompile(final String projectName, final List<IResource> solidityFiles, | |
final IResource outputDir) | |
throws IOException, InterruptedException, ClassNotFoundException { | |
String solcCompilerPath = InstanceScope.INSTANCE.getNode(SolidityPreferenceConstants.PREF_NODE) | |
.get(SolidityPreferenceConstants.PREF_KEY, ""); | |
if (solcCompilerPath.isEmpty()) { | |
return "Compiler is not set... Please set it in solidity preference page"; | |
} | |
for (IResource solFile : solidityFiles) { | |
String tempLocation = outputDir.getLocation().toOSString() + File.separator + "temp"; | |
File tempOutputDir = new File(tempLocation); | |
if (tempOutputDir.exists() && tempOutputDir.isDirectory()) { | |
tempOutputDir.delete(); | |
} | |
tempOutputDir.mkdir(); | |
String compileCommand = | |
this.solcCommand.replace("solc-path", getCmdLinePath(solcCompilerPath + File.separator + "solc")) | |
.replace("solidity-file", getCmdLinePath(solFile.getLocation().toOSString())) | |
.replace("output-directory", getCmdLinePath(tempOutputDir.getAbsolutePath())); | |
Process solcExe = Runtime.getRuntime().exec("cmd"); | |
StringJoiner inputStream = new StringJoiner(System.lineSeparator()); | |
StringJoiner errorStream = new StringJoiner(System.lineSeparator()); | |
cmdRead(solcExe, inputStream); | |
cmdReadError(solcExe, errorStream); | |
PrintWriter writer = new PrintWriter(solcExe.getOutputStream()); | |
writer.println(compileCommand); | |
writer.close(); | |
solcExe.waitFor(); | |
solcExe.destroy(); | |
if (inputStream.toString().contains("Error") || errorStream.toString().contains("Error")) { | |
return "Some errors occurred during compilation please check the console!!!"; | |
} | |
transferArtifactsFromTempToOutput(tempOutputDir.getAbsolutePath(), outputDir.getLocation().toOSString(), | |
solFile.getName().replace(".sol", "")); | |
// Reading abi json | |
storeABIinSolidityMap( | |
outputDir.getLocation().toOSString() + File.separator + solFile.getName().replace(".sol", ".abi"), | |
solFile.getLocation().toOSString()); | |
// Solidity ABI javaType update | |
CoreCommandExecutor.getInstance().updateSolABIMap(solFile.getLocation().toOSString(), updateSolJavaTypes( | |
projectName, CoreCommandExecutor.getInstance().getSolABIMap(solFile.getLocation().toOSString()))); | |
// Java Wrapper Creation | |
String web3jCmd = this.web3jCommand | |
.replace("web3j-path", getCmdLinePath(unzipAndGetWeb3jPath()) + File.separator + "web3j") | |
.replace("abi-path", | |
getCmdLinePath( | |
outputDir.getLocation().toOSString() + File.separator + solFile.getName().replace(".sol", ".abi"))) | |
.replace("bin-path", | |
getCmdLinePath( | |
outputDir.getLocation().toOSString() + File.separator + solFile.getName().replace(".sol", ".bin"))) | |
.replace("output-directory", getCmdLinePath(outputDir.getLocation().toOSString())); | |
EthereumLogService.INSTANCE.log("web3j command -> " + web3jCmd); | |
Process web3jExe = Runtime.getRuntime().exec("cmd"); | |
cmdRead(web3jExe, inputStream); | |
cmdReadError(web3jExe, errorStream); | |
writer = new PrintWriter(web3jExe.getOutputStream()); | |
writer.println("set JAVA_HOME=" + getJDKPath()); | |
writer.println(web3jCmd); | |
ClassLoader classLoader = CoreCommandExecutor.class.getClassLoader(); | |
ClasspathEntry[] hostClasspathEntries = | |
((EquinoxClassLoader) classLoader).getClasspathManager().getHostClasspathEntries(); | |
String cp = ""; | |
for (ClasspathEntry c : hostClasspathEntries) { | |
cp = cp + c.getBundleFile().getBaseFile().toString() + ";"; | |
} | |
writer | |
.println( | |
"javac " + | |
getCmdLinePath(outputDir.getLocation().toOSString() + File.separator + "com" + File.separator + | |
"bosch" + File.separator + solFile.getName().replace(".sol", ".java")) + | |
" -cp " + getCmdLinePath(cp)); | |
writer.close(); | |
web3jExe.waitFor(); | |
web3jExe.destroy(); | |
ProjectCreator.getInstance().getEthProject(projectName).addCompiledSolidityFiles(solFile); | |
FileUtils.deleteDirectory(tempOutputDir); | |
} | |
return ""; | |
} | |
private String getCmdLinePath(final String path) { | |
return "\"" + path + "\""; | |
} | |
private SolidityABI[] updateSolJavaTypes(final String projectName, final SolidityABI[] solABI) | |
throws ClassNotFoundException, IOException, InterruptedException { | |
SolidityABI[] updatedSolABI = new SolidityABI[solABI.length]; | |
for (int i = 0; i < solABI.length; i++) { | |
updatedSolABI[i] = solABI[i]; | |
if (updatedSolABI[i].getInputs() != null) { | |
for (IOABI ioa : updatedSolABI[i].getInputs()) { | |
SolidityDynamicValueCasterHandler.assignJavaType(projectName, | |
SolidityToJavaDataTypeResolver.getInstance().getJavaType(ioa.getType(), ioa), ioa); | |
} | |
} | |
if (updatedSolABI[i].getOutputs() != null) { | |
for (IOABI ioa : updatedSolABI[i].getOutputs()) { | |
SolidityDynamicValueCasterHandler.assignJavaType(projectName, | |
SolidityToJavaDataTypeResolver.getInstance().getJavaType(ioa.getType(), ioa), ioa); | |
} | |
} | |
} | |
return updatedSolABI; | |
} | |
private String unzipAndGetWeb3jPath() throws IOException { | |
Bundle bundle = Platform.getBundle("org.eclipse.blockchain.core"); | |
return unzipWeb3jZip(FileLocator.toFileURL(bundle.getEntry("res/web3j-4.3.0.zip")).getPath()); | |
} | |
private String unzipWeb3jZip(final String zipPath) throws IOException { | |
ZipFile web3jZip = new ZipFile(zipPath); | |
String destinationDir = ResourcesPlugin.getWorkspace().getRoot().getLocation().toOSString(); | |
File web3jZipContainer = new File(destinationDir + File.separator + "web3jContainer"); | |
if (!web3jZipContainer.exists()) { | |
web3jZipContainer.mkdir(); | |
final byte[] buf = new byte[4096]; | |
final Enumeration<? extends ZipEntry> zipEnum = web3jZip.entries(); | |
while (zipEnum.hasMoreElements()) { | |
final ZipEntry item = zipEnum.nextElement(); | |
if (item.isDirectory()) { | |
final File newdir = new File(web3jZipContainer + File.separator + item.getName()); | |
newdir.mkdir(); | |
} | |
else { | |
final String newfilePath = web3jZipContainer + File.separator + item.getName(); | |
final File newFile = new File(newfilePath); | |
if (!newFile.getParentFile().exists()) { | |
newFile.getParentFile().mkdirs(); | |
} | |
try (InputStream is = web3jZip.getInputStream(item); | |
FileOutputStream fos = new FileOutputStream(newfilePath);) { | |
int len; | |
while ((len = is.read(buf)) > 0) { | |
fos.write(buf, 0, len); | |
} | |
is.close(); | |
fos.close(); | |
} | |
} | |
} | |
} | |
web3jZip.close(); | |
return web3jZipContainer.getAbsolutePath() + File.separator + "web3j-4.3.0" + File.separator + "bin"; | |
} | |
/** | |
* @return - | |
* @throws IOException - | |
* @throws InterruptedException - | |
*/ | |
public String getJDKPath() throws IOException, InterruptedException { | |
String jdkPath = ""; | |
Process process = Runtime.getRuntime().exec("cmd"); | |
PrintWriter writer = new PrintWriter(process.getOutputStream()); | |
StringJoiner readJDKPath = new StringJoiner(System.lineSeparator()); | |
cmdRead(process, readJDKPath); | |
writer.println("where javac"); | |
writer.close(); | |
process.waitFor(); | |
process.destroy(); | |
String[] lines = readJDKPath.toString().split(System.lineSeparator()); | |
for (String line : lines) { | |
if (line.contains("javac.exe")) { | |
jdkPath = line.replace("\\bin\\javac.exe", "").replace("\\", "\\\\"); | |
break; | |
} | |
} | |
return getCmdLinePath(jdkPath); | |
} | |
private void storeABIinSolidityMap(final String abiPath, final String solidityFilePath) throws IOException { | |
String abiJson = readABI(abiPath); | |
ObjectMapper jsonMapper = new ObjectMapper(); | |
SolidityABI[] readValue = jsonMapper.readValue(abiJson, SolidityABI[].class); | |
for (SolidityABI sabi : readValue) { | |
if (sabi.isPayable()) { | |
IOABI[] inputs = sabi.getInputs(); | |
IOABI[] newInputs = new IOABI[inputs.length + 1]; | |
for (int o = 0; o < inputs.length; o++) { | |
newInputs[o] = inputs[o]; | |
} | |
IOABI payableInput = new IOABI(); | |
payableInput.setName("payableAmount"); | |
payableInput.setType("uint256"); | |
newInputs[inputs.length] = payableInput; | |
sabi.setInputs(newInputs); | |
} | |
} | |
this.solidityABIMap.put(solidityFilePath, readValue); | |
} | |
/** | |
* @param solPath - The absolute path of solidity file | |
* @param onlyConstructor - If true will return only constructor ui components | |
* @return - The UI content to be constructed in transactions view | |
*/ | |
public Map<String, String> getUIComponentForSolidityFile(final String solPath, final boolean onlyConstructor) { | |
SolidityABI[] solABi = this.solidityABIMap.get(solPath); | |
Map<String, String> uiMap = new HashMap<>(); | |
if (solABi != null) { | |
for (SolidityABI sABI : solABi) { | |
if (sABI.getType().equalsIgnoreCase("constructor")) { | |
if (onlyConstructor) { | |
String key = "deploy"; | |
IOABI[] inputs = sABI.getInputs(); | |
String value = constructUIValue(inputs); | |
uiMap.put(key, value); | |
} | |
} | |
else if (sABI.getType().equalsIgnoreCase("function")) { | |
if (!onlyConstructor) { | |
String key = sABI.getName(); | |
IOABI[] inputs = sABI.getInputs(); | |
String value = constructUIValue(inputs); | |
uiMap.put(key + "-" + value, value); | |
} | |
} | |
} | |
} | |
return uiMap; | |
} | |
private String constructUIValue(final IOABI[] inputs) { | |
StringJoiner uiElemString = new StringJoiner(";"); | |
for (IOABI input : inputs) { | |
uiElemString.add(input.getJavaType().getSimpleName()); | |
} | |
return uiElemString.toString(); | |
} | |
/** | |
* @param abiPath - | |
* @return - | |
*/ | |
public SolidityABI[] getSolABIMap(final String abiPath) { | |
return this.solidityABIMap.get(abiPath); | |
} | |
/** | |
* @param abiPath - | |
* @param updatedSolABI - | |
*/ | |
public void updateSolABIMap(final String abiPath, final SolidityABI[] updatedSolABI) { | |
this.solidityABIMap.put(abiPath, updatedSolABI); | |
} | |
private String readABI(final String abiPath) throws IOException { | |
StringJoiner sj = new StringJoiner(""); | |
try (BufferedReader br = new BufferedReader(new FileReader(new File(abiPath)))) { | |
String line = ""; | |
while ((line = br.readLine()) != null) { | |
sj.add(line); | |
} | |
} | |
return sj.toString(); | |
} | |
/** | |
* @return - | |
* @throws IOException - | |
* @throws InterruptedException - | |
*/ | |
public String isGethInstalled() throws IOException, InterruptedException { | |
/** | |
* This is not fully constructed but this should be first step check when someone tries to invoke ethereum project | |
* creation | |
*/ | |
StringJoiner inputStream = new StringJoiner(System.lineSeparator()); | |
StringJoiner errorStream = new StringJoiner(System.lineSeparator()); | |
String gethCheck = ""; | |
Process gethProcess = Runtime.getRuntime().exec("cmd"); | |
cmdRead(gethProcess, inputStream); | |
cmdReadError(gethProcess, errorStream); | |
PrintWriter processWriter = new PrintWriter(gethProcess.getOutputStream()); | |
processWriter.println("geth version"); | |
processWriter.close(); | |
gethProcess.waitFor(); | |
gethCheck = errorStream.toString(); | |
gethProcess.destroy(); | |
return gethCheck; | |
} | |
/** | |
* @param dataDir - | |
* @param initFilePath - | |
* @param localGethOptions - | |
* @return - Return if any error occurs during server start | |
* @throws IOException - | |
* @throws InterruptedException | |
*/ | |
public String startGethServer(final String dataDir, final String initFilePath, | |
final Map<String, String> localGethOptions) | |
throws IOException, InterruptedException { | |
if (isGethInstalled() | |
.equals(NLS.bind(CoreCommandMessages.FRAMEWORK_NOT_INSTALLED, "'geth'", System.lineSeparator()))) { | |
return "Either Geth is not installed (or) its reference is not set in PATH env variable"; | |
} | |
this.gethServerStartError = "Geth"; | |
StringJoiner inputStream = new StringJoiner(System.lineSeparator()); | |
StringJoiner errorStream = new StringJoiner(System.lineSeparator()); | |
this.gethDataDirectory = dataDir; | |
CoreCommandExecutor.getInstance().gethOptions = localGethOptions; | |
this.gethServer = Runtime.getRuntime().exec("cmd.exe"); | |
cmdRead(this.gethServer, inputStream); | |
cmdReadError(this.gethServer, errorStream); | |
String initFile = initFilePath; | |
String genesisFilePath = dataDir + File.separator + "genesis.json"; | |
if (new File(genesisFilePath).exists()) { | |
initFile = genesisFilePath; | |
} | |
else { | |
if (initFilePath.isEmpty()) { | |
initFile = createGethInitFile(dataDir); | |
} | |
} | |
startGethServerLocal(dataDir, initFile, localGethOptions); | |
return ""; | |
} | |
private void startGethServerLocal(final String dataDir, final String initFile, | |
final Map<String, String> localGethOptions) { | |
PrintWriter processWriter = new PrintWriter(this.gethServer.getOutputStream()); | |
if (!initFile.isEmpty() && !new File(dataDir + File.separator + "geth").exists()) { | |
processWriter.println("geth --datadir " + getCmdLinePath(dataDir) + " init " + getCmdLinePath(initFile) + ""); | |
} | |
String args = constructGethArguments(localGethOptions); | |
processWriter.println("geth --datadir " + getCmdLinePath(dataDir) + " " + args); | |
processWriter.close(); | |
/** | |
* This below code is required because geth once started won't terminate and it should not terminate because its a | |
* server | |
*/ | |
Display.getDefault().syncExec(() -> { | |
new Thread(() -> { | |
try { | |
this.gethServer.waitFor(); | |
} | |
catch (InterruptedException e) { | |
BlockchainCore.getInstance().logException("", e.getMessage(), e); | |
} | |
}, "Geth Server").start(); | |
}); | |
} | |
/** | |
* @return - True if geth is started/ false otherwise | |
*/ | |
public boolean isGethStarted() { | |
return (this.gethServer != null) && this.gethServer.isAlive() && !this.gethIPC.isEmpty(); | |
} | |
/** | |
* @return - The geth server data directory | |
*/ | |
public String getDataDir() { | |
return this.gethDataDirectory; | |
} | |
/** | |
* @return -The geth command line options | |
*/ | |
public Map<String, String> getGethOptions() { | |
return this.gethOptions; | |
} | |
/** | |
* @return - Returns the default network id | |
*/ | |
public String getDefaultNetworkIdForGeth() { | |
String defaultNetworkId = ""; | |
try (BufferedReader br = | |
new BufferedReader(new InputStreamReader(CoreCommandExecutor.class.getResourceAsStream("genesis.template")));) { | |
String genesisContent = ""; | |
while ((genesisContent = br.readLine()) != null) { | |
if (genesisContent.contains("chainId")) { | |
defaultNetworkId = genesisContent.substring(genesisContent.indexOf(':') + 1).replace(",", "").trim(); | |
} | |
} | |
} | |
catch (IOException e) { | |
BlockchainCore.getInstance().logException("", e.getMessage(), e); | |
} | |
return defaultNetworkId; | |
} | |
private String constructGethArguments(final Map<String, String> localGethOptions) { | |
StringJoiner arguments = new StringJoiner(" "); | |
localGethOptions.forEach((k, v) -> arguments.add("--" + k + "" + (v.isEmpty() ? "" : " " + v))); | |
return arguments.toString(); | |
} | |
/** | |
* Terminate geth server | |
*/ | |
public void terminateGethServer() { | |
if (CoreCommandExecutor.getInstance().gethServer != null) { | |
this.gethIPC = ""; | |
this.gethServer.destroyForcibly(); | |
try { | |
Process terminator = Runtime.getRuntime().exec("cmd.exe"); | |
PrintWriter pw = new PrintWriter(terminator.getOutputStream()); | |
pw.println("taskkill /F /IM geth.exe"); | |
pw.close(); | |
terminator.waitFor(); | |
terminator.destroy(); | |
} | |
catch (IOException | InterruptedException e) { | |
BlockchainCore.getInstance().logException("", e.getMessage(), e); | |
} | |
} | |
} | |
private String createGethInitFile(final String dataDir) throws IOException { | |
File gethInitFile = new File(dataDir + File.separator + "genesis.json"); | |
gethInitFile.createNewFile();// NOSONAR | |
try ( | |
BufferedReader br = new BufferedReader( | |
new InputStreamReader(CoreCommandExecutor.class.getResourceAsStream("genesis.template"))); | |
BufferedWriter bw = new BufferedWriter(new FileWriter(gethInitFile));) { | |
String genesisContent = ""; | |
while ((genesisContent = br.readLine()) != null) { | |
bw.append(genesisContent); | |
bw.append(System.lineSeparator()); | |
} | |
} | |
return gethInitFile.getAbsolutePath(); | |
} | |
/** | |
* Read output stream of process going to be executed | |
* | |
* @param process - The process that is going to start | |
* @param inputStream - A log recording object | |
*/ | |
public void cmdRead(final Process process, final StringJoiner inputStream) { | |
Thread processReadThread = new Thread(() -> { | |
String line = ""; | |
try (BufferedReader processReader = new BufferedReader(new InputStreamReader(process.getInputStream()));) { | |
while ((line = processReader.readLine()) != null) { | |
inputStream.add(line.trim()); | |
if (line.contains("Error") && this.gethServerStartError.equals("Geth")) { | |
this.gethServerStartError = line; | |
} | |
if (line.contains("IPC endpoint opened")) {// To determine IPC endpoint when geth server is started. | |
this.gethIPC = line.substring(line.indexOf("url=") + 4); | |
} | |
EthereumLogService.INSTANCE.log(line); | |
System.err.println(line); | |
} | |
} | |
catch (IOException e) { | |
BlockchainCore.getInstance().logException("", e.getMessage(), e); | |
} | |
}, "Process Read Thread"); | |
processReadThread.start(); | |
} | |
/** | |
* @return - the geth socket handle | |
*/ | |
public String getIPCPath() { | |
return this.gethIPC; | |
} | |
/** | |
* Read error stream of process going to be executed | |
* | |
* @param process - The process that is going to start | |
* @param errorStream - A log recording object | |
*/ | |
public void cmdReadError(final Process process, final StringJoiner errorStream) { | |
Thread processErrorThread = new Thread(() -> { | |
String line = ""; | |
try (BufferedReader processReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));) { | |
while ((line = processReader.readLine()) != null) { | |
errorStream.add(line.trim()); | |
if (line.contains("Error") && this.gethServerStartError.equals("Geth")) { | |
this.gethServerStartError = line; | |
} | |
if (line.contains("IPC endpoint opened")) {// To determine IPC endpoint when geth server is started. | |
this.gethIPC = line.substring(line.indexOf("url=") + 4); | |
} | |
EthereumLogService.INSTANCE.errorLog(line); | |
System.err.println(line); | |
} | |
} | |
catch (IOException e) { | |
BlockchainCore.getInstance().logException("", e.getMessage(), e); | |
} | |
}, "Process Error Thread"); | |
processErrorThread.start(); | |
} | |
} |