# Updating a Channel Configuration

## What is a Channel Configuration?

Channel configurations contain all of the information relevant to the
administration of a channel. Most importantly, the channel configuration
specifies which organizations are members of channel, but it also includes other
channel-wide configuration information such as channel access policies and block
batch sizes.

This configuration is stored on the ledger in a **block**, and is therefore
known as a configuration (config) block. Configuration blocks contain a single
configuration. The first of these blocks is known as the "genesis block" and
contains the initial configuration required to bootstrap a channel. Each time
the configuration of a channel changes it is done through a new configuration
block, with the latest configuration block representing the current channel
configuration. Orderers and peers keep the current channel configuration in
memory to facilitate all channel operations such as cutting a new block and
validating block transactions.

Because configurations are stored in blocks, updating a config happens through a
process called a "configuration transaction" (even though the process is a
little different from a normal transaction). Updating a config is a process of
pulling the config, translating into a format that humans can read, modifying it
and then submitting it for approval.

For a more in-depth look at the process for pulling a config and translating it
into JSON, check out [Adding an Org to a Channel](./channel_update_tutorial.html).
In this doc, we'll be focusing on the different ways you can edit a config and
the process for getting it signed.

## Editing a Config

Channels are highly configurable, but not infinitely so. Different configuration
elements have different modification policies (which specify the group of
identities required to sign the config update).

To see the scope of what's possible to change it's important to look at a config
in JSON format. The [Adding an Org to a Channel](./channel_update_tutorial.html)
tutorial generates one, so if you've gone through that doc you can simply refer to it.
For those who have not, we'll provide one here (for ease of readability, it might be
helpful to put this config into a viewer that supports JSON folding, like atom or
Visual Studio).

