zoukankan      html  css  js  c++  java
  • Hyperledger Fabric——balance transfer(四)安装和实例化chaincode

    详细解析blance transfer示例的安装(install)和实例化(Instantiate)链码(chaincode)的过程。安装chaincode会根据本地的链码文件生成chaincode镜像,实例化chaincode则会启动该镜像,使链码在docker容器中运行。

    安装chaincode

    1.首先看app.js中的路由函数

    app.post('/chaincodes', async function(req, res) {
        var peers = req.body.peers;                             // 目标节点列表
        var chaincodeName = req.body.chaincodeName;             // chaincode名称
        var chaincodePath = req.body.chaincodePath;             // chaincode路径
        var chaincodeVersion = req.body.chaincodeVersion;       // chaincode版本
        var chaincodeType = req.body.chaincodeType;             // chaincode类型    Eg. golong
        /*
           省略了参数校验
        */
        // 安装chaincode
        let message = await install.installChaincode(peers, chaincodeName, chaincodePath, chaincodeVersion, chaincodeType, req.username, req.orgname)
        res.send(message);
    });

    2.再来看install-chaincode.js

    var installChaincode = async function(peers, chaincodeName, chaincodePath,
        chaincodeVersion, chaincodeType, username, org_name) {
        logger.debug('
    
    ============ Install chaincode on organizations ============
    ');
        helper.setupChaincodeDeploy();
        let error_message = null;
        try {
            // 创建该组织对应的client,该client中包含用户信息_userContext
            var client = await helper.getClientForOrg(org_name, username);
            // admin transactionID
            tx_id = client.newTransactionID(true);
            // 打包请求参数 
            var request = {
                targets: peers,
                chaincodePath: chaincodePath,
                chaincodeId: chaincodeName,
                chaincodeVersion: chaincodeVersion,
                chaincodeType: chaincodeType
            };
            // 调用SDK中的installChaincode()方法,根据request生成交易提案
            // 然后通过sendPeersProposal()方法提交给所有背书节点,该方法获得提案响应的集合
            // 最终返回 生成的交易提案 和 收集到的提案响应集合(内含背书签名)
            // 之后将两者会作为交易的内容发送给orderer服务
            let results = await client.installChaincode(request);
            var proposalResponses = results[0];         // 背书响应集合 
            var proposal = results[1];                  // 交易提案
    
            // 检查提案响应是否均存在且合格
            var all_good = true;
            for (var i in proposalResponses) {
                let one_good = false;
                if (proposalResponses && proposalResponses[i].response &&
                    proposalResponses[i].response.status === 200) {
                    one_good = true;
                    logger.info('install proposal was good');
                } else {
                    logger.error('install proposal was bad %j',proposalResponses.toJSON());
                }
                all_good = all_good & one_good;
            }
            if (all_good) {
                logger.info('Successfully sent install Proposal and received ProposalResponse');
            } else {
                error_message = 'Failed to send install Proposal or receive valid response. Response null or status is not 200'
                logger.error(error_message);
            }
        } 

    这一步完成后会生成chiancode镜像,内部包含chaincode源码go文件编译生成的可执行文件。

    实例化chaincode

    1.首先看app.js中的路由函数

    app.post('/channels/:channelName/chaincodes', async function(req, res) {
        var peers = req.body.peers;
        var chaincodeName = req.body.chaincodeName;
        var chaincodeVersion = req.body.chaincodeVersion;
        var channelName = req.params.channelName;
        var chaincodeType = req.body.chaincodeType;
        var fcn = req.body.fcn;
        var args = req.body.args;
        // 实例化chaincode
        let message = await instantiate.instantiateChaincode(peers, channelName, chaincodeName, chaincodeVersion, chaincodeType, fcn, args, req.username, req.orgname);
        res.send(message);
    });

    2.再来看instantiate-chaincode.js

    var instantiateChaincode = async function(peers, channelName, chaincodeName, chaincodeVersion, functionName, chaincodeType, args, username, org_name) {
        var error_message = null;
    
        try {
            // 创建该组织名对应的client,并为其分配了用户对象
            var client = await helper.getClientForOrg(org_name, username);
            // 获取channel对象
            var channel = client.getChannel(channelName);
            // 获取基于msp管理员的TransactionID,这表示实例化链码的交易提案
            // 需要用到组织管理员的身份进行签名
            var tx_id = client.newTransactionID(true); 
    
            // 这个transaction ID 会用来登记(register)事件监听
            var deployId = tx_id.getTransactionID();
    
            // 构造请求结构
            var request = {
                targets : peers,
                chaincodeId: chaincodeName,
                chaincodeType: chaincodeType,
                chaincodeVersion: chaincodeVersion,
                args: args,
                txId: tx_id
            };
    
            if (functionName)
                request.fcn = functionName;
    
            let results = await channel.sendInstantiateProposal(request, 60000); 
    
            // 返回的 交易提案 和 提案相应
            var proposalResponses = results[0];
            var proposal = results[1];
    
            // 检查提案响应中是否包含正确的背书签名
            var all_good = true;
            for (var i in proposalResponses) {
                let one_good = false;
                if (proposalResponses && proposalResponses[i].response &&
                    proposalResponses[i].response.status === 200) {
                    one_good = true;
                    logger.info('instantiate proposal was good');
                } else {
                    logger.error('instantiate proposal was bad');
                }
                all_good = all_good & one_good;
            }
                // 等待channel的eventHub通知我们交易被peer节点提交
                var promises = [];
                let event_hubs = channel.getChannelEventHubsForOrg();
                #event_hubs.forEach((eh) => {
                    #let instantiateEventPromise = new Promise((resolve, reject) => {
                        #let event_timeout = setTimeout(() => {
                            let message = 'REQUEST_TIMEOUT:' + eh.getPeerAddr();
                            logger.error(message);
                            eh.disconnect();
                        }, 60000);
                        // 注册交易事件监听
                        #eh.registerTxEvent(deployId, (tx, code, block_num) => {
                            clearTimeout(event_timeout);
                        }, (err) => {
                            clearTimeout(event_timeout);
                            logger.error(err);
                            reject(err);
                        },          
                            {unregister: true, disconnect: true}
                        );
                        eh.connect();
                    });
                    promises.push(instantiateEventPromise);
                });
                // 构造交易请求,包含交易id、交易提案、提案响应
                var orderer_request = {
                    txId: tx_id,            // 组织admin进行签名的交易id
                    proposalResponses: proposalResponses,
                    proposal: proposal
                };
                // 发送交易请求到Orderer节点,内部通过调用orderer.sendBroadcast(envelope)实现
                var sendPromise = channel.sendTransaction(orderer_request);
    
            } else {
                error_message = util.format('Failed to send Proposal and receive all good ProposalResponse');
                logger.debug(error_message);
            }
        } catch (error) {
            logger.error('Failed to send instantiate due to error: ' + error.stack ? error.stack : error);
            error_message = error.toString();
        }
    };

    测试

    • 安装chaincode

      curl -s -X POST 
        http://localhost:4000/chaincodes 
        -H "authorization: Bearer <Token>" 
        -H "content-type: application/json" 
        -d '{
          "peers": ["peer0.org1.example.com","peer1.org1.example.com"],
          "chaincodeName":"mycc",
          "chaincodePath":"github.com/example_cc/go",
          "chaincodeType": "golang",
          "chaincodeVersion":"v0"
      }'

      结果:

      {"success":true,"message":"Successfully install chaincode"}
    • 实例化chaincode

      curl -s -X POST 
        http://localhost:4000/channels/mychannel/chaincodes 
        -H "authorization: Bearer <token>" 
        -H "content-type: application/json" 
        -d '{
          "peers": ["peer0.org1.example.com","peer1.org1.example.com"],
          "chaincodeName":"mycc",
          "chaincodeVersion":"v0",
          "chaincodeType": "golang",
          "args":["a","100","b","200"]
      }'

      结果:

      {"success":true,"message":"Successfully instantiate chaingcode in organization Org1 to the channel 'mychannel'"}
  • 相关阅读:
    【opencv.js】将图片转换为灰度图
    【快速创建】第一个 opencv.js 项目
    【踩坑无数】Anaconda(2020.02) + Tensorflow2.1 + python3.7 (CPU版本)的安装
    Thread的join方法
    常用语句
    获取当前托管线程的唯一标识符
    修改文件或文件夹的权限,为指定用户、用户组添加完全控制权限(转载)
    C#中Monitor和Lock以及区别(转载)
    LIBRA查询
    Select()和SelectMany()的区别
  • 原文地址:https://www.cnblogs.com/zhayujie/p/12941554.html
Copyright © 2011-2022 走看看