0

This question picks up from my earlier question about adding a new org to an existing channel using fabric node sdk.

Gari helped addressing my issues with using the Node SDK and I was able to successfully add the Org to the channel mychannel, which is part of byfn.sh.

Now, following the original tutorial which I had adapted, I want to add the new Org's peers to join the channel mychannel. I am stuck here at the moment and have not been able to find a solution despite looking on Stackoverflow, HL Lists and HL Jira.

At a high level, the steps I am following are these:

  1. Add the new Org to the channel (uses Client.updateChannel API). I can do this successfully.
  2. I then bring up the peer and the couchdb docker containers for the peers associated with the new Org. The new org is Org3 and here is the connection profile
{
    "name": "first-network-org3",
    "version": "1.0.0",
    "client": {
        "organization": "Org3",
        "connection": {
            "timeout": {
                "peer": {
                    "endorser": "300"
                }
            }
        }
    },
    "organizations": {
        "Org3": {
            "mspid": "Org3MSP",
            "peers": [
                "peer0.org3.example.com"
            ]
        }
    },
    "peers": {
        "peer0.org3.example.com": {
            "url": "grpcs://localhost:11051",
            "tlsCACerts": {
                "path": "/usr/local/fabric/fabric-samples/first-network/crypto-config/peerOrganizations/org3.example.com/tlsca/tlsca.org3.example.com-cert.pem"
            },
            "grpcOptions": {
                "ssl-target-name-override": "peer0.org3.example.com"
            }
        }
    }
}
  1. I use a client pointing to the Org1 connection profile and extract the Network and Channel objects, and subsequently retrieve the channel's genesis block.
  2. I then create a new connection profile to point to Org3 peers and connect to it, and get a new (Org3) client reference.
  3. Using this Org3 client, I create a new Peer object (Client.newPeer)
  4. I then issue a channel.joinChannel(request).

Every single time, I get the following error from the client application

Error: 2 UNKNOWN: access denied: channel [] creator org [Org1MSP]

Docker logs for Peer 3 say this:

2020-01-24 19:46:47.774 UTC [protoutils] ValidateProposalMessage -> WARN 039 channel []: MSP error: expected MSP ID Org3MSP, received Org1MSP

2020-01-24 19:46:47.774 UTC [comm.grpc.server] 1 -> INFO 03a unary call completed grpc.service=protos.Endorser grpc.method=ProcessProposal grpc.peer_address=192.168.240.1:49860 error="access denied: channel [] creator org [Org1MSP]" grpc.code=Unknown grpc.call_duration=329.567µs

I know this error is because the MSP ID being submitted with the Channel.joinChannel request is Org1MSP but I am not sure why. I am submitting a peer created using an Org3 client and the transaction ID is also an Org3 Admin transaction ID.

Here is my code:

public async addPeerToChannel(orgJSON) {
        try {
            let json = JSON.parse(JSON.stringify(orgJSON));

            if (json.name === undefined || json.msp === undefined || json.domain === undefined || json.peer === undefined
                ||
                json.peerport === undefined || json.channel === undefined || json.peerurl === undefined) {
                throw new Error("Invalid org info provided to addPeerToChannel method");
            }

            let client = this.loanGateway.getClient(); // get the client reference for Org1 ccp
            let cMSP = client.getMspid(); // confirms MSP ID is Org1MSP
            let network = await this.loanGateway.getNetwork(json.channel); // mychannel
            let channel = network.getChannel();

            if (client === undefined || network === undefined || channel === undefined) {
                throw new Error(`Invalid network, orderer, channel or client handle in function addPeerToChannel. Error.`);
            }

            let data = fs.readFileSync(SyndLoanConfig.chainconfig.networkpath + `/crypto-config/peerOrganizations/${json.domain}/peers/${json.peer}/tls/ca.crt`).toString();

            // load a new client for Org3
            const gateway = new Gateway();
            const wallet = this.localWallet;
            const ccpFile = fs.readFileSync(path.join(SyndLoanConfig.chainconfig.networkpath,'connection-org3_ac.json'));
            const ccp = JSON.parse(ccpFile.toString());
            await this.importWalletIdentityFromCryptoConfig('Admin@org3.example.com','Org3MSP');
            await gateway.connect(ccp, {
                identity: 'Admin@org3.example.com',
                wallet: wallet
            });

            let newClient = gateway.getClient();

            let peer = newClient.newPeer(json.peerurl,
                {
                    'pem': Buffer.from(data).toString(),
                    'ssl-target-name-override': json.peer,
                    'name': json.peer,
                    'grpc.keepalive_timeout_ms': 10000

                })

            if (peer === undefined) {
                throw new Error(`Could not create the peer for URL ${json.peerurl}. Error.`)
            }

            channel.addPeer(peer, json.msp);

            let request = {
                txId: client.newTransactionID() //the generated transaction id
            };

            let gBlock = await channel.getGenesisBlock(request);


          //  for(let p of ccp.peers)
          //  {
          //      ccp.peers[p].tlsCACerts.path = path.join(SyndLoanConfig.chainconfig.networkpath,ccp.peers[p].tlsCACerts.path);
          //  }

          //  let newNetwork = await gateway.getNetwork("mychannel");
          //  let newChannel = newNetwork.getChannel();

            let channel_request = {
                targets: [peer],
                block: gBlock,
                txId: newClient.newTransactionID(true)
            }


            let proposal_response = {};
            proposal_response = await channel.joinChannel(channel_request);

            if (proposal_response[0].code !== 200) 
            {
                    throw new Error(`Could not make the peer ${json.peer} join channel ${json.channel}. Error: ${proposal_response[0].message}`);

            }
        }
        catch (err) {
            throw new Error(err.message);
        }
    }

I am sure I am missing something but I am not able to figure out what, and why the joinChannel request is being submitted with MSP set to Org1MSP (by the way, where is this set?)

Appreciate any advice on how to proceed. Thank you.

Ashish Chandra
  • 111
  • 1
  • 8

1 Answers1

0

Was finally able to locate some sample code for Channel.joinChannel.

For those interested, these examples by ksachdeva are extremely helpful.

Essentially, what I was doing wrong was using a channel object associated with an Org1MSP client context, and using that to submit the Channel.joinChannel call.

So, the fix was this (broadly speaking)

Assuming the Org has already been added to the channel,

  1. Create a new client instance using the new Org's common connection profile, or you can create a new client instance from scratch using this sample code by ksachdeva.
  2. Create a new channel instance using Client.newChannel("mychannel") or whatever channel you are joining.
  3. Create a new Orderer instance using Client.newOrderer call, that serves as the Orderer for the channel you are joining. In byfn.sh terminology, this is grpcs://localhost:7050 aka orderer.example.com.
  4. Create a new Peer instance using the peer information for the peer you are adding to the channel.
  5. Add the orderer from Step 3 above to the channel object created in Step 2 using Channel.addOrderer(orderer) API.
  6. Then, the rest of the steps can be followed from the tutorial on Fabric Node SDK site i.e. fetch the genesis block, create a request for joining the peer, and submit the Channel.joinChannel(request).

Please review ksachdeva's example code (link provided earlier in this response) for a complete end-to-end code sample.

Ashish Chandra
  • 111
  • 1
  • 8