本文已在我的公众号Fabric技术分享原创首发。
转载请标明出处:
https://blog.csdn.net/qq_27818541/article/details/78339763
本文出自:【BigManing的博客】
前言
这篇文章展示如何把peer节点加入到channel中,其中需要两个参数
- channelName 加入到哪个channel
- peers 把哪个节点加进去
定义好这两个参数,然后调用相关API 就可以了。
路由
app.js
//加入到channel Join Channel
app.post('/channels/:channelName/peers', function(req, res) {
logger.info('<<<<<<<<<<<<<<<<< J O I N C H A N N E L >>>>>>>>>>>>>>>>>');
//1 校验必要参数
var channelName = req.params.channelName;
var peers = req.body.peers;
logger.debug('channelName : ' + channelName);
logger.debug('peers : ' + peers);
if (!channelName) {
res.json(getErrorMessage('\'channelName\''));
return;
}
if (!peers || peers.length == 0) {
res.json(getErrorMessage('\'peers\''));
return;
}
//2 使用封装好js方法 来 具体实现
join.joinChannel(channelName, peers, req.username, req.orgname)
.then(function(message) {
res.send(message);
});
});
具体实现
join-channel.js
var util = require('util');
var path = require('path');
var fs = require('fs');
var Peer = require('fabric-client/lib/Peer.js');
var EventHub = require('fabric-client/lib/EventHub.js');
var tx_id = null;
var nonce = null;
var config = require('../config.json');
var helper = require('./helper.js');
var logger = helper.getLogger('Join-Channel');
//helper.hfc.addConfigFile(path.join(__dirname, 'network-config.json'));
var ORGS = helper.ORGS;
var allEventhubs = [];
//
//Attempt to send a request to the orderer with the sendCreateChain method
// 在admin user下 获取 channel的 genises.block 然后 指定peers加入channel
//
var joinChannel = function(channelName, peers, username, org) {
//关闭事件回调连接
var closeConnections = function(isSuccess) {
if (isSuccess) {
logger.debug('\n============ Join Channel is SUCCESS ============\n');
} else {
logger.debug('\n!!!!!!!! ERROR: Join Channel FAILED !!!!!!!!\n');
}
logger.debug('');
for (var key in allEventhubs) {
var eventhub = allEventhubs[key];
if (eventhub && eventhub.isconnected()) {
//logger.debug('Disconnecting the event hub');
eventhub.disconnect();
}
}
};
//logger.debug('\n============ Join Channel ============\n')
logger.info(util.format(
'Calling peers in organization "%s" to join the channel', org));
var client = helper.getClientForOrg(org);
var channel = helper.getChannelForOrg(org);
var eventhubs = [];
// 1 在管理员环境下 获取原始块(peer想要加入channel 就得需要这个东西)
return helper.getOrgAdmin(org).then((admin) => {
logger.info(util.format('received member object for admin of the organization "%s": ', org));
tx_id = client.newTransactionID();
let request = {
txId : tx_id
};
return channel.getGenesisBlock(request);
}).then((genesis_block) => {
// 2 封装加入到channel的请求
tx_id = client.newTransactionID();
var request = {
targets: helper.newPeers(peers, org),
txId: tx_id,
block: genesis_block
};
// 3.1 设置事件监听连接
eventhubs = helper.newEventHubs(peers, org);
for (let key in eventhubs) {
let eh = eventhubs[key];
eh.connect();
allEventhubs.push(eh);
}
var eventPromises = [];
eventhubs.forEach((eh) => {
let txPromise = new Promise((resolve, reject) => {
//3.2 监听区块信息 并设置超时时间
let handle = setTimeout(reject, parseInt(config.eventWaitTime));
eh.registerBlockEvent((block) => {
clearTimeout(handle);
// in real-world situations, a peer may have more than one channels so
// we must check that this block came from the channel we asked the peer to join
if (block.data.data.length === 1) {
// Config block must only contain one transaction
var channel_header = block.data.data[0].payload.header.channel_header;
//3.3 属于本channel的信息 就继续执行 否则就拒绝
if (channel_header.channel_id === channelName) {
resolve();
}
else {
reject();
}
}
});
});
//3.4 设置 eventPromises集合
eventPromises.push(txPromise);
});
//4 请求加入到channel
let sendPromise = channel.joinChannel(request);
// 5 promise流 ( 监听事件 发送事件 ) 的 promise 全荣俱荣 一损俱损
return Promise.all([sendPromise].concat(eventPromises));
}, (err) => {
logger.error('Failed to enroll user \'' + username + '\' due to error: ' +
err.stack ? err.stack : err);
throw new Error('Failed to enroll user \'' + username +
'\' due to error: ' + err.stack ? err.stack : err);
}).then((results) => {
//7 根据state 判断结果 如果到这里了 说明是sendPromise 返回的结果
logger.debug(util.format('Join Channel R E S P O N S E : %j', results));
// 加入成功
if (results[0] && results[0][0] && results[0][0].response && results[0][0]
.response.status == 200) {
logger.info(util.format(
'Successfully joined peers in organization %s to the channel \'%s\'',
org, channelName));
closeConnections(true);
let response = {
success: true,
message: util.format(
'Successfully joined peers in organization %s to the channel \'%s\'',
org, channelName)
};
return response;
} else {
//加入失败
logger.error(' Failed to join channel');
closeConnections();
throw new Error('Failed to join channel');
}
}, (err) => {
logger.error('Failed to join channel due to error: ' + err.stack ? err.stack :
err);
closeConnections();
throw new Error('Failed to join channel due to error: ' + err.stack ? err.stack :
err);
});
};
exports.joinChannel = joinChannel;
基本流程
API访问
指定org1的两个peer加入到channel,在具体实现第2
点里,helper.js
会根据org
,peer
获取到peer对应的grpc地址,然后封装成一个完整的request
。
echo "POST request Join channel on Org1"
echo
curl -s -X POST \
http://localhost:4000/channels/mychannel/peers \
-H "authorization: Bearer $ORG1_TOKEN" \
-H "content-type: application/json" \
-d '{
"peers": ["peer1","peer2"]
}'
echo
echo
控制台打印:
POST request Join channel on Org1
{"success":true,"message":"Successfully joined peers in organization org1 to the channel 'mychannel'"}
后台打印:
[2017-10-16 11:07:11.584] [DEBUG] SampleWebApp - Decoded from JWT token: username - Jim, orgname - org1
[2017-10-16 11:07:11.584] [INFO] SampleWebApp - <<<<<<<<<<<<<<<<< J O I N C H A N N E L >>>>>>>>>>>>>>>>>
// 获取到的参数
[2017-10-16 11:07:11.585] [DEBUG] SampleWebApp - channelName : mychannel
[2017-10-16 11:07:11.585] [DEBUG] SampleWebApp - peers : peer1,peer2
[2017-10-16 11:07:11.585] [INFO] Join-Channel - Calling peers in organization "org1" to join the channel
[2017-10-16 11:07:11.586] [DEBUG] Helper - [crypto_ecdsa_aes]: constructor, keySize: 256
[2017-10-16 11:07:11.586] [DEBUG] Helper - [crypto_ecdsa_aes]: Hash algorithm: SHA2, hash output size: 256
[2017-10-16 11:07:11.587] [DEBUG] Helper - [utils.CryptoKeyStore]: CryptoKeyStore, constructor - start
// 获取admin
[2017-10-16 11:07:11.587] [DEBUG] Helper - [utils.CryptoKeyStore]: constructor, no super class specified, using config: fabric-client/lib/impl/FileKeyValueStore.js
[2017-10-16 11:07:11.587] [DEBUG] Helper - [FileKeyValueStore.js]: FileKeyValueStore.js - constructor
[2017-10-16 11:07:11.588] [DEBUG] Helper - Msp ID : Org1MSP
[2017-10-16 11:07:11.588] [DEBUG] Helper - [crypto_ecdsa_aes]: importKey - start
[2017-10-16 11:07:11.590] [DEBUG] Helper - [crypto_ecdsa_aes]: importKey - have the key [Circular]
[2017-10-16 11:07:11.591] [DEBUG] Helper - [utils.CryptoKeyStore]: This class requires a CryptoKeyStore to save keys, using the store: {"opts":{"path":"/tmp/fabric-client-kvs_peerOrg1"}}
[2017-10-16 11:07:11.591] [DEBUG] Helper - [FileKeyValueStore.js]: FileKeyValueStore.js - constructor
[2017-10-16 11:07:11.591] [DEBUG] Helper - [utils.CryptoKeyStore]: _getKeyStore returning ks
[2017-10-16 11:07:11.591] [DEBUG] Helper - [ecdsa/key.js]: ECDSA curve param X: 0a66f3503a3322b2ca8e9dce03322d486ee6ec5970efaad3f153bc13aa2d942c
[2017-10-16 11:07:11.591] [DEBUG] Helper - [ecdsa/key.js]: ECDSA curve param Y: 312ad05190fa592fb9e8ac2dcdb23c84df7f49e4ee295c2aa1200a50c9146c46
[2017-10-16 11:07:11.592] [DEBUG] Helper - [FileKeyValueStore.js]: FileKeyValueStore -- setValue
[2017-10-16 11:07:11.593] [DEBUG] Helper - [crypto_ecdsa_aes]: importKey - start
[2017-10-16 11:07:11.593] [DEBUG] Helper - [crypto_ecdsa_aes]: importKey - have the key [Circular]
[2017-10-16 11:07:11.593] [DEBUG] Helper - [utils.CryptoKeyStore]: _getKeyStore resolving store
[2017-10-16 11:07:11.594] [DEBUG] Helper - [ecdsa/key.js]: ECDSA curve param X: 0a66f3503a3322b2ca8e9dce03322d486ee6ec5970efaad3f153bc13aa2d942c
[2017-10-16 11:07:11.594] [DEBUG] Helper - [ecdsa/key.js]: ECDSA curve param Y: 312ad05190fa592fb9e8ac2dcdb23c84df7f49e4ee295c2aa1200a50c9146c46
[2017-10-16 11:07:11.594] [DEBUG] Helper - [FileKeyValueStore.js]: FileKeyValueStore -- setValue
[2017-10-16 11:07:11.596] [DEBUG] Helper - [ecdsa/key.js]: ECDSA curve param X: 0a66f3503a3322b2ca8e9dce03322d486ee6ec5970efaad3f153bc13aa2d942c
[2017-10-16 11:07:11.596] [DEBUG] Helper - [ecdsa/key.js]: ECDSA curve param Y: 312ad05190fa592fb9e8ac2dcdb23c84df7f49e4ee295c2aa1200a50c9146c46
[2017-10-16 11:07:11.596] [DEBUG] Helper - [ecdsa/key.js]: ECDSA curve param X: 0a66f3503a3322b2ca8e9dce03322d486ee6ec5970efaad3f153bc13aa2d942c
[2017-10-16 11:07:11.596] [DEBUG] Helper - [ecdsa/key.js]: ECDSA curve param Y: 312ad05190fa592fb9e8ac2dcdb23c84df7f49e4ee295c2aa1200a50c9146c46
[2017-10-16 11:07:11.597] [DEBUG] Helper - [ecdsa/key.js]: ECDSA curve param X: 0a66f3503a3322b2ca8e9dce03322d486ee6ec5970efaad3f153bc13aa2d942c
[2017-10-16 11:07:11.597] [DEBUG] Helper - [ecdsa/key.js]: ECDSA curve param Y: 312ad05190fa592fb9e8ac2dcdb23c84df7f49e4ee295c2aa1200a50c9146c46
[2017-10-16 11:07:11.597] [DEBUG] Helper - [FileKeyValueStore.js]: FileKeyValueStore -- setValue
[2017-10-16 11:07:11.600] [INFO] Join-Channel - received member object for admin of the organization "org1":
[2017-10-16 11:07:11.604] [DEBUG] Helper - [crypto_ecdsa_aes]: ecdsa signature: Signature {
r: <BN: 7d10c289f1015a3597b929ec079652692dd9104fa2bda7326f8320281e33123d>,
s: <BN: 50167788c3fc57609ab56e14ca8397bc47fffc2469fd683ddc5a51fae5190958>,
recoveryParam: 0 }
// 设置监听事件
info: [EventHub.js]: _connect - options {"grpc.ssl_target_name_override":"peer0.org1.example.com","grpc.default_authority":"peer0.org1.example.com"}
[2017-10-16 11:07:11.634] [DEBUG] Helper - [crypto_ecdsa_aes]: ecdsa signature: Signature {
r: <BN: e1cdeef11d37de28810bed04d525abf4ed4959899f64e7129483110b07d9ef50>,
s: <BN: 65720ba0dfcdb959cce0a3d69b016097c7895aab1891172ded659aece90d467e>,
recoveryParam: 1 }
info: [EventHub.js]: _connect - options {"grpc.ssl_target_name_override":"peer1.org1.example.com","grpc.default_authority":"peer1.org1.example.com"}
[2017-10-16 11:07:11.643] [DEBUG] Helper - [crypto_ecdsa_aes]: ecdsa signature: Signature {
r: <BN: e1cdeef11d37de28810bed04d525abf4ed4959899f64e7129483110b07d9ef50>,
s: <BN: 65720ba0dfcdb959cce0a3d69b016097c7895aab1891172ded659aece90d467e>,
recoveryParam: 1 }
[2017-10-16 11:07:11.652] [DEBUG] Helper - [crypto_ecdsa_aes]: ecdsa signature: Signature {
r: <BN: ba3afad71ae6cd1889974364672ed04f15ed3ef6d5c6801ce59ce78bffe27a93>,
s: <BN: 66b904b771bd6dda916e329e1fc8e5d25b2bae369948bde8e3d12ac3848ac8aa>,
recoveryParam: 1 }
// 发送请求后的相应
[2017-10-16 11:07:11.957] [DEBUG] Join-Channel - Join Channel R E S P O N S E : [[{"version":0,"timestamp":null,"response":{"status":200,"message":"","payload":{"type":"Buffer","data":[]}},"payload":{"type":"Buffer","data":[]},"endorsement":null},{"version":0,"timestamp":null,"response":{"status":200,"message":"","payload":{"type":"Buffer","data":[]}},"payload":{"type":"Buffer","data":[]},"endorsement":null}],null,null]
[2017-10-16 11:07:11.957] [INFO] Join-Channel - Successfully joined peers in organization org1 to the channel 'mychannel'
[2017-10-16 11:07:11.957] [DEBUG] Join-Channel -
//
============ Join Channel is SUCCESS ============
[2017-10-16 11:07:11.957] [DEBUG] Join-Channel -
[2017-10-16 11:07:11.964] [DEBUG] Helper - [crypto_ecdsa_aes]: ecdsa signature: Signature {
r: <BN: ab6a1ea9d36c8cabc53cad8cfdf545dc0f7e7751bf43979552bb980f7fcb4b7e>,
s: <BN: 1839adef53808d6e3ffba1f40495827cc6b4fa047d2c03dfe9ab76933581d35b>,
recoveryParam: 1 }
[2017-10-16 11:07:11.969] [DEBUG] Helper - [crypto_ecdsa_aes]: ecdsa signature: Signature {
r: <BN: ab6a1ea9d36c8cabc53cad8cfdf545dc0f7e7751bf43979552bb980f7fcb4b7e>,
s: <BN: 1839adef53808d6e3ffba1f40495827cc6b4fa047d2c03dfe9ab76933581d35b>,
recoveryParam: 1 }