根据TXID查询数据
本文是在fabric-sdk-java 成功添加区块并自定义查询的基础上, 实现通过txid查询数据; 由于fabric-sdk-java 的示例网络上比较多, 我是根据 github上的demo 开发的,只实现了添加数据,和查询功能.
demo fabric-sdk-java-demo的下载地址:
github 下载地址
码云 下载地址
以下的解析只是符合我自己的需求,下面是官方源码的位置截图,源码过多我就不贴了
fabric-sdk-java的源码下载地址:
下载地址(github)
下载地址(码云)
解析时需要用的常量和方法
static String printableString(String string) {
if (StringUtils.isBlank(string)) {
return null;
}
return string.replaceAll("[^\\p{Print}]", "?");
}
Map<String, Long> expectedMoveRCMap = new HashMap<>();
private static final byte[] EXPECTED_EVENT_DATA = "!".getBytes(UTF_8);
private static final String EXPECTED_EVENT_NAME = "event";
private static final Map<String, String> TX_EXPECTED;
static {
TX_EXPECTED = new HashMap<>();
TX_EXPECTED.put("readset1", "Missing readset for channel bar block 1");
TX_EXPECTED.put("writeset1", "Missing writeset for channel bar block 1");
}
正式解析区块之前, 要说明一下;
channel 需要自己获取,由于我进行了封装,所以不方便展示,另外 代码中使用的 fabricconfig是配置文件,获取的是 channel名称和 chaincode链码名称
@Override
public ResultJson<List<JSONObject>> queryFromBlockByTxId(String txid) throws Exception {
// 获取通道配置
if (this.channel == null) {
getChannel();
}
/**
* 通过txid 获取区块信息
*/
BlockInfo blockInfo = this.channel.queryBlockByTransactionID(txid);
if (blockInfo == null) {
return new ResultJson<>(ResultCode.TXID_NOT_EXIST);
}
long blockNumber = blockInfo.getBlockNumber();
log.info("当前区块编号:{} 数据hash ={}", blockNumber, Hex.encodeHexString(blockInfo.getDataHash()));
log.info("当前区块编号:{} 前块hash = {}", blockNumber, Hex.encodeHexString(blockInfo.getPreviousHash()));
// 如果一个通道内有多个链码,就不能通过索引获取了 --- 个人分析未论证
// BlockInfo.EnvelopeInfo tmp = blockInfo.getEnvelopeInfo(0);
// String channelId1 = tmp.getChannelId();
// System.out.println(channelId1);
Iterable<BlockInfo.EnvelopeInfo> envelopeInfos = blockInfo.getEnvelopeInfos();
List<JSONObject> list = new ArrayList<>();
for (BlockInfo.EnvelopeInfo envelopeInfo :envelopeInfos) {
// 从区块中获取channelId = mychannel
final String channelId = envelopeInfo.getChannelId();
log.info(" 通道 id: {}", channelId);
/**
* 判断不是指定通道名称,则跳过
*/
if (!channelId.equals(fabricConfig.getChannelName())) {
log.error("通道名称不正确跳过,配置通道id= {},获取的通道id = {}", fabricConfig.getChannelName(), channelId);
continue;
}
/**
* 获取落块时间
*/
String time = TimeUtil.parseToyyyyMMddmmssSSS(envelopeInfo.getTimestamp());
log.info(" 时间: {}", time);
// 需要定位是组织内的哪个节点
log.info(" 提交事务的身份: {}", envelopeInfo.getCreator().getMspid());
if (envelopeInfo.getType() != TRANSACTION_ENVELOPE) {
log.error("envelopeInfo的type值不正确,常量 ={} 解析 ={}", TRANSACTION_ENVELOPE, envelopeInfo.getType());
continue;
}
// 强转类型
BlockInfo.TransactionEnvelopeInfo transactionEnvelopeInfo = (BlockInfo.TransactionEnvelopeInfo) envelopeInfo;
log.info(" 是否经过校验 {}", transactionEnvelopeInfo.isValid());
// 获取操作事务的信息
for (BlockInfo.TransactionEnvelopeInfo.TransactionActionInfo transactionActionInfo : transactionEnvelopeInfo.getTransactionActionInfos()) {
// 链码名称
String chaincodeIDName = transactionActionInfo.getChaincodeIDName();
// 链码版本
String chaincodeIDVersion = transactionActionInfo.getChaincodeIDVersion();
log.info(" proposal chaincodeIDName:{}, chaincodeIDVersion: {}", chaincodeIDName, chaincodeIDVersion);
// 操作事务的读写集
TxReadWriteSetInfo rwsetInfo = transactionActionInfo.getTxReadWriteSet();
if (null != rwsetInfo) {
//我只要了写集合的数据
for (TxReadWriteSetInfo.NsRwsetInfo nsRwsetInfo : rwsetInfo.getNsRwsetInfos()) {
// 含有默认链码 _lifecycle 和 自定义链码 mycc
String namespace = nsRwsetInfo.getNamespace();
// 只要符合要求的链码的 mycc
if (!namespace.equals(fabricConfig.getChainCodeName())) {
log.error("链码名称不正确 跳过 ,namespace ={} fabricConfig.getChainCodeName() ={}", namespace, fabricConfig.getChainCodeName());
continue;
}
KvRwset.KVRWSet rws = nsRwsetInfo.getRwset();
for (KvRwset.KVWrite writeList : rws.getWritesList()) {
String valAsString = printableString(new String(writeList.getValue().toByteArray(), UTF_8));
log.info("Namespace {} key {} has value '{}' ", namespace, writeList.getKey(), valAsString);
if (StringUtils.isNotBlank(valAsString)) {
list.add(JSON.parseObject(valAsString, JSONObject.class));
}
}
}
}
}
}
return new ResultJson<List<JSONObject>>(ResultCode.OK, list);
}