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('\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();
}
};
测试
安装
chaincodecurl -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"}实例化
chaincodecurl -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的更多相关文章
- Hyperledger Fabric——balance transfer(一)启动示例
Blacne transfer是Hyperledger fabric Node SDK的一个示例应用,主要使用了SDK中fabric-client 和 fabric-ca-client 模块中的API ...
- Hyperledger Fabric——balance transfer(六)查询
balance transfer 提供了很多查询接口,包括链码查询,根据区块号查询区块数据,根据交易ID查询交易信息,查询链上的区块数,查询已安装或已实例化的链码,查询通道. 源码解析 1.调用链码查 ...
- Hyperledger Fabric——balance transfer(五)执行交易
链码安装和实例化之后就可以调用chaincode执行交易,下面分析简单的账户转账操作是如何完成的. 源码分析 1.首先看app.js的路由函数 app.post('/channels/:channel ...
- Hyperledger Fabric——balance transfer(三)创建和加入Channel
详细解析blance transfer示例的创建通道(Channel)和加入节点到通道的过程. 创建Channel 1.首先看app.js的路由函数 var createChannel = requi ...
- Hyperledger Fabric——balance transfer(二)注册用户
详细分析blance transfer示例的用户注册(register)与登录(enroll)功能. 源码分析 1.首先分析项目根目录的app.js文件中关于用户注册和登录的路由函数.注意这里的tok ...
- Hyperledger Fabric v1.1.0安装记录(国内源版)
1. 安装虚拟机 虚拟机软件采用:VirtualBox 操作系统选择:Ubuntu 14.04 内存:4G CPU:2核 硬盘:20G 2.(可选)更改 ...
- Hyperledger Fabric (1.0)环境部署 chaincode【转】
三.测试Fabric 其实我们在前面运行./network_setup.sh up的时候系统已经运行了一个Example02的ChainCode测试,部署上去的ChainCodeName是mycc,所 ...
- 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 ...
- Hyperledger Fabric Chaincode for Operators——实操智能合约
什么是Chaincode(智能合约)? chaincode是一个程序,它是使用Go语言编写的,最终在Java等其他编程语言中实现了指定的接口.chaincode运行在一个被背书peer进程独立出来的安 ...
随机推荐
- Linux安装jdk(详细教程)
一.JDK介绍 JDK是 Java 语言的软件开发工具包,主要用于移动设备.嵌入式设备上的java应用程序.JDK是整个java开发的核心,它包含了JAVA的运行环境(JVM+Java系统类库)和JA ...
- java 8 Streams简介
目录 简介 Functional Interface Function:一个参数一个返回值 BiFunction:接收两个参数,一个返回值 Supplier:无参的Function Consumer: ...
- jQuery动态时钟
效果图: 引用的jQuery.js自己百度 代码: <!DOCTYPE html> <html> <head> <meta charset="utf ...
- nginx 反向代理转发导致css,js,图片失效
为什么80%的码农都做不了架构师?>>> 需要添加以下配置 location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { proxy_pass htt ...
- 基于opencv的人脸识别程序
1. 解析opencv自带人脸识别源码(……/opencv-3.1.0/samples/cpp/facedetect.cpp) @ 操作系统:Ubuntu 15.04 OpenCV版本:3.1.0 # ...
- JDK 安装及配置环境变量(基于 Linux)
1.先确定虚拟机系统是 32 位还是 64 位 #Linux 指令下输入 getconf LONG_BIT 2.建目录 JDK mkdir JDK 3.通过 rz 导入压缩包 jdk-8u144-li ...
- Jmeter 结构体系及运行顺序
一.Jmeter 运行原理: Jmeter 时以线程的方式来运行的(由于Jmeter 是 java 开发的所以是运行在 JVM 虚拟机上的,java 也是支持多线程的) 二.Jmeter 结构体系 1 ...
- undef用法
#undef的语法 定义:#undef 标识符,用来将前面定义的宏标识符取消定义. 整理了如下几种#undef的常见用法. 1. 防止宏定义冲突在一个程序块中用完宏定义后,为防止后面标识符冲突需要取消 ...
- 题目分享L
题意:n个人围成一个环,每个人初始有一些金币,每个人可以把金币递给相邻的人,问最少传递多少金币使每个人金币数相同? 分析:首先在保证最优的情况下不可能会出现相邻的两个人互相送金币,因为这样他们公共的部 ...
- 程序猿使用Python的tkinter库进行GUI编程肯定要会的事件处理
事件类型用户通过鼠标.键盘.游戏控制设备在与图形界面交互时,就会触发事件.tkinter事件通常采用了将事件名称放置于尖括号内的字符串表示,尖括号中的内容我们称之为事件类型.事件类型有其通用的定义方式 ...