From 5fe5896ac3f8011042a527d8758034abf1450550 Mon Sep 17 00:00:00 2001 From: kyonRay Date: Wed, 20 Mar 2024 18:46:55 +0800 Subject: [PATCH] (transaction): fix transaction not set address bug. --- .../sdk/v3/test/contract/ContractTest.java | 72 ++++++ .../test/contract/solidity/Incremental.java | 224 ++++++++++++++++++ .../org/fisco/bcos/sdk/v3/client/Client.java | 7 + .../fisco/bcos/sdk/v3/client/ClientImpl.java | 30 ++- .../fisco/bcos/sdk/v3/contract/Contract.java | 2 + .../sdk/v3/crypto/signature/SM2Signature.java | 1 + .../DefaultTransactionManager.java | 14 +- .../ProxySignTransactionManager.java | 14 +- 8 files changed, 347 insertions(+), 17 deletions(-) create mode 100644 src/integration-test/java/org/fisco/bcos/sdk/v3/test/contract/ContractTest.java create mode 100644 src/integration-test/java/org/fisco/bcos/sdk/v3/test/contract/solidity/Incremental.java diff --git a/src/integration-test/java/org/fisco/bcos/sdk/v3/test/contract/ContractTest.java b/src/integration-test/java/org/fisco/bcos/sdk/v3/test/contract/ContractTest.java new file mode 100644 index 000000000..aa8fa5884 --- /dev/null +++ b/src/integration-test/java/org/fisco/bcos/sdk/v3/test/contract/ContractTest.java @@ -0,0 +1,72 @@ +package org.fisco.bcos.sdk.v3.test.contract; + +import org.fisco.bcos.sdk.v3.BcosSDK; +import org.fisco.bcos.sdk.v3.client.Client; +import org.fisco.bcos.sdk.v3.client.protocol.model.JsonTransactionResponse; +import org.fisco.bcos.sdk.v3.model.ConstantConfig; +import org.fisco.bcos.sdk.v3.model.TransactionReceipt; +import org.fisco.bcos.sdk.v3.test.contract.solidity.Incremental; +import org.fisco.bcos.sdk.v3.transaction.model.exception.ContractException; +import org.fisco.bcos.sdk.v3.transaction.nonce.DefaultNonceAndBlockLimitProvider; +import org.fisco.bcos.sdk.v3.transaction.nonce.NonceAndBlockLimitProvider; +import org.fisco.bcos.sdk.v3.utils.Hex; +import org.junit.Assert; +import org.junit.Test; + +import java.math.BigInteger; +import java.util.UUID; + +public class ContractTest { + private static final String CONFIG_FILE = + "src/integration-test/resources/" + ConstantConfig.CONFIG_FILE_NAME; + private static final String GROUP = "group0"; + private final Client client; + private final Incremental incremental; + private final NonceAndBlockLimitProvider nonceAndBlockLimitProvider = + new DefaultNonceAndBlockLimitProvider(); + + public ContractTest() throws ContractException { + // init the sdk, and set the config options. + BcosSDK sdk = BcosSDK.build(CONFIG_FILE); + // group + client = sdk.getClient("group0"); + incremental = Incremental.deploy(client, client.getCryptoSuite().getCryptoKeyPair()); + } + + @Test + public void testV2Contract() throws ContractException { + if (!client.isSupportTransactionV2()) { + return; + } + String uuid = UUID.randomUUID().toString().replace("-", ""); + BigInteger blockLimit = nonceAndBlockLimitProvider.getBlockLimit(client); + TransactionReceipt receipt = + incremental + .buildMethodInc(uuid) + .setNonce(null) + .setBlockLimit(blockLimit) + .setExtension(uuid.getBytes()) + .send(); + Assert.assertTrue(receipt.isStatusOK()); + String msg = incremental.getIncEventEvents(receipt).get(0).msg; + Assert.assertEquals(msg, uuid); + + JsonTransactionResponse jsonTransactionResponse = + client.getTransaction(receipt.getTransactionHash(), true).getTransaction().get(); + Assert.assertFalse(jsonTransactionResponse.getNonce().isEmpty()); + Assert.assertEquals(jsonTransactionResponse.getBlockLimit(), blockLimit.longValue()); + + String nonce = nonceAndBlockLimitProvider.getNonce(); + TransactionReceipt receipt1 = incremental + .buildMethodInc(nonce) + .setNonce(nonce) + .setBlockLimit(blockLimit) + .setExtension("hello".getBytes()) + .send(); + Assert.assertTrue(receipt1.isStatusOK()); + JsonTransactionResponse jsonTransactionResponse1 = client.getTransaction(receipt1.getTransactionHash(), true).getTransaction().get(); + Assert.assertEquals(jsonTransactionResponse1.getNonce(), Hex.toHexString(nonce.getBytes())); + Assert.assertEquals(jsonTransactionResponse1.getBlockLimit(), blockLimit.longValue()); + Assert.assertEquals(new String(jsonTransactionResponse1.getExtension()), "hello"); + } +} diff --git a/src/integration-test/java/org/fisco/bcos/sdk/v3/test/contract/solidity/Incremental.java b/src/integration-test/java/org/fisco/bcos/sdk/v3/test/contract/solidity/Incremental.java new file mode 100644 index 000000000..69a67cade --- /dev/null +++ b/src/integration-test/java/org/fisco/bcos/sdk/v3/test/contract/solidity/Incremental.java @@ -0,0 +1,224 @@ +package org.fisco.bcos.sdk.v3.test.contract.solidity; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.fisco.bcos.sdk.v3.client.Client; +import org.fisco.bcos.sdk.v3.codec.datatypes.Event; +import org.fisco.bcos.sdk.v3.codec.datatypes.Function; +import org.fisco.bcos.sdk.v3.codec.datatypes.Type; +import org.fisco.bcos.sdk.v3.codec.datatypes.TypeReference; +import org.fisco.bcos.sdk.v3.codec.datatypes.Utf8String; +import org.fisco.bcos.sdk.v3.codec.datatypes.generated.Uint256; +import org.fisco.bcos.sdk.v3.codec.datatypes.generated.tuples.generated.Tuple1; +import org.fisco.bcos.sdk.v3.contract.Contract; +import org.fisco.bcos.sdk.v3.contract.FunctionWrapper; +import org.fisco.bcos.sdk.v3.crypto.CryptoSuite; +import org.fisco.bcos.sdk.v3.crypto.keypair.CryptoKeyPair; +import org.fisco.bcos.sdk.v3.eventsub.EventSubCallback; +import org.fisco.bcos.sdk.v3.model.CryptoType; +import org.fisco.bcos.sdk.v3.model.TransactionReceipt; +import org.fisco.bcos.sdk.v3.model.callback.TransactionCallback; +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; + +@SuppressWarnings("unchecked") +public class Incremental extends Contract { + public static final String[] BINARY_ARRAY = { + "60806040526000805534801561001457600080fd5b50610235806100246000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80633fa4f2451461003b578063bdcbbf5414610056575b600080fd5b61004460005481565b60405190815260200160405180910390f35b6100446100643660046100d3565b600060016000808282546100789190610184565b90915550506040517f7ed53cbadbbc7d8800605823ac88c67b7d9c9fa9d54d45a68d221760e0a86552906100ad9084906101aa565b60405180910390a1505060005490565b634e487b7160e01b600052604160045260246000fd5b6000602082840312156100e557600080fd5b813567ffffffffffffffff808211156100fd57600080fd5b818401915084601f83011261011157600080fd5b813581811115610123576101236100bd565b604051601f8201601f19908116603f0116810190838211818310171561014b5761014b6100bd565b8160405282815287602084870101111561016457600080fd5b826020860160208301376000928101602001929092525095945050505050565b600082198211156101a557634e487b7160e01b600052601160045260246000fd5b500190565b600060208083528351808285015260005b818110156101d7578581018301518582016040015282016101bb565b818111156101e9576000604083870101525b50601f01601f191692909201604001939250505056fea26469706673582212204f4929b54be1544a8e77f16102dc301071ee72f711fad9923c31e0e272bc48d164736f6c634300080b0033" + }; + + public static final String BINARY = + org.fisco.bcos.sdk.v3.utils.StringUtils.joinAll("", BINARY_ARRAY); + + public static final String[] SM_BINARY_ARRAY = { + "60806040526000805534801561001457600080fd5b50610235806100246000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80632d92c59d1461003b57806386ff705814610056575b600080fd5b61004460005481565b60405190815260200160405180910390f35b6100446100643660046100d3565b600060016000808282546100789190610184565b90915550506040517f7d280234d3c48f94f1914a272412c3e0030dd7a5841f7933ab1e45658bfaabbe906100ad9084906101aa565b60405180910390a1505060005490565b63b95aa35560e01b600052604160045260246000fd5b6000602082840312156100e557600080fd5b813567ffffffffffffffff808211156100fd57600080fd5b818401915084601f83011261011157600080fd5b813581811115610123576101236100bd565b604051601f8201601f19908116603f0116810190838211818310171561014b5761014b6100bd565b8160405282815287602084870101111561016457600080fd5b826020860160208301376000928101602001929092525095945050505050565b600082198211156101a55763b95aa35560e01b600052601160045260246000fd5b500190565b600060208083528351808285015260005b818110156101d7578581018301518582016040015282016101bb565b818111156101e9576000604083870101525b50601f01601f191692909201604001939250505056fea26469706673582212203b3bc5791505a1493d2d8c6acd87f26438a740b84bb247353830397fa78e254264736f6c634300080b0033" + }; + + public static final String SM_BINARY = + org.fisco.bcos.sdk.v3.utils.StringUtils.joinAll("", SM_BINARY_ARRAY); + + public static final String[] ABI_ARRAY = { + "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"msg\",\"type\":\"string\"}],\"name\":\"incEvent\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"msg\",\"type\":\"string\"}],\"name\":\"inc\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"value\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]" + }; + + public static final String ABI = org.fisco.bcos.sdk.v3.utils.StringUtils.joinAll("", ABI_ARRAY); + + public static final String FUNC_INC = "inc"; + + public static final String FUNC_VALUE = "value"; + + public static final Event INCEVENT_EVENT = + new Event( + "incEvent", + Arrays.>asList(new TypeReference() {}));; + + protected Incremental(String contractAddress, Client client, CryptoKeyPair credential) { + super(getBinary(client.getCryptoSuite()), contractAddress, client, credential); + this.transactionManager = new ProxySignTransactionManager(client); + } + + protected Incremental( + String contractAddress, Client client, TransactionManager transactionManager) { + super(getBinary(client.getCryptoSuite()), contractAddress, client, transactionManager); + } + + public static String getBinary(CryptoSuite cryptoSuite) { + return (cryptoSuite.getCryptoTypeConfig() == CryptoType.ECDSA_TYPE ? BINARY : SM_BINARY); + } + + public static String getABI() { + return ABI; + } + + public List getIncEventEvents(TransactionReceipt transactionReceipt) { + List valueList = + extractEventParametersWithLog(INCEVENT_EVENT, transactionReceipt); + ArrayList responses = + new ArrayList(valueList.size()); + for (EventValuesWithLog eventValues : valueList) { + IncEventEventResponse typedResponse = new IncEventEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.msg = (String) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public void subscribeIncEventEvent( + BigInteger fromBlock, + BigInteger toBlock, + List otherTopics, + EventSubCallback callback) { + String topic0 = eventEncoder.encode(INCEVENT_EVENT); + subscribeEvent(topic0, otherTopics, fromBlock, toBlock, callback); + } + + public void subscribeIncEventEvent(EventSubCallback callback) { + String topic0 = eventEncoder.encode(INCEVENT_EVENT); + subscribeEvent(topic0, callback); + } + + public TransactionReceipt inc(String msg) { + final Function function = + new Function( + FUNC_INC, + Arrays.asList(new Utf8String(msg)), + Collections.>emptyList(), + 0); + return executeTransaction(function); + } + + public Function getMethodIncRawFunction(String msg) throws ContractException { + final Function function = + new Function( + FUNC_INC, + Arrays.asList(new Utf8String(msg)), + Arrays.>asList(new TypeReference() {})); + return function; + } + + public FunctionWrapper buildMethodInc(String msg) throws ContractException { + final Function function = + new Function( + FUNC_INC, + Arrays.asList(new Utf8String(msg)), + Arrays.>asList(new TypeReference() {})); + return new FunctionWrapper(this, function); + } + + public String getSignedTransactionForInc(String msg) { + final Function function = + new Function( + FUNC_INC, + Arrays.asList(new Utf8String(msg)), + Collections.>emptyList(), + 0); + return createSignedTransaction(function); + } + + public String inc(String msg, TransactionCallback callback) { + final Function function = + new Function( + FUNC_INC, + Arrays.asList(new Utf8String(msg)), + Collections.>emptyList(), + 0); + return asyncExecuteTransaction(function, callback); + } + + public Tuple1 getIncInput(TransactionReceipt transactionReceipt) { + String data = transactionReceipt.getInput().substring(10); + final Function function = + new Function( + FUNC_INC, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + List results = + this.functionReturnDecoder.decode(data, function.getOutputParameters()); + return new Tuple1((String) results.get(0).getValue()); + } + + public Tuple1 getIncOutput(TransactionReceipt transactionReceipt) { + String data = transactionReceipt.getOutput(); + final Function function = + new Function( + FUNC_INC, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + List results = + this.functionReturnDecoder.decode(data, function.getOutputParameters()); + return new Tuple1((BigInteger) results.get(0).getValue()); + } + + public BigInteger value() throws ContractException { + final Function function = + new Function( + FUNC_VALUE, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + return executeCallWithSingleValueReturn(function, BigInteger.class); + } + + public Function getMethodValueRawFunction() throws ContractException { + final Function function = + new Function( + FUNC_VALUE, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + return function; + } + + public static Incremental load( + String contractAddress, Client client, TransactionManager transactionManager) { + return new Incremental(contractAddress, client, transactionManager); + } + + public static Incremental load(String contractAddress, Client client) { + return new Incremental(contractAddress, client, new ProxySignTransactionManager(client)); + } + + public static Incremental deploy(Client client, CryptoKeyPair credential) + throws ContractException { + Incremental contract = + deploy( + Incremental.class, + client, + credential, + getBinary(client.getCryptoSuite()), + getABI(), + null, + null); + contract.setTransactionManager(new ProxySignTransactionManager(client)); + return contract; + } + + public static class IncEventEventResponse { + public TransactionReceipt.Logs log; + + public String msg; + } +} diff --git a/src/main/java/org/fisco/bcos/sdk/v3/client/Client.java b/src/main/java/org/fisco/bcos/sdk/v3/client/Client.java index e8972bc4b..887437ce0 100644 --- a/src/main/java/org/fisco/bcos/sdk/v3/client/Client.java +++ b/src/main/java/org/fisco/bcos/sdk/v3/client/Client.java @@ -993,6 +993,13 @@ void getChainCompatibilityVersionAsync( */ boolean isSupportTransactionV1(); + /** + * Check this client whether supporting sending transaction with v2 version or not. + * + * @return is this client support sending transaction with v2 version + */ + boolean isSupportTransactionV2(); + /** * get node name to send rpc request directly * diff --git a/src/main/java/org/fisco/bcos/sdk/v3/client/ClientImpl.java b/src/main/java/org/fisco/bcos/sdk/v3/client/ClientImpl.java index e03b7a470..5c1dfa5d4 100644 --- a/src/main/java/org/fisco/bcos/sdk/v3/client/ClientImpl.java +++ b/src/main/java/org/fisco/bcos/sdk/v3/client/ClientImpl.java @@ -1276,6 +1276,31 @@ public boolean isSupportTransactionV1() { return (protocol >> 16) >= 2; } + @Override + public boolean isSupportTransactionV2() { + return isSupportTransactionV1() + && getGroupInfoList().getResult().stream() + .filter(group -> Objects.equals(groupInfo.getGroupID(), groupID)) + .allMatch( + info -> + info.getNodeList().stream() + .allMatch( + node -> + EnumNodeVersion.getClassVersion( + node.getIniConfig() + .getBinaryInfo() + .getVersion()) + .toCompatibilityVersion() + >= EnumNodeVersion + .BCOS_3_7_0 + .getVersion())); + } + + @Override + public String getNodeToSendRequest() { + return this.nodeToSendRequest; + } + /** * Get the protocol version after SDK and Blockchain node negotiated. This method returns int * with max and min version bits combined, which is (max|min). Max protocol version is in first @@ -1283,11 +1308,6 @@ public boolean isSupportTransactionV1() { * * @return (max|min) bits combined. */ - @Override - public String getNodeToSendRequest() { - return this.nodeToSendRequest; - } - @Override public int getNegotiatedProtocol() { return negotiatedProtocol; diff --git a/src/main/java/org/fisco/bcos/sdk/v3/contract/Contract.java b/src/main/java/org/fisco/bcos/sdk/v3/contract/Contract.java index 1a7d7a688..95e1bd8a7 100644 --- a/src/main/java/org/fisco/bcos/sdk/v3/contract/Contract.java +++ b/src/main/java/org/fisco/bcos/sdk/v3/contract/Contract.java @@ -572,6 +572,7 @@ protected String asyncExecuteTransaction( } AbiEncodedRequest abiEncodedRequest = new TransactionRequestBuilder() + .setTo(this.contractAddress) .setNonce(functionWrapper.getNonce()) .setBlockLimit(functionWrapper.getBlockLimit()) .setExtension(functionWrapper.getExtension()) @@ -623,6 +624,7 @@ protected TransactionReceipt executeTransaction(FunctionWrapper functionWrapper) try { AbiEncodedRequest abiEncodedRequest = new TransactionRequestBuilder() + .setTo(this.contractAddress) .setNonce(functionWrapper.getNonce()) .setBlockLimit(functionWrapper.getBlockLimit()) .setExtension(functionWrapper.getExtension()) diff --git a/src/main/java/org/fisco/bcos/sdk/v3/crypto/signature/SM2Signature.java b/src/main/java/org/fisco/bcos/sdk/v3/crypto/signature/SM2Signature.java index f170878d3..a79733da1 100644 --- a/src/main/java/org/fisco/bcos/sdk/v3/crypto/signature/SM2Signature.java +++ b/src/main/java/org/fisco/bcos/sdk/v3/crypto/signature/SM2Signature.java @@ -38,6 +38,7 @@ public String signWithStringSignature(final String message, final CryptoKeyPair return signMessage(message, keyPair); } + @Deprecated() public String signMessage(String message, CryptoKeyPair keyPair) { if (!keyPair.getCurveName().equals(CryptoKeyPair.SM2_CURVE_NAME)) { 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 a577e4f4a..709c10325 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 @@ -134,12 +134,14 @@ public TxPair createSignedTransaction(AbiEncodedRequest request) throws JniExcep 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(); + String nonce = request.getNonce(); + if (nonce == null || nonce.isEmpty()) { + nonce = getNonceProvider().getNonce(); + } + BigInteger blockLimit = request.getBlockLimit(); + if (blockLimit == null || blockLimit.longValue() <= 0) { + blockLimit = getNonceProvider().getBlockLimit(client); + } EIP1559Struct eip1559Struct = null; if (getGasProvider().isEIP1559Enabled() || request.isEIP1559Enabled()) { eip1559Struct = 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 f910afbcd..72bc68972 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 @@ -153,12 +153,14 @@ public TxPair createSignedTransaction(AbiEncodedRequest request) throws JniExcep 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(); + String nonce = request.getNonce(); + if (nonce == null || nonce.isEmpty()) { + nonce = getNonceProvider().getNonce(); + } + BigInteger blockLimit = request.getBlockLimit(); + if (blockLimit == null || blockLimit.longValue() <= 0) { + blockLimit = getNonceProvider().getBlockLimit(client); + } EIP1559Struct eip1559Struct = null; if (getGasProvider().isEIP1559Enabled() || request.isEIP1559Enabled()) { eip1559Struct =