<details>
  <summary>
    **Click here to see the config**
  </summary>
  ```
  {
  "channel_group": {
    "groups": {
      "Application": {
        "groups": {
          "Org1MSP": {
            "mod_policy": "Admins",
            "policies": {
              "Admins": {
                "mod_policy": "Admins",
                "policy": {
                  "type": 1,
                  "value": {
                    "identities": [
                      {
                        "principal": {
                          "msp_identifier": "Org1MSP",
                          "role": "ADMIN"
                        },
                        "principal_classification": "ROLE"
                      }
                    ],
                    "rule": {
                      "n_out_of": {
                        "n": 1,
                        "rules": [
                          {
                            "signed_by": 0
                          }
                        ]
                      }
                    },
                    "version": 0
                  }
                },
                "version": "0"
              },
              "Readers": {
                "mod_policy": "Admins",
                "policy": {
                  "type": 1,
                  "value": {
                    "identities": [
                      {
                        "principal": {
                          "msp_identifier": "Org1MSP",
                          "role": "MEMBER"
                        },
                        "principal_classification": "ROLE"
                      }
                    ],
                    "rule": {
                      "n_out_of": {
                        "n": 1,
                        "rules": [
                          {
                            "signed_by": 0
                          }
                        ]
                      }
                    },
                    "version": 0
                  }
                },
                "version": "0"
              },
              "Writers": {
                "mod_policy": "Admins",
                "policy": {
                  "type": 1,
                  "value": {
                    "identities": [
                      {
                        "principal": {
                          "msp_identifier": "Org1MSP",
                          "role": "MEMBER"
                        },
                        "principal_classification": "ROLE"
                      }
                    ],
                    "rule": {
                      "n_out_of": {
                        "n": 1,
                        "rules": [
                          {
                            "signed_by": 0
                          }
                        ]
                      }
                    },
                    "version": 0
                  }
                },
                "version": "0"
              }
            },
            "values": {
              "AnchorPeers": {
                "mod_policy": "Admins",
                "value": {
                  "anchor_peers": [
                    {
                      "host": "peer0.org1.example.com",
                      "port": 7051
                    }
                  ]
                },
                "version": "0"
              },
              "MSP": {
                "mod_policy": "Admins",
                "value": {
                  "config": {
                    "admins": [
                      " "
                    ],
                    "crypto_config": {
                      "identity_identifier_hash_function": "SHA256",
                      "signature_hash_family": "SHA2"
                    },
                    "name": "Org1MSP",
                    "root_certs": [
                      " "
                    ],
                    "tls_root_certs": [
                      " "
                    ]
                  },
                  "type": 0
                },
                "version": "0"
              }
            },
            "version": "1"
          },
          "Org2MSP": {
            "mod_policy": "Admins",
            "policies": {
              "Admins": {
                "mod_policy": "Admins",
                "policy": {
                  "type": 1,
                  "value": {
                    "identities": [
                      {
                        "principal": {
                          "msp_identifier": "Org2MSP",
                          "role": "ADMIN"
                        },
                        "principal_classification": "ROLE"
                      }
                    ],
                    "rule": {
                      "n_out_of": {
                        "n": 1,
                        "rules": [
                          {
                            "signed_by": 0
                          }
                        ]
                      }
                    },
                    "version": 0
                  }
                },
                "version": "0"
              },
              "Readers": {
                "mod_policy": "Admins",
                "policy": {
                  "type": 1,
                  "value": {
                    "identities": [
                      {
                        "principal": {
                          "msp_identifier": "Org2MSP",
                          "role": "MEMBER"
                        },
                        "principal_classification": "ROLE"
                      }
                    ],
                    "rule": {
                      "n_out_of": {
                        "n": 1,
                        "rules": [
                          {
                            "signed_by": 0
                          }
                        ]
                      }
                    },
                    "version": 0
                  }
                },
                "version": "0"
              },
              "Writers": {
                "mod_policy": "Admins",
                "policy": {
                  "type": 1,
                  "value": {
                    "identities": [
                      {
                        "principal": {
                          "msp_identifier": "Org2MSP",
                          "role": "MEMBER"
                        },
                        "principal_classification": "ROLE"
                      }
                    ],
                    "rule": {
                      "n_out_of": {
                        "n": 1,
                        "rules": [
                          {
                            "signed_by": 0
                          }
                        ]
                      }
                    },
                    "version": 0
                  }
                },
                "version": "0"
              }
            },
            "values": {
              "AnchorPeers": {
                "mod_policy": "Admins",
                "value": {
                  "anchor_peers": [
                    {
                      "host": "peer0.org2.example.com",
                      "port": 9051
                    }
                  ]
                },
                "version": "0"
              },
              "MSP": {
                "mod_policy": "Admins",
                "value": {
                  "config": {
                    "admins": [
                      " "
                    ],
                    "crypto_config": {
                      "identity_identifier_hash_function": "SHA256",
                      "signature_hash_family": "SHA2"
                    },
                    "name": "Org2MSP",
                    "root_certs": [
                      " "
                    ],
                    "tls_root_certs": [
                      " "
                    ]
                  },
                  "type": 0
                },
                "version": "0"
              }
            },
            "version": "1"
          },
          "Org3MSP": {
            "groups": {},
            "mod_policy": "Admins",
            "policies": {
              "Admins": {
                "mod_policy": "Admins",
                "policy": {
                  "type": 1,
                  "value": {
                    "identities": [
                      {
                        "principal": {
                          "msp_identifier": "Org3MSP",
                          "role": "ADMIN"
                        },
                        "principal_classification": "ROLE"
                      }
                    ],
                    "rule": {
                      "n_out_of": {
                        "n": 1,
                        "rules": [
                          {
                            "signed_by": 0
                          }
                        ]
                      }
                    },
                    "version": 0
                  }
                },
                "version": "0"
              },
              "Readers": {
                "mod_policy": "Admins",
                "policy": {
                  "type": 1,
                  "value": {
                    "identities": [
                      {
                        "principal": {
                          "msp_identifier": "Org3MSP",
                          "role": "MEMBER"
                        },
                        "principal_classification": "ROLE"
                      }
                    ],
                    "rule": {
                      "n_out_of": {
                        "n": 1,
                        "rules": [
                          {
                            "signed_by": 0
                          }
                        ]
                      }
                    },
                    "version": 0
                  }
                },
                "version": "0"
              },
              "Writers": {
                "mod_policy": "Admins",
                "policy": {
                  "type": 1,
                  "value": {
                    "identities": [
                      {
                        "principal": {
                          "msp_identifier": "Org3MSP",
                          "role": "MEMBER"
                        },
                        "principal_classification": "ROLE"
                      }
                    ],
                    "rule": {
                      "n_out_of": {
                        "n": 1,
                        "rules": [
                          {
                            "signed_by": 0
                          }
                        ]
                      }
                    },
                    "version": 0
                  }
                },
                "version": "0"
              }
            },
            "values": {
              "MSP": {
                "mod_policy": "Admins",
                "value": {
                  "config": {
                    "admins": [
                      " "
                    ],
                    "crypto_config": {
                      "identity_identifier_hash_function": "SHA256",
                      "signature_hash_family": "SHA2"
                    },
                    "name": "Org3MSP",
                    "root_certs": [
                      " "
                    ],
                    "tls_root_certs": [
                      " "
                    ]
                  },
                  "type": 0
                },
                "version": "0"
              }
            },
            "version": "0"
          }
        },
        "mod_policy": "Admins",
        "policies": {
          "Admins": {
            "mod_policy": "Admins",
            "policy": {
              "type": 3,
              "value": {
                "rule": "MAJORITY",
                "sub_policy": "Admins"
              }
            },
            "version": "0"
          },
          "Readers": {
            "mod_policy": "Admins",
            "policy": {
              "type": 3,
              "value": {
                "rule": "ANY",
                "sub_policy": "Readers"
              }
            },
            "version": "0"
          },
          "Writers": {
            "mod_policy": "Admins",
            "policy": {
              "type": 3,
              "value": {
                "rule": "ANY",
                "sub_policy": "Writers"
              }
            },
            "version": "0"
          }
        },
        "version": "1"
      },
      "Orderer": {
        "groups": {
          "OrdererOrg": {
            "mod_policy": "Admins",
            "policies": {
              "Admins": {
                "mod_policy": "Admins",
                "policy": {
                  "type": 1,
                  "value": {
                    "identities": [
                      {
                        "principal": {
                          "msp_identifier": "OrdererMSP",
                          "role": "ADMIN"
                        },
                        "principal_classification": "ROLE"
                      }
                    ],
                    "rule": {
                      "n_out_of": {
                        "n": 1,
                        "rules": [
                          {
                            "signed_by": 0
                          }
                        ]
                      }
                    },
                    "version": 0
                  }
                },
                "version": "0"
              },
              "Readers": {
                "mod_policy": "Admins",
                "policy": {
                  "type": 1,
                  "value": {
                    "identities": [
                      {
                        "principal": {
                          "msp_identifier": "OrdererMSP",
                          "role": "MEMBER"
                        },
                        "principal_classification": "ROLE"
                      }
                    ],
                    "rule": {
                      "n_out_of": {
                        "n": 1,
                        "rules": [
                          {
                            "signed_by": 0
                          }
                        ]
                      }
                    },
                    "version": 0
                  }
                },
                "version": "0"
              },
              "Writers": {
                "mod_policy": "Admins",
                "policy": {
                  "type": 1,
                  "value": {
                    "identities": [
                      {
                        "principal": {
                          "msp_identifier": "OrdererMSP",
                          "role": "MEMBER"
                        },
                        "principal_classification": "ROLE"
                      }
                    ],
                    "rule": {
                      "n_out_of": {
                        "n": 1,
                        "rules": [
                          {
                            "signed_by": 0
                          }
                        ]
                      }
                    },
                    "version": 0
                  }
                },
                "version": "0"
              }
            },
            "values": {
              "MSP": {
                "mod_policy": "Admins",
                "value": {
                  "config": {
                    "admins": [
                      " "
                    ],
                    "crypto_config": {
                      "identity_identifier_hash_function": "SHA256",
                      "signature_hash_family": "SHA2"
                    },
                    "name": "OrdererMSP",
                    "root_certs": [
                      " "
                    ],
                    "tls_root_certs": [
                      " "
                    ]
                  },
                  "type": 0
                },
                "version": "0"
              }
            },
            "version": "0"
          }
        },
        "mod_policy": "Admins",
        "policies": {
          "Admins": {
            "mod_policy": "Admins",
            "policy": {
              "type": 3,
              "value": {
                "rule": "MAJORITY",
                "sub_policy": "Admins"
              }
            },
            "version": "0"
          },
          "BlockValidation": {
            "mod_policy": "Admins",
            "policy": {
              "type": 3,
              "value": {
                "rule": "ANY",
                "sub_policy": "Writers"
              }
            },
            "version": "0"
          },
          "Readers": {
            "mod_policy": "Admins",
            "policy": {
              "type": 3,
              "value": {
                "rule": "ANY",
                "sub_policy": "Readers"
              }
            },
            "version": "0"
          },
          "Writers": {
            "mod_policy": "Admins",
            "policy": {
              "type": 3,
              "value": {
                "rule": "ANY",
                "sub_policy": "Writers"
              }
            },
            "version": "0"
          }
        },
        "values": {
          "BatchSize": {
            "mod_policy": "Admins",
            "value": {
              "absolute_max_bytes": 103809024,
              "max_message_count": 10,
              "preferred_max_bytes": 524288
            },
            "version": "0"
          },
          "BatchTimeout": {
            "mod_policy": "Admins",
            "value": {
              "timeout": "2s"
            },
            "version": "0"
          },
          "ChannelRestrictions": {
            "mod_policy": "Admins",
            "version": "0"
          },
          "ConsensusType": {
            "mod_policy": "Admins",
            "value": {
              "type": "solo"
            },
            "version": "0"
          }
        },
        "version": "0"
      }
    },
    "mod_policy": "",
    "policies": {
      "Admins": {
        "mod_policy": "Admins",
        "policy": {
          "type": 3,
          "value": {
            "rule": "MAJORITY",
            "sub_policy": "Admins"
          }
        },
        "version": "0"
      },
      "Readers": {
        "mod_policy": "Admins",
        "policy": {
          "type": 3,
          "value": {
            "rule": "ANY",
            "sub_policy": "Readers"
          }
        },
        "version": "0"
      },
      "Writers": {
        "mod_policy": "Admins",
        "policy": {
          "type": 3,
          "value": {
            "rule": "ANY",
            "sub_policy": "Writers"
          }
        },
        "version": "0"
      }
    },
    "values": {
      "BlockDataHashingStructure": {
        "mod_policy": "Admins",
        "value": {
          "width": 4294967295
        },
        "version": "0"
      },
      "Consortium": {
        "mod_policy": "Admins",
        "value": {
          "name": "SampleConsortium"
        },
        "version": "0"
      },
      "HashingAlgorithm": {
        "mod_policy": "Admins",
        "value": {
          "name": "SHA256"
        },
        "version": "0"
      },
      "OrdererAddresses": {
        "mod_policy": "/Channel/Orderer/Admins",
        "value": {
          "addresses": [
            "orderer.example.com:7050"
          ]
        },
        "version": "0"
      }
    },
    "version": "0"
  },
  "sequence": "3",
  "type": 0
}
```
</details>

