SDK查询机制
async indexPage ( ctx ) { //异步函数indexPage
const title = 'admin page' //设置一个title的常量
let result = '' //设置一个块变量result
const body = ctx.request.body; //获取传入请求的内容
console.log(`request`,body.k0) //打印出请求的内容k0
var fabric_client = new Fabric_Client(); //新建一个客户端实例
var key = "name" //变量key,初值name
// setup the fabric network 启动fabric网络
var channel = fabric_client.newChannel('mychannel'); //发送消息到order来构建一个新的channel,命名为mychannel,返回一个空对象
var peer = fabric_client.newPeer('grpc://localhost:7051'); //创建一个新的节点
channel.addPeer(peer); //将节点添加到通道
//设置成员变量为空
var member_user = null;
var store_path = path.join(os.homedir(), '.hfc-key-store'); //设置文件存储路径
console.log('Store path:'+store_path); //打印文件存储路径
var tx_id = null; //设置交易id为空
// create the key value store as defined in the fabric-client/config/default.json 'key-value-store' setting
//设置加密材料的默认存储路径
result = await Fabric_Client.newDefaultKeyValueStore({ path: store_path
}).then((state_store) => {
// assign the store to the fabric client //客户端设置存储路径
fabric_client.setStateStore(state_store);
var crypto_suite = Fabric_Client.newCryptoSuite(); //设置加密模块
// use the same location for the state store (where the users' certificate are kept)
// and the crypto store (where the users' keys are kept) //客户端将密匙调用设置为该路径下
var crypto_store = Fabric_Client.newCryptoKeyStore({path: store_path});
crypto_suite.setCryptoKeyStore(crypto_store); //加密模块将生成密匙路径设置为同样路径
fabric_client.setCryptoSuite(crypto_suite);
//检查用户1是否已经注册,这个用户信息从持久存储文件中获得,用户将签名所有的请求
// get the enrolled user from persistence, this user will sign all requests
return fabric_client.getUserContext('user1', true);
}).then((user_from_store) => { //如果用户已经注册,则将用户设置为成员用户
if (user_from_store && user_from_store.isEnrolled()) {
console.log('Successfully loaded user1 from persistence');
member_user = user_from_store;
} else { //否则再次注册
throw new Error('Failed to get user1.... run registerUser.js');
}
//构建查询请求对象,四个参数,包括链码名称、交易id,调用函数、参数。
// queryTuna - requires 1 argument, ex: args: ['4'],
const request = {
chaincodeId: 'dateContract10',
txId: tx_id,
fcn: 'query',
args: [body.k0,body.k1]
};
//将请求发送到指定对等节点,并由其对应的chaincode返回结果,所有的调用发送到invoke方法,同时在chaincode实现该方法,用字节数组返回结果。
// send the query proposal to the peer
return channel.queryByChaincode(request);
}).then((query_responses) => { //得到查询结果,打印日志
console.log("Query has completed, checking results");
//如果使用多个对等点作为目标,query_responses可以具有多个结果
// query_responses could have more than one results if there multiple peers were used as targets
//如果查询结果为一个,则
if (query_responses && query_responses.length == 1) {
if (query_responses[0] instanceof Error) { //如果查询结果继承了错误,则打印错误日志,结果为未获得数据
console.error("error from query = ", query_responses[0]);
result = "Could not locate tuna"
} else { //否则打印出成功响应,且以string形式返回返回结果
console.log("Response is ", query_responses[0].toString());
return query_responses[0].toString()
}
} else { //没有从查询返回有效响应
console.log("No payloads were returned from query");
result = "Could not locate tuna"
}
}).catch((err) => { //打印出错误,结果未查询失败
console.error('Failed to query successfully :: ' + err);
result = 'Failed to query successfully :: ' + err
}); //使用查询结果result和title,渲染query模板。
await ctx.render('query', {
title,result
})
},
流程:
与前端交互,获取前端输入内容,新建一个客户端实例,初始化网络,设置通道,节点,文件路径,加密材料存储路径,交易ID,构造请求参数,然后发送到背书节点,链码模拟执行,返回背书结果(字节数组),然后使用render渲染模板,实现前端更新。