我正在尝试使用在官方fabric-samples存储库中找到的invoke函数同时将两个事务提交到Fabric。

如果我每次提交一笔交易,则该交易已成功提交到分类账。

相反,当我尝试执行多个并发事务时,出现此错误:

Error: Shutdown due to disconnect on transaction id registration
at ChannelEventHub._callTransactionListener (/Users/node_modules/fabric-client/lib/ChannelEventHub.js:1304:21)
at ChannelEventHub._checkTransactionId (/Users/node_modules/fabric-client/lib/ChannelEventHub.js:1282:9)
at ChannelEventHub._processTxEvents (/Users/node_modules/fabric-client/lib/ChannelEventHub.js:1261:11)
at ClientDuplexStream._stream.on (/Users/node_modules/fabric-client/lib/ChannelEventHub.js:405:11)
at emitOne (events.js:116:13)
at ClientDuplexStream.emit (events.js:211:7)
at addChunk (_stream_readable.js:263:12)
at readableAddChunk (_stream_readable.js:250:11)
at ClientDuplexStream.Readable.push (_stream_readable.js:208:10)
at Object.onReceiveMessage (/Users/node_modules/grpc/src/client_interceptors.js:1276:19)
at InterceptingListener.recvMessageWithContext (/Users/node_modules/grpc/src/client_interceptors.js:603:19)
at /Users/node_modules/grpc/src/client_interceptors.js:702:14

这是我正在使用的代码片段

var invokeChaincode = async function(peerNames, channelName, chaincodeName, fcn, args, username, org_name) {
    logger.debug(util.format('\n============ invoke transaction on channel %s ============\n', channelName));
    var error_message = null;
    var tx_id_string = null;
    try {
        // first setup the client for this org
        var client = await helper.getClientForOrg(org_name, username);
        logger.debug('Successfully got the fabric client for the organization "%s"', org_name);
        var channel = client.getChannel(channelName);
        if(!channel) {
            let message = util.format('Channel %s was not defined in the connection profile', channelName);
            logger.error(message);
            throw new Error(message);
        }
        var tx_id = client.newTransactionID();
        // will need the transaction ID string for the event registration later
        tx_id_string = tx_id.getTransactionID();

        // send proposal to endorser
        var request = {
            targets: peerNames,
            chaincodeId: chaincodeName,
            fcn: fcn,
            args: args,
            chainId: channelName,
            txId: tx_id
        };

        let results = await channel.sendTransactionProposal(request);

        // the returned object has both the endorsement results
        // and the actual proposal, the proposal will be needed
        // later when we send a transaction to the orderer
        var proposalResponses = results[0];
        var proposal = results[1];

        // lets have a look at the responses to see if they are
        // all good, if good they will also include signatures
        // required to be committed
        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('invoke chaincode proposal was good');
            } else {
                logger.error('invoke chaincode proposal was bad');
            }
            all_good = all_good & one_good;
        }

        if (all_good) {
            logger.info(util.format(
                'Successfully sent Proposal and received ProposalResponse: Status - %s, message - "%s", metadata - "%s", endorsement signature: %s',
                proposalResponses[0].response.status, proposalResponses[0].response.message,
                proposalResponses[0].response.payload, proposalResponses[0].endorsement.signature));

            // wait for the channel-based event hub to tell us
            // that the commit was good or bad on each peer in our organization
            var promises = [];
            let event_hubs = channel.getChannelEventHubsForOrg();
            event_hubs.forEach((eh) => {
                logger.debug('invokeEventPromise - setting up event');
                let invokeEventPromise = new Promise((resolve, reject) => {
                    let event_timeout = setTimeout(() => {
                        let message = 'REQUEST_TIMEOUT:' + eh.getPeerAddr();
                        logger.error(message);
                        eh.disconnect();
                    }, 3000);
                    eh.registerTxEvent(tx_id_string, (tx, code, block_num) => {
                        logger.info('The chaincode invoke chaincode transaction has been committed on peer %s',eh.getPeerAddr());
                        logger.info('Transaction %s has status of %s in blocl %s', tx, code, block_num);
                        clearTimeout(event_timeout);

                        if (code !== 'VALID') {
                            let message = util.format('The invoke chaincode transaction was invalid, code:%s',code);
                            logger.error(message);
                            reject(new Error(message));
                        } else {
                            let message = 'The invoke chaincode transaction was valid.';
                            logger.info(message);
                            resolve(message);
                        }
                    }, (err) => {
                        clearTimeout(event_timeout);
                        logger.error(err);
                        reject(err);
                    },
                        // the default for 'unregister' is true for transaction listeners
                        // so no real need to set here, however for 'disconnect'
                        // the default is false as most event hubs are long running
                        // in this use case we are using it only once
                        {unregister: true, disconnect: true}
                    );
                    eh.connect();
                });
                promises.push(invokeEventPromise);
            });

            var orderer_request = {
                txId: tx_id,
                proposalResponses: proposalResponses,
                proposal: proposal
            };
            var sendPromise = channel.sendTransaction(orderer_request);
            // put the send to the orderer last so that the events get registered and
            // are ready for the orderering and committing
            promises.push(sendPromise);
            let results = await Promise.all(promises);
            logger.debug(util.format('------->>> R E S P O N S E : %j', results));
            let response = results.pop(); //  orderer results are last in the results
            if (response.status === 'SUCCESS') {
                logger.info('Successfully sent transaction to the orderer.');
            } else {
                error_message = util.format('Failed to order the transaction. Error code: %s',response.status);
                logger.debug(error_message);
            }

            // now see what each of the event hubs reported
            for(let i in results) {
                let event_hub_result = results[i];
                let event_hub = event_hubs[i];
                logger.debug('Event results for event hub :%s',event_hub.getPeerAddr());
                if(typeof event_hub_result === 'string') {
                    logger.debug(event_hub_result);
                } else {
                    if(!error_message) error_message = event_hub_result.toString();
                    logger.debug(event_hub_result.toString());
                }
            }
        } else {
            error_message = util.format('Failed to send Proposal and receive all good ProposalResponse');
            logger.debug(error_message);
        }
    } catch (error) {
        logger.error('Failed to invoke due to error: ' + error.stack ? error.stack : error);
        error_message = error.toString();
    }

    if (!error_message) {
        let message = util.format(
            'Successfully invoked the chaincode %s to the channel \'%s\' for transaction ID: %s',
            org_name, channelName, tx_id_string);
        logger.info(message);

        return tx_id_string;
    } else {
        let message = util.format('Failed to invoke chaincode. cause:%s',error_message);
        logger.error(message);
        throw new Error(message);
    }
};