A config might look intimidating in this form, but once you study it you'll see
that it has a logical structure.

Beyond the definitions of the policies -- defining who can do certain things
at the channel level, and who has the permission to change who can change the
config -- channels also have other kinds of features that can be modified using
a config update. [Adding an Org to a Channel](./channel_update_tutorial.html)
takes you through one of the most important -- adding an org to a channel. Some
other things that are possible to change with a config update include:

* **Batch Size.** These parameters dictate the number and size of transactions
in a block. No block will appear larger than `absolute_max_bytes` large or
with more than `max_message_count` transactions inside the block. If it is
possible to construct a block under `preferred_max_bytes`, then a block will
be cut prematurely, and transactions larger than this size will appear in
their own block.

   ```
   {
     "absolute_max_bytes": 102760448,
     "max_message_count": 10,
     "preferred_max_bytes": 524288
   }
  ```

* **Batch Timeout.** The amount of time to wait after the first transaction
arrives for additional transactions before cutting a block. Decreasing this
value will improve latency, but decreasing it too much may decrease throughput
by not allowing the block to fill to its maximum capacity.

  ```
  { "timeout": "2s" }
  ```

* **Channel Restrictions.** The total number of channels the orderer is willing
to allocate may be specified as max_count. This is primarily useful in
pre-production environments with weak consortium `ChannelCreation` policies.

  ```
  {
   "max_count":1000
  }
  ```

