SDK查询机制
async indexPage ( ctx ) { //异步函数indexPageconst title = 'admin page' //设置一个title的常量let result = '' //设置一个块变量resultconst 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 requestsreturn 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 peerreturn 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渲染模板,实现前端更新。