diff --git a/build.gradle b/build.gradle index 45ff05d1..9e6b5201 100644 --- a/build.gradle +++ b/build.gradle @@ -40,7 +40,7 @@ dependencies { //implementation 'org.fisco-bcos:solcJ:0.4.25.1' //implementation 'org.fisco-bcos:solcJ:0.6.10.1' //implementation 'org.fisco-bcos:solcJ:0.5.2.1' - implementation 'org.fisco-bcos:solcJ:0.8.11.1' + implementation 'org.fisco-bcos:solcJ:1.0.0-SNAPSHOT' implementation ('org.fisco-bcos.java-sdk:fisco-bcos-java-sdk:3.7.0') { exclude group: "org.slf4j" @@ -53,7 +53,7 @@ dependencies { implementation('org.jline:jline:3.21.0') implementation('io.bretty:console-table-builder:1.2') implementation('com.github.jsqlparser:jsqlparser:2.0') - implementation('org.fisco-bcos.code-generator:bcos-code-generator:1.5.0') { + implementation('org.fisco-bcos.code-generator:bcos-code-generator:1.6.0-SNAPSHOT') { exclude group: "org.fisco-bcos.java-sdk" exclude group: "org.slf4j" } diff --git a/src/main/java/console/command/model/HelpInfo.java b/src/main/java/console/command/model/HelpInfo.java index c9e35424..6ec3d7e7 100644 --- a/src/main/java/console/command/model/HelpInfo.java +++ b/src/main/java/console/command/model/HelpInfo.java @@ -227,7 +227,7 @@ public static void deployHelp(boolean isWasm) { System.out.println( "Deploy a " + "\033[32m" + "Solidity" + "\033[m" + " contract on blockchain."); System.out.println( - "Usage: \ndeploy contractNameOrPath parameters... [--parallel-analysis/-p]"); + "Usage: \ndeploy contractNameOrPath parameters... [--parallel-analysis/-p --sol-version/-v 0.8.11]"); System.out.println( "* contractNameOrPath -- The name of a contract or the path of a contract (Default load contract from the \"contracts/solidity\" path when using contractName)."); System.out.println( @@ -237,6 +237,8 @@ public static void deployHelp(boolean isWasm) { + " link must locate under '/apps', and be composed of contract name and version "); System.out.println( "* --parallel-analysis/-p[Optional] -- parallel conflict analysis with the contract, default: no."); + System.out.println( + "* --sol-version/-v[Optional] -- The version of solidity compiler supported 0.4.25, 0.5.2, 0.6.10, 0.8.11, default is 0.8.11."); } else { System.out.println( "Deploy a " + "\033[32m" + "Liquid" + "\033[m" + " contract on blockchain."); diff --git a/src/main/java/console/common/ConsoleUtils.java b/src/main/java/console/common/ConsoleUtils.java index 03220624..6ed682b7 100644 --- a/src/main/java/console/common/ConsoleUtils.java +++ b/src/main/java/console/common/ConsoleUtils.java @@ -40,6 +40,8 @@ import org.fisco.bcos.sdk.v3.codec.datatypes.generated.tuples.generated.Tuple2; import org.fisco.bcos.sdk.v3.codec.wrapper.ABIObject; import org.fisco.bcos.sdk.v3.codec.wrapper.ContractCodecTools; +import org.fisco.bcos.sdk.v3.utils.StringUtils; +import org.fisco.solc.compiler.Version; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,6 +54,7 @@ public class ConsoleUtils { public static final String JAVA_PATH = "contracts/sdk/java/"; public static final String ABI_PATH = "contracts/sdk/abi/"; public static final String BIN_PATH = "contracts/sdk/bin/"; + public static final String DOC_PATH = "contracts/sdk/doc/"; public static final String SOL_SUFFIX = ".sol"; public static final String WASM_SUFFIX = ".wasm"; public static final String GM_ACCOUNT_SUFFIX = "_gm"; @@ -315,11 +318,13 @@ public static void compileSolToJava( File solFile, String abiDir, String binDir, + String docDir, String librariesOption, String specifyContract, boolean isContractParallelAnalysis, boolean enableAsyncCall, - String transactionVersion) + String transactionVersion, + Version version) throws IOException, CompileContractException { String contractName = solFile.getName().split("\\.")[0]; @@ -334,7 +339,8 @@ public static void compileSolToJava( ContractCompiler.All, librariesOption, specifyContract, - isContractParallelAnalysis); + isContractParallelAnalysis, + version); System.out.println("INFO: Compile for solidity " + solFile.getName() + " success."); File abiFile = new File(abiDir + contractName + ".abi"); File binFile = new File(binDir + contractName + ".bin"); @@ -344,11 +350,16 @@ public static void compileSolToJava( FileUtils.writeStringToFile(binFile, abiAndBin.getBin()); File smBinFile = new File(binDir + "/sm/" + contractName + ".bin"); + File smAbiFile = new File(abiDir + "/sm/" + contractName + ".abi"); String smBinFilePath = smBinFile.getAbsolutePath(); - FileUtils.writeStringToFile( - new File(abiDir + "/sm/" + contractName + ".abi"), abiAndBin.getAbi()); + FileUtils.writeStringToFile(smAbiFile, abiAndBin.getAbi()); FileUtils.writeStringToFile(smBinFile, abiAndBin.getSmBin()); + File devdocFile = new File(docDir + contractName + ".devdoc"); + if (!StringUtils.isEmpty(abiAndBin.getDevdoc())) { + FileUtils.writeStringToFile(devdocFile, abiAndBin.getDevdoc()); + } + List args = new ArrayList<>( Arrays.asList( @@ -356,6 +367,7 @@ public static void compileSolToJava( "-a", abiFilePath, "-b", binFilePath, "-s", smBinFilePath, + "-d", devdocFile.getAbsolutePath(), "-p", packageName, "-o", javaDir)); if (enableAsyncCall) { @@ -376,9 +388,11 @@ public static void compileAllSolToJava( File solFileList, String abiDir, String binDir, + String docDir, boolean isContractParallelAnalysis, boolean enableAsyncCall, - String transactionVersion) + String transactionVersion, + Version version) throws IOException { File[] solFiles = solFileList.listFiles(); if (solFiles.length == 0) { @@ -400,11 +414,13 @@ public static void compileAllSolToJava( solFile, abiDir, binDir, + docDir, null, null, isContractParallelAnalysis, enableAsyncCall, - transactionVersion); + transactionVersion, + version); } catch (Exception e) { System.out.println( "ERROR:convert solidity to java for " @@ -843,6 +859,9 @@ public static void main(String[] args) { String DEFAULT_SOL = SOLIDITY_PATH; String LIBS_OPTION = "libraries"; + String SOL_VERSION_OPTION = "sol-version"; + Version DEFAULT_SOL_VERSION = Version.V0_8_11; + String BIN_OPTION = "bin"; String SM_BIN_OPTION = "sm-bin"; String ABI_OPTION = "abi"; @@ -870,6 +889,16 @@ public static void main(String[] args) { solidityFilePathOption.setRequired(false); options.addOption(solidityFilePathOption); + Option solidityVersionPathOption = + new Option( + "v", + SOL_VERSION_OPTION, + true, + "[Optional] The solidity compiler version, default is " + + DEFAULT_SOL_VERSION); + solidityFilePathOption.setRequired(false); + options.addOption(solidityVersionPathOption); + // libraries Option libraryOption = new Option( @@ -953,6 +982,9 @@ public static void main(String[] args) { String transactionVersionStr = "V" + cmd.getOptionValue(TRANSACTION_VERSION, "0"); if (mode.equals("solidity")) { String solPathOrDir = cmd.getOptionValue(SOL_OPTION, DEFAULT_SOL); + Version solVersion = + convertStringToVersion( + cmd.getOptionValue(SOL_VERSION_OPTION, DEFAULT_SOL_VERSION.toString())); String librariesOption = cmd.getOptionValue(LIBS_OPTION, ""); boolean useDagAnalysis = !cmd.hasOption(NO_ANALYSIS_OPTION); boolean enableAsyncCall = cmd.hasOption(ENABLE_ASYNC_CALL_OPTION); @@ -977,11 +1009,13 @@ public static void main(String[] args) { sol, ABI_PATH, BIN_PATH, + DOC_PATH, librariesOption, specifyContract, useDagAnalysis, enableAsyncCall, - transactionVersionStr); + transactionVersionStr, + solVersion); } else { // input dir compileAllSolToJava( fullJavaDir, @@ -989,9 +1023,11 @@ public static void main(String[] args) { sol, ABI_PATH, BIN_PATH, + DOC_PATH, useDagAnalysis, enableAsyncCall, - transactionVersionStr); + transactionVersionStr, + solVersion); } } catch (IOException | CompileContractException e) { System.out.print(e.getMessage()); @@ -1020,4 +1056,8 @@ public static void main(String[] args) { CodeGenMain.main(params.toArray(new String[0])); } } + + public static Version convertStringToVersion(String version) { + return Version.valueOf("V" + version.replace('.', '_')); + } } diff --git a/src/main/java/console/contract/ConsoleContractImpl.java b/src/main/java/console/contract/ConsoleContractImpl.java index 473580c3..864b01de 100644 --- a/src/main/java/console/contract/ConsoleContractImpl.java +++ b/src/main/java/console/contract/ConsoleContractImpl.java @@ -75,6 +75,7 @@ import org.fisco.bcos.sdk.v3.utils.StringUtils; import org.fisco.solc.compiler.CompilationResult; import org.fisco.solc.compiler.SolidityCompiler; +import org.fisco.solc.compiler.Version; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -244,16 +245,38 @@ private void deployLink(String linkPath, String address, String abiString) throw public TransactionResponse deploySolidity( String contractName, String contractNameOrPath, List inputParams) throws ConsoleMessageException { - List tempInputParams = inputParams; try { boolean isContractParallelAnalysis = false; + Version version = Version.V0_8_11; if (!inputParams.isEmpty()) { - if ("-p".equals(inputParams.get(inputParams.size() - 1)) - || "--parallel-analysis".equals(inputParams.get(inputParams.size() - 1))) { + int lastIndexOf = inputParams.lastIndexOf("-p"); + if (lastIndexOf != -1) { isContractParallelAnalysis = true; - tempInputParams = inputParams.subList(0, inputParams.size() - 1); - logger.info( - "deploy contract {} with '--parallel-analysis' or '-p'", contractName); + inputParams.remove(lastIndexOf); + logger.info("deploy contract {} with '-p'", contractName); + } + + lastIndexOf = inputParams.lastIndexOf("--parallel-analysis"); + if (lastIndexOf != -1) { + isContractParallelAnalysis = true; + inputParams.remove(lastIndexOf); + logger.info("deploy contract {} with '--parallel-analysis'", contractName); + } + + lastIndexOf = inputParams.lastIndexOf("-v"); + if (lastIndexOf != -1 && lastIndexOf != inputParams.size() - 1) { + version = ConsoleUtils.convertStringToVersion(inputParams.get(lastIndexOf + 1)); + inputParams.remove(lastIndexOf); + inputParams.remove(lastIndexOf); + logger.info("deploy contract {} with '-v'", contractName); + } + + lastIndexOf = inputParams.lastIndexOf("--sol-version"); + if (lastIndexOf != -1 && lastIndexOf != inputParams.size() - 1) { + version = ConsoleUtils.convertStringToVersion(inputParams.get(lastIndexOf + 1)); + inputParams.remove(lastIndexOf); + inputParams.remove(lastIndexOf); + logger.info("deploy contract {} with '--sol-version'", contractName); } } @@ -263,7 +286,11 @@ public TransactionResponse deploySolidity( == CryptoType.HSM_TYPE); AbiAndBin abiAndBin = ContractCompiler.compileContract( - contractNameOrPath, contractName, sm, isContractParallelAnalysis); + contractNameOrPath, + contractName, + sm, + isContractParallelAnalysis, + version); String bin = abiAndBin.getBin(); if (sm) { bin = abiAndBin.getSmBin(); @@ -273,12 +300,12 @@ public TransactionResponse deploySolidity( DeployTransactionRequestWithStringParams request = new TransactionRequestBuilder(abiAndBin.getAbi(), bin) .setExtension(extension) - .buildDeployStringParamsRequest(tempInputParams); + .buildDeployStringParamsRequest(inputParams); response = assembleTransactionService.deployContract(request); } else { response = this.assembleTransactionProcessor.deployAndGetResponseWithStringParams( - abiAndBin.getAbi(), bin, tempInputParams, null); + abiAndBin.getAbi(), bin, inputParams, null); } if (response.getReturnCode() != PrecompiledRetCode.CODE_SUCCESS.getCode()) { System.out.println("deploy contract for " + contractName + " failed!"); @@ -367,8 +394,8 @@ public TransactionResponse deployWasm( // save the bin and abi AbiAndBin abiAndBin = client.getCryptoSuite().getCryptoTypeConfig() == CryptoType.SM_TYPE - ? new AbiAndBin(abi, null, binStr) - : new AbiAndBin(abi, binStr, null); + ? new AbiAndBin(abi, null, binStr, null) + : new AbiAndBin(abi, binStr, null, null); String contractAddress = Base64.getUrlEncoder() @@ -644,7 +671,7 @@ public void call(String[] params, String pwd) throws Exception { } abi = list.getValue2().get(0).getExt().get(1); } - AbiAndBin abiAndBin = new AbiAndBin(abi, "", ""); + AbiAndBin abiAndBin = new AbiAndBin(abi, "", "", null); String functionName = params[2]; List inputParams = Arrays.asList(params).subList(3, params.length); callContract(abiAndBin, "", address, functionName, inputParams); @@ -1051,21 +1078,14 @@ private String getSolidityAbi(String contractFileName) throws Exception { List defaultOptions = Arrays.asList(ABI, BIN, METADATA); List options = new ArrayList<>(defaultOptions); - if (ContractCompiler.solcJVersion.compareToIgnoreCase(ConsoleUtils.COMPILE_WITH_BASE_PATH) - >= 0) { - logger.debug( - "compileSolToBinAndAbi, solc version:{} ,basePath: {}", - ContractCompiler.solcJVersion, - solFile.getParentFile().getCanonicalPath()); - SolidityCompiler.Option basePath = - new SolidityCompiler.CustomOption( - "base-path", solFile.getParentFile().getCanonicalPath()); - options.add(basePath); - } else { - logger.debug( - "compileSolToBinAndAbi, solc version:{}", - org.fisco.solc.compiler.Version.version); - } + logger.debug( + "compileSolToBinAndAbi, solc version:{} ,basePath: {}", + Version.V0_8_11, + solFile.getParentFile().getCanonicalPath()); + SolidityCompiler.Option basePath = + new SolidityCompiler.CustomOption( + "base-path", solFile.getParentFile().getCanonicalPath()); + options.add(basePath); // compile ecdsa SolidityCompiler.Result res = @@ -1073,6 +1093,7 @@ private String getSolidityAbi(String contractFileName) throws Exception { solFile, (client.getCryptoType() == CryptoType.SM_TYPE), true, + Version.V0_8_11, options.toArray(new SolidityCompiler.Option[0])); if (logger.isDebugEnabled()) { diff --git a/src/main/java/console/contract/model/AbiAndBin.java b/src/main/java/console/contract/model/AbiAndBin.java index 3cc25cfc..6167e2d2 100644 --- a/src/main/java/console/contract/model/AbiAndBin.java +++ b/src/main/java/console/contract/model/AbiAndBin.java @@ -4,13 +4,15 @@ public class AbiAndBin { private String abi = ""; private String bin = ""; private String smBin = ""; + private String devdoc = ""; public AbiAndBin() {} - public AbiAndBin(String abi, String bin, String smBin) { + public AbiAndBin(String abi, String bin, String smBin, String devdoc) { this.abi = abi; this.bin = bin; this.smBin = smBin; + this.devdoc = devdoc; } public String getSmBin() { @@ -32,4 +34,8 @@ public String getBin() { public void setBin(String bin) { this.bin = bin; } + + public String getDevdoc() { + return devdoc; + } } diff --git a/src/main/java/console/contract/utils/ContractCompiler.java b/src/main/java/console/contract/utils/ContractCompiler.java index d998e1f9..2b96d178 100644 --- a/src/main/java/console/contract/utils/ContractCompiler.java +++ b/src/main/java/console/contract/utils/ContractCompiler.java @@ -16,7 +16,9 @@ import static org.fisco.solc.compiler.SolidityCompiler.Options.ABI; import static org.fisco.solc.compiler.SolidityCompiler.Options.BIN; +import static org.fisco.solc.compiler.SolidityCompiler.Options.DEVDOC; import static org.fisco.solc.compiler.SolidityCompiler.Options.METADATA; +import static org.fisco.solc.compiler.SolidityCompiler.Options.USERDOC; import console.common.ConsoleUtils; import console.contract.exceptions.CompileContractException; @@ -35,6 +37,7 @@ import org.fisco.evm.analysis.EvmAnalyser; import org.fisco.solc.compiler.CompilationResult; import org.fisco.solc.compiler.SolidityCompiler; +import org.fisco.solc.compiler.Version; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -57,40 +60,20 @@ public class ContractCompiler { public static final String BIN_SUFFIX = ".bin"; public static final String ABI_SUFFIX = ".abi"; public static final String WASM_SUFFIX = ".wasm"; - public static String solcJVersion; - - static { - if (solcJVersion == null) { - try { - String runGetVersionOutput = SolidityCompiler.runGetVersionOutput(false); - solcJVersion = - runGetVersionOutput.substring( - runGetVersionOutput.indexOf("Version: ") + "Version: ".length(), - runGetVersionOutput.lastIndexOf("+commit")); - if (!solcJVersion.matches("^([0-9]\\d|[0-9])(\\.([0-9]\\d|\\d)){2}$")) { - solcJVersion = org.fisco.solc.compiler.Version.version; - } - } catch (Exception e) { - logger.info( - "Load solcJ version error, use default version string, version:{}", - org.fisco.solc.compiler.Version.version); - solcJVersion = org.fisco.solc.compiler.Version.version; - } - } - } public static AbiAndBin compileContract( String contractNameOrPath, String specifyContractName, boolean sm, - boolean isContractParallelAnalysis) + boolean isContractParallelAnalysis, + Version version) throws CompileContractException { // if absolute path File contractFile = new File(contractNameOrPath); // the contractPath if (contractFile.exists() && !contractFile.isDirectory()) { return dynamicCompileSolFilesToJava( - contractFile, specifyContractName, sm, isContractParallelAnalysis); + contractFile, specifyContractName, sm, isContractParallelAnalysis, version); } // if absolute path without sol @@ -98,7 +81,7 @@ public static AbiAndBin compileContract( contractFile = new File(contractNameOrPath + SOL_SUFFIX); if (contractFile.exists() && !contractFile.isDirectory()) { return dynamicCompileSolFilesToJava( - contractFile, specifyContractName, sm, isContractParallelAnalysis); + contractFile, specifyContractName, sm, isContractParallelAnalysis, version); } // if relative path in contracts/ @@ -110,14 +93,15 @@ public static AbiAndBin compileContract( "There is no " + contractFileName + " in the directory of " + SOLIDITY_PATH); } return dynamicCompileSolFilesToJava( - contractFile, specifyContractName, sm, isContractParallelAnalysis); + contractFile, specifyContractName, sm, isContractParallelAnalysis, version); } public static AbiAndBin dynamicCompileSolFilesToJava( File contractFile, String specifyContractName, boolean sm, - boolean isContractParallelAnalysis) + boolean isContractParallelAnalysis, + Version version) throws CompileContractException { try { return compileSolToBinAndAbi( @@ -127,7 +111,8 @@ public static AbiAndBin dynamicCompileSolFilesToJava( sm ? OnlySM : OnlyNonSM, null, specifyContractName, - isContractParallelAnalysis); + isContractParallelAnalysis, + version); } catch (IOException e) { throw new CompileContractException( "compile " + contractFile.getName() + " failed, error info: " + e.getMessage(), @@ -143,7 +128,8 @@ public static AbiAndBin compileSolToBinAndAbi( int compileType, String librariesOption, String specifyContractName, - boolean isContractParallelAnalysis) + boolean isContractParallelAnalysis, + Version version) throws IOException, CompileContractException { if (compileType == OnlyNonSM) { return compileSolToBinAndAbi( @@ -153,7 +139,8 @@ public static AbiAndBin compileSolToBinAndAbi( false, librariesOption, specifyContractName, - isContractParallelAnalysis); + isContractParallelAnalysis, + version); } else if (compileType == OnlySM) { return compileSolToBinAndAbi( contractFile, @@ -162,7 +149,8 @@ public static AbiAndBin compileSolToBinAndAbi( true, librariesOption, specifyContractName, - isContractParallelAnalysis); + isContractParallelAnalysis, + version); } else { AbiAndBin abiAndBin = compileSolToBinAndAbi( @@ -172,7 +160,8 @@ public static AbiAndBin compileSolToBinAndAbi( false, librariesOption, specifyContractName, - isContractParallelAnalysis); + isContractParallelAnalysis, + version); AbiAndBin abiAndBinSM = compileSolToBinAndAbi( contractFile, @@ -181,8 +170,13 @@ public static AbiAndBin compileSolToBinAndAbi( true, librariesOption, specifyContractName, - isContractParallelAnalysis); - return new AbiAndBin(abiAndBin.getAbi(), abiAndBin.getBin(), abiAndBinSM.getSmBin()); + isContractParallelAnalysis, + version); + return new AbiAndBin( + abiAndBin.getAbi(), + abiAndBin.getBin(), + abiAndBinSM.getSmBin(), + abiAndBin.getDevdoc()); } } @@ -194,7 +188,8 @@ public static AbiAndBin compileSolToBinAndAbi( boolean sm, String librariesOption, String specifyContractName, - boolean isContractParallelAnalysis) + boolean isContractParallelAnalysis, + Version version) throws IOException, CompileContractException { SolidityCompiler.Option libraryOption = null; if (librariesOption != null && !librariesOption.isEmpty()) { @@ -205,28 +200,33 @@ public static AbiAndBin compileSolToBinAndAbi( if (!StringUtils.isEmpty(specifyContractName)) { contractName = specifyContractName; } - List defaultOptions = Arrays.asList(ABI, BIN, METADATA); + List defaultOptions = + Arrays.asList(ABI, BIN, METADATA, USERDOC, DEVDOC); List options = new ArrayList<>(defaultOptions); if (libraryOption != null) { options.add(libraryOption); } - if (solcJVersion.compareToIgnoreCase(ConsoleUtils.COMPILE_WITH_BASE_PATH) >= 0) { + if (version.toString().compareToIgnoreCase(ConsoleUtils.COMPILE_WITH_BASE_PATH) >= 0) { logger.debug( "compileSolToBinAndAbi, solc version:{} ,basePath: {}", - solcJVersion, + version, contractFile.getParentFile().getCanonicalPath()); SolidityCompiler.Option basePath = new SolidityCompiler.CustomOption( "base-path", contractFile.getParentFile().getCanonicalPath()); options.add(basePath); } else { - logger.debug("compileSolToBinAndAbi, solc version:{}", solcJVersion); + logger.debug("compileSolToBinAndAbi, solc version:{}", version); } SolidityCompiler.Result res = SolidityCompiler.compile( - contractFile, sm, true, options.toArray(new SolidityCompiler.Option[0])); + contractFile, + sm, + true, + version, + options.toArray(new SolidityCompiler.Option[0])); logger.debug( " solidity compiler result, sm: {}, success: {}, output: {}, error: {}", @@ -243,7 +243,7 @@ public static AbiAndBin compileSolToBinAndAbi( String bin = sm ? "" : meta.bin; String smBin = sm ? meta.bin : ""; - AbiAndBin abiAndBin = new AbiAndBin(meta.abi, bin, smBin); + AbiAndBin abiAndBin = new AbiAndBin(meta.abi, bin, smBin, meta.devdoc); // evm static analysis File abiFile = new File(abiDir + contractName + ".abi"); @@ -358,7 +358,7 @@ public static AbiAndBin loadAbi(String groupId, String contractName, String cont } String abiContent = new String(CodeGenUtils.readBytes(abiPath)); - return new AbiAndBin(abiContent, "", ""); + return new AbiAndBin(abiContent, "", "", null); } public static AbiAndBin loadAbiAndBin( @@ -403,6 +403,6 @@ public static AbiAndBin loadAbiAndBin( binPath); } - return new AbiAndBin(abiContent, sm ? "" : binContent, sm ? binContent : ""); + return new AbiAndBin(abiContent, sm ? "" : binContent, sm ? binContent : "", null); } }