* **Channel Creation Policy.** Defines the policy value which will be set as the
mod_policy for the Application group of new channels for the consortium it is defined in.
The signature set attached to the channel creation request will be checked against
the instantiation of this policy in the new channel to ensure that the channel
creation is authorized. Note that this config value is only set in the orderer
system channel.

  ```
  {
  "type": 3,
  "value": {
    "rule": "ANY",
    "sub_policy": "Admins"
    }
  }
  ```

* **Kafka brokers.** When `ConsensusType` is set to `kafka`, the `brokers` list
enumerates some subset (or preferably all) of the Kafka brokers for the
orderer to initially connect to at startup. *Note that it is not possible to
change your consensus type after it has been established (during the
bootstrapping of the genesis block)*.

  ```
  {
    "brokers": [
      "kafka0:9092",
      "kafka1:9092",
      "kafka2:9092",
      "kafka3:9092"
    ]
  }
  ```

* **Anchor Peers Definition.** Defines the location of the anchor peers for
each Org.

  ```
  {
    "host": "peer0.org2.example.com",
      "port": 9051
  }
  ```

* **Hashing Structure.** The block data is an array of byte arrays. The hash of
the block data is computed as a Merkle tree. This value specifies the width of
that Merkle tree. For the time being, this value is fixed to `4294967295`
which corresponds to a simple flat hash of the concatenation of the block data
bytes.

  ```
  { "width": 4294967295 }
  ```