任何想法?

#1楼 票数:0 已采纳

我发现了问题。

// the default for 'unregister' is true for transaction listeners
// so no real need to set here, however for 'disconnect'
// the default is false as most event hubs are long running
// in this use case we are using it only once
{unregister: true, disconnect: false}

断开连接选项必须设置为false,否则在将事务通知给事件时关闭连接。

  ask by Leonardo Carraro translate from so

未解决问题?本站智能推荐:

3回复

为什么hyperledger-fabric需要多个orderer?

基本上我有很多问题,但我会问最需要的问题。 谢谢你的帮助。 1)为什么hyperledger网络需要多个订购者节点? 如果我理解正确,在节点验证事务之后,它们会将这些事务传递给orderer节点。 orderer节点将对这些事务加时间戳,将它们推入块中并将该块发送回节点。 节点会将
1回复

Hyperledger-fabric 用例

我目前希望在数百台主机上安全地复制数百 Gb 的数据。 我正在研究 hyperledger-fabric 私有区块链,因为它使用 TLS 和对等八卦协议进行数据传输,当然还有区块链本身的安全性。 我考虑使用区块链作为安全地进行数据复制的方式是否合理? 我还没有在任何区块链用例中看到这一点,但从我读
2回复

Hyperledger-fabric区块链

我真的是hyperledger-fabric的新手,我也想基于该技术和框架构建自己的应用程序,但是我的知识还有一些空白(在hyperledger fabric的区块链中存储了哪些信息?
1回复

Hyperledger Composer / Fabric-更新资产数据模型

我有一个关于如何更新已经存储在区块链中的资产的数据模型的问题。 1-是否可以更改资产的数据模型? 例如,通过添加新字段或更改现有字段。 2-是否可以将新资产添加到分类帐? 通过创建一个不存在的新文件。 3-这些逻辑既可以应用于HL Composer,又可以应用于HL Fab
1回复

如何在Hyperledger-Fabric中的多台机器中连接多个对等端

我已经关注了Hyperledger Fabric文档并安装了Fabric示例,但是现在我想使用另一台计算机将另一个对等点连接到网络中
1回复

Hyperledger-Fabric基于属性的访问控制

我已经从master分支中提取了布料存储库。 使用节点SDK 我正在尝试注册用户并为他注册一个属性hf.registrar.Role属性,并请求具有相同属性的证书 然后我正在调用一个事务,并尝试用链码解码他的属性 我也在尝试在节点层解码他的属性,但是我将属性设置为nu
2回复

更改fabcar示例Hyperledger-Fabric

一段时间以来,我一直在研究hyperledger-fabric样本/ fabcar示例,并且能够在fabcar.go中添加更多字段和功能,但是当我完全更改字段时。 我在部署中遇到错误。 这是我在fabcar.go中进行的更改的示例。 这是我运行startFabric.sh时遇到的
1回复

Hyperledger-fabric中的组织内部共识

我需要在特定组织内不同部门的3个同行的同意下执行特定交易,如何使用Hyperledger-fabric进行处理