java-sdk
java-sdk copied to clipboard
DynamicArray构建的empty数组,调用智能合约时,触发内部调用的getTypeAsString报错NullPointerException
sdk版本:2.10.2-SNAPSHOT
通过DynamicArray.empty方法构建的空数组,调用智能合约时,触发内部调用的getTypeAsString报错NullPointerException
原因初步分析:
通过empty方法构建的空数组,只初始化了type字段,而没有初始化typeClass,作者设计的empty方法只接收跟初始化type的意图应该是希望用户在构建空数组时,自己定义type,所以空数组时getTypeAsString()应该是直接返回用户定义的type,而不是通过typeClass来动态生成?
能否提供一下调用时的合约函数参数以及入参?
能否提供一下调用时的合约函数参数以及入参?
以下为测试重现的一些素材 智能合约: TestContract.sol
//SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.9.0;
pragma experimental ABIEncoderV2;
struct TestStruct {
string text;
string[] values;
}
contract TestContract {
function store(TestStruct memory test) public returns (uint256) {
return test.values.length;
}
}
智能合约对应java的contract文件 TestContract.java
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.fisco.bcos.sdk.abi.FunctionReturnDecoder;
import org.fisco.bcos.sdk.abi.TypeReference;
import org.fisco.bcos.sdk.abi.datatypes.DynamicArray;
import org.fisco.bcos.sdk.abi.datatypes.DynamicStruct;
import org.fisco.bcos.sdk.abi.datatypes.Function;
import org.fisco.bcos.sdk.abi.datatypes.Type;
import org.fisco.bcos.sdk.abi.datatypes.Utf8String;
import org.fisco.bcos.sdk.abi.datatypes.generated.Uint256;
import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple1;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.contract.Contract;
import org.fisco.bcos.sdk.crypto.CryptoSuite;
import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
import org.fisco.bcos.sdk.model.CryptoType;
import org.fisco.bcos.sdk.model.TransactionReceipt;
import org.fisco.bcos.sdk.model.callback.TransactionCallback;
import org.fisco.bcos.sdk.transaction.model.exception.ContractException;
@SuppressWarnings("unchecked")
public class TestContract extends Contract {
public static final String[] BINARY_ARRAY = {"608060405234801561001057600080fd5b506102ee806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80634c7d33a514610030575b600080fd5b61004a600480360381019061004591906101b3565b610060565b6040516100579190610203565b60405180910390f35b60008160200151519050919050565b600082601f83011261008057600080fd5b813561009361008e8261024b565b61021e565b9150818183526020840193506020810190508360005b838110156100d957813586016100bf88826100e3565b8452602084019350602083019250506001810190506100a9565b5050505092915050565b600082601f8301126100f457600080fd5b813561010761010282610273565b61021e565b9150808252602083016020830185838301111561012357600080fd5b61012e8382846102a9565b50505092915050565b60006040828403121561014957600080fd5b610153604061021e565b9050600082013567ffffffffffffffff81111561016f57600080fd5b61017b848285016100e3565b600083015250602082013567ffffffffffffffff81111561019b57600080fd5b6101a78482850161006f565b60208301525092915050565b6000602082840312156101c557600080fd5b600082013567ffffffffffffffff8111156101df57600080fd5b6101eb84828501610137565b91505092915050565b6101fd8161029f565b82525050565b600060208201905061021860008301846101f4565b92915050565b6000604051905081810181811067ffffffffffffffff8211171561024157600080fd5b8060405250919050565b600067ffffffffffffffff82111561026257600080fd5b602082029050602081019050919050565b600067ffffffffffffffff82111561028a57600080fd5b601f19601f8301169050602081019050919050565b6000819050919050565b8281833760008383015250505056fea2646970667358221220dfe29f3658fa934d4cdd57f0d6325a5a418b5b510faa9fed101a0fca0f34455e64736f6c634300060a0033"};
public static final String BINARY = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", BINARY_ARRAY);
public static final String[] SM_BINARY_ARRAY = {"608060405234801561001057600080fd5b506102ee806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c806392bac43614610030575b600080fd5b61004a600480360381019061004591906101b3565b610060565b6040516100579190610203565b60405180910390f35b60008160200151519050919050565b600082601f83011261008057600080fd5b813561009361008e8261024b565b61021e565b9150818183526020840193506020810190508360005b838110156100d957813586016100bf88826100e3565b8452602084019350602083019250506001810190506100a9565b5050505092915050565b600082601f8301126100f457600080fd5b813561010761010282610273565b61021e565b9150808252602083016020830185838301111561012357600080fd5b61012e8382846102a9565b50505092915050565b60006040828403121561014957600080fd5b610153604061021e565b9050600082013567ffffffffffffffff81111561016f57600080fd5b61017b848285016100e3565b600083015250602082013567ffffffffffffffff81111561019b57600080fd5b6101a78482850161006f565b60208301525092915050565b6000602082840312156101c557600080fd5b600082013567ffffffffffffffff8111156101df57600080fd5b6101eb84828501610137565b91505092915050565b6101fd8161029f565b82525050565b600060208201905061021860008301846101f4565b92915050565b6000604051905081810181811067ffffffffffffffff8211171561024157600080fd5b8060405250919050565b600067ffffffffffffffff82111561026257600080fd5b602082029050602081019050919050565b600067ffffffffffffffff82111561028a57600080fd5b601f19601f8301169050602081019050919050565b6000819050919050565b8281833760008383015250505056fea2646970667358221220ecb47a01b2a3561f2126a0b86bac118c202c890e9d65c3783b8dfc1447fbb52964736f6c634300060a0033"};
public static final String SM_BINARY = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", SM_BINARY_ARRAY);
public static final String[] ABI_ARRAY = {"[{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"text\",\"type\":\"string\"},{\"internalType\":\"string[]\",\"name\":\"values\",\"type\":\"string[]\"}],\"internalType\":\"struct TestStruct\",\"name\":\"test\",\"type\":\"tuple\"}],\"name\":\"store\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"};
public static final String ABI = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", ABI_ARRAY);
public static final String FUNC_STORE = "store";
protected TestContract(String contractAddress, Client client, CryptoKeyPair credential) {
super(getBinary(client.getCryptoSuite()), contractAddress, client, credential);
}
public static String getBinary(CryptoSuite cryptoSuite) {
return (cryptoSuite.getCryptoTypeConfig() == CryptoType.ECDSA_TYPE ? BINARY : SM_BINARY);
}
public TransactionReceipt store(TestStruct test) {
final Function function = new Function(
FUNC_STORE,
Arrays.<Type>asList(test),
Collections.<TypeReference<?>>emptyList());
return executeTransaction(function);
}
public byte[] store(TestStruct test, TransactionCallback callback) {
final Function function = new Function(
FUNC_STORE,
Arrays.<Type>asList(test),
Collections.<TypeReference<?>>emptyList());
return asyncExecuteTransaction(function, callback);
}
public String getSignedTransactionForStore(TestStruct test) {
final Function function = new Function(
FUNC_STORE,
Arrays.<Type>asList(test),
Collections.<TypeReference<?>>emptyList());
return createSignedTransaction(function);
}
public Tuple1<TestStruct> getStoreInput(TransactionReceipt transactionReceipt) {
String data = transactionReceipt.getInput().substring(10);
final Function function = new Function(FUNC_STORE,
Arrays.<Type>asList(),
Arrays.<TypeReference<?>>asList(new TypeReference<TestStruct>() {}));
List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
return new Tuple1<TestStruct>(
(TestStruct) results.get(0)
);
}
public Tuple1<BigInteger> getStoreOutput(TransactionReceipt transactionReceipt) {
String data = transactionReceipt.getOutput();
final Function function = new Function(FUNC_STORE,
Arrays.<Type>asList(),
Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
return new Tuple1<BigInteger>(
(BigInteger) results.get(0).getValue()
);
}
public static TestContract load(String contractAddress, Client client, CryptoKeyPair credential) {
return new TestContract(contractAddress, client, credential);
}
public static TestContract deploy(Client client, CryptoKeyPair credential) throws ContractException {
return deploy(TestContract.class, client, credential, getBinary(client.getCryptoSuite()), "");
}
public static class TestStruct extends DynamicStruct {
public String text;
public List<String> values;
public TestStruct(Utf8String text, DynamicArray<Utf8String> values) {
super(text,values);
this.text = text.getValue();
this.values = values.getNativeValue();
}
public TestStruct(String text, List<String> values) {
super(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(text),new org.fisco.bcos.sdk.abi.datatypes.DynamicArray<org.fisco.bcos.sdk.abi.datatypes.Utf8String>(values.stream().map(obj -> new org.fisco.bcos.sdk.abi.datatypes.Utf8String(obj)).collect(java.util.stream.Collectors.toList())));
this.text = text;
this.values = values;
}
}
}
java UT的方法:
@Test
public void store() {
String hexPrivateKey = ""; //替换为密钥
Client client = clientService.newClient(fiscoConfig.getGroupId(), hexPrivateKey);
TestContract contract = TestContract.load(
"0x....." //替换为智能合约的地址
, client
, client.getCryptoSuite().getCryptoKeyPair()
);
TestStruct struct = new TestStruct(new Utf8String(""), DynamicArray.empty("string[]"));
contract.store(struct);
System.out.println("--------------------");
System.out.println(struct.getTypeAsString());
System.out.println("--------------------");
}
报错的堆栈信息如下:
java.lang.NullPointerException
at java.base/java.lang.Class.isAssignableFrom(Native Method)
at org.fisco.bcos.sdk.abi.datatypes.DynamicArray.getTypeAsString([DynamicArray.java:59](vscode-file://vscode-app/d:/Programs/Microsoft%20VS%20Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
at org.fisco.bcos.sdk.abi.datatypes.DynamicStruct.getTypeAsString([DynamicStruct.java:43](vscode-file://vscode-app/d:/Programs/Microsoft%20VS%20Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
at java.base/java.util.stream.ReferencePipeline$3$1.accept([ReferencePipeline.java:197](vscode-file://vscode-app/d:/Programs/Microsoft%20VS%20Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining([Spliterators.java:1024](vscode-file://vscode-app/d:/Programs/Microsoft%20VS%20Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
at java.base/java.util.stream.AbstractPipeline.copyInto([AbstractPipeline.java:509](vscode-file://vscode-app/d:/Programs/Microsoft%20VS%20Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto([AbstractPipeline.java:499](vscode-file://vscode-app/d:/Programs/Microsoft%20VS%20Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential([ReduceOps.java:921](vscode-file://vscode-app/d:/Programs/Microsoft%20VS%20Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
at java.base/java.util.stream.AbstractPipeline.evaluate([AbstractPipeline.java:234](vscode-file://vscode-app/d:/Programs/Microsoft%20VS%20Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
at java.base/java.util.stream.ReferencePipeline.collect([ReferencePipeline.java:682](vscode-file://vscode-app/d:/Programs/Microsoft%20VS%20Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
at org.fisco.bcos.sdk.abi.FunctionEncoder.buildMethodSignature([FunctionEncoder.java:67](vscode-file://vscode-app/d:/Programs/Microsoft%20VS%20Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
at org.fisco.bcos.sdk.abi.FunctionEncoder.encode([FunctionEncoder.java:27](vscode-file://vscode-app/d:/Programs/Microsoft%20VS%20Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
at org.fisco.bcos.sdk.contract.Contract.executeTransaction([Contract.java:288](vscode-file://vscode-app/d:/Programs/Microsoft%20VS%20Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
at fx.blockchain.contracts.TestContract.store([TestContract.java:54](vscode-file://vscode-app/d:/Programs/Microsoft%20VS%20Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
at fx.blockchain.contract.TestContractTest.store([TestContractTest.java:41](vscode-file://vscode-app/d:/Programs/Microsoft%20VS%20Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
at java.base/java.util.ArrayList.forEach([ArrayList.java:1596](vscode-file://vscode-app/d:/Programs/Microsoft%20VS%20Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
at java.base/java.util.ArrayList.forEach([ArrayList.java:1596](vscode-file://vscode-app/d:/Programs/Microsoft%20VS%20Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
非常感谢提供样例,我们会在下个版本尽快修复这个问题。