* **Hashing Algorithm.** The algorithm used for computing the hash values
encoded into the blocks of the blockchain. In particular, this affects the
data hash, and the previous block hash fields of the block. Note, this field
currently only has one valid value (`SHA256`) and should not be changed.

  ```
  { "name": "SHA256" }
  ```

* **Block Validation.** This policy specifies the signature requirements for a
block to be considered valid. By default, it requires a signature from some
member of the ordering org.

  ```
  {
    "type": 3,
    "value": {
      "rule": "ANY",
      "sub_policy": "Writers"
    }
  }
  ```

* **Orderer Address.** A list of addresses where clients may invoke the orderer
`Broadcast` and `Deliver` functions. The peer randomly chooses among these
addresses and fails over between them for retrieving blocks.

  ```
  {
    "addresses": [
      "orderer.example.com:7050"
    ]
  }
  ```

Just as we add an Org by adding their artifacts and MSP information, you can remove
them by reversing the process.

**Note** that once the consensus type has been defined and the network has been
bootstrapped, it is not possible to change it through a configuration update.

There is another important channel configuration (especially for v1.1) known as
**Capability Requirements**. It has its own doc that can be found
[here](./capability_requirements.html).

Let's say you want to edit the block batch size for the channel (because this is
a single numeric field, it's one of the easiest changes to make). First to make
referencing the JSON path easy, we define it as an environment variable.

To establish this, take a look at your config, find what you're looking for, and
back track the path.

If you find batch size, for example, you'll see that it's a `value` of the
`Orderer`. `Orderer` can be found under `groups`, which is under
`channel_group`. The batch size value has a parameter under `value` of
`max_message_count`.

Which would make the path this:

```
 export MAXBATCHSIZEPATH=".channel_group.groups.Orderer.values.BatchSize.value.max_message_count"
```

Next, display the value of that property:

```
jq "$MAXBATCHSIZEPATH" config.json
```

Which should return a value of `10` (in our sample network at least).

Now, let's set the new batch size and display the new value:

```
 jq "$MAXBATCHSIZEPATH = 20" config.json > modified_config.json
 jq "$MAXBATCHSIZEPATH" modified_config.json
```

Once you've modified the JSON, it's ready to be converted and submitted. The
scripts and steps in [Adding an Org to a Channel](./channel_update_tutorial.html)
will take you through the process for converting the JSON, so let's look at the
process of submitting it.

## Get the Necessary Signatures

Once you've successfully generated the protobuf file, it's time to get it
signed. To do this, you need to know the relevant policy for whatever it is you're
trying to change.

By default, editing the configuration of:
* **A particular org** (for example, changing anchor peers) requires only the admin
signature of that org.
* **The application** (like who the member orgs are) requires a majority of the
application organizations' admins to sign.
* **The orderer** requires a majority of the ordering organizations' admins (of
which there are by default only 1).
* **The top level `channel` group** requires both the agreement of a majority of
application organization admins and orderer organization admins.

If you have made changes to the default policies in the channel, you'll need to
compute your signature requirements accordingly.

*Note: you may be able to script the signature collection, dependent on your
application. In general, you may always collect more signatures than are
required.*

The actual process of getting these signatures will depend on how you've set up
your system, but there are two main implementations. Currently, the Fabric
command line defaults to a "pass it along" system. That is, the Admin of the Org
proposing a config update sends the update to someone else (another Admin,
typically) who needs to sign it. This Admin signs it (or doesn't) and passes it
along to the next Admin, and so on, until there are enough signatures for the
config to be submitted.

This has the virtue of simplicity -- when there are enough signatures, the last
Admin can simply submit the config transaction (in Fabric, the `peer channel update`
command includes a signature by default). However, this process will only be
practical in smaller channels, since the "pass it along" method can be time
consuming.

The other option is to submit the update to every Admin on a channel and wait
for enough signatures to come back. These signatures can then be stitched
together and submitted. This makes life a bit more difficult for the Admin who
created the config update (forcing them to deal with a file per signer) but is
the recommended workflow for users which are developing Fabric management
applications.

Once the config has been added to the ledger, it will be a best practice to
pull it and convert it to JSON to check to make sure everything was added
correctly. This will also serve as a useful copy of the latest config.

<!--- Licensed under Creative Commons Attribution 4.0 International License
https://creativecommons.org/licenses/by/4.0/ -->
