diff --git a/build.gradle b/build.gradle index 4163f8b75..4bb7b1fa8 100644 --- a/build.gradle +++ b/build.gradle @@ -24,7 +24,7 @@ ext { webankJavaCryptoVersion = "1.0.3" junitVersion = '4.13.2' commonsCollections4Version = "4.4" - bcosSdkJniVersion = "3.6.0-DEV-SNAPSHOT" + bcosSdkJniVersion = "3.6.0-SNAPSHOT" slf4jApiVerison = '1.7.36' mockitoVersion = '4.8.0' gsonVersion = '2.10.1' diff --git a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/transactionv1/DefaultTransactionManager.java b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/transactionv1/DefaultTransactionManager.java index 2b9d6df2f..2879682db 100644 --- a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/transactionv1/DefaultTransactionManager.java +++ b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/transactionv1/DefaultTransactionManager.java @@ -152,18 +152,9 @@ public TransactionReceipt sendTransaction( return bcosTransactionReceipt.getTransactionReceipt(); } - // @Override + @Override public TransactionReceipt sendTransaction(AbiEncodedRequest request) throws JniException { - String signedTransaction = - createSignedTransaction( - request.getTo(), - request.getEncodedData(), - request.getValue(), - request.getGasPrice(), - request.getGasLimit(), - request.getBlockLimit(), - request.getAbi(), - request.getAbi() != null); + String signedTransaction = createSignedTransaction(request).getSignedTx(); BcosTransactionReceipt bcosTransactionReceipt = client.sendTransaction(signedTransaction, false); return bcosTransactionReceipt.getTransactionReceipt(); @@ -222,6 +213,55 @@ public String createSignedTransaction( return txPair.getSignedTx(); } + @Override + public TxPair createSignedTransaction(AbiEncodedRequest request) throws JniException { + if (!request.isTransactionEssentialSatisfy()) { + throw new JniException( + "Transaction essential fields are not satisfied: encodedData, to."); + } + int transactionAttribute; + if (client.isWASM()) { + transactionAttribute = TransactionAttribute.LIQUID_SCALE_CODEC; + if (request.isCreate()) { + transactionAttribute |= TransactionAttribute.LIQUID_CREATE; + } + } else { + transactionAttribute = TransactionAttribute.EVM_ABI_CODEC; + } + byte[] methodId = new byte[4]; + if (!request.isCreate() && (request.getEncodedData().length >= 4)) { + System.arraycopy(request.getEncodedData(), 0, methodId, 0, 4); + } + String nonce = + request.getNonce() == null ? getNonceProvider().getNonce() : request.getNonce(); + BigInteger blockLimit = + request.getBlockLimit() == null + ? getNonceProvider().getBlockLimit(client) + : request.getBlockLimit(); + BigInteger gasPrice = + request.getGasPrice() == null + ? getGasProvider().getGasPrice(methodId) + : request.getGasPrice(); + BigInteger gasLimit = + request.getGasLimit() == null + ? getGasProvider().getGasLimit(methodId) + : request.getGasLimit(); + return TransactionBuilderV1JniObj.createSignedTransactionWithFullFields( + client.getCryptoSuite().getCryptoKeyPair().getJniKeyPair(), + client.getGroup(), + client.getChainId(), + request.getTo(), + nonce, + request.getEncodedData(), + request.isCreate() ? request.getAbi() : "", + blockLimit.longValue(), + Numeric.toHexString(request.getValue()), + Numeric.toHexString(gasPrice), + gasLimit.longValue(), + transactionAttribute, + client.getExtraData()); + } + /** * Send tx with abi field asynchronously * @@ -351,6 +391,14 @@ public String asyncSendTransaction( return txPair.getTxHash(); } + @Override + public String asyncSendTransaction(AbiEncodedRequest request, TransactionCallback callback) + throws JniException { + TxPair txPair = createSignedTransaction(request); + client.sendTransactionAsync(txPair.getSignedTx(), false, callback); + return txPair.getTxHash(); + } + /** * Send tx with EIP1559 * diff --git a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/transactionv1/ProxySignTransactionManager.java b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/transactionv1/ProxySignTransactionManager.java index 20f591d73..0f6bea5ce 100644 --- a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/transactionv1/ProxySignTransactionManager.java +++ b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/transactionv1/ProxySignTransactionManager.java @@ -7,6 +7,7 @@ import org.fisco.bcos.sdk.jni.common.JniException; import org.fisco.bcos.sdk.jni.utilities.tx.TransactionBuilderV1JniObj; import org.fisco.bcos.sdk.jni.utilities.tx.TransactionVersion; +import org.fisco.bcos.sdk.jni.utilities.tx.TxPair; import org.fisco.bcos.sdk.v3.client.Client; import org.fisco.bcos.sdk.v3.client.protocol.model.TransactionAttribute; import org.fisco.bcos.sdk.v3.client.protocol.request.Transaction; @@ -23,6 +24,7 @@ import org.fisco.bcos.sdk.v3.transaction.gasProvider.ContractGasProvider; import org.fisco.bcos.sdk.v3.transaction.gasProvider.DefaultGasProvider; import org.fisco.bcos.sdk.v3.transaction.gasProvider.EIP1559Struct; +import org.fisco.bcos.sdk.v3.transaction.manager.transactionv1.dto.AbiEncodedRequest; import org.fisco.bcos.sdk.v3.transaction.nonce.DefaultNonceAndBlockLimitProvider; import org.fisco.bcos.sdk.v3.transaction.nonce.NonceAndBlockLimitProvider; import org.fisco.bcos.sdk.v3.transaction.signer.AsyncTransactionSignercInterface; @@ -173,6 +175,12 @@ public TransactionReceipt sendTransaction( return client.sendTransaction(signedTransaction, false).getTransactionReceipt(); } + @Override + public TransactionReceipt sendTransaction(AbiEncodedRequest request) throws JniException { + TxPair txPair = createSignedTransaction(request); + return client.sendTransaction(txPair.getSignedTx(), false).getTransactionReceipt(); + } + /** * This method is used to create a signed transaction. * @@ -265,6 +273,94 @@ public String createSignedTransaction( client.getExtraData()); } + @Override + public TxPair createSignedTransaction(AbiEncodedRequest request) throws JniException { + if (!request.isTransactionEssentialSatisfy()) { + throw new JniException("Transaction essential fields are not satisfied"); + } + int transactionAttribute; + if (client.isWASM()) { + transactionAttribute = TransactionAttribute.LIQUID_SCALE_CODEC; + if (request.isCreate()) { + transactionAttribute |= TransactionAttribute.LIQUID_CREATE; + } + } else { + transactionAttribute = TransactionAttribute.EVM_ABI_CODEC; + } + byte[] methodId = new byte[4]; + if (!request.isCreate() && (request.getEncodedData().length >= 4)) { + System.arraycopy(request.getEncodedData(), 0, methodId, 0, 4); + } + String nonce = + request.getNonce() == null ? getNonceProvider().getNonce() : request.getNonce(); + BigInteger blockLimit = + request.getBlockLimit() == null + ? getNonceProvider().getBlockLimit(client) + : request.getBlockLimit(); + BigInteger gasPrice = + request.getGasPrice() == null + ? getGasProvider().getGasPrice(methodId) + : request.getGasPrice(); + BigInteger gasLimit = + request.getGasLimit() == null + ? getGasProvider().getGasLimit(methodId) + : request.getGasLimit(); + + String dataHash = + TransactionBuilderV1JniObj.calcTransactionDataHashWithFullFields( + cryptoType, + TransactionVersion.V1, + client.getGroup(), + client.getChainId(), + request.getTo(), + nonce, + request.getEncodedData(), + request.isCreate() ? request.getAbi() : "", + blockLimit.longValue(), + Numeric.toHexString(request.getValue()), + Numeric.toHexString(gasPrice), + gasLimit.longValue(), + "", + ""); + CompletableFuture signFuture = new CompletableFuture<>(); + SignatureResult signatureResult; + try { + asyncTxSigner.signAsync( + Hex.decode(dataHash), + signature -> { + signFuture.complete(signature); + return 0; + }); + signatureResult = + signFuture.get( + client.getConfigOption().getNetworkConfig().getTimeout(), + TimeUnit.MILLISECONDS); + } catch (Exception e) { + logger.error("Sign transaction failed, error message: {}", e.getMessage(), e); + throw new JniException("Sign transaction failed, error message: " + e.getMessage()); + } + String signedTransactionWithSignature = + TransactionBuilderV1JniObj.createSignedTransactionWithSignature( + signatureResult.encode(), + dataHash, + TransactionVersion.V1, + client.getGroup(), + client.getChainId(), + request.getTo(), + nonce, + request.getEncodedData(), + request.isCreate() ? request.getAbi() : "", + blockLimit.longValue(), + Numeric.toHexString(request.getValue()), + Numeric.toHexString(gasPrice), + gasLimit.longValue(), + "", + "", + transactionAttribute, + client.getExtraData()); + return new TxPair(dataHash, signedTransactionWithSignature); + } + /** * Send tx with abi field asynchronously * @@ -474,6 +570,14 @@ public void onResponse(TransactionReceipt receipt) { return dataHash; } + @Override + public String asyncSendTransaction(AbiEncodedRequest request, TransactionCallback callback) + throws JniException { + TxPair txPair = createSignedTransaction(request); + client.sendTransactionAsync(txPair.getSignedTx(), false, callback); + return txPair.getTxHash(); + } + /** * Send tx with EIP1559 * diff --git a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/transactionv1/TransactionManager.java b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/transactionv1/TransactionManager.java index 6ad9e9bcb..5a6c4b655 100644 --- a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/transactionv1/TransactionManager.java +++ b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/transactionv1/TransactionManager.java @@ -2,6 +2,7 @@ import java.math.BigInteger; import org.fisco.bcos.sdk.jni.common.JniException; +import org.fisco.bcos.sdk.jni.utilities.tx.TxPair; import org.fisco.bcos.sdk.v3.client.Client; import org.fisco.bcos.sdk.v3.client.protocol.response.Call; import org.fisco.bcos.sdk.v3.model.TransactionReceipt; @@ -9,6 +10,7 @@ import org.fisco.bcos.sdk.v3.model.callback.TransactionCallback; import org.fisco.bcos.sdk.v3.transaction.gasProvider.ContractGasProvider; import org.fisco.bcos.sdk.v3.transaction.gasProvider.EIP1559Struct; +import org.fisco.bcos.sdk.v3.transaction.manager.transactionv1.dto.AbiEncodedRequest; import org.fisco.bcos.sdk.v3.transaction.nonce.NonceAndBlockLimitProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -116,8 +118,8 @@ public abstract TransactionReceipt sendTransaction( boolean constructor) throws JniException; - // public abstract TransactionReceipt sendTransaction(AbiEncodedRequest request) throws - // JniException; + public abstract TransactionReceipt sendTransaction(AbiEncodedRequest request) + throws JniException; /** * This method is used to create a signed transaction. @@ -145,6 +147,8 @@ public abstract String createSignedTransaction( boolean constructor) throws JniException; + public abstract TxPair createSignedTransaction(AbiEncodedRequest request) throws JniException; + /** * Simple send tx asynchronously * @@ -230,6 +234,9 @@ public abstract String asyncSendTransaction( TransactionCallback callback) throws JniException; + public abstract String asyncSendTransaction( + AbiEncodedRequest request, TransactionCallback callback) throws JniException; + /** * Send tx with EIP1559 * diff --git a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/transactionv1/dto/AbiEncodedRequest.java b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/transactionv1/dto/AbiEncodedRequest.java index a82198950..10fe9ffb4 100644 --- a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/transactionv1/dto/AbiEncodedRequest.java +++ b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/transactionv1/dto/AbiEncodedRequest.java @@ -3,28 +3,60 @@ import java.math.BigInteger; import org.fisco.bcos.sdk.v3.transaction.gasProvider.EIP1559Struct; -public class AbiEncodedRequest extends BasicRequest { +public class AbiEncodedRequest { // required protected byte[] encodedData; + // required + protected String to; + // optional + protected String abi; // optional protected BigInteger blockLimit; // optional protected String nonce; + // optional + protected BigInteger value; + // optional + protected BigInteger gasPrice; + // optional + protected BigInteger gasLimit; + // optional + protected EIP1559Struct eip1559Struct; + + public AbiEncodedRequest(byte[] encodedData, String to) { + this.encodedData = encodedData; + this.to = to; + } public AbiEncodedRequest( + byte[] encodedData, String to, + String abi, + BigInteger blockLimit, + String nonce, BigInteger value, BigInteger gasPrice, BigInteger gasLimit, EIP1559Struct eip1559Struct) { - super("", "", to, value, gasPrice, gasLimit, eip1559Struct); + this.encodedData = encodedData; + this.to = to; + this.abi = abi; + this.blockLimit = blockLimit; + this.nonce = nonce; + this.value = value; + this.gasPrice = gasPrice; + this.gasLimit = gasLimit; + this.eip1559Struct = eip1559Struct; } - @Override public boolean isTransactionEssentialSatisfy() { return encodedData != null && to != null; } + public boolean isCreate() { + return this.abi != null && !this.abi.isEmpty(); + } + public byte[] getEncodedData() { return encodedData; } @@ -49,7 +81,51 @@ public void setNonce(String nonce) { this.nonce = nonce; } + public String getTo() { + return to; + } + + public void setTo(String to) { + this.to = to; + } + + public String getAbi() { + return abi; + } + public void setAbi(String abi) { this.abi = abi; } + + public BigInteger getValue() { + return value; + } + + public void setValue(BigInteger value) { + this.value = value; + } + + public BigInteger getGasPrice() { + return gasPrice; + } + + public void setGasPrice(BigInteger gasPrice) { + this.gasPrice = gasPrice; + } + + public BigInteger getGasLimit() { + return gasLimit; + } + + public void setGasLimit(BigInteger gasLimit) { + this.gasLimit = gasLimit; + } + + public EIP1559Struct getEip1559Struct() { + return eip1559Struct; + } + + public void setEip1559Struct(EIP1559Struct eip1559Struct) { + this.eip1559Struct = eip1559Struct; + } } diff --git a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/transactionv1/utils/AbiEncodedRequestBuilder.java b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/transactionv1/utils/AbiEncodedRequestBuilder.java new file mode 100644 index 000000000..4aa0a7d80 --- /dev/null +++ b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/transactionv1/utils/AbiEncodedRequestBuilder.java @@ -0,0 +1,78 @@ +package org.fisco.bcos.sdk.v3.transaction.manager.transactionv1.utils; + +import java.math.BigInteger; +import org.fisco.bcos.sdk.v3.transaction.gasProvider.EIP1559Struct; +import org.fisco.bcos.sdk.v3.transaction.manager.transactionv1.dto.AbiEncodedRequest; + +public class AbiEncodedRequestBuilder { + private byte[] encodedData; + private String to; + private String abi; + private BigInteger blockLimit; + private String nonce; + private BigInteger value; + private BigInteger gasPrice; + private BigInteger gasLimit; + private EIP1559Struct eip1559Struct; + + public AbiEncodedRequestBuilder(byte[] encodedData, String to) { + this.encodedData = encodedData; + this.to = to; + } + + public AbiEncodedRequestBuilder(byte[] encodedData, String to, String abi) { + this.encodedData = encodedData; + this.to = to; + this.abi = abi; + } + + public AbiEncodedRequestBuilder setEncodedData(byte[] encodedData) { + this.encodedData = encodedData; + return this; + } + + public AbiEncodedRequestBuilder setTo(String to) { + this.to = to; + return this; + } + + public AbiEncodedRequestBuilder setAbi(String abi) { + this.abi = abi; + return this; + } + + public AbiEncodedRequestBuilder setBlockLimit(BigInteger blockLimit) { + this.blockLimit = blockLimit; + return this; + } + + public AbiEncodedRequestBuilder setNonce(String nonce) { + this.nonce = nonce; + return this; + } + + public AbiEncodedRequestBuilder setValue(BigInteger value) { + this.value = value; + return this; + } + + public AbiEncodedRequestBuilder setGasPrice(BigInteger gasPrice) { + this.gasPrice = gasPrice; + return this; + } + + public AbiEncodedRequestBuilder setGasLimit(BigInteger gasLimit) { + this.gasLimit = gasLimit; + return this; + } + + public AbiEncodedRequestBuilder setEIP1559Struct(EIP1559Struct eip1559Struct) { + this.eip1559Struct = eip1559Struct; + return this; + } + + public AbiEncodedRequest build() { + return new AbiEncodedRequest( + encodedData, to, abi, blockLimit, nonce, value, gasPrice, gasLimit, eip1559Struct); + } +} diff --git a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/transactionv1/utils/TransactionRequestBuilder.java b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/transactionv1/utils/TransactionRequestBuilder.java index bd79638c9..4cc540a40 100644 --- a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/transactionv1/utils/TransactionRequestBuilder.java +++ b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/transactionv1/utils/TransactionRequestBuilder.java @@ -3,7 +3,6 @@ import java.math.BigInteger; import java.util.List; import org.fisco.bcos.sdk.v3.transaction.gasProvider.EIP1559Struct; -import org.fisco.bcos.sdk.v3.transaction.manager.transactionv1.dto.AbiEncodedRequest; import org.fisco.bcos.sdk.v3.transaction.manager.transactionv1.dto.DeployTransactionRequest; import org.fisco.bcos.sdk.v3.transaction.manager.transactionv1.dto.DeployTransactionRequestWithStringParams; import org.fisco.bcos.sdk.v3.transaction.manager.transactionv1.dto.TransactionRequest; @@ -13,13 +12,10 @@ public class TransactionRequestBuilder { private String abi; private String method; - private byte[] abiEncodedData; private String to; private BigInteger value; private BigInteger gasPrice; private BigInteger gasLimit; - private BigInteger blockLimit; - private String nonce; private String bin; private EIP1559Struct eip1559Struct; @@ -69,21 +65,6 @@ public TransactionRequestBuilder setBin(String bin) { return this; } - public TransactionRequestBuilder setAbiEncodedData(byte[] abiEncodedData) { - this.abiEncodedData = abiEncodedData; - return this; - } - - public TransactionRequestBuilder setBlockLimit(BigInteger blockLimit) { - this.blockLimit = blockLimit; - return this; - } - - public TransactionRequestBuilder setNonce(String nonce) { - this.nonce = nonce; - return this; - } - public TransactionRequest buildRequest(List params) throws ContractException { if (params == null) { throw new ContractException("SendTransaction params is null, please set it manually."); @@ -166,24 +147,4 @@ public DeployTransactionRequestWithStringParams buildDeployStringParamsRequest( request.setStringParams(stringParams); return request; } - - public AbiEncodedRequest buildAbiEncodedRequest(boolean isCreate) throws ContractException { - if (abiEncodedData == null) { - throw new ContractException( - "AbiEncodedRequest abiEncodedData is null, please set it manually."); - } - if (isCreate && abi == null) { - throw new ContractException("AbiEncodedRequest abi is null, please set it manually."); - } - AbiEncodedRequest request = - new AbiEncodedRequest( - this.to, this.value, this.gasPrice, this.gasLimit, this.eip1559Struct); - request.setEncodedData(abiEncodedData); - request.setBlockLimit(blockLimit); - request.setNonce(nonce); - if (isCreate) { - request.setAbi(abi); - } - return request; - } }