链上数据查询请求解析不到原数据
以上是solidity合约源码
上链合约方法是addOfflineData和setOfflineData
以下是我自己的java代码请求上链,是可以成功上链数据的
HttpUtil httpUtil = new HttpUtil();
ResponseEntity<String> response = httpUtil.sendPostRequestFileAndGetResponse(environment.getProperty("ipfs_path"), basePath + fileName);
System.out.println("ipfs上传数据返回的值是:"+response);
if (response.getStatusCode().is2xxSuccessful()){
try {
String body = response.getBody();
JSONObject resultJson = JSONObject.parseObject(body);
//ipfs中文件存储的hash
String fileHash = (String) resultJson.get("Hash");
Map<String, byte[]> firstParams = new HashMap<>();
//构建参数集合
List<Type> firstOfflineData = new ArrayList<>();
firstOfflineData.add(new Utf8String(IdGenerate.generateStrID()));
firstOfflineData.add(new Utf8String(orgName));
firstOfflineData.add(new Utf8String(sysUser.getUserId().toString()));
firstOfflineData.add(new Utf8String(sysUser.getUserName()));
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String nowDate = format.format(date);
firstOfflineData.add(new Utf8String(nowDate));
firstOfflineData.add(new Utf8String("0"));
//调用第一个合约
ContractRequets contractRequets = new ContractRequets(chainClientConfig);
ResultOuterClass.TxResponse responseInfo = contractRequets.requestContract(sysUser, firstParams, firstOfflineData,CertConstants.PUSH_DATA_CHAIN_CONTRACT_NAME,CertConstants.PUSTH_DATA_CHAIN_METHOD_NAME_ADD);
//上个合约地址
System.out.println("第一次请求合约执行后返回值是:"+ Numeric.toBigInt(responseInfo.getContractResult().getResult().toByteArray()));
//调用第二个合约
Map<String, byte[]> secondParams = new HashMap<>();
List<Type> secondOfflineData = new ArrayList<>();
secondOfflineData.add(new Utf8String(dbName));
secondOfflineData.add(new Utf8String(tableName));
secondOfflineData.add(new Utf8String(createSql));
secondOfflineData.add(new Utf8String(metadata.get(1)));
secondOfflineData.add(new Utf8String("1"));
secondOfflineData.add(new Utf8String(fileHash));
BigInteger amount = Numeric.toBigInt(responseInfo.getContractResult().getResult().toByteArray());
secondOfflineData.add(new Uint256(amount));
ContractRequets secondContractRequets = new ContractRequets(chainClientConfig);
ResultOuterClass.TxResponse seconRresponseInfo = secondContractRequets.requestContract(sysUser, secondParams, secondOfflineData,CertConstants.PUSH_DATA_CHAIN_CONTRACT_NAME,CertConstants.PUSTH_DATA_CHAIN_METHOD_NAME_SET);
//上个合约地址
System.out.println("第二次请求合约执行后返回值是:"+ Numeric.toBigInt(seconRresponseInfo.getContractResult().getResult().toByteArray()));
TableSyncRecord sucSyncRecord = new TableSyncRecord();
sucSyncRecord.setId(syncID);
sucSyncRecord.setSyncStatus(1);//同步成功
tableSyncRecordMapper.updateSynStatus(sucSyncRecord);
} catch (Exception exception) {
exception.printStackTrace();
TableSyncRecord failSyncRecord = new TableSyncRecord();
failSyncRecord.setId(syncID);
failSyncRecord.setSyncStatus(2);//同步出错
failSyncRecord.setFailedReason(exception.getMessage());
tableSyncRecordMapper.updateSynStatus(failSyncRecord);
}
}else{
log.error("ipfs上传文件错误");
}
链上请求数据的合约方法是getOnlineData
public List<TableRecordDownloadConfig> findByConfigID(String configID) {
//获取人
Integer userID = SecurityUtils.getCurrentLoginUser().getSysUser().getUserId();
//根据人id获取证书
String signCrtPath= CertConstants.USER_ADMIN_CERT_PATH+userID+"/"+userID+".sign.crt";
String signKeyPath= CertConstants.USER_ADMIN_CERT_PATH+userID+"/"+userID+".sign.key";
String tlsCrtPath= CertConstants.USER_ADMIN_CERT_PATH+userID+"/"+userID+".tls.crt";
String tlsKeyPath= CertConstants.USER_ADMIN_CERT_PATH+userID+"/"+userID+".tls.key";
try {
SysUser sysUser = new SysUser();
sysUser.setSignCrtPath(signCrtPath);
sysUser.setSignKeyPath(signKeyPath);
sysUser.setTlsCrtPath(tlsCrtPath);
sysUser.setTlsKeyPath(tlsKeyPath);
Map<String, byte[]> params = new HashMap<>();
//调用合约
ContractRequets contractRequets = new ContractRequets(chainClientConfig);
ResultOuterClass.TxResponse responseInfo = contractRequets.requestContract(sysUser, params, null,CertConstants.PUSH_DATA_CHAIN_CONTRACT_NAME,"getAllOfflineData");
String result = responseInfo.getContractResult().getResult().toStringUtf8();
log.info("请求合约执行后返回值是:"+ responseInfo);
//加入缓存
cacheUtil.addToCache(userID.toString(),result);
//获取同步的数据状态
ChainClient chainClient = chainClientConfig.initWithNoConfig(sysUser.getTlsKeyPath(), sysUser.getTlsCrtPath(), sysUser.getSignKeyPath(), sysUser.getSignCrtPath());
//查询本次交易结果
log.info("交易id是:"+ responseInfo.getTxId());
//根据交易id查询交易
ChainmakerTransaction.TransactionInfo tx = chainClient.getTxByTxId(responseInfo.getTxId(), 1000);
log.info("本次交易结果是:"+ tx);
//解析参数
Request.KeyValuePair keyValuePair = tx.getTransaction().getPayload().getParameters(0);
log.info("keyValuePair:"+ keyValuePair);
String v = keyValuePair.getValue().toStringUtf8().substring(0,10);
log.info("v的结果是:"+v);
Function f = new Function("getAllOfflineData",
Collections.emptyList(),
Arrays.asList(
new TypeReference<Utf8String>() {},
new TypeReference<Utf8String>() {},
new TypeReference<Utf8String>() {},
new TypeReference<Utf8String>() {},
new TypeReference<Utf8String>() {},
new TypeReference<Utf8String>() {}
)
);
String formatted = "0x" + String.format("%64s", v.substring(2)).replace(' ', '0');
System.out.println(formatted);
List<Type> typeList = FunctionReturnDecoder.decode(formatted, f.getOutputParameters());
log.info("解析的参数是::"+ typeList);
} catch (SdkException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
其中ChainClientConfig代码如下
@Component
public class ChainClientConfig extends org.chainmaker.sdk.config.ChainClientConfig {
private static final String ORG_CERT_PREFIX="cert/";
private static final int MAX_MESSAGE_SIZE = 16;
@Value("${tls_host_name}")
private String tlsHostName;
@Value("${node_grpc_url}")
private String nodeGrpcUrl;
@Value("${connect_count}")
private int connectCount;
@Value("${chain_id}")
private String chainId;
@Autowired
private Environment environment;
@Autowired
private ResourceLoader resourceLoader;
public ChainClient initWithNoConfig(String clientTlsKeyPath, String clientTlsCertPath, String signKeyPath, String signCertPath) throws SdkException, IOException {
ChainClient chainClient;
ChainManager chainManager;
//用yml文件中获取organization,经过判断后从resource文件夹中获取ca证书路径
String caPath=ORG_CERT_PREFIX + environment.getProperty("organization") + "/ca.crt";
byte[][] tlsCaCerts = loadCertificate(caPath);
SdkConfig sdkConfig = new SdkConfig();
ChainClientConfig chainClientConfig = new ChainClientConfig();
sdkConfig.setChainClient(chainClientConfig);
RpcClientConfig rpcClientConfig = new RpcClientConfig();
rpcClientConfig.setMaxReceiveMessageSize(MAX_MESSAGE_SIZE);
NodeConfig nodeConfig = new NodeConfig();
nodeConfig.setTrustRootBytes(tlsCaCerts);
System.out.println("tlsHostName:"+tlsHostName);
nodeConfig.setTlsHostName(tlsHostName);
nodeConfig.setEnableTls(true);
System.out.println("nodeGrpcUrl:"+nodeGrpcUrl);
nodeConfig.setNodeAddr(nodeGrpcUrl);
System.out.println("connectCount:"+connectCount);
nodeConfig.setConnCnt(connectCount);
NodeConfig[] nodeConfigs = new NodeConfig[]{nodeConfig};
chainManager = ChainManager.getInstance();
chainClient = chainManager.getChainClient(chainId);
//客户端用户配置
chainClientConfig.setOrgId(environment.getProperty("organization"));
chainClientConfig.setChainId(chainId);
chainClientConfig.setUserKeyBytes(FileUtils.getFileBytes(clientTlsKeyPath));
chainClientConfig.setUserCrtBytes(FileUtils.getFileBytes(clientTlsCertPath));
chainClientConfig.setUserSignKeyBytes(FileUtils.getFileBytes(signKeyPath));
chainClientConfig.setUserSignCrtBytes(FileUtils.getFileBytes(signCertPath));
chainClientConfig.setRpcClient(rpcClientConfig);
chainClientConfig.setNodes(nodeConfigs);
//客户端管理配置
if (chainClient == null) {
chainClient = chainManager.createChainClient(sdkConfig);
}
return chainClient;
}
public byte[][] loadCertificate(String certPath) throws IOException {
Resource resource = resourceLoader.getResource("classpath:"+certPath);
try (InputStream inputStream = resource.getInputStream()) {
byte[] certificateBytes = IOUtils.toByteArray(inputStream);
return new byte[][] { certificateBytes };
}
}
}
其中ContractRequets代码如下
public class ContractRequets {
private ChainClientConfig chainClientConfig;
public ContractRequets(ChainClientConfig chainClientConfig) {
this.chainClientConfig = chainClientConfig;
}
public ResultOuterClass.TxResponse requestContract(SysUser sysUser, Map<String, byte[]> firstParams, List<Type> firstOfflineData, String contractName, String methodName) throws SdkException, IOException {
Function function = new Function(methodName, firstOfflineData==null?Collections.emptyList():firstOfflineData, Collections.emptyList());
String methodDataStr = FunctionEncoder.encode(function);
String method = methodDataStr.substring(0, 10);
firstParams.put(CertConstants.CONTRACT_ARGS_EVM_PARAM, methodDataStr.getBytes());
//创建链客户端
ChainClient chainClient = chainClientConfig.initWithNoConfig(sysUser.getTlsKeyPath(), sysUser.getTlsCrtPath(), sysUser.getSignKeyPath(), sysUser.getSignCrtPath());
ResultOuterClass.TxResponse responseInfo = chainClient.invokeContract(contractName,
method, null, firstParams, 10000,10000);
return responseInfo;
}
}
使用FunctionReturnDecoder.decode(formatted, f.getOutputParameters());解析结果时候,如果直接拿formatted=0x221d1464,如果将 0x221d1464补全64位的话,报错就是上面的错误日志
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information