From c43d930bc622439d4a0c70678fad0473609c6be3 Mon Sep 17 00:00:00 2001 From: Kyon <32325790+kyonRay@users.noreply.github.com> Date: Thu, 10 Aug 2023 19:54:12 +0800 Subject: [PATCH 1/7] (v2,v3): fix v3,v2 lib struct name compile error, fix v2 event overload bug. (#20) --- build.gradle | 2 +- .../v2/wrapper/SolidityContractWrapper.java | 54 ++++++++++++++----- .../codegen/v3/wrapper/ContractWrapper.java | 21 +++++--- .../bcos/codegen/v2/test/CodeGenV2Test.java | 19 ++++++- .../bcos/codegen/v3/test/CodeGenV3Test.java | 16 ++++++ src/test/resources/StructReqRespContract.abi | 1 + src/test/resources/SupplyChainFin.abi | 1 + 7 files changed, 93 insertions(+), 21 deletions(-) create mode 100644 src/test/resources/StructReqRespContract.abi create mode 100644 src/test/resources/SupplyChainFin.abi diff --git a/build.gradle b/build.gradle index 2a6d525..f2545b0 100644 --- a/build.gradle +++ b/build.gradle @@ -50,7 +50,7 @@ sourceSets { // integrationTest.mustRunAfter test allprojects { group = 'org.fisco-bcos.code-generator' - version = '1.1.0' + version = '1.2.0-SNAPSHOT' apply plugin: 'maven-publish' apply plugin: 'idea' apply plugin: 'eclipse' diff --git a/src/main/java/org/fisco/bcos/codegen/v2/wrapper/SolidityContractWrapper.java b/src/main/java/org/fisco/bcos/codegen/v2/wrapper/SolidityContractWrapper.java index 5de004a..eb97518 100644 --- a/src/main/java/org/fisco/bcos/codegen/v2/wrapper/SolidityContractWrapper.java +++ b/src/main/java/org/fisco/bcos/codegen/v2/wrapper/SolidityContractWrapper.java @@ -241,9 +241,10 @@ private FieldSpec createDefinition(String type, String binayArrayName) { .build(); } - private FieldSpec createEventDefinition(String name, List parameters) { + private FieldSpec createEventDefinition( + String rawEventName, String name, List parameters) { - CodeBlock initializer = buildVariableLengthEventInitializer(name, parameters); + CodeBlock initializer = buildVariableLengthEventInitializer(rawEventName, parameters); return FieldSpec.builder(Event.class, buildEventDefinitionName(name)) .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) @@ -270,6 +271,20 @@ private static boolean isOverLoadFunction( return count > 1; } + private static boolean isOverLoadEvent(String name, List functionDefinitions) { + int count = 0; + for (ABIDefinition functionDefinition : functionDefinitions) { + if (!functionDefinition.getType().equals("event")) { + continue; + } + + if (functionDefinition.getName().equals(name)) { + count += 1; + } + } + return count > 1; + } + private List buildFunctionDefinitions( TypeSpec.Builder classBuilder, List functionDefinitions) throws ClassNotFoundException { @@ -302,7 +317,11 @@ private List buildFunctionDefinitions( } } } else if (functionDefinition.getType().equals("event")) { - methodSpecs.addAll(buildEventFunctions(functionDefinition, classBuilder)); + boolean isOverloadEvent = + isOverLoadEvent(functionDefinition.getName(), functionDefinitions); + + methodSpecs.addAll( + buildEventFunctions(functionDefinition, classBuilder, isOverloadEvent)); } } @@ -1209,9 +1228,10 @@ private MethodSpec buildEventTransactionReceiptFunction( } private List buildEventFunctions( - ABIDefinition functionDefinition, TypeSpec.Builder classBuilder) + ABIDefinition functionDefinition, TypeSpec.Builder classBuilder, boolean isOverload) throws ClassNotFoundException { - String functionName = functionDefinition.getName(); + + String functionName = getInputOutputFunctionName(functionDefinition, isOverload); List inputs = functionDefinition.getInputs(); String responseClassName = StringUtils.capitaliseFirstLetter(functionName) + "EventResponse"; @@ -1255,7 +1275,8 @@ private List buildEventFunctions( parameters.add(parameter); } - classBuilder.addField(createEventDefinition(functionName, parameters)); + classBuilder.addField( + createEventDefinition(functionDefinition.getName(), functionName, parameters)); classBuilder.addType( buildEventResponseObject( @@ -1819,12 +1840,21 @@ private static TypeName buildStructArrayTypeName(ABIDefinition.NamedType namedTy .structIdentifier()) .toString(); } else { - structName = - namedType - .getInternalType() - .substring( - namedType.getInternalType().lastIndexOf(" ") + 1, - namedType.getInternalType().indexOf("[")); + if (namedType.getInternalType().contains(".")) { + structName = + namedType + .getInternalType() + .substring( + namedType.getInternalType().lastIndexOf(".") + 1, + namedType.getInternalType().indexOf("[")); + } else { + structName = + namedType + .getInternalType() + .substring( + namedType.getInternalType().lastIndexOf(" ") + 1, + namedType.getInternalType().indexOf("[")); + } } return ParameterizedTypeName.get( diff --git a/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java b/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java index 7a94dc2..94c6c2b 100644 --- a/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java +++ b/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java @@ -837,12 +837,21 @@ private TypeName buildStructArrayTypeName(ABIDefinition.NamedType namedType) { namedType.getInternalType().lastIndexOf(".") + 1, namedType.getInternalType().indexOf("[")); } else { - structName = - namedType - .getInternalType() - .substring( - namedType.getInternalType().lastIndexOf(" ") + 1, - namedType.getInternalType().indexOf("[")); + if (namedType.getInternalType().contains(".")) { + structName = + namedType + .getInternalType() + .substring( + namedType.getInternalType().lastIndexOf(".") + 1, + namedType.getInternalType().indexOf("[")); + } else { + structName = + namedType + .getInternalType() + .substring( + namedType.getInternalType().lastIndexOf(" ") + 1, + namedType.getInternalType().indexOf("[")); + } } } diff --git a/src/test/java/org/fisco/bcos/codegen/v2/test/CodeGenV2Test.java b/src/test/java/org/fisco/bcos/codegen/v2/test/CodeGenV2Test.java index 1bf167f..6e76193 100644 --- a/src/test/java/org/fisco/bcos/codegen/v2/test/CodeGenV2Test.java +++ b/src/test/java/org/fisco/bcos/codegen/v2/test/CodeGenV2Test.java @@ -100,8 +100,23 @@ public void weidABICodeGen() throws IOException { codeGenTest(ABI_FILE, CONTRACT_NAME); } - // FIXME: v2 event override bug - // @Test + @Test + public void StructReqRespCodeGen() throws IOException { + // abi from https://github.com/FISCO-BCOS/code-generator/issues/19 + final String ABI_FILE = "StructReqRespContract.abi"; + final String CONTRACT_NAME = "StructReqRespContract"; + codeGenTest(ABI_FILE, CONTRACT_NAME); + } + + @Test + public void SupplyChainFinCodeGen() throws IOException { + // abi from https://github.com/FISCO-BCOS/java-sdk/issues/801 + final String ABI_FILE = "SupplyChainFin.abi"; + final String CONTRACT_NAME = "SupplyChainFin"; + codeGenTest(ABI_FILE, CONTRACT_NAME); + } + + @Test public void eventTestCodeGen() throws IOException { final String ABI_FILE = "EventSubDemo.abi"; final String CONTRACT_NAME = "EventSubDemo"; diff --git a/src/test/java/org/fisco/bcos/codegen/v3/test/CodeGenV3Test.java b/src/test/java/org/fisco/bcos/codegen/v3/test/CodeGenV3Test.java index 9d36a51..9308638 100644 --- a/src/test/java/org/fisco/bcos/codegen/v3/test/CodeGenV3Test.java +++ b/src/test/java/org/fisco/bcos/codegen/v3/test/CodeGenV3Test.java @@ -100,6 +100,22 @@ public void weidABICodeGen() throws IOException { codeGenTest(ABI_FILE, CONTRACT_NAME); } + @Test + public void StructReqRespCodeGen() throws IOException { + // abi from https://github.com/FISCO-BCOS/code-generator/issues/19 + final String ABI_FILE = "StructReqRespContract.abi"; + final String CONTRACT_NAME = "StructReqRespContract"; + codeGenTest(ABI_FILE, CONTRACT_NAME); + } + + @Test + public void SupplyChainFinCodeGen() throws IOException { + // abi from https://github.com/FISCO-BCOS/java-sdk/issues/801 + final String ABI_FILE = "SupplyChainFin.abi"; + final String CONTRACT_NAME = "SupplyChainFin"; + codeGenTest(ABI_FILE, CONTRACT_NAME); + } + @Test public void liquidCodeTestCodeGen() throws IOException { final String ABI_FILE = "codec_test.abi"; diff --git a/src/test/resources/StructReqRespContract.abi b/src/test/resources/StructReqRespContract.abi new file mode 100644 index 0000000..bfd744e --- /dev/null +++ b/src/test/resources/StructReqRespContract.abi @@ -0,0 +1 @@ +[{"inputs":[{"components":[{"components":[{"internalType":"string","name":"req","type":"string"}],"internalType":"struct StructLibrary.Req[]","name":"reqs","type":"tuple[]"}],"internalType":"struct StructLibrary.StructReq","name":"req","type":"tuple"}],"name":"request","outputs":[{"components":[{"internalType":"string","name":"resp","type":"string"}],"internalType":"struct StructLibrary.StructResp","name":"resp","type":"tuple"}],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/src/test/resources/SupplyChainFin.abi b/src/test/resources/SupplyChainFin.abi new file mode 100644 index 0000000..b9d67e8 --- /dev/null +++ b/src/test/resources/SupplyChainFin.abi @@ -0,0 +1 @@ +[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"banks","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"senderAddress","type":"address"},{"name":"accepterAddress","type":"address"},{"name":"amount","type":"uint256"},{"name":"receiptType","type":"uint8"}],"name":"companyToCompanyReceipt","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"companies","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"name","type":"string"},{"name":"bankAddress","type":"address"},{"name":"credit","type":"uint256"}],"name":"addBank","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"name","type":"string"},{"name":"companyAddress","type":"address"}],"name":"addCompany","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"senderAddress","type":"address"},{"name":"accepterAddress","type":"address"},{"name":"amount","type":"uint256"},{"name":"receiptType","type":"uint8"}],"name":"companyToBankReceipt","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"companyAddress","type":"address"}],"name":"getCompany","outputs":[{"name":"","type":"string"},{"name":"","type":"address"},{"name":"","type":"uint256"},{"name":"","type":"uint256[]"},{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getAllBankAddress","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"receiptIndex","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"senderAddress","type":"address"},{"name":"accepterAddress","type":"address"},{"name":"amount","type":"uint256"},{"name":"receiptType","type":"uint8"}],"name":"bankToCompanyReceipt","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"bankAddress","type":"address"}],"name":"getBank","outputs":[{"name":"","type":"string"},{"name":"","type":"address"},{"name":"","type":"uint256"},{"name":"","type":"uint256[]"},{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"superviosrIns","outputs":[{"name":"supervisorName","type":"string"},{"name":"supervisorAddress","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"index","type":"uint256"}],"name":"getReceipt","outputs":[{"name":"","type":"address"},{"name":"","type":"address"},{"name":"","type":"uint8"},{"name":"","type":"uint8"},{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getAllCompanyAddress","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"name","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}] \ No newline at end of file From 56d8082c5ec17350dd7256e3af83d08066c723f4 Mon Sep 17 00:00:00 2001 From: kyonRay Date: Mon, 16 Oct 2023 11:01:26 +0800 Subject: [PATCH 2/7] (project): update version to 1.2.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f2545b0..07fd567 100644 --- a/build.gradle +++ b/build.gradle @@ -50,7 +50,7 @@ sourceSets { // integrationTest.mustRunAfter test allprojects { group = 'org.fisco-bcos.code-generator' - version = '1.2.0-SNAPSHOT' + version = '1.2.0' apply plugin: 'maven-publish' apply plugin: 'idea' apply plugin: 'eclipse' From 82777c25f8620e328132f73ac4e528443cbf91b3 Mon Sep 17 00:00:00 2001 From: Kyon <32325790+kyonRay@users.noreply.github.com> Date: Mon, 25 Dec 2023 18:32:44 +0800 Subject: [PATCH 3/7] (V3): adapt TransactionManager interface, add event subcribe feature, add getRawFunction feature. (#23) --- build.gradle | 4 +- .../org/fisco/bcos/codegen/CodeGenMain.java | 10 +- .../codegen/v3/wrapper/ContractGenerator.java | 16 +- .../codegen/v3/wrapper/ContractWrapper.java | 276 ++++++++++++++---- .../bcos/codegen/v3/test/CodeGenV3Test.java | 3 +- 5 files changed, 246 insertions(+), 63 deletions(-) diff --git a/build.gradle b/build.gradle index 07fd567..3eef2ec 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,7 @@ ext { junitVersion = '4.13.2' commonsLang3Version = '3.12.0' - javaSDKVersion3 = "3.3.0" + javaSDKVersion3 = "3.6.0-SNAPSHOT" javaSDKVersion2 = "2.9.1" slf4jVersion = "1.7.32" } @@ -50,7 +50,7 @@ sourceSets { // integrationTest.mustRunAfter test allprojects { group = 'org.fisco-bcos.code-generator' - version = '1.2.0' + version = '1.3.0-SNAPSHOT' apply plugin: 'maven-publish' apply plugin: 'idea' apply plugin: 'eclipse' diff --git a/src/main/java/org/fisco/bcos/codegen/CodeGenMain.java b/src/main/java/org/fisco/bcos/codegen/CodeGenMain.java index fc40ce4..df59062 100644 --- a/src/main/java/org/fisco/bcos/codegen/CodeGenMain.java +++ b/src/main/java/org/fisco/bcos/codegen/CodeGenMain.java @@ -104,9 +104,14 @@ static class PicocliRunner implements Runnable { @Option( names = {"-e", "--enableAsyncCall"}, - description = "enable async call.") + description = "enable async call, only V3 enable.") private boolean enableAsyncCall = false; + @Option( + names = {"-n", "--newTxManager"}, + description = "use new transaction manager interface, only V3 enable.") + private boolean useNewTransactionManager = false; + @Override public void run() { if (version.equals(Version.V2)) { @@ -125,7 +130,8 @@ public void run() { abiFile, destinationFileDir, packageName, - enableAsyncCall) + enableAsyncCall, + useNewTransactionManager) .generateJavaFiles(); } catch (Exception e) { org.fisco.bcos.codegen.v3.utils.CodeGenUtils.exitError(e); diff --git a/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractGenerator.java b/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractGenerator.java index d8ce5b8..b5cbc90 100644 --- a/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractGenerator.java +++ b/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractGenerator.java @@ -53,6 +53,7 @@ public class ContractGenerator { private String basePackageName; private boolean enableAsyncCall = false; + private boolean useNewTransactionManager = false; public ContractGenerator( File binFile, @@ -78,6 +79,18 @@ public ContractGenerator( this.enableAsyncCall = enableAsyncCall; } + public ContractGenerator( + File binFile, + File smBinFile, + File abiFile, + File destinationDir, + String basePackageName, + boolean enableAsyncCall, + boolean useNewTransactionManager) { + this(binFile, smBinFile, abiFile, destinationDir, basePackageName, enableAsyncCall); + this.useNewTransactionManager = useNewTransactionManager; + } + public void generateJavaFiles() throws CodeGenException, IOException, ClassNotFoundException { // get binary byte[] binary = CodeGenUtils.readBytes(this.binFile); @@ -103,7 +116,8 @@ public void generateJavaFiles() throws CodeGenException, IOException, ClassNotFo new String(abiBytes), destinationDir.toString(), basePackageName, - enableAsyncCall); + enableAsyncCall, + useNewTransactionManager); } private byte[] calculateWasmBytes(byte[] binary) throws IOException { diff --git a/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java b/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java index 94c6c2b..82b7c9b 100644 --- a/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java +++ b/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java @@ -52,6 +52,8 @@ import org.fisco.bcos.sdk.v3.model.TransactionReceipt; import org.fisco.bcos.sdk.v3.model.callback.CallCallback; import org.fisco.bcos.sdk.v3.model.callback.TransactionCallback; +import org.fisco.bcos.sdk.v3.transaction.manager.transactionv2.ProxySignTransactionManager; +import org.fisco.bcos.sdk.v3.transaction.manager.transactionv2.TransactionManager; import org.fisco.bcos.sdk.v3.transaction.model.exception.ContractException; import org.fisco.bcos.sdk.v3.utils.Collection; import org.fisco.bcos.sdk.v3.utils.StringUtils; @@ -87,6 +89,8 @@ public class ContractWrapper { private static final String FUNC_NAME_PREFIX = "FUNC_"; private static final String EVENT_ENCODER = "eventEncoder"; + private static final String TRANSACTION_MANAGER = "transactionManager"; + private static final String TUPLE_REGEX = "tuple\\.Tuple(\\d+)"; private static final Pattern TUPLE_PATTERN = Pattern.compile(TUPLE_REGEX); @@ -98,6 +102,7 @@ public class ContractWrapper { private static final List structsNamedTypeList = new ArrayList<>(); private boolean enableAsyncCall = false; + private boolean useNewTransactionManager = false; public ContractWrapper(boolean isWasm) { this.isWasm = isWasm; @@ -110,9 +115,11 @@ public void generateJavaFiles( String abi, String destinationDir, String basePackageName, - boolean enableAsyncCall) + boolean enableAsyncCall, + boolean useNewTransactionManager) throws IOException, ClassNotFoundException, UnsupportedOperationException { this.enableAsyncCall = enableAsyncCall; + this.useNewTransactionManager = useNewTransactionManager; String[] nameParts = contractName.split("_"); for (int i = 0; i < nameParts.length; ++i) { nameParts[i] = StringUtils.capitaliseFirstLetter(nameParts[i]); @@ -153,6 +160,9 @@ public void generateJavaFiles( .collect(Collectors.toList())); classBuilder.addMethods(this.buildFunctionDefinitions(classBuilder, abiDefinitions)); classBuilder.addMethod(buildLoad(className)); + if (useNewTransactionManager) { + classBuilder.addMethod(buildDefaultLoad(className)); + } classBuilder.addMethods(this.buildDeployMethods(isWasm, className, abiDefinitions)); this.write(basePackageName, classBuilder.build(), destinationDir); @@ -281,6 +291,8 @@ private List buildFunctionDefinitions( if (functionDefinition.getType().equals("function")) { MethodSpec ms = this.buildFunction(functionDefinition); methodSpecs.add(ms); + MethodSpec msRawFunction = buildRawFunctionReturn(functionDefinition); + methodSpecs.add(msRawFunction); if (functionDefinition.isConstant() && enableAsyncCall) { MethodSpec msCallback = this.buildFunctionWithCallback(functionDefinition); methodSpecs.add(msCallback); @@ -655,19 +667,36 @@ private static MethodSpec buildGetABIMethod() { return toReturn.build(); } - private static MethodSpec buildConstructor() { - MethodSpec.Builder toReturn = - MethodSpec.constructorBuilder() - .addModifiers(Modifier.PROTECTED) - .addParameter(String.class, CONTRACT_ADDRESS) - .addParameter(Client.class, CLIENT) - .addParameter(CryptoKeyPair.class, ContractWrapper.CREDENTIAL) - .addStatement( - "super($N, $N, $N, $N)", - getBinaryFuncDefinition(), - CONTRACT_ADDRESS, - CLIENT, - ContractWrapper.CREDENTIAL); + private MethodSpec buildConstructor() { + MethodSpec.Builder toReturn; + if (this.useNewTransactionManager) { + toReturn = + MethodSpec.constructorBuilder() + .addModifiers(Modifier.PROTECTED) + .addParameter(String.class, CONTRACT_ADDRESS) + .addParameter(Client.class, CLIENT) + .addParameter( + TransactionManager.class, ContractWrapper.TRANSACTION_MANAGER) + .addStatement( + "super($N, $N, $N, $N)", + getBinaryFuncDefinition(), + CONTRACT_ADDRESS, + CLIENT, + ContractWrapper.TRANSACTION_MANAGER); + } else { + toReturn = + MethodSpec.constructorBuilder() + .addModifiers(Modifier.PROTECTED) + .addParameter(String.class, CONTRACT_ADDRESS) + .addParameter(Client.class, CLIENT) + .addParameter(CryptoKeyPair.class, ContractWrapper.CREDENTIAL) + .addStatement( + "super($N, $N, $N, $N)", + getBinaryFuncDefinition(), + CONTRACT_ADDRESS, + CLIENT, + ContractWrapper.CREDENTIAL); + } return toReturn.build(); } @@ -684,43 +713,78 @@ private MethodSpec buildDeploy( } } - private static MethodSpec buildDeployWithParams( + private MethodSpec buildDeployWithParams( boolean isWasm, MethodSpec.Builder methodBuilder, String className, String inputParams) { - methodBuilder - .addStatement( - "byte[] encodedConstructor = $T.encodeConstructor(" - + "$T.<$T>asList($L)" - + ")", - isWasm - ? org.fisco.bcos.sdk.v3.codec.scale.FunctionEncoder.class - : org.fisco.bcos.sdk.v3.codec.abi.FunctionEncoder.class, - Arrays.class, - Type.class, - inputParams) - .addStatement( - "return deploy(" + "$L.class, $L, $L, $L, $L, encodedConstructor, $L)", - className, - CLIENT, - ContractWrapper.CREDENTIAL, - getBinaryFuncDefinition(), - getABIFuncDefinition(), - isWasm ? PATH : "null"); + methodBuilder.addStatement( + "byte[] encodedConstructor = $T.encodeConstructor(" + "$T.<$T>asList($L)" + ")", + isWasm + ? org.fisco.bcos.sdk.v3.codec.scale.FunctionEncoder.class + : org.fisco.bcos.sdk.v3.codec.abi.FunctionEncoder.class, + Arrays.class, + Type.class, + inputParams); + if (this.useNewTransactionManager) { + methodBuilder + .addStatement( + "$L contract = deploy(" + + "$L.class, $L, $L, $L, $L, encodedConstructor, $L)", + className, + className, + CLIENT, + ContractWrapper.CREDENTIAL, + getBinaryFuncDefinition(), + getABIFuncDefinition(), + isWasm ? PATH : "null") + .addStatement( + "contract.setTransactionManager(new $T($L))", + ProxySignTransactionManager.class, + CLIENT) + .addStatement("return contract"); + } else { + methodBuilder.addStatement( + "return deploy(" + "$L.class, $L, $L, $L, $L, encodedConstructor, $L)", + className, + CLIENT, + ContractWrapper.CREDENTIAL, + getBinaryFuncDefinition(), + getABIFuncDefinition(), + isWasm ? PATH : "null"); + } return methodBuilder.build(); } - private static MethodSpec buildDeployNoParams( + private MethodSpec buildDeployNoParams( boolean isWasm, MethodSpec.Builder methodBuilder, String className) { - methodBuilder.addStatement( - "return deploy($L.class, $L, $L, $L, $L, null, $L)", - className, - CLIENT, - ContractWrapper.CREDENTIAL, - getBinaryFuncDefinition(), - getABIFuncDefinition(), - isWasm ? PATH : "null"); + if (this.useNewTransactionManager) { + methodBuilder + .addStatement( + "$L contract = deploy($L.class, $L, $L, $L, $L, null, $L)", + className, + className, + CLIENT, + ContractWrapper.CREDENTIAL, + getBinaryFuncDefinition(), + getABIFuncDefinition(), + isWasm ? PATH : "null") + .addStatement( + "contract.setTransactionManager(new $T($L))", + ProxySignTransactionManager.class, + CLIENT) + .addStatement("return contract"); + } else { + + methodBuilder.addStatement( + "return deploy($L.class, $L, $L, $L, $L, null, $L)", + className, + CLIENT, + ContractWrapper.CREDENTIAL, + getBinaryFuncDefinition(), + getABIFuncDefinition(), + isWasm ? PATH : "null"); + } return methodBuilder.build(); } @@ -738,20 +802,54 @@ private static MethodSpec.Builder getDeployMethodSpec(boolean isWasm, String cla return methodSpec; } - private static MethodSpec buildLoad(String className) { + private MethodSpec buildLoad(String className) { + MethodSpec.Builder toReturn; + if (this.useNewTransactionManager) { + toReturn = + MethodSpec.methodBuilder("load") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC) + .returns(TypeVariableName.get(className, Type.class)) + .addParameter(String.class, CONTRACT_ADDRESS) + .addParameter(Client.class, CLIENT) + .addParameter( + TransactionManager.class, ContractWrapper.TRANSACTION_MANAGER) + .addStatement( + "return new $L($L, $L, $L)", + className, + CONTRACT_ADDRESS, + CLIENT, + ContractWrapper.TRANSACTION_MANAGER); + } else { + toReturn = + MethodSpec.methodBuilder("load") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC) + .returns(TypeVariableName.get(className, Type.class)) + .addParameter(String.class, CONTRACT_ADDRESS) + .addParameter(Client.class, CLIENT) + .addParameter(CryptoKeyPair.class, ContractWrapper.CREDENTIAL) + .addStatement( + "return new $L($L, $L, $L)", + className, + CONTRACT_ADDRESS, + CLIENT, + ContractWrapper.CREDENTIAL); + } + return toReturn.build(); + } + + private MethodSpec buildDefaultLoad(String className) { MethodSpec.Builder toReturn = MethodSpec.methodBuilder("load") .addModifiers(Modifier.PUBLIC, Modifier.STATIC) .returns(TypeVariableName.get(className, Type.class)) .addParameter(String.class, CONTRACT_ADDRESS) .addParameter(Client.class, CLIENT) - .addParameter(CryptoKeyPair.class, ContractWrapper.CREDENTIAL) .addStatement( "return new $L($L, $L, $L)", className, CONTRACT_ADDRESS, CLIENT, - ContractWrapper.CREDENTIAL); + "new ProxySignTransactionManager(" + CLIENT + ")"); return toReturn.build(); } @@ -1250,6 +1348,73 @@ private MethodSpec buildFunctionWithOutputDecoder( return methodBuilder.build(); } + private MethodSpec buildRawFunctionReturn(ABIDefinition functionDefinition) + throws ClassNotFoundException { + String functionName = functionDefinition.getName(); + + if (!SourceVersion.isName(functionName)) { + functionName = "_" + functionName; + } + + MethodSpec.Builder methodBuilder = + MethodSpec.methodBuilder( + "getMethod" + + org.apache.commons.lang3.StringUtils.capitalize( + functionName) + + "RawFunction") + .addModifiers(Modifier.PUBLIC); + + String inputParams = this.addParameters(methodBuilder, functionDefinition.getInputs()); + + List outputParameterTypes = buildTypeNames(functionDefinition.getOutputs()); + + methodBuilder.addException(ContractException.class); + if (outputParameterTypes.isEmpty()) { + methodBuilder.addStatement( + "throw new RuntimeException" + + "(\"cannot call constant function with void return type\")"); + } else if (outputParameterTypes.size() == 1) { + TypeName typeName = outputParameterTypes.get(0); + TypeName nativeReturnTypeName; + ABIDefinition.NamedType outputType = functionDefinition.getOutputs().get(0); + if (outputType.getType().equals("tuple")) { + nativeReturnTypeName = structClassNameMap.get(outputType.structIdentifier()); + } else if (outputType.getType().startsWith("tuple") + && outputType.getType().contains("[")) { + TypeName argument = + ((ParameterizedTypeName) buildStructArrayTypeName(outputType)) + .typeArguments.get(0); + nativeReturnTypeName = + ParameterizedTypeName.get( + ClassName.get(List.class), ClassName.get("", argument.toString())); + } else { + nativeReturnTypeName = this.getWrapperRawType(typeName); + } + + methodBuilder.returns(nativeReturnTypeName); + + methodBuilder.addStatement( + "final $T function = " + + "new $T($N, \n$T.<$T>asList($L), " + + "\n$T.<$T>asList(new $T<$T>() {}))", + Function.class, + Function.class, + funcNameToConst(functionName), + Arrays.class, + Type.class, + inputParams, + Arrays.class, + TypeReference.class, + TypeReference.class, + typeName); + CodeBlock.Builder callCode = CodeBlock.builder(); + callCode.addStatement("return function"); + + methodBuilder.returns(Function.class).addCode(callCode.build()); + } + return methodBuilder.build(); + } + private void buildConstantFunction( ABIDefinition functionDefinition, MethodSpec.Builder methodBuilder, @@ -1509,27 +1674,24 @@ private MethodSpec buildSubscribeEventFunction(String eventName) throws ClassNot MethodSpec.Builder getEventMethodBuilder = MethodSpec.methodBuilder(generatedFunctionName) .addModifiers(Modifier.PUBLIC) - .addParameter(String.class, FROM_BLOCK) - .addParameter(String.class, TO_BLOCK); + .addParameter(BigInteger.class, FROM_BLOCK) + .addParameter(BigInteger.class, TO_BLOCK); this.addParameter(getEventMethodBuilder, "string[]", OTHER_TOPICS); - // FIXME: implement event sub - // getEventMethodBuilder.addParameter(EventCallback.class, CALLBACK_VALUE); + getEventMethodBuilder.addParameter(EventSubCallback.class, CALLBACK_VALUE); getEventMethodBuilder.addStatement( "String topic0 = $N.encode(" + this.buildEventDefinitionName(eventName) + ")", EVENT_ENCODER); getEventMethodBuilder.addStatement( - "subscribeEvent(ABI,BINARY" + "subscribeEvent(topic0" + "," - + "topic0" + + OTHER_TOPICS + "," + FROM_BLOCK + "," + TO_BLOCK + "," - + OTHER_TOPICS - + "," + CALLBACK_VALUE + ")"); @@ -1549,8 +1711,7 @@ private MethodSpec buildDefaultSubscribeEventLog(String eventName) { "String topic0 = $N.encode(" + buildEventDefinitionName(eventName) + ")", EVENT_ENCODER); - getEventMethodBuilder.addStatement( - "subscribeEvent(ABI,BINARY" + ",topic0" + "," + CALLBACK_VALUE + ")"); + getEventMethodBuilder.addStatement("subscribeEvent(topic0" + "," + CALLBACK_VALUE + ")"); return getEventMethodBuilder.build(); } @@ -1658,7 +1819,8 @@ private List buildEventFunctions( methods.add( this.buildEventTransactionReceiptFunction( responseClassName, functionName, indexedParameters, nonIndexedParameters)); - + methods.add(buildSubscribeEventFunction(functionName)); + methods.add(buildDefaultSubscribeEventLog(functionName)); return methods; } diff --git a/src/test/java/org/fisco/bcos/codegen/v3/test/CodeGenV3Test.java b/src/test/java/org/fisco/bcos/codegen/v3/test/CodeGenV3Test.java index 9308638..cec4bc6 100644 --- a/src/test/java/org/fisco/bcos/codegen/v3/test/CodeGenV3Test.java +++ b/src/test/java/org/fisco/bcos/codegen/v3/test/CodeGenV3Test.java @@ -162,7 +162,8 @@ private void codeGenTest(String abiFileName, String codeFilePath, String contrac DEFAULT_PACKAGE, "-o", javaOutPut, - "-e") + "-e", + "-n") .toArray(new String[0])); JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); DiagnosticCollector collector = new DiagnosticCollector<>(); From b09d86dcf75bee671d4d05ecc9b301b33ce11dff Mon Sep 17 00:00:00 2001 From: Kyon <32325790+kyonRay@users.noreply.github.com> Date: Thu, 28 Dec 2023 17:38:30 +0800 Subject: [PATCH 4/7] (V3): fix get raw function interface bug, fix transaction version option conflict. (#24) --- .../org/fisco/bcos/codegen/CodeGenMain.java | 23 ++++++-- .../codegen/v3/wrapper/ContractGenerator.java | 8 +-- .../codegen/v3/wrapper/ContractWrapper.java | 59 +++++++++++++++---- .../bcos/codegen/v3/test/CodeGenV3Test.java | 3 +- 4 files changed, 73 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/fisco/bcos/codegen/CodeGenMain.java b/src/main/java/org/fisco/bcos/codegen/CodeGenMain.java index df59062..f980190 100644 --- a/src/main/java/org/fisco/bcos/codegen/CodeGenMain.java +++ b/src/main/java/org/fisco/bcos/codegen/CodeGenMain.java @@ -24,6 +24,21 @@ public class CodeGenMain { public static final String COMMAND_GENERATE = "generate"; public static final String COMMAND_PREFIX = COMMAND_SOLIDITY + " " + COMMAND_GENERATE; + public enum TransactionVersion { + V0(0), + V1(1); + + private final int v; + + TransactionVersion(int v) { + this.v = v; + } + + public int getV() { + return v; + } + } + public enum Version { V3(3), V2(2); @@ -108,9 +123,9 @@ static class PicocliRunner implements Runnable { private boolean enableAsyncCall = false; @Option( - names = {"-n", "--newTxManager"}, - description = "use new transaction manager interface, only V3 enable.") - private boolean useNewTransactionManager = false; + names = {"-t", "--txVersion"}, + description = "specify transaction version, default is 0, only V3 enable.") + private TransactionVersion transactionVersion = TransactionVersion.V0; @Override public void run() { @@ -131,7 +146,7 @@ public void run() { destinationFileDir, packageName, enableAsyncCall, - useNewTransactionManager) + transactionVersion.getV()) .generateJavaFiles(); } catch (Exception e) { org.fisco.bcos.codegen.v3.utils.CodeGenUtils.exitError(e); diff --git a/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractGenerator.java b/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractGenerator.java index b5cbc90..6909893 100644 --- a/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractGenerator.java +++ b/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractGenerator.java @@ -53,7 +53,7 @@ public class ContractGenerator { private String basePackageName; private boolean enableAsyncCall = false; - private boolean useNewTransactionManager = false; + private int transactionVersion = 0; public ContractGenerator( File binFile, @@ -86,9 +86,9 @@ public ContractGenerator( File destinationDir, String basePackageName, boolean enableAsyncCall, - boolean useNewTransactionManager) { + int transactionVersion) { this(binFile, smBinFile, abiFile, destinationDir, basePackageName, enableAsyncCall); - this.useNewTransactionManager = useNewTransactionManager; + this.transactionVersion = transactionVersion; } public void generateJavaFiles() throws CodeGenException, IOException, ClassNotFoundException { @@ -117,7 +117,7 @@ public void generateJavaFiles() throws CodeGenException, IOException, ClassNotFo destinationDir.toString(), basePackageName, enableAsyncCall, - useNewTransactionManager); + transactionVersion); } private byte[] calculateWasmBytes(byte[] binary) throws IOException { diff --git a/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java b/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java index 82b7c9b..4e2b181 100644 --- a/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java +++ b/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java @@ -28,6 +28,7 @@ import java.util.stream.Collectors; import javax.lang.model.SourceVersion; import javax.lang.model.element.Modifier; +import org.fisco.bcos.codegen.CodeGenMain; import org.fisco.bcos.codegen.v3.utils.CodeGenUtils; import org.fisco.bcos.sdk.v3.client.Client; import org.fisco.bcos.sdk.v3.client.protocol.model.TransactionAttribute; @@ -102,7 +103,7 @@ public class ContractWrapper { private static final List structsNamedTypeList = new ArrayList<>(); private boolean enableAsyncCall = false; - private boolean useNewTransactionManager = false; + private int transactionVersion = 0; public ContractWrapper(boolean isWasm) { this.isWasm = isWasm; @@ -116,10 +117,10 @@ public void generateJavaFiles( String destinationDir, String basePackageName, boolean enableAsyncCall, - boolean useNewTransactionManager) + int transactionVersion) throws IOException, ClassNotFoundException, UnsupportedOperationException { this.enableAsyncCall = enableAsyncCall; - this.useNewTransactionManager = useNewTransactionManager; + this.transactionVersion = transactionVersion; String[] nameParts = contractName.split("_"); for (int i = 0; i < nameParts.length; ++i) { nameParts[i] = StringUtils.capitaliseFirstLetter(nameParts[i]); @@ -160,7 +161,7 @@ public void generateJavaFiles( .collect(Collectors.toList())); classBuilder.addMethods(this.buildFunctionDefinitions(classBuilder, abiDefinitions)); classBuilder.addMethod(buildLoad(className)); - if (useNewTransactionManager) { + if (transactionVersion == CodeGenMain.TransactionVersion.V1.getV()) { classBuilder.addMethod(buildDefaultLoad(className)); } classBuilder.addMethods(this.buildDeployMethods(isWasm, className, abiDefinitions)); @@ -669,7 +670,7 @@ private static MethodSpec buildGetABIMethod() { private MethodSpec buildConstructor() { MethodSpec.Builder toReturn; - if (this.useNewTransactionManager) { + if (this.transactionVersion == CodeGenMain.TransactionVersion.V1.getV()) { toReturn = MethodSpec.constructorBuilder() .addModifiers(Modifier.PROTECTED) @@ -726,7 +727,7 @@ private MethodSpec buildDeployWithParams( Arrays.class, Type.class, inputParams); - if (this.useNewTransactionManager) { + if (this.transactionVersion == CodeGenMain.TransactionVersion.V1.getV()) { methodBuilder .addStatement( "$L contract = deploy(" @@ -758,7 +759,7 @@ private MethodSpec buildDeployWithParams( private MethodSpec buildDeployNoParams( boolean isWasm, MethodSpec.Builder methodBuilder, String className) { - if (this.useNewTransactionManager) { + if (this.transactionVersion == CodeGenMain.TransactionVersion.V1.getV()) { methodBuilder .addStatement( "$L contract = deploy($L.class, $L, $L, $L, $L, null, $L)", @@ -804,7 +805,7 @@ private static MethodSpec.Builder getDeployMethodSpec(boolean isWasm, String cla private MethodSpec buildLoad(String className) { MethodSpec.Builder toReturn; - if (this.useNewTransactionManager) { + if (this.transactionVersion == CodeGenMain.TransactionVersion.V1.getV()) { toReturn = MethodSpec.methodBuilder("load") .addModifiers(Modifier.PUBLIC, Modifier.STATIC) @@ -1370,9 +1371,27 @@ private MethodSpec buildRawFunctionReturn(ABIDefinition functionDefinition) methodBuilder.addException(ContractException.class); if (outputParameterTypes.isEmpty()) { - methodBuilder.addStatement( - "throw new RuntimeException" - + "(\"cannot call constant function with void return type\")"); + if (functionDefinition.isConstant()) { + methodBuilder.addStatement( + "throw new RuntimeException" + + "(\"cannot call constant function with void return type\")"); + } else { + methodBuilder.addStatement( + "final $T function = " + + "new $T($N, \n$T.<$T>asList($L), " + + "\n$T.<$T>asList())", + Function.class, + Function.class, + funcNameToConst(functionName), + Arrays.class, + Type.class, + inputParams, + Arrays.class, + TypeReference.class); + CodeBlock.Builder callCode = CodeBlock.builder(); + callCode.addStatement("return function"); + methodBuilder.returns(Function.class).addCode(callCode.build()); + } } else if (outputParameterTypes.size() == 1) { TypeName typeName = outputParameterTypes.get(0); TypeName nativeReturnTypeName; @@ -1410,6 +1429,24 @@ private MethodSpec buildRawFunctionReturn(ABIDefinition functionDefinition) CodeBlock.Builder callCode = CodeBlock.builder(); callCode.addStatement("return function"); + methodBuilder.returns(Function.class).addCode(callCode.build()); + } else { + List returnTypes = new ArrayList<>(); + for (int i = 0; i < functionDefinition.getOutputs().size(); ++i) { + ABIDefinition.NamedType outputType = functionDefinition.getOutputs().get(i); + if (outputType.getType().equals("tuple")) { + returnTypes.add(structClassNameMap.get(outputType.structIdentifier())); + } else if (outputType.getType().startsWith("tuple") + && outputType.getType().contains("[")) { + returnTypes.add(buildStructArrayTypeName(outputType)); + } else { + returnTypes.add(getNativeType(outputParameterTypes.get(i))); + } + } + buildVariableLengthReturnFunctionConstructor( + methodBuilder, functionName, inputParams, outputParameterTypes); + CodeBlock.Builder callCode = CodeBlock.builder(); + callCode.addStatement("return function"); methodBuilder.returns(Function.class).addCode(callCode.build()); } return methodBuilder.build(); diff --git a/src/test/java/org/fisco/bcos/codegen/v3/test/CodeGenV3Test.java b/src/test/java/org/fisco/bcos/codegen/v3/test/CodeGenV3Test.java index cec4bc6..2d97394 100644 --- a/src/test/java/org/fisco/bcos/codegen/v3/test/CodeGenV3Test.java +++ b/src/test/java/org/fisco/bcos/codegen/v3/test/CodeGenV3Test.java @@ -163,7 +163,8 @@ private void codeGenTest(String abiFileName, String codeFilePath, String contrac "-o", javaOutPut, "-e", - "-n") + "-t", + "V1") .toArray(new String[0])); JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); DiagnosticCollector collector = new DiagnosticCollector<>(); From 2feda24fccd6083ac01fa06df730f3e6abbde1a8 Mon Sep 17 00:00:00 2001 From: Kyon <32325790+kyonRay@users.noreply.github.com> Date: Thu, 11 Jan 2024 11:09:38 +0800 Subject: [PATCH 5/7] (v3): fix v3 codeGen wrapper use v1 tx generate constructor bug. (#25) --- .../codegen/v3/wrapper/ContractWrapper.java | 42 ++++++++++++------- .../bcos/codegen/v3/test/CodeGenV3Test.java | 32 +++++++++++--- 2 files changed, 53 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java b/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java index 4e2b181..487bc47 100644 --- a/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java +++ b/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java @@ -143,6 +143,9 @@ public void generateJavaFiles( classBuilder.addMethod(buildGetBinaryMethod()); classBuilder.addMethod(buildGetABIMethod()); classBuilder.addMethod(buildConstructor()); + if (this.transactionVersion == CodeGenMain.TransactionVersion.V1.getV()) { + classBuilder.addMethod(buildTransactionV1Constructor()); + } classBuilder.addFields(this.buildFuncNameConstants(abiDefinitions)); classBuilder.addTypes(this.buildStructTypes(abiDefinitions)); @@ -669,8 +672,29 @@ private static MethodSpec buildGetABIMethod() { } private MethodSpec buildConstructor() { - MethodSpec.Builder toReturn; + MethodSpec.Builder toReturn = + MethodSpec.constructorBuilder() + .addModifiers(Modifier.PROTECTED) + .addParameter(String.class, CONTRACT_ADDRESS) + .addParameter(Client.class, CLIENT) + .addParameter(CryptoKeyPair.class, ContractWrapper.CREDENTIAL) + .addStatement( + "super($N, $N, $N, $N)", + getBinaryFuncDefinition(), + CONTRACT_ADDRESS, + CLIENT, + ContractWrapper.CREDENTIAL); + toReturn.addStatement( + "this.$N = new $T($N)", + ContractWrapper.TRANSACTION_MANAGER, + ProxySignTransactionManager.class, + CLIENT); + return toReturn.build(); + } + + private MethodSpec buildTransactionV1Constructor() { if (this.transactionVersion == CodeGenMain.TransactionVersion.V1.getV()) { + MethodSpec.Builder toReturn; toReturn = MethodSpec.constructorBuilder() .addModifiers(Modifier.PROTECTED) @@ -684,21 +708,9 @@ private MethodSpec buildConstructor() { CONTRACT_ADDRESS, CLIENT, ContractWrapper.TRANSACTION_MANAGER); - } else { - toReturn = - MethodSpec.constructorBuilder() - .addModifiers(Modifier.PROTECTED) - .addParameter(String.class, CONTRACT_ADDRESS) - .addParameter(Client.class, CLIENT) - .addParameter(CryptoKeyPair.class, ContractWrapper.CREDENTIAL) - .addStatement( - "super($N, $N, $N, $N)", - getBinaryFuncDefinition(), - CONTRACT_ADDRESS, - CLIENT, - ContractWrapper.CREDENTIAL); + return toReturn.build(); } - return toReturn.build(); + return null; } private MethodSpec buildDeploy( diff --git a/src/test/java/org/fisco/bcos/codegen/v3/test/CodeGenV3Test.java b/src/test/java/org/fisco/bcos/codegen/v3/test/CodeGenV3Test.java index 2d97394..b95317d 100644 --- a/src/test/java/org/fisco/bcos/codegen/v3/test/CodeGenV3Test.java +++ b/src/test/java/org/fisco/bcos/codegen/v3/test/CodeGenV3Test.java @@ -7,7 +7,9 @@ import java.io.OutputStream; import java.net.URI; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import javax.tools.DiagnosticCollector; import javax.tools.JavaCompiler; @@ -18,8 +20,22 @@ import org.fisco.bcos.codegen.CodeGenMain; import org.junit.Assert; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +@RunWith(Parameterized.class) public class CodeGenV3Test { + + @Parameterized.Parameter public boolean useV1Tx; + + @Parameterized.Parameters + public static Collection data() { + return Arrays.asList( + new Object[][] { + {false}, {true}, + }); + } + private static final String JAVA_OUTPUT_DIR = "sdk"; private static final String DEFAULT_PACKAGE = "com"; @@ -148,8 +164,9 @@ private void codeGenTest(String abiFileName, String codeFilePath, String contrac String abiFile = CodeGenV3Test.class.getClassLoader().getResource(abiFileName).getPath(); String binFile = CodeGenV3Test.class.getClassLoader().getResource(codeFilePath).getPath(); String javaOutPut = new File(abiFile).getParent() + File.separator + JAVA_OUTPUT_DIR; - CodeGenMain.main( - Arrays.asList( + ArrayList args = + new ArrayList<>( + Arrays.asList( "-v", "V3", "-a", @@ -162,10 +179,13 @@ private void codeGenTest(String abiFileName, String codeFilePath, String contrac DEFAULT_PACKAGE, "-o", javaOutPut, - "-e", - "-t", - "V1") - .toArray(new String[0])); + "-e")); + + if (useV1Tx) { + args.add("-t"); + args.add("V1"); + } + CodeGenMain.main(args.toArray(new String[0])); JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); DiagnosticCollector collector = new DiagnosticCollector<>(); JavaFileManager javaFileManager = From df8ba5af3f49d0270783c90efb6ffba8fc45055e Mon Sep 17 00:00:00 2001 From: Kyon <32325790+kyonRay@users.noreply.github.com> Date: Thu, 1 Feb 2024 09:51:12 +0800 Subject: [PATCH 6/7] (v3): add payable wrapper feature. (#26) --- .../codegen/v3/wrapper/ContractWrapper.java | 101 ++++++++++++++---- .../bcos/codegen/v3/test/CodeGenV3Test.java | 7 ++ src/test/resources/PayableTest.abi | 1 + 3 files changed, 90 insertions(+), 19 deletions(-) create mode 100644 src/test/resources/PayableTest.abi diff --git a/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java b/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java index 487bc47..a84217b 100644 --- a/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java +++ b/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java @@ -81,6 +81,7 @@ public class ContractWrapper { private static final String CLIENT = "client"; private static final String PATH = "contractPath"; private static final String CREDENTIAL = "credential"; + private static final String VALUE = "value"; private static final String CRYPTO_SUITE = "cryptoSuite"; private static final String CONTRACT_ADDRESS = "contractAddress"; private static final String FROM_BLOCK = "fromBlock"; @@ -612,8 +613,10 @@ private List buildDeployMethods( } // constructor will not be specified in ABI file if its empty if (!constructor) { - MethodSpec.Builder credentialsMethodBuilder = getDeployMethodSpec(isWasm, className); - methodSpecs.add(buildDeployNoParams(isWasm, credentialsMethodBuilder, className)); + MethodSpec.Builder credentialsMethodBuilder = + getDeployMethodSpec(isWasm, className, false); + methodSpecs.add( + buildDeployNoParams(isWasm, credentialsMethodBuilder, className, false)); } return methodSpecs; } @@ -716,13 +719,14 @@ private MethodSpec buildTransactionV1Constructor() { private MethodSpec buildDeploy( boolean isWasm, String className, ABIDefinition functionDefinition) throws ClassNotFoundException { - MethodSpec.Builder methodBuilder = getDeployMethodSpec(isWasm, className); + boolean isPayable = isPayable(functionDefinition); + MethodSpec.Builder methodBuilder = getDeployMethodSpec(isWasm, className, isPayable); String inputParams = this.addParameters(methodBuilder, functionDefinition.getInputs()); if (!inputParams.isEmpty()) { - return buildDeployWithParams(isWasm, methodBuilder, className, inputParams); + return buildDeployWithParams(isWasm, methodBuilder, className, inputParams, isPayable); } else { - return buildDeployNoParams(isWasm, methodBuilder, className); + return buildDeployNoParams(isWasm, methodBuilder, className, isPayable); } } @@ -730,7 +734,8 @@ private MethodSpec buildDeployWithParams( boolean isWasm, MethodSpec.Builder methodBuilder, String className, - String inputParams) { + String inputParams, + boolean isPayable) { methodBuilder.addStatement( "byte[] encodedConstructor = $T.encodeConstructor(" + "$T.<$T>asList($L)" + ")", isWasm @@ -740,10 +745,15 @@ private MethodSpec buildDeployWithParams( Type.class, inputParams); if (this.transactionVersion == CodeGenMain.TransactionVersion.V1.getV()) { + String format = + "$L contract = deploy($L.class, $L, $L, $L, $L, encodedConstructor, $L)"; + if (isPayable) { + format = + "$L contract = deploy($L.class, $L, $L, $L, $L, encodedConstructor, $L, value)"; + } methodBuilder .addStatement( - "$L contract = deploy(" - + "$L.class, $L, $L, $L, $L, encodedConstructor, $L)", + format, className, className, CLIENT, @@ -770,11 +780,15 @@ private MethodSpec buildDeployWithParams( } private MethodSpec buildDeployNoParams( - boolean isWasm, MethodSpec.Builder methodBuilder, String className) { + boolean isWasm, MethodSpec.Builder methodBuilder, String className, boolean isPayable) { if (this.transactionVersion == CodeGenMain.TransactionVersion.V1.getV()) { + String format = "$L contract = deploy($L.class, $L, $L, $L, $L, null, $L)"; + if (isPayable) { + format = "$L contract = deploy($L.class, $L, $L, $L, $L, null, $L, value)"; + } methodBuilder .addStatement( - "$L contract = deploy($L.class, $L, $L, $L, $L, null, $L)", + format, className, className, CLIENT, @@ -801,7 +815,8 @@ private MethodSpec buildDeployNoParams( return methodBuilder.build(); } - private static MethodSpec.Builder getDeployMethodSpec(boolean isWasm, String className) { + private static MethodSpec.Builder getDeployMethodSpec( + boolean isWasm, String className, boolean isPayable) { MethodSpec.Builder methodSpec = MethodSpec.methodBuilder("deploy") .addException(ContractException.class) @@ -812,6 +827,9 @@ private static MethodSpec.Builder getDeployMethodSpec(boolean isWasm, String cla if (isWasm) { methodSpec.addParameter(String.class, PATH); } + if (isPayable) { + methodSpec.addParameter(BigInteger.class, ContractWrapper.VALUE); + } return methodSpec; } @@ -1184,11 +1202,19 @@ private MethodSpec buildFunction(ABIDefinition functionDefinition) this.buildConstantFunction( functionDefinition, methodBuilder, outputParameterTypes, inputParams); } else { + if (isPayable(functionDefinition)) { + methodBuilder.addParameter(BigInteger.class, VALUE); + } this.buildTransactionFunction(functionDefinition, methodBuilder, inputParams); } return methodBuilder.build(); } + private boolean isPayable(ABIDefinition functionDefinition) { + return functionDefinition.isPayable() + && this.transactionVersion == CodeGenMain.TransactionVersion.V1.getV(); + } + private MethodSpec buildFunctionSignedTransaction(ABIDefinition functionDefinition) throws ClassNotFoundException { String functionName = "getSignedTransactionFor"; @@ -1203,6 +1229,9 @@ private MethodSpec buildFunctionSignedTransaction(ABIDefinition functionDefiniti String inputParams = this.addParameters(methodBuilder, functionDefinition.getInputs()); + if (isPayable(functionDefinition)) { + methodBuilder.addParameter(BigInteger.class, VALUE); + } this.buildTransactionFunctionSeq(functionDefinition, methodBuilder, inputParams); return methodBuilder.build(); @@ -1224,6 +1253,9 @@ private MethodSpec buildFunctionWithCallback(ABIDefinition functionDefinition) functionDefinition, methodBuilder, outputParameterTypes, inputParams); } else { String inputParams = this.addParameters(methodBuilder, functionDefinition.getInputs()); + if (isPayable(functionDefinition)) { + methodBuilder.addParameter(BigInteger.class, VALUE); + } methodBuilder.addParameter(TransactionCallback.class, "callback"); this.buildTransactionFunctionWithCallback( functionDefinition, methodBuilder, inputParams); @@ -1388,10 +1420,19 @@ private MethodSpec buildRawFunctionReturn(ABIDefinition functionDefinition) "throw new RuntimeException" + "(\"cannot call constant function with void return type\")"); } else { - methodBuilder.addStatement( + String format = "final $T function = " + "new $T($N, \n$T.<$T>asList($L), " - + "\n$T.<$T>asList())", + + "\n$T.<$T>asList())"; + if (isPayable(functionDefinition)) { + methodBuilder.addParameter(BigInteger.class, VALUE); + format = + "final $T function = " + + "new $T($N, \n$T.<$T>asList($L), " + + "\n$T.<$T>asList(), 0, value)"; + } + methodBuilder.addStatement( + format, Function.class, Function.class, funcNameToConst(functionName), @@ -1601,9 +1642,17 @@ private void buildTransactionFunction( methodBuilder.returns(TypeName.get(TransactionReceipt.class)); int dagAttribute = getDagAttribute(functionDefinition); - methodBuilder.addStatement( + String format = "final $T function = new $T(\n$N, \n$T.<$T>asList($L), \n$T" - + ".<$T>emptyList(), $L)", + + ".<$T>emptyList(), $L)"; + if (isPayable(functionDefinition)) { + format = + "final $T function = new $T(\n$N, \n$T.<$T>asList($L), \n$T" + + ".<$T>emptyList(), $L, value)"; + } + + methodBuilder.addStatement( + format, Function.class, Function.class, funcNameToConst(functionName), @@ -1638,9 +1687,16 @@ private void buildTransactionFunctionWithCallback( methodBuilder.returns(String.class); int dagAttribute = getDagAttribute(functionDefinition); - methodBuilder.addStatement( + String format = "final $T function = new $T(\n$N, \n$T.<$T>asList($L), \n$T" - + ".<$T>emptyList(), $L)", + + ".<$T>emptyList(), $L)"; + if (isPayable(functionDefinition)) { + format = + "final $T function = new $T(\n$N, \n$T.<$T>asList($L), \n$T" + + ".<$T>emptyList(), $L, value)"; + } + methodBuilder.addStatement( + format, Function.class, Function.class, funcNameToConst(functionName), @@ -1662,9 +1718,16 @@ private void buildTransactionFunctionSeq( TypeName returnType = TypeName.get(String.class); methodBuilder.returns(returnType); int dagAttribute = getDagAttribute(functionDefinition); - methodBuilder.addStatement( + String format = "final $T function = new $T(\n$N, \n$T.<$T>asList($L), \n$T" - + ".<$T>emptyList(), $L)", + + ".<$T>emptyList(), $L)"; + if (isPayable(functionDefinition)) { + format = + "final $T function = new $T(\n$N, \n$T.<$T>asList($L), \n$T" + + ".<$T>emptyList(), $L, value)"; + } + methodBuilder.addStatement( + format, Function.class, Function.class, funcNameToConst(functionName), diff --git a/src/test/java/org/fisco/bcos/codegen/v3/test/CodeGenV3Test.java b/src/test/java/org/fisco/bcos/codegen/v3/test/CodeGenV3Test.java index b95317d..f3b1ba5 100644 --- a/src/test/java/org/fisco/bcos/codegen/v3/test/CodeGenV3Test.java +++ b/src/test/java/org/fisco/bcos/codegen/v3/test/CodeGenV3Test.java @@ -155,6 +155,13 @@ public void eventTestCodeGen() throws IOException { codeGenTest(ABI_FILE, CONTRACT_NAME); } + @Test + public void payableTestCodeGen() throws IOException { + final String ABI_FILE = "PayableTest.abi"; + final String CONTRACT_NAME = "PayableTest"; + codeGenTest(ABI_FILE, CONTRACT_NAME); + } + private void codeGenTest(String abiFileName, String contractName) throws IOException { codeGenTest(abiFileName, abiFileName, contractName); } diff --git a/src/test/resources/PayableTest.abi b/src/test/resources/PayableTest.abi new file mode 100644 index 0000000..3dcbcfe --- /dev/null +++ b/src/test/resources/PayableTest.abi @@ -0,0 +1 @@ +[{"inputs":[],"stateMutability":"payable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"msg","type":"string"}],"name":"incEvent","type":"event"},{"inputs":[{"internalType":"string","name":"mesg","type":"string"}],"name":"inc","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"mesg","type":"string"}],"name":"incWithPayable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"value","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}] \ No newline at end of file From f0ecb2f0505f2247685c0a47d8c967eaef648750 Mon Sep 17 00:00:00 2001 From: kyonRay Date: Wed, 7 Feb 2024 18:53:51 +0800 Subject: [PATCH 7/7] (v3): fix transaction v2 to v1. --- .../org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java b/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java index a84217b..b9a0edb 100644 --- a/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java +++ b/src/main/java/org/fisco/bcos/codegen/v3/wrapper/ContractWrapper.java @@ -53,8 +53,8 @@ import org.fisco.bcos.sdk.v3.model.TransactionReceipt; import org.fisco.bcos.sdk.v3.model.callback.CallCallback; import org.fisco.bcos.sdk.v3.model.callback.TransactionCallback; -import org.fisco.bcos.sdk.v3.transaction.manager.transactionv2.ProxySignTransactionManager; -import org.fisco.bcos.sdk.v3.transaction.manager.transactionv2.TransactionManager; +import org.fisco.bcos.sdk.v3.transaction.manager.transactionv1.ProxySignTransactionManager; +import org.fisco.bcos.sdk.v3.transaction.manager.transactionv1.TransactionManager; import org.fisco.bcos.sdk.v3.transaction.model.exception.ContractException; import org.fisco.bcos.sdk.v3.utils.Collection; import org.fisco.bcos.sdk.v3.utils.StringUtils;