-
Notifications
You must be signed in to change notification settings - Fork 8.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FAB-17270] Create a channel tutorial part2 #1105
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As usual Nik, you lay it all out nicely and make it feel straightforward.
I've read through it but would still like to run through all the commands and try it out.
806c1f4
to
a12a0bd
Compare
Going to take the draft tag off of this, though will need lots more comment before we can merge. We may want to merge this series one at a time if it is easier. |
/azp run |
Azure Pipelines successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Loving the new policy diagrams
3e38e4a
to
0712670
Compare
58c6d44
to
a150e2a
Compare
982a98b
to
1b2bccd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really excellent piece of work here. A few comments throughout.
The only other thing I would mention is would it be worth breaking the Policies piece of this topic into a 3rd section of the tutorial? There's a clear delineation in the content here and that would make it overall shorter to read through each one separately.
But not required.
|
||
- The `Policies` section is used create a set of signature policies associated with each organization. We will discuss these policies in more detail when we discuss [channel policies](#channel-policies). | ||
|
||
- The `AnchorPeers` field lists the anchor peers for an organization. Anchor peers are required in order to take advantage of features such as private data and service discovery. It is recommended that organizations select at least one anchor peer. While an organization can select their anchor peers on the channel for the first time using the `configtxgen` tool, it is recommended that each organization set anchor peers by using the `configtxlator` tool to [update the channel configuration](create_channel.html#set-anchor-peers). As a result, this field is not required. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While an organization can select their anchor peers on the channel for the first time using the configtxgen
tool, it is recommended that each organization set anchor peers by using the configtxlator
tool to update the channel configuration
I thought the peers had to be joined to the channel first before they can be made an anchor peer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That detail is provided in the other tutorial: https://hyperledger-fabric.readthedocs.io/en/latest/create_channel/create_channel.html#set-anchor-peers
After an organizations has joined their peers to the channel, they should select at least one of their peers to become an anchor peer
|
||
## Application | ||
|
||
The application section defines the policies that govern how peer organizations can interact with application channels. These policies govern the number of organizations that need to approve a chaincode definition or sign a request to update the channel configuration. These policies are also used to restrict access to channel resources, such as the ability to write to the channel ledger or to query channel events. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: These policies govern the number of [peer] organizations that need to approve a chaincode definition or sign a request to update the channel configuration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
## Profiles | ||
|
||
The `configtxgen` tool reads the channel profiles in the **Profiles** section to build a channel configuration. Each profile uses YAML syntax to gather data from other sections of the file. The `configtxgen` tool uses this configuration to create a channel creation transaction for an applications channel, or to write the channel genesis block for a system channel. To learn more about YAML syntax, [Wikipedia](https://en.wikipedia.org/wiki/YAML) provides a good place to get started. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: I would insert a simple heading here: TwoOrgsOrdererGenesis and then another further down (line 157) when you switch to the second profile to TwoOrgsChannel for the reader to more easily switch gears.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
<<: *ApplicationCapabilities | ||
``` | ||
|
||
The system channel is used by the ordering service as a template to create application channels. The nodes of the ordering service that are defined in the system channel become the default consenter set of new channels, while the administrators of the ordering service become the orderer administrators of the channel. The channel MSPs of channel members are transferred to the new channel from the system channel. After the channel is created, ordering nodes can be added or removed from the channel by updating the channel configuration. You can also update the channel configuration to [add other organizations as channel members](../channel_update_tutorial.html). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nicely said!
|
||
The system channel is used by the ordering service as a template to create application channels. The nodes of the ordering service that are defined in the system channel become the default consenter set of new channels, while the administrators of the ordering service become the orderer administrators of the channel. The channel MSPs of channel members are transferred to the new channel from the system channel. After the channel is created, ordering nodes can be added or removed from the channel by updating the channel configuration. You can also update the channel configuration to [add other organizations as channel members](../channel_update_tutorial.html). | ||
|
||
The `TwoOrgsChannel` provides name of the `SampleConsortium` hosted by the test network system channel. As a result, the ordering service defined in the `TwoOrgsOrdererGenesis` profile becomes channel consenter set. In the `Application` section, both organizations from the consortium, Org1 and Org2, are included as channel members. The channel uses `V2_0` as the application capabilities, and uses the default policies from the **Application** section to govern how peer organizations will interact with the channel. The application channel also uses the default policies from the **Channel** section and enables `V2_0` as the channel capability level. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The TwoOrgsChannel
provides [the] name of the SampleConsortium
..
or
The TwoOrgsChannel
includes the SampleConsortium
that was defined in the system channel.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we call out that the Application section is unique to/only required for application channels?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the second point, I think that is self evident. I still think people will still use the examples very closely, but just have more context now.
|
||
### Channel modification policies | ||
|
||
The channel **structure** is governed by modification policies within the channel configuration. Every group within the channel configuration has a modification policy that needs to be satisfied in order to update the information contained within the group. As example, the group that defines an organization, the group the defines the complete set of channel members, and the group that defines the channel consenter set each have a different modification policy. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As [an] example,
For example,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
peer/Propose: /Channel/Application/Writers | ||
``` | ||
|
||
Most of the default ACLs point to the ImplicitMeta policies in the application section of the channel configuration. To extend the example above, an organization can invoke a chaincode if they if the can satisfy the `/Channel/Application/Writers` policy. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if they if the can satisfy the
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
![channel writer policies](application-writers.png) | ||
|
||
*Figure 4: The peer/Propose ACL is satisfied by the /Channel/Application/Writers policy. This policy can be satisfied by a transaction submitted by a client application from any organization with the writers signature policy.* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These diagrams are really helpful. One thing that occurred to me is that if we included examples of the signature policies in the right column, they would tie all this together.
So for example in this diagram, instead of in the Org1 box where you have Writers, we could have
Writers "OR('Org1MSP.admin', 'Org1MSP.client')"
Just an idea. I know that could be alot of work and might clutter up your diagrams, but for me it visually ties the ImplicitMeta and Signature policies together.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea, but I think it would get awfully busy, so I will leave for now.
|
||
![Application admins](application-admins.png) | ||
|
||
*Figure 2: A request submitted to the channel contains signatures from Org1, Org2, and Org3, satisfying the signature policies for each organization. As a result, the request satisfies the Channel/Application/Admins policy. The Org3 check is in light green because the signature was not required to reach to a majority.* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like your usage of the light green checkmark to visually convey this concept.
|
||
While it is possible to build the channel creation transaction file manually, it is easier to create a channel by using the `configtx.yaml` file and the [configtxgen](../commands/configtxgen.html) tool. The `configtx.yaml` file contains the information that is required to build the channel configuration in a format that can be easily read and edited by humans. The `configtxgen` tool reads the information in the `configtx.yaml` file and writes it to the [protobuf format](https://developers.google.com/protocol-buffers) that can be read by Fabric. | ||
|
||
You can use this tutorial to learn how to use the `configtx.yaml` file to build the initial channel configuration that is stored in the genesis block. The tutorial will discuss the portion of channel configuration that is built by each section of file. Because different sections of the file work together to create the policies that govern the channel, we will discuss channel policies in a [their own section](#channel-policies). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After reading the entire topic I came back to this section. I think it deserves more focus. Maybe a heading like Purpose of this tutorial or something like that.
I love how you take apart and explain each element in each section - very well done. I was not prepared for that when I started reading this topic. Would it benefit from links here to each section below? I'm torn because I think it is useful to read from top to bottom to understand it all and more importantly how the Profiles section uses the content from the other sections. But when I come back later and want to re-read a section it might be nice to have a link directly to the portion of the file that I am interested in. Maybe it will already be there in the left toc? Certainly not a requirement but a nice to have.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will put an overview heading after the first two paragraphs to break up the text. A list of sections of links wont either, and will help tie the channel policies together as a section.
|
||
## Signature policies | ||
|
||
Each channel member is associated with a set of signature policies. Signature policies read the digital signatures that are attached to the transactions or channel update requests that are submitted to the channel. Each signature policy lists a set of organizations and roles whose signatures need to be attached to a transaction in order to satisfy the policy. You can see the set of signature policies associated with peer organization Org1 in the **Organizations** section of `configtx.yaml` below: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Each channel member is associated with a set of signature policies
This is technically correct, in that you could create a mapping from channel member to signature policies which include them, but this is a really very weird way to look at it to me. Rather, signature policies reference channel members, rather than the other way around.
Signature policies read the digital signatures that are attached to the transactions or channel update requests that are submitted to the channel.
I don't mean to be pedantic, but policies do not read signatures. Fabric (the peer or the orderer) reads signatures from some structure, be it a transaction, a proposal, a deliver request, a block, a service discovery request, what have you. The signatures which Fabric reads are then given as a parameter to a policy, and the policy evaluates that set of signatures to determine if they satisfy the policy.
While I'm being overly pedantic, I'll add that "signature policies" are poorly named. All of the policies are actually evaluated over identities, and identities are validated by signature. The name was chosen before design was completed and we thought there would be other types of data a policy might evaluate over, but that never happened. I don't think it's appropriate to add this confusion to the doc, but wanted to share.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replacing this paragraph with the following: By default, each channel member defines a set of signature policies that references their organization. When a transaction or channel update request is submitted to the peer and ordering nodes on the channel channel, the nodes read the signatures attached to the transaction and evaluate them against the signature policies defined in the channel configuration. Every signature policy has rule that specifies the set of organizations and identities whose signatures can satisfy the policy.
Rule: "OR('Org1MSP.peer')" | ||
``` | ||
|
||
Org1 is associated with four signature policies. The policies can only be satisfied by signatures from Org1. However, each policy lists a different set of roles from within the organization that satisfy the policy. The `Admins` policy can only be satisfied by the transactions submitted by an identity with an admin role, while only identities with a peer role can satisfy the Endorsement policy. Each transaction can satisfy multiple signature policies. For example, if a transaction submitted to eh channel was endorsed by a peer from Org1 and Org2, the transaction would satisfy the `Endorsement` signature policy that is associated with both Org1 and Org2. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Org1 is associated with four signature policies.
Same language problem here. Org1 defines four signature policies. It may be referenced or associated with other signature policies in the system.
The
Admins
policy can only be satisfied by the transactions submitted by an identity with an admin role, while only identities with a peer role can satisfy the Endorsement policy.
You say transactions for admins, but identities for endorsement. 'identities' is correct for both.
Each transaction can satisfy multiple signature policies. For example, if a transaction submitted to eh channel was endorsed by a peer from Org1 and Org2, the transaction would satisfy the
Endorsement
signature policy that is associated with both Org1 and Org2.
I would say "A single signature set may satisfy multiple signature policies. For example, if the endorsements attached to a transaction were provided by both Org1 and Org2, then this signature set would satisfy the 'Endorsement' policy of Org1 and Org2.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replacing the paragraph with the following: All the policies above can be satisfied by signatures from Org1. However, each policy lists a different set of roles from within the organization that are able to satisfy the policy. The
Adminspolicy can only be satisfied by the transactions submitted by an identity with an admin role, while only identities with a peer role can satisfy the Endorsement policy. A set of signatures attached to a single transaction can satisfy multiple signature policies. For example, if the endorsements attached to a transaction were provided by both Org1 and Org2, then this signature set would satisfy the
Endorsement policy of Org1 and Org2.
|
||
## ImplicitMeta Policies | ||
|
||
The signature policies for each organization are read by ImplicitMeta policies at higher levels of the channel configuration. Instead of directly reading the signatures that are submitted to the channel, ImplicitMeta policies read other policies in the channel configuration. An ImplicitMeta policies is satisfied if a transaction satisfies the signature policies that are referenced by that policy. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's hard for me to read whether the language is all referring only to the sample configtx.yaml here, or whether it's talking more broadly about policies. I would say that "In the default" or "In the sample" configtx.yaml, the signature policies of each organization are evaluated by ImplicitMeta policies at higher levels of the channel configuration.
For instance, if you set a signature policy at the application level for /Channel/Application/Readers, then the /Channel/Application/Org*/Readers policies are no longer used for anything.
Instead of directly reading the signatures that are submitted to the channel, ImplicitMeta policies read other policies in the channel configuration.
Same issue above about 'reading', policies are handed signature sets (or, identity sets really) and evaluated. In the ImplicitMeta case, these policies evaluate policies defined more deeply in the channel config tree, but if anything, the sort of verb being done to the signature set and the sort of verb being done to the sub-policies strikes me as different.
An ImplicitMeta policies is satisfied if a transaction satisfies the signature policies that are referenced by that policy.
Well, the ImplicitMeta policy has a Rule, which indicates how many of the sub-policies (which may be signature policies, or may be more implicit meta policies) must be satisfied. Notably 'All', 'Any', or 'Majority'.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The article is about the default policies work, with understanding that once users have the background they need, they can change them. I added this sentence to the opening:
If you use the default policies used by the Fabric test network or the Fabric sample configuration, each channel you create will use a combination of signature policies, ImplicitMeta policies, and Access Control Lists to determine how organizations interact with the channel and agree to update the channel structure.`
I also updated the ImplictMeta paragraph in response to your comments: If your channel uses the default policies, the signature policies for each organization are evaluated by ImplicitMeta policies at higher levels of the channel configuration. Instead of directly evaluating the signatures that are submitted to the channel, ImplicitMeta policies have rules specify a set of other policies in the channel configuration that can satisfy the policy. A transaction can satisfy an ImplicitMeta policy if it can satisfy the underlying set of signature policies that are referenced by the policy.
|
||
![Application policies](application-policies.png) | ||
|
||
*Figure 1: The Admins ImplicitMeta policy is satisfied by the Admins signature policy associated with each organization.* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, it's satisfied by any majority of the Admins signature policies of the organizations. It's common (and typical) that an implicit policy will not satisfy all of the sub-policies (unless the rule 'All' is used, which, we don't use as a default anywhere).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated caption: Figure 1: The Admins ImplicitMeta policy can be satisfied by a majority of the Admins signature policies that are defined by each organization.
|
||
## Channel modification policies | ||
|
||
The channel **structure** is governed by modification policies within the channel configuration. Every group within the channel configuration has a modification policy that needs to be satisfied in order to update the information contained within the group. For example, the group that defines an organization, the group the defines the complete set of channel members, and the group that defines the channel consenter set each have a different modification policy. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For better, or perhaps for worse, it's not simply every group, but every item. So, adding an organization is 'modifying the membership of the application group', so triggers that group's mod policy. On the other hand, modifying the ACLs of the application group is simply modifying one of the group's values, and not the group itself, so in this case, the mod policy of the ACLs is checked.
This is a bit of a headache because it means there are tons of permutations, which is why we default (almost) all of the mod policies to be simply 'Admins'. Since this is read as a relative path, this implies the 'Admins' policy of the containing group. But, you can, and we see users who do, modify this to point to explicit policies. For instance, the orderer admins may set the /Channel/Orderer/BatchTimeout value's mod_policy to be "/Channel/Application/Admins" so as to give up control over the batch timeout to the application admins.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updating the first paragraph: Each component of the channel configuration has a modification policy that needs to be satisfied in order to be updated by channel members. For example, the policies and channel MSP defined by each organization, the application group that contains the members of the channel, and the components of the configuration that define the channel consenter set each have a different modification policy.
Again, I think i will leave the changes that more advanced users can make to the reader, or to other tutorials.
|
||
*Figure 6: A request submitted to remove an ordering node from the channel contains signatures from the three ordering organizations in the network, satisfying the Channel/Orderer/Admins policy. The Org3 check is in light green because the signature was not required to reach to a majority.* | ||
|
||
The `Channel/Orderer/BlockValidation` policy governs which ordering nodes have the ability to write new blocks to the channel. Because all ordering administrators have the writers signature policy, all ordering organizations can write new blocks to the channel. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't make sense to me. I would say:
The Channel/Orderer/BlockValidation
policy is used by peers when receiving blocks (either from ordering, or via gossip). The peers check that the signature set attesting to the block's validity satisfies the block validation policy to confirm that the block was generated by ordering. By default, any ordering org 'Writers' are authorized to attest to a block's validity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An edited version of your suggestion: The `Channel/Orderer/BlockValidation` policy is used by peers to confirm that new blocks being added to the channel were generated by an ordering node that is part of the channel consenter set, and that the block was not tampered with or created by another peer organization. By default, any orderer organization with a `writers` signature policy can create and validate blocks for the channel.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the updates @nikhil550 looks much better. Found a few typos or minor things in the new text. We can always merge as is, or fix them here, up to you.
|
||
## Signature policies | ||
|
||
By default, each channel member defines a set of signature policies that references their organization. When a transaction or channel update request is submitted to the peer and ordering nodes on the channel channel, the nodes read the signatures attached to the transaction and evaluate them against the signature policies defined in the channel configuration. Every signature policy has rule that specifies the set of organizations and identities whose signatures can satisfy the policy. You can see the signature policies defined by Org1 in the **Organizations** section of `configtx.yaml` below: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: "channel channel"
When a transaction or channel update request is submitted to the peer and ordering nodes
Maybe: When a proposal is submitted to a peer, or a transaction is submitted to the ordering nodes
My concern is confusion caused by this sentence implying that config updates are submitted to peers -- they are not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
channel channel
Removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Going to use your suggestion: When a proposal is submitted to a peer, or a transaction is submitted to the ordering nodes.
Rule: "OR('Org1MSP.peer')" | ||
``` | ||
|
||
All the policies above can be satisfied by signatures from Org1. However, each policy lists a different set of roles from within the organization that are able to satisfy the policy. The `Admins` policy can only be satisfied by the transactions submitted by an identity with an admin role, while only identities with a peer role can satisfy the Endorsement policy. A set of signatures attached to a single transaction can satisfy multiple signature policies. For example, if the endorsements attached to a transaction were provided by both Org1 and Org2, then this signature set would satisfy the `Endorsement` policy of Org1 and Org2. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
Admins
policy can only be satisfied by the transactions submitted by an identity
Typo, I think? Should say "satisfied by transactions", not "satisfied by the transactions". Though I might opt simply to change this to "satisfied by an identity" like is done for the Endorsement policy in the second half of the sentence.
Also, Admins
is monospace code, but Endorsement is not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Going to say: The Admins
policy can only be satisfied by transactions submitted by an identity with an admin role, while only identities with a peer role can satisfy the Endorsement
policy.
By transactions seems redundant, but I think will help keep things grounded for more users.
|
||
*Figure 6: A request submitted to remove an ordering node from the channel contains signatures from the three ordering organizations in the network, satisfying the Channel/Orderer/Admins policy. The Org3 check is in light green because the signature was not required to reach to a majority.* | ||
|
||
The `Channel/Orderer/BlockValidation` policy is used by peers to confirm that new blocks being added to the channel were generated by an ordering node that is part of the channel consenter set, and that the block was not tampered with or created by another peer organization. By default, any orderer organization with a `writers` signature policy can create and validate blocks for the channel. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small typo: writers
instead of Writers
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Signed-off-by: NIKHIL E GUPTA <negupta@us.ibm.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@Mergifyio backport release-2.1 |
Command
|
Signed-off-by: NIKHIL E GUPTA <negupta@us.ibm.com> Co-authored-by: NIKHIL E GUPTA <negupta@us.ibm.com> (cherry picked from commit a6ad9d8)
Signed-off-by: NIKHIL E GUPTA <negupta@us.ibm.com> Co-authored-by: NIKHIL E GUPTA <negupta@us.ibm.com> (cherry picked from commit a6ad9d8)
Signed-off-by: NIKHIL E GUPTA <negupta@us.ibm.com> Co-authored-by: NIKHIL E GUPTA <negupta@us.ibm.com>
Signed-off-by: NIKHIL E GUPTA negupta@us.ibm.com
Type of change
Description
The create a channel tutorial as a series of tutorials. This draft PR offers the second two in the series for review