详细解析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. Libra白皮书解读

    文章目录 Libra简介 Libra区块链 Libra货币和存储 Libra协会 Libra简介 Libra是facebook发起的一个区块链项目,其使命是建立一套简单的.无国界的货币和为数十亿人服务 ...

  2. unix域源码解析

    首先我们先要创建一个用于通信的结构unix_proto_data ,并初始化某些字段 static int unix_proto_create(struct socket *sock, int pro ...

  3. mac OS 安装 Eclipse

    安装Eclipse前先确认你的Mac上是否已安装Java运行环境.进入终端,输入"java -version",如果返回了java版本号则说明已安装 访问Eclipse官方首页ht ...

  4. Vue.js中scoped引发的CSS作用域探讨

    前言 在Vue.js的组件化开发中,常常会对某个组件的style标签加上scoped属性,如<style lang='less' scoped>,这样做的目的在于使这个组件的样式不能轻易在 ...

  5. codeforce 266c Below the Diagonal 矩阵变换 (思维题)

    C. Below the Diagonal You are given a square matrix consisting of n rows and n columns. We assume th ...

  6. python(re 模块)

    1.re.match() 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none. group() 以str形式返回对象中match的元素 start() 返回 ...

  7. 数据可视化:使用python代码实现可视数据随机漫步图

    #2020/4/5 ,是开博的第一天,希望和大家相互交流学习,很开森,哈哈~ #像个傻子哟~       #好,我们进入正题, #实现功能:利用python实现数据随机漫步,漫步点数据可视化 #什么是 ...

  8. Flutter 粘合剂CustomScrollView控件

    老孟导读:快乐的51假期结束了,切换为努力模式,今天给大家分享CustomScrollView组件,此组件在以后的项目中会经常用到,CustomScrollView就像一个粘合剂,将多个组件粘合在一起 ...

  9. 能量项链(区间DP入门)

    题面:能量项链https://www.luogu.com.cn/problem/P1063 乍一看和石子合并差不多,可是多了头值和尾值,看起来十分麻烦 我们画一张图,紫色表示头值,蓝色表示尾值.规定西 ...

  10. react-redux的理解

    react-redux是辅助redux的,我们正常使用redux是很麻烦的,需要在每个组件中去监听数据变化,执行数据更新等 但是通过react-redux,我们可以简化组件使用公共数据的操作, rea ...