美文网首页hyperledger-fabric学习
fabric-1.0动态加入组织

fabric-1.0动态加入组织

作者: John_Xuxu | 来源:发表于2017-09-12 10:20 被阅读2579次

    fabric的组织配置信息一般是提前写在configtx.yaml文件中的,通过configtx.yaml生成系统创世区块和通道文件。而系统启动和通道创建是通过创世区块和通道文件进行的,因此要在fabric系统运行时添加组织则是非常困难的。

    还好,fabric-1.0提供了configtxlator工具,为动态修改fabric通道信息提供可能。本文将介绍如何利用configtxlator为fabric-1.0网络动态添加组织。

    运行fabric网络

    本文利用fabric-sample项目中的first-network作为测试的示例。文档参考

    下载fabric-sample

    从github上克隆fabric-sample项目

    $ git clone https://github.com/hyperledger/fabric-samples.git
    $ cd fabric-samples
    

    下载镜像和binary包

    $ curl -sSL https://goo.gl/eYdRbX | bash
    

    这一步可能需要翻墙,可以从这里下载,然后运行,或者

    $ curl -sSL http://oui195df4.bkt.clouddn.com/download-bin.sh | bash
    

    这一步会拉取fabric-1.0的镜像和binary包

    生成证书和通道文件

    为了测试添加组织,先利用cryptogen工具生成三个组织的证书。
    修改first-network,添加org3

    crypto-org3

    生成证书和通道文件

    $ ./byfn.sh -m generate
    

    证书文件在crypto-config文件夹里,通道文件在channel-artifacts文件夹中

    启动两个组织的fabric网络

    执行

    $ ./byfn.sh -m up
    

    启动包括两个组织的fabric网络,cli容器会执行scripts/script.sh脚本进行创建mychannel通道,加入通道,部署chaincode,调用和查询chaincode等。

    在系统channel中添加org

    参考configtxlator工具的文档

    启动configtxlator服务

    $ configtxlator start
    

    获取系统通道的配置

    设置MSP为Orderer

    
    $ export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/users/Admin\@example.com/msp/
    $ export CORE_PEER_LOCALMSPID=OrdererMSP
    

    获取通道

    # peer channel fetch config config_block.pb -o orderer.example.com:7050 -c testchainid
    

    生成添加组织的增量文件

    • 将配置信息区块转换为可读的json文件
    $ curl -X POST --data-binary @config_block.pb http://127.0.0.1:7059/protolator/decode/common.Block > config_block.json
    
    • 获取config区域
    $ jq .data.data[0].payload.data.config config_block.json > config.json
    
    • 修改config.json,添加org3信息

    这一步可以利用configtxgen工具生成org3的配置信息,并将配置信息添加到config.json文件中,修改后的文件保存为updated_config.json,部分内容如图:

    updated-config
    • 将original config和updated config打包成proto文件
    $ curl -X POST --data-binary @config.json http://127.0.0.1:7059/protolator/encode/common.Config > config.pb
    

    $ curl -X POST --data-binary @updated_config.json http://127.0.0.1:7059/protolator/encode/common.Config > updated_config.pb
    
    • 生成增量文件
    $ curl -X POST -F original=@config.pb -F updated=@updated_config.pb http://127.0.0.1:7059/configtxlator/compute/update-from-configs -F channel=testchainid > config_update.pb
    

    至此,更新通道的数据已经准备好了。利用SDK可以签名和打包此消息,发送更新通道交易。值得注意的是,这个交易需要所有通道中已存在的org进行签名。

    由于系统channel中只有一个组织——OrdererMSP,因此也可以直接通过命令行发送交易。

    更新通道

    • 将增量文件转换为pb格式
    $ curl -X POST --data-binary @config_update.pb http://127.0.0.1:7059/protolator/decode/common.ConfigUpdate > config_update.json
    
    • 打包数据
    $ echo '{"payload":{"header":{"channel_header":{"channel_id":"testchainid", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' > config_update_as_envelope.json
    
    • 转换为pb文件
    $ curl -X POST --data-binary @config_update_as_envelope.json http://127.0.0.1:7059/protolator/encode/common.Envelope > config_update_as_envelope.pb
    
    • 进入cli,更新通道
    root@d96f70c3b3ab:/#
    root@d96f70c3b3ab:/# peer channel update -f config_update_as_envelope.pb -c testchainid -o 127.0.0.1:7050
    

    此时系统channel——testchainid中则拥有了org3的信息。启动org3,则其可以进入fabric网络。但是org3无法加入mychannel通道,只能新建通道。

    向mychannel添加org

    向mychannel中添加org和向系统channel中添加org流程上是相同的,不同的是需要用所有PeerOrg进行签名。

    生成增量pb文件

    通过上述流程,生成增量pb文件,步骤省略。

    发送更新通道交易

    由于mychannel中有两个org,发送更新通道交易需要两个组织进行对更新交易进行多重签名,而通过执行peer channel update命令无法实现多重签名,因此需要通过SDK发送交易。

    本文采用nodejs-sdk,创建更新交易js脚本,部分内容为

    var signatures = [];
    //读取增量pb文件
    var config_proto = fs.readFileSync(path.join(__dirname, 'mychannel_config_update.pb'));
    
    return Client.newDefaultKeyValueStore({
            path: 'kvs_' + org
        }).then((store) => {
            client.setStateStore(store);
            client._userContext = null;
            return getPeerAdmin(client, 'org1');
        }).then((admin) => {
            logger.info('Successfully enrolled user \'admin\' for org1');
            the_user = admin;
            //org1对config_proto进行签名
            var signature = client.signChannelConfig(config_proto);
            logger.info('Successfully signed config update by org1');
            signatures.push(signature);
            client._userContext = null;
            return getPeerAdmin(client, 'org2');
        }).then((admin) => {
            logger.info('Successfully enrolled user \'admin\' for org2');
            the_user = admin;
            //org2对config_proto进行签名
            var signature = client.signChannelConfig(config_proto); 
            logger.info('Successfully signed config update by org2');
            signatures.push(signature);
            client._userContext = null;
            return getOrdererAdmin(client);
        }).then((admin) => {
            logger.info('Successfully enrolled user \'admin\' for orderer');
            the_user = admin;
            //orderer对config_proto进行签名
            var signature = client.signChannelConfig(config_proto);
            logger.info('Successfully signed config update by org2');
            signatures.push(signature);
            let tx_id = client.newTransactionID();
            request = {
                config: config_proto,
                signatures : signatures,
                name : channelName,
                orderer : orderer,
                txId  : tx_id
            };
            //更新通道
            return client.updateChannel(request);
        }).then((result) => {
            if(result.status && result.status === 'SUCCESS') {
                logger.info('Successfully updated the channel.');
                return sleep(5000);
            } else {
                logger.error('Failed to update the channel. ');
                Promise.reject('Failed to update the channel');
            }
        }).then((nothing) => {
            logger.info('Successfully waited to make sure new channel was updated.');
    

    执行js脚本文件,更新通道。

    此时org3则能成功加入mychannel通道。

    总结

    从流程来看,动态添加组织过程还是比较复杂的,涉及到文件的多次转换,多重签名等步骤。

    更重要的是,更新交易需要多个组织进行签名,而在实际运用过程中,一个组织不可能获取所有组织的私钥,因此需要增量数据在各个组织间进行审核、流转,这个过程也是非常繁琐的。因此,未来需要开发在线审核流转工具,协助对数据签名。


    by. xuyuzhuang
    date. 2017-08-22

    相关文章

      网友评论

      • e5b21af4fea6:您好 getOrdererAdmin getPeerAdmin两个函数是参照fabric-sdk-node/test/unit/util.js中的函数写的吗?
      • 3d71d914ea27:那如果是已经加入到channel的节点,由于各种原因出错了,又重新部署了这个peer,这个peer怎么再次加入channel呢
      • 2d32f5f4cd2b:您好,能留下联系方式么,微信 QQ,我想详细咨询下
      • 悟空先森_7ddd:这太麻烦了,请问是否可以通过重新configtxgen来生成通道配置,然后重启各节点的方法来升级呢?
      • 044f66ef4078:请问下,如何删除组织呢?
        John_Xuxu:@xyz_3396 理论上来说,把config区块中的组织信息删除,发送更新交易就可以实现,但是还没有实验过
      • 332390048f14:您好,请问新的节点加入后,能够对链上的信息进行查询,却一直无法invoke,这是为什么呢?下面是ivoke 调用时nodejs的log错误信息
        [2017-12-13 20:46:34.925] [ERROR] invoke-chaincode - The balance transfer transaction was invalid, code = ENDORSEMENT_POLICY_FAILURE
        [2017-12-13 20:46:34.925] [ERROR] invoke-chaincode - Failed to send transaction and get notifications within the timeout period.
        [2017-12-13 20:46:34.925] [ERROR] invoke-chaincode - Failed to order the transaction. Error code: undefined
        [2017-12-13 20:46:34.929] [DEBUG] Helper - [crypto_ecdsa_aes]: ecdsa signature: Signature {
        r: <BN: b920b65a2f2a90f2f13c34a7a3ad5bb3ca91ac5a2d53522c6be6c2c9bbca6dc5>,
        s: <BN: 45eb884fd2de0c2727756f54047a9766cdef68d3ec49bf0b43adeb37efb173b6>,
        recoveryParam: 1 }
        [2017-12-13 20:46:34.930] [ERROR] invoke-chaincode - The balance transfer transaction was invalid, code = ENDORSEMENT_POLICY_FAILURE
        John_Xuxu:@徐晶晶_c63f 原来版本的cc会存在,因此数据不会自动导入新版本的cc,需要自己在cc代码中实现reinit方法
        332390048f14:@许玉壮 今天实验了一下,确实是实例化的问题,如果在新org加入前仅在org1,org2上安装chaincode而不实例化,在新节点加入mychannel后再执行实例化操作,新的org是可以执行invoke的!那么新加入节点后必须还要升级一下chaincode版本了。。升级chaincode版本原来的数据会丢失吗?
        John_Xuxu:@徐晶晶_c63f 看错误是没有满足背书策略,是不是实例化的cc没有新组织MSP
      • kamiSDY:问一下,更改系统org的时候。更改MSP是否也是在cli中?为什么我更改后连接不到,fetch不成功?
        kamiSDY:@许玉壮 而且,您是否知道mode_ppolicy对于在提交个orderer的时候,是否可以指定签名的数量?而不用所有的org都签名
        kamiSDY:@许玉壮 为什么我改了之后还是连接不到?peer都没有问题。也配置类orderer_ca
        John_Xuxu:@kamiSDY 是在cli中,msp和mspId都需要更改成orderer的
      • 1cce9535bece:博主你好,发送更新通道交易以前的内容都可以完成,但是在最后使用nodejs-sdk这里更新了多次依旧不能成功,mychannel的原型数据里面一直没有org3的信息,由于自己刚刚接触nodejs,并不精通,所以楼主可以更详细的说明一下应该如何运行这个js文件名,还有对应的增量文件是不是有特定的存储位置这些细节应该怎么处理.
        1cce9535bece:感谢,已经运行成功,但是还是有很多疑惑
        1cce9535bece:@许玉壮 博主 echo '{"payload":{"header":{"channel_header":{"channel_id":"testchainid", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' > config_update_as_envelope.json
        这个命令中的type:2是啥意思,为啥是2不是1或者3呢?
        John_Xuxu:增量文件放在与js文件同一个目录就行。缺少org3的信息,是不是因为没有在系统通道中加入org3?
      • 4ce954a488a3:你好,在修改mychannel通道时,提示版本不一致的错误:2017-11-21 08:16:33.685 UTC [orderer/common/broadcast] Handle -> WARN 116d Rejecting CONFIG_UPDATE because: Error authorizing update: Error validating ReadSet: Readset expected key [Groups] /Channel/Application/CmbAmdPeerMSP at version 0, but got version 1。但是我看了我的mychannel_config_update.pb文件,其中: "read_set": {
        "groups": {
        "Application": {
        "groups": {
        "CmbAmdPeerMSP": {},
        "TebonPeerMSP": {}
        },
        "policies": {
        "Admins": {},
        "Readers": {},
        "Writers": {}
        },
        "version": "1"
        }
        }
        },
        version明明就是1,不知道为什么orderer获取的是0,求解求解啊?
        John_Xuxu:@一叶风舟 看错误信息好像是说希望获取version0,但是实际获取的是1
      • 4ce954a488a3:请问刚开始configtxgen工具产生的系统创世块gensis.block文件包含了org3了吗?如果未包含,那么后续增加org3时不需要对这个进行更新吗
        John_Xuxu: @一叶风舟 刚开始不包含org3的,因此首先需要在系统channel中添加org3
      • 4973b88a7067:如果上线后,在需要动态添加Org4,MSP 公钥私钥等配置如何生成?直接在orderer机器上重新生成就行吗?不重启orderer
        John_Xuxu:@许相贤 Orderer节点的作用是做交易排序和区块广播。Org4的MSP证书可以通过fabric-ca生成。动态添加组织是不用重启orderer的
      • Moro_5fa7:请问一下,“configtxgen工具生成org3的配置信息”,这一步是重新按配置生成全部3个组织的信息吗。
        John_Xuxu:是的,在一开始就生成了三个组织的MSP。只是在启动fabric网络时,只配置了org1和org2的MSP

      本文标题:fabric-1.0动态加入组织

      本文链接:https://www.haomeiwen.com/subject/zxaqsxtx.html