
This tutorial illustrates the creation of a Hyperledger Fabric channel using
the Node.js fabric-client SDK. It shows how to use an initial (default) 
channel definition and how to start with that definition to build a 
custom definition. The process to create a network and channels 
also involves creating and working with cryptographic material,
this will not be discussed here.

For more information on:
* getting started with Hyperledger Fabric see
[Building your first network](http://hyperledger-fabric.readthedocs.io/en/latest/build_network.html).
* the configuration of a channel in Hyperledger Fabric and the internal
process of creating and updating see
[Hyperledger Fabric channel configuration](http://hyperledger-fabric.readthedocs.io/en/latest/configtx.html)
* cryptographic generation see
[cryptogen](http://hyperledger-fabric.readthedocs.io/en/latest/build_network.html#crypto-generator)
* configuration transaction generator see
[configtxgen](http://hyperledger-fabric.readthedocs.io/en/latest/build_network.html#configuration-transaction-generator)
* configuration translation tool see
[configtxlator](https://github.com/hyperledger/fabric/tree/master/examples/configtxupdate)

The following assumes an understanding of the Hyperledger Fabric network
(orderers and peers),
[protobuf](https://developers.google.com/protocol-buffers/),
and of Node application development, including the use of the
Javascript `Promise`.

The examples shown below are based on the `balance-transfer` sample application. see [Hyperledger Fabric Samples](http://hyperledger-fabric.readthedocs.io/en/latest/samples.html)

### steps of a channel create:
  * run the configtxgen tool to generate a genesis block
  * run the configtxgen tool to generate an initial binary
  configuration definition
  * get a sign-able channel definition in one of two ways
    1. use the initial binary channel configuration definition
      * use the fabric-client SDK to extract the sign-able channel definition
      from the initial binary channel configuration definition
    2. build a custom definition
      * use the configtxlator to convert the initial binary channel
      configuration definition to readable text
      * edit the readable text
      [more info](http://hyperledger-fabric.readthedocs.io/en/latest/configtx.html)
      * use the configtxlator to convert the edited text to a
      sign-able channel definition
  * use the fabric-client SDK to sign the sign-able channel definition
  * use the fabric-client SDK to send the signatures and the
  sign-able channel definition
   to the orderer
  * use the fabric-client SDK to have the peer join the channel
  * then new channel may be used

## Use the initial definition to build a sign-able channel definition

The initial binary channel configuration definition generated by the
[configtxgen tool](http://hyperledger-fabric.readthedocs.io/en/latest/configtxgen.html)
is a binary file containing the Hyperledger Fabric configuration protobuf
`common.Envelope` element. Inside this element is the `common.ConfigUpdate`
protobuf element. This configuration element is the one that must be signed.
A profile element in the `configtx.yaml` is the source for the initial binary channel
configuration definition created by the configtxgen tool.

```
../../../bin/configtxgen -channelID mychannel -outputCreateChannelTx mychannel.tx -profile TwoOrgsChannel
```
Have the fabric-client SDK extract the config update element from the
`mychannel.tx` file
```
// first read in the file, this gives us a binary config envelope
let envelope_bytes = fs.readFileSync(path.join(__dirname, 'fabric-samples/balance-transfer/artifacts/channel/mychannel.tx'));
// have the nodeSDK extract out the config update
var config_update = client.extractChannelConfig(envelope_bytes);
```
The binary config_update may now be used in the signing process and sent to the
orderer for channel creation.

You may ask why is a `common.ConfigUpdate` used for a create. This makes the
process of create and update the same. The create of a new channel is a delta
on what is defined in the system channel and an update is a delta on what is
defined in the channel. The `common.ConfigUpdate` object submitted will only
contain the changes for both a create and an update.

## Creating a custom sign-able channel definition

The easiest way to get started with creating a custom channel configuration
is to have the configtxlator convert an existing binary that has been or could
be used to create a new channel to human readable JSON. There are many elements
of the configuration and it would be very difficult to start with nothing.
Using the same configtx.yaml file used to generate your Hyperledger Fabric
network, use the configtxgen tool to create a initial binary
configuration definition for a new channel.
Then by sending that binary to the configtxlator to convert it to JSON, you
will be able to see the layout and have a starting point. That JSON could also
be used as a template for creating other new channels on your network.
A new channel will inherit settings from the system channel for settings not
defined in the new channel configuration. Organizations that will be on the
new channel must be defined in a consortium on the system channel. Therefore
having the readable definition of the system channel of your network would be
helpful when creating a new channel. Send the `genesis.block` that was used
to start the Hyperledger Fabric network to the configtxlator to get a
JSON file to be used as a reference.

Use the configtxgen tool to produce the binary config files. From the 
sample directory `fabric-samples/balance-transfer/artifacts/channel`.
<pre>
export FABRIC_CFG_PATH=$PWD
../../../bin/configtxgen -outputBlock genesis.block -profile TwoOrgsOrdererGenesis
../../../bin/configtxgen -channelID mychannel -outputCreateChannelTx mychannel.tx -profile TwoOrgsChannel
</pre>
Send the two binary files to the configtxlator service. Since this step is done
only once and does not require a Node.js application, we will use cURL to
simplify and speed up getting the results. Notice that configtxlator service
path has `decode` (convert from binary to JSON). The path must also include
the type of object of the binary, in the first case, it is a `common.Block`.
The "decode" or "encode" may be done for any of the protobuf `message` object
types found in the `fabric-client\lib\protos` directory protobuf files.
First start the configtxlator service, from the `fabric-samples/bin` directory
```
./configtxlator start
```

Then 
```
curl -X POST --data-binary @genesis.block http://127.0.0.1:7059/protolator/decode/common.Block > genesis.json
curl -X POST --data-binary @mychannel.tx http://127.0.0.1:7059/protolator/decode/common.Envelope > mychannel.json
```
The results of decoding the file `mychannel.tx` which is a `common.Envelope`
produced by the configtxgen tool contains a `common.ConfigUpdate` object.
This object has the name "config_update" within the "payload.data" JSON object.
This is the object that is needed as the source of the template to be used for
creating new channels. The `common.ConfigUpdate` is the object that will be
signed by all organizations and submitted to the orderer to create a
new channel.

The following is the extracted JSON "config_update" (`common.ConfigUpdate`)
object from the decode of the "TwoOrgsChannel" channel create
binary generated above.
```
{
  "channel_id": "mychannel",
  "read_set": {
    "groups": {
      "Application": {
        "groups": {
          "Org1MSP": {}
        }
      }
    },
    "values": {
      "Consortium": {
        "value": {
          "name": "SampleConsortium"
        }
      }
    }
  },
  "write_set": {
    "groups": {
      "Application": {
        "groups": {
          "Org1MSP": {}
        },
        "mod_policy": "Admins",
        "policies": {
          "Admins": {
            "policy": {
              "type": 3,
              "value": {
                "rule": "MAJORITY",
                "sub_policy": "Admins"
              }
            }
          },
          "Readers": {
            "policy": {
              "type": 3,
              "value": {
                "sub_policy": "Readers"
              }
            }
          },
          "Writers": {
            "policy": {
              "type": 3,
              "value": {
                "sub_policy": "Writers"
              }
            }
          }
        },
        "version": "1"
      }
    },
    "values": {
      "Consortium": {
        "value": {
          "name": "SampleConsortium"
        }
      }
    }
  }
}
```
Note that the `Consortium` name used must exist on the system channel.
All organizations that you wish to add to the new channel must be defined
under in the `Consortium` section with that name on the system channel.
Use the decoded genesis block to verify all values, for example by looking
in the `genesis.json` file generated above. To add an organizations to the
channel, they must be placed under the `groups` section under the
`Applications` section as shown above. See that `Org1MSP` is a property of
`Applications.groups` section. In this example all of the settings for the
organization `Org1MSP` will be inherited from the system channel (notice
  the empty object "{}" for this organization's properties). To see the
  current settings for this organization look within the `SampleConsortium`
  section under the `Consortium` section of the system channel (the genesis
    block of the system channel).

Once you have a JSON configuration representing your channel, send it the
`configtxlator` to be encoded into a configuration binary. The following
example of sending a REST request to the `configtxlator` uses the Node.js
package `superagent` because of the ease of use for HTTP requests.
```
var response = superagent.post('http://127.0.0.1:7059/protolator/encode/common.ConfigUpdate',
  config_json.toString())
  .buffer()
  .end((err, res) => {
    if(err) {
      logger.error(err);
      return;
    }
    config_proto = res.body;
  });
```

## Signing and submitting the channel update

The binary configuration must be signed by all organizations. The application
will have to store the binary configuration and have it available to be signed
along with storing all the signatures as it collects them. Then once the
signing is complete, the application will send the binary configuration and
all the signatures to the orderer using the fabric-client
SDK API `createChannel()`.

First the signing, assuming the `client` fabric-client SDK object has
a valid user in a required organization
```
var signature = client.signChannelConfig(config_proto);
signatures.push(signature);
```
Now it is time for the channel create, assuming that the `signatures` object
is an array of `common.ConfigSignature` returned
by the `client.signChannelConfig()` method. 

Note: The orderer must be started with the `genesis.block` that was generated
from the same configuration file as the initial binary channel
configuration definition 
```
// create an orderer object to represent the orderer of the network
var orderer = client.newOrderer(url,opts);

// have the SDK generate a transaction id
let tx_id = client.newTransactionID();

request = {
  config: config_proto, //the binary config
  signatures : signatures, // the collected signatures
  name : 'mychannel', // the channel name
  orderer : orderer, //the orderer from above
  txId  : tx_id //the generated transaction id
};

// this call will return a Promise
client.createChannel(request)
```
The `createChannel` API returns a `Promise` to return the status of the submit.
The channel create will take place asynchronously by the orderer.

After a small delay of a few seconds the channel will have been created by the
orderer and may now be joined by the peers. Issue the following to the peers
that are required on the channel. This is a two step process of first getting
the genesis block of the channel and then sending it to the peer. In the
following example the genesis block was retrieved from the orderer,
but could have also been loaded from a file.
```
// set the channel up with network endpoints
var orderer  = client.newOrderer(orderer_url,orderer_opts);
channel.addOrderer(orderer);
var peer = client.newPeer(peer_url,peer_opts);
channel.addPeer(peer);

tx_id = client.newTransactionID();
let g_request = {
  txId : 	tx_id
};

// get the genesis block from the orderer
channel.getGenesisBlock(g_request).then((block) =>{
  genesis_block = block;
  tx_id = client.newTransactionID();
  let j_request = {
    targets : targets,
    block : genesis_block,
    txId : 	tx_id
  };

  // send genesis block to the peer
  return channel.joinChannel(j_request);
}).then((results) =>{
  if(results && results.response && results.response.status == 200) {
    // join successful
  } else {
    // not good
  }
});
```



<a rel="license" href="http://creativecommons.org/licenses/by/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by/4.0/88x31.png" /></a><br />This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>.
