详细解析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('\n\n============ Install chaincode on organizations ============\n');
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'"}

Hyperledger Fabric——balance transfer(四)安装和实例化chaincode的更多相关文章

  1. Hyperledger Fabric——balance transfer(一)启动示例

    Blacne transfer是Hyperledger fabric Node SDK的一个示例应用,主要使用了SDK中fabric-client 和 fabric-ca-client 模块中的API ...

  2. Hyperledger Fabric——balance transfer(六)查询

    balance transfer 提供了很多查询接口,包括链码查询,根据区块号查询区块数据,根据交易ID查询交易信息,查询链上的区块数,查询已安装或已实例化的链码,查询通道. 源码解析 1.调用链码查 ...

  3. Hyperledger Fabric——balance transfer(五)执行交易

    链码安装和实例化之后就可以调用chaincode执行交易,下面分析简单的账户转账操作是如何完成的. 源码分析 1.首先看app.js的路由函数 app.post('/channels/:channel ...

  4. Hyperledger Fabric——balance transfer(三)创建和加入Channel

    详细解析blance transfer示例的创建通道(Channel)和加入节点到通道的过程. 创建Channel 1.首先看app.js的路由函数 var createChannel = requi ...

  5. Hyperledger Fabric——balance transfer(二)注册用户

    详细分析blance transfer示例的用户注册(register)与登录(enroll)功能. 源码分析 1.首先分析项目根目录的app.js文件中关于用户注册和登录的路由函数.注意这里的tok ...

  6. Hyperledger Fabric v1.1.0安装记录(国内源版)

    1. 安装虚拟机     虚拟机软件采用:VirtualBox     操作系统选择:Ubuntu 14.04     内存:4G     CPU:2核     硬盘:20G     2.(可选)更改 ...

  7. Hyperledger Fabric (1.0)环境部署 chaincode【转】

    三.测试Fabric 其实我们在前面运行./network_setup.sh up的时候系统已经运行了一个Example02的ChainCode测试,部署上去的ChainCodeName是mycc,所 ...

  8. Ubuntu16.04下安装Hyperledger Fabric 1.0.0

    系统环境 * Ubuntu: 16.04 * Go: 1.9.2 * NodeJS: v6.12.0 * Docker: 17.09.0-ce * HyperLedger Fabric: 1.0.0 ...

  9. Hyperledger Fabric Chaincode for Operators——实操智能合约

    什么是Chaincode(智能合约)? chaincode是一个程序,它是使用Go语言编写的,最终在Java等其他编程语言中实现了指定的接口.chaincode运行在一个被背书peer进程独立出来的安 ...

随机推荐

  1. 疫情之下微软收入猛增15%!远程办公产品Teams日活达7500万

    当地时间 2020 年 4 月 29 日,微软公布了截止 2020 年 3 月 31 日的 2020 财年第三季度财报. 这是微软首次在财报中显示新冠疫情的影响——疫情之下,远程办公.远程教育和游戏场 ...

  2. 本周ASP.NET英文技术文章推荐[02/03 - 02/16]:MVC、Visual Studio 2008、安全性、性能、LINQ to JavaScript、jQuery...

    摘要 继续坚持,继续推荐.本期共有9篇文章: 最新的ASP.NET MVC框架开发计划 Visual Studio 2008 Web开发相关的Hotfix发布 ASP.NET安全性教程系列 ASP.N ...

  3. L3.二.return

    # 函数的返回值 def get_max(a,b,c): max_num=a if b > max_num: max_num = b if c > max_num: max_num = c ...

  4. 使用mysqldump自动备份数据库脚本

    每天利用计划任务在凌晨1点自动执行,备份zabbix的数据库至本地的/backup/mysql_backup目录 #!/bin/sh DUMP=/usr/bin/mysqldump OUT_DIR=/ ...

  5. Ubuntu上安装配置Java环境

    参考文献:在Ubuntu 14.04中安装JDK 方法一: @ 安装 1. 添加PPA repository系统 PPA repository介绍 $sudo add-apt-repository p ...

  6. keep-alive的深入理解与使用(配合router-view缓存整个路由页面)

    原文链接: 点我 在搭建 vue 项目时,有某些组件没必要多次渲染,所以需要将组件在内存中进行‘持久化’,此时 <keep-alive> 便可以派上用场了. <keep-alive& ...

  7. C语言编程入门题目--No.8

    题目:输出9*9口诀. 1.程序分析:分行与列考虑,共9行9列,i控制行,j控制列. 2.程序源代码: #include "stdio.h" main() { int i,j,re ...

  8. RF(读写 excel)

    1.安装 ExcelLibrary 库:pip install robotframework-ExcelLibrary 但是 Python3.0 通过上面的命令安装 ExcelLibrary 时,会发 ...

  9. Django model重写save方法及update踩坑记录

    一个非常实用的小方法 试想一下,Django中如果我们想对保存进数据库的数据做校验,有哪些实现的方法? 我们可以在view中去处理,每当view接收请求,就对提交的数据做校验,校验不通过直接返回错误, ...

  10. spring的单元测试

    如果spring 4.3.18这个版本的spring要使用junit,需要使用junit的junit-4.12之上的版本.使用这个版本junit的时 候需要引入hamcrest-all的jar包.之前 ...