HyperLedger 2.3.1 在提交者上连接失败

问题描述

我正在尝试在 Hyperledger 结构测试网络(Fabcar javascript 智能合约)上执行智能合约,当我尝试使用 fabcar javascript 示例中的 invoke.js 文件调用代码时出现以下错误

错误:[ServiceEndpoint]:错误:未能在提交者的截止日期前连接-名称:orderer0.example.com:7050,url:grpcs://localhost:7050,connected:false,connectAttempted:true 2021-05-05T23:44:02.951Z - 错误:[ServiceEndpoint]: waitForReady - 无法连接到远程 gRPC 服务器 orderer0.example.com:7050 url:grpcs://localhost:7050 timeout:3000 2021-05-05T23:44:02.952Z - 错误:[discoveryService]: _buildOrderer[mychannel] - 无法连接到发现的订购者 orderer0.example.com:7050 由于错误:未能在提交者名称的截止日期前连接: orderer0.example.com:7050,connectAttempted:true 2021-05-05T23:44:05.957Z - 错误:[ServiceEndpoint]:错误:无法在 Endorser 的截止日期前连接 - 名称:peer0.org01.example.com:7051,url:grpcs://localhost:7051,连接:假,连接尝试:真 2021-05-05T23:44:05.957Z - 错误:[ServiceEndpoint]: waitForReady - 无法连接到远程 gRPC 服务器 peer0.org01.example.com:7051 url:grpcs://localhost:7051 timeout:3000 2021-05-05T23:44:05.958Z - 错误:[discoveryService]: _buildPeer[mychannel] - 无法连接到发现的 peer0.org01.example.com:7051 由于错误:无法在 Endorser 的截止日期前连接- 名称:peer0.org01.example.com:7051,url:grpcs://localhost:7051,connectAttempted:true

需要注意的一点是,我已经更改了认测试网络中的端口转发和对等/组织名称。我的连接配置文件如下(为了清晰起见,删除了证书):

{
"name": "test-network-org1","version": "1.0.0","client": {
    "organization": "Org1","connection": {
        "timeout": {
            "peer": {
                "endorser": "300"
            }
        }
    }
},"channels": {
    "mychannel": {
        "orderers": [
            "orderer0.example.com"
        ],"peers": [
            "peer0.org01.example.com"
        ]
    }
},"organizations": {
    "Org1": {
        "mspid": "Org1MSP","peers": [
            "peer0.org01.example.com"
        ],"certificateAuthorities": [
            "ca.org1.example.com"
        ]
    }
},"peers": {
    "peer0.org01.example.com": {
        "url": "grpcs://localhost:6041","tlsCACerts": {
            "pem": "-----BEGIN CERTIFICATE-----**********-----END CERTIFICATE-----\n"
        },"grpcoptions": {
            "ssl-target-name-override": "peer0.org01.example.com","hostnameOverride": "peer0.org01.example.com"
        }
    }
},"orderers": {
    "orderer0.example.com": {
        "url": "grpcs://localhost:6040","grpcoptions": {
            "ssl-target-name-override": "orderer0.example.com"
        }
    }
},"certificateAuthorities": {
    "ca.org1.example.com": {
        "url": "https://localhost:6054","caName": "ca-org1","tlsCACerts": {
            "pem": ["-----BEGIN CERTIFICATE-----******-----END CERTIFICATE-----\n"]
        },"httpOptions": {
            "verify": false
        }
    }
}

}

令我困惑的一件事(我认为这是错误的根本原因)是订购者的 grpcs url。在连接配置文件中,我已明确指定它为 grpcs://localhost:6041,但是从错误中可以看出,错误将 url 声明为 grpcs://localhost: 7050。我已经查看了测试网络中的各种文件,但无法弄清楚为什么没有从连接配置文件中读取 grpcs url。

这个问题仅限于fabcar例子中的query.js和invoke.js文件(我可以在网络上成功执行enrollAdmin.js和registerUser.js)。

以下是我执行的导致上述错误的 invoke.js 文件

   'use strict';

const { Gateway,Wallets } = require('fabric-network');
const fs = require('fs');
const path = require('path');

async function main() {
    try {
        // load the network configuration
        const ccpPath = path.resolve(__dirname,'..','test-network','organizations','peerOrganizations','org1.example.com','connection-org1.json');
        let ccp = JSON.parse(fs.readFileSync(ccpPath,'utf8'));

        // Create a new file system based wallet for managing identities.
        const walletPath = path.join(process.cwd(),'wallet');
        const wallet = await Wallets.newFileSystemWallet(walletPath);
        console.log(`Wallet path: ${walletPath}`);

        // Check to see if we've already enrolled the user.
        const identity = await wallet.get('appUser3');
        if (!identity) {
            console.log('An identity for the user "appUser3" does not exist in the wallet');
            console.log('Run the registerUser.js application before retrying');
            return;
        }

        // Create a new gateway for connecting to our peer node.
        const gateway = new Gateway();
        await gateway.connect(ccp,{ wallet,identity: 'appUser3',discovery: { enabled: true,asLocalhost: true } });

        // Get the network (channel) our contract is deployed to.
        const network = await gateway.getNetwork('mychannel');

        // Get the contract from the network.
        const contract = network.getContract('fabcar');

        // Submit the specified transaction.
        // createCar transaction - requires 5 argument,ex: ('createCar','CAR12','Honda','Accord','Black','Tom')
        // changeCarOwner transaction - requires 2 args,ex: ('changeCarOwner','Dave')
        await contract.submitTransaction('createCar','CAR312','Skoda','Kadiq','White','JOHNSON');
        console.log('Transaction has been submitted');

        // disconnect from the gateway.
        await gateway.disconnect();

    } catch (error) {
        console.error(`Failed to submit transaction: ${error}`);
        process.exit(1);
    }
}

main();

任何帮助将不胜感激。谢谢

解决方法

我认为关键信息是错误消息的这一部分:

无法连接到发现的订购者 orderer0.example.com:7050

这是客户端使用服务发现定位的节点,未在您的连接配置文件中定义。

我怀疑发生的情况是,即使您更改了本地机器和 Docker 网络之间的端口映射,排序器仍在侦听 Docker 网络中的 7050 端口。

discovery.asLocalhost 连接选项用于支持区块链网络在客户端本地机器上的 Docker 网络中运行的场景,因此它会导致任何发现的主机名被视为 localhost,但是它使发现的端口号保持不变。因此,在使用 discovery.asLocalhost 选项时,节点在 Docker 网络内侦听的端口号必须映射到本地机器上的相同端口号。

如果您想更改端口号,那么您需要在实际节点本身上更改它们,而不仅仅是在您的 Docker 网络映射中。