Step 8: Invite Another AWS Account to be a Member and Create a Multi-Member Channel - Amazon Managed Blockchain (AMB)

Step 8: Invite Another AWS Account to be a Member and Create a Multi-Member Channel

Now that you have a Hyperledger Fabric network set up using Amazon Managed Blockchain (AMB), with an initial member in your AWS account and a VPC endpoint with a service name, you are ready to invite additional members. You invite additional members by creating a proposal for an invitation that existing members vote on. Since the blockchain network at this point consists of only one member, the first member always has the only vote on the invitation proposal for the second member. In the steps that follow, the network creator has an initial member named org1 and the invited member is named org2. For proof of concept, you can create an invitation proposal for an additional member in the same AWS account that you used to create the network, or you can create an invitation proposal for a different AWS account.

After the invitation proposal is approved, the invited account can create a member. Invited members are free to reject the invitation or ignore it until the invitation proposal expires. The invited account needs the network ID and VPC endpoint service name of the blockchain network to create a member. For more information, see Work with Invitations. The invited account also needs to fulfill the prerequisites listed in Prerequisites and Considerations.

Step 8.1: Create an Invitation Proposal

Create a proposal to invite an AWS account to create a member and join the network according to the following procedures. You need the AWS account ID of the member you want to invite. You can also invite your own account to create an additional member. If you are using the CLI, you also need the Network ID and Member ID that you created in Step 1: Create the Network and First Member.

  1. Open the AMB Access console at https://console.aws.amazon.com/managedblockchain/.

  2. From the navigation pane, choose Networks, and then choose the network to which you want to invite an AWS account.

  3. Choose Proposals and then choose Propose invitation.

  4. For Submit proposal as, choose the member in your account that submits the proposal.

    Note

    The member who submits the proposal must also vote on it. A Yes vote is not automatically assumed.

  5. Enter an optional Description . The description appears to other members. It's a good way to communicate key points or a reminder about the proposal before they vote.

  6. For each AWS account that you want to invite, enter the account number in the space provided. Choose Add to enter additional accounts.

  7. Choose Create.

  • Type a command similar to the following. Replace the value of Principal with the AWS account ID that you want to invite. Replace the value of --member-id with the value for the member in your account that submits the proposal.

    [ec2-user@ip-192-0-2-17 ~]$ aws managedblockchain create-proposal \ --actions Invitations=[{Principal=123456789012}] \ --network-id n-MWY63ZJZU5HGNCMBQER7IN6OIU \ --member-id m-K46ICRRXJRCGRNNS4ES4XUUS5A

    The command returns the proposal ID, as shown in the following example:

    { "ProposalId": "p-ZR7KUD2YYNESLNG6RQ33X3FUFE" }

Step 8.2: Vote Yes on the Proposal

After you create the invitation proposal, use the first member that you created to vote Yes and approve the proposal. You must do this within the duration defined by the network voting policy.

  1. Open the AMB Access console at https://console.aws.amazon.com/managedblockchain/.

  2. From the navigation pane, choose Networks, and then choose the Network for which the proposal was made.

  3. Choose Proposals.

  4. Under Active, choose the Proposal ID to vote on.

  5. Under Vote on proposal, select the member in your account to vote as. If your account has multiple members, each member gets a vote.

  6. Choose Yes to vote to approve the proposal. Voting yes is a requirement for the second member to be created in the next step. Choosing No rejects the proposal and an invitation is not created.

  7. Choose to Confirm your vote.

Step 8.3: Create the New Member

To accept an invitation to create a member and join a network, the steps are similar whether you are creating a member in a AMB Access network in a different AWS account or your own AWS account. You first create the member as shown in the following procedures. If you use the AWS CLI, make sure that you have the relevant information, including the Network ID and the Invitation ID that the network sent to your account. When you create a member, you specify the name that identifies your member on the network. You also specify the admin user and password to authenticate to your member certificate authority (CA).

  1. Open the AMB Access console at https://console.aws.amazon.com/managedblockchain/.

  2. From the navigation pane, choose Invitations.

  3. Select the invitation that you want to accept from the list, and then choose Accept invitation. To view more information about the network you are invited to join, choose the network Name from the list

  4. Under Create member and join network, configure your network member according to the following guidelines:

    1. Enter a Member name that will be visible to all members and an optional Description.

    2. Under Hyperledger Fabric certificate authority (CA) configuration specify a username and password to be used as the administrator on the Hyperledger Fabric CA. Remember the user name and password. You need them later any time that you create users and resources that need to authenticate.

  5. Choose Create member and join network.

  • Use the create-member command similar to the example below. Replace the value of --network-id with the Network ID that you are joining and --invitation-id with the Invitation ID sent to your account from the network.

    aws managedblockchain create-member \ --network-id n-MWY63ZJZU5HGNCMBQER7IN6OIU \ --invitation-id i-XL9MDD6LVWWDNA9FF94Y4TFTE \ --member-configuration 'Name=org2,Description=MyMemberDesc,\ FrameworkConfiguration={Fabric={AdminUsername=MyAdminUsername,\ AdminPassword=Example-Password123}}'

    The command returns output similar to the following:

    { "MemberId": "m-J46DNSFRTVCCLONS9DT5TTLS2A" }

Additional Steps to Configure a Member

After you create the member, perform the following steps to configure the member. As you perform the steps, replace values with those specific to your member configuration, including the Member ID returned by the previous command. The Network ID and OrderingServiceEndpoint are the same for all members.

Step 8.4: Share Artifacts and Information with the Network Creator

Before a shared channel can be created, the following artifacts and information need to be shared with org1 by org2:

  • org1 needs the org2 administrative certificate—This certificate is saved the /home/ec2-user/admin-msp/admincerts directory on org2's Hyperledger Fabric client after Step 5: Enroll an Administrative User. This is referenced in the following steps as Org2AdminCerts

  • org1 needs the org2 root CA—This certificate is saved to org2's /home/ec2-user/admin-msp/cacerts directory on org2's Hyperledger Fabric client after the same step as previous. This is referenced in the following steps as Org2CACerts

  • org1 needs the Endpoint of the peer node that will join the channel—This Endpoint value is output by the get-node command after Step 3: Create a Peer Node in Your Membership is complete.

Step 8.5: The Channel Creator (org1) Creates Artifacts for org2's MSP

In the following example, the channel creator is org1. The CA administrator for org1 copies the certificates from the step above to a location on the Hyperledger Fabric client computer. The Membership Service Provider (MSP) uses the certificates to authenticate the member.

On the channel creator's Hyperledger Fabric client, use the following commands to create directories to store the certificates, and then copy the certificates from the previous step to the new directories:

mkdir /home/ec2-user/org2-msp mkdir /home/ec2-user/org2-msp/admincerts mkdir /home/ec2-user/org2-msp/cacerts cp Org2AdminCerts /home/ec2-user/org2-msp/admincerts cp Org2CACerts /home/ec2-user/org2-msp/cacerts

Org1 needs org2's member ID. You can get this by running the list-members command on org1's Hyperledger Fabric client as shown in the following example:

aws managedblockchain list-members \ --network-id n-MWY63ZJZU5HGNCMBQER7IN6OIU

The channel creator (org1) should verify that the required artifacts for channel creation are saved on the Hyperledger Fabric client as shown in the following list:

  • Org1 MSP artifacts:

    • /home/ec2-user/admin-msp/signcerts/certname.pem

    • /home/ec2-user/admin-msp/admincerts/certname.pem

    • /home/ec2-user/admin-msp/cacerts/certname.pem

    • /home/ec2-user/admin-msp/keystore/keyname_sk

  • Org2 MSP artifacts

    • /home/ec2-user/org2-msp/admincerts/certname.pem

    • /home/ec2-user/org2-msp/cacerts/certname.pem

  • The TLS CA cert used for the Region:

    • /home/ec2-user/managedblockchain-tls-chain.pem

  • Addresses of all peer nodes to join the channel for both org1 and org2.

  • The respective member IDs of org1 and org2.

  • A configtx.yaml file, which you create in the following step, saved to the /home/ec2-user directory on the channel creator's Hyperledger Fabric client.

    Note

    If you created this configtx file earlier, delete the old file, rename it, or replace it.

Step 8.6: Create configtx for the Multi-Member Channel

The configtx.yaml file contains details of the channel configuration. For more information, see Channel Configuration (configtx) in the Hyperledger Fabric documentation.

The channel creator creates this file on the Hyperledger File client. If you compare this file to the file created in Step 6.1: Create configtx for Hyperledger Fabric Channel Creation, you see that this configtx.yaml specifies two members in the channel.

Use a text editor to create a file with the following contents and save it as configtx.yaml on your Hyperledger File client.

  • Replace Org1MemberID with the MemberID of the first member that you created when you created the network. For example, m-K46ICRRXJRCGRNNS4ES4XUUS5A.

  • For &Org1, the MSPDir is set to the same directory location, /opt/home/admin-msp, that you established using the CORE_PEER_MSPCONFIGPATH environment variable in the Docker container for the Hyperledger Fabric CLI in step 4.4 above.

  • Replace Org2MemberID with the MemberID of the second member that you created in step 8.3. For example, m-J46DNSFRTVCCLONS9DT5TTLS2A.

  • For &Org2, the MSPDir is set to the same directory location, /opt/home/org2-msp, that you created and copied artifacts to in step 8.5.

Important

This file is sensitive. Artifacts from pasting can cause the file to fail with marshalling errors. We recommend using emacs to edit it. You can also use VI, but before using VI, enter :set paste, press i to enter insert mode, paste the contents, press escape, and then enter :set nopaste before saving.

################################################################################ # # ORGANIZATIONS # # This section defines the organizational identities that can be referenced # in the configuration profiles. # ################################################################################ Organizations: # Org1 defines an MSP using the sampleconfig. It should never be used # in production but may be used as a template for other definitions. - &Org1 # Name is the key by which this org will be referenced in channel # configuration transactions. # Name can include alphanumeric characters as well as dots and dashes. Name: Org1MemberID # ID is the key by which this org's MSP definition will be referenced. # ID can include alphanumeric characters as well as dots and dashes. ID: Org1MemberID # SkipAsForeign can be set to true for org definitions which are to be # inherited from the orderer system channel during channel creation. This # is especially useful when an admin of a single org without access to the # MSP directories of the other orgs wishes to create a channel. Note # this property must always be set to false for orgs included in block # creation. SkipAsForeign: false Policies: &Org1Policies Readers: Type: Signature Rule: "OR('Org1.member', 'Org2.member')" # If your MSP is configured with the new NodeOUs, you might # want to use a more specific rule like the following: # Rule: "OR('Org1.admin', 'Org1.peer', 'Org1.client')" Writers: Type: Signature Rule: "OR('Org1.member', 'Org2.member')" # If your MSP is configured with the new NodeOUs, you might # want to use a more specific rule like the following: # Rule: "OR('Org1.admin', 'Org1.client')" Admins: Type: Signature Rule: "OR('Org1.admin')" # MSPDir is the filesystem path which contains the MSP configuration. MSPDir: /opt/home/admin-msp # AnchorPeers defines the location of peers which can be used for # cross-org gossip communication. Note, this value is only encoded in # the genesis block in the Application section context. AnchorPeers: - Host: 127.0.0.1 Port: 7051 - &Org2 Name: Org2MemberID ID: Org2MemberID SkipAsForeign: false Policies: &Org2Policies Readers: Type: Signature Rule: "OR('Org2.member', 'Org1.member')" # If your MSP is configured with the new NodeOUs, you might # want to use a more specific rule like the following: # Rule: "OR('Org1.admin', 'Org1.peer', 'Org1.client')" Writers: Type: Signature Rule: "OR('Org2.member', 'Org1.member')" # If your MSP is configured with the new NodeOUs, you might # want to use a more specific rule like the following: # Rule: "OR('Org1.admin', 'Org1.client')" Admins: Type: Signature Rule: "OR('Org2.admin')" # MSPDir is the filesystem path which contains the MSP configuration. MSPDir: /opt/home/org2-msp # AnchorPeers defines the location of peers which can be used for # cross-org gossip communication. Note, this value is only encoded in # the genesis block in the Application section context. AnchorPeers: - Host: 127.0.0.1 Port: 7052 ################################################################################ # # CAPABILITIES # # This section defines the capabilities of fabric network. This is a new # concept as of v1.1.0 and should not be utilized in mixed networks with # v1.0.x peers and orderers. Capabilities define features which must be # present in a fabric binary for that binary to safely participate in the # fabric network. For instance, if a new MSP type is added, newer binaries # might recognize and validate the signatures from this type, while older # binaries without this support would be unable to validate those # transactions. This could lead to different versions of the fabric binaries # having different world states. Instead, defining a capability for a channel # informs those binaries without this capability that they must cease # processing transactions until they have been upgraded. For v1.0.x if any # capabilities are defined (including a map with all capabilities turned off) # then the v1.0.x peer will deliberately crash. # ################################################################################ Capabilities: # Channel capabilities apply to both the orderers and the peers and must be # supported by both. # Set the value of the capability to true to require it. # Note that setting a later Channel version capability to true will also # implicitly set prior Channel version capabilities to true. There is no need # to set each version capability to true (prior version capabilities remain # in this sample only to provide the list of valid values). Channel: &ChannelCapabilities # V2.0 for Channel is a catchall flag for behavior which has been # determined to be desired for all orderers and peers running at the v2.0.0 # level, but which would be incompatible with orderers and peers from # prior releases. # Prior to enabling V2.0 channel capabilities, ensure that all # orderers and peers on a channel are at v2.0.0 or later. V2_0: true # Orderer capabilities apply only to the orderers, and may be safely # used with prior release peers. # Set the value of the capability to true to require it. Orderer: &OrdererCapabilities # V1.1 for Orderer is a catchall flag for behavior which has been # determined to be desired for all orderers running at the v1.1.x # level, but which would be incompatible with orderers from prior releases. # Prior to enabling V2.0 orderer capabilities, ensure that all # orderers on a channel are at v2.0.0 or later. V2_0: true # Application capabilities apply only to the peer network, and may be safely # used with prior release orderers. # Set the value of the capability to true to require it. # Note that setting a later Application version capability to true will also # implicitly set prior Application version capabilities to true. There is no need # to set each version capability to true (prior version capabilities remain # in this sample only to provide the list of valid values). Application: &ApplicationCapabilities # V2.0 for Application enables the new non-backwards compatible # features and fixes of fabric v2.0. # Prior to enabling V2.0 orderer capabilities, ensure that all # orderers on a channel are at v2.0.0 or later. V2_0: true ################################################################################ # # CHANNEL # # This section defines the values to encode into a config transaction or # genesis block for channel related parameters. # ################################################################################ Channel: &ChannelDefaults # Policies defines the set of policies at this level of the config tree # For Channel policies, their canonical path is # /Channel/<PolicyName> Policies: # Who may invoke the 'Deliver' API Readers: Type: ImplicitMeta Rule: "ANY Readers" # Who may invoke the 'Broadcast' API Writers: Type: ImplicitMeta Rule: "ANY Writers" # By default, who may modify elements at this config level Admins: Type: ImplicitMeta Rule: "MAJORITY Admins" # Capabilities describes the channel level capabilities, see the # dedicated Capabilities section elsewhere in this file for a full # description Capabilities: <<: *ChannelCapabilities ################################################################################ # # APPLICATION # # This section defines the values to encode into a config transaction or # genesis block for application-related parameters. # ################################################################################ Application: &ApplicationDefaults # Organizations is the list of orgs which are defined as participants on # the application side of the network Organizations: # Policies defines the set of policies at this level of the config tree # For Application policies, their canonical path is # /Channel/Application/<PolicyName> Policies: &ApplicationDefaultPolicies LifecycleEndorsement: Type: ImplicitMeta Rule: "ANY Readers" Endorsement: Type: ImplicitMeta Rule: "ANY Readers" Readers: Type: ImplicitMeta Rule: "ANY Readers" Writers: Type: ImplicitMeta Rule: "ANY Writers" Admins: Type: ImplicitMeta Rule: "MAJORITY Admins" Capabilities: <<: *ApplicationCapabilities ################################################################################ # # PROFILES # # Different configuration profiles may be encoded here to be specified as # parameters to the configtxgen tool. The profiles which specify consortiums # are to be used for generating the orderer genesis block. With the correct # consortium members defined in the orderer genesis block, channel creation # requests may be generated with only the org member names and a consortium # name. # ################################################################################ Profiles: TwoOrgChannel: <<: *ChannelDefaults Consortium: AWSSystemConsortium Application: <<: *ApplicationDefaults Organizations: - *Org1 - *Org2

Run the following command to generate the configtx peer block:

docker exec cli configtxgen \ -outputCreateChannelTx /opt/home/ourchannel.pb \ -profile TwoOrgChannel -channelID ourchannel \ --configPath /opt/home/

Step 8.7: Create the Channel

The channel creator (org1) uses the following command on their Hyperledger Fabric client to submit the channel to the orderer, which creates the channel ourchannel. The command example assumes that Docker environment variables have been configured as described in Step 4.4: Configure and Run Docker Compose to Start the Hyperledger Fabric CLI and that the $ORDERER environment variable has been set on the client.

docker exec cli peer channel create -c ourchannel \ -f /opt/home/ourchannel.pb -o $ORDERER \ --cafile /opt/home/managedblockchain-tls-chain.pem --tls

Step 8.8: Get Channel Genesis Block

Both org1 and org2 need to run the following command on their respective Hyperledger Fabric clients to get the channel's genesis (oldest) block. For more information about the peer channel command, see peer channel in Hyperledger Fabric documentation.

docker exec cli peer channel fetch oldest /opt/home/ourchannel.block \ -c ourchannel -o $ORDERER \ --cafile /opt/home/managedblockchain-tls-chain.pem --tls

Step 8.9: Join Peer Nodes to the Channel

Both org1 and org2 need to run the following command on their respective Hyperledger Fabric clients to join their peer nodes to the channel. For more information, see the peer channel join command example in peer channel section of in the Hyperledger Fabric documentation.

docker exec cli peer channel join -b /opt/home/ourchannel.block \ -o $ORDERER --cafile /opt/home/managedblockchain-tls-chain.pem --tls

Optionally, after you join a peer to a channel, you can set up the peer node as an anchor peer. Anchor peers support the gossip protocol, which is required for some features of Hyperledger Fabric, such as private data collections and service discovery. For more information, see Add an Anchor Peer to a Channel.

Step 8.10: Install Chaincode

Both org1 and org2 run the following commands on their respective Hyperledger Fabric clients to install example chaincode on their respective peer nodes:

  1. Install the example chaincode package on the peer node.

    docker exec cli peer lifecycle chaincode install abstore.tar.gz
  2. Verify that the chaincode package is installed on the peer node.

    docker exec cli peer lifecycle chaincode queryinstalled

    The command returns the following if the package is installed successfully.

    Installed chaincodes on peer: Package ID: MyPackageID, Label: abstore_1
  3. Approve the chaincode definition for the organization. Replace MyPackageID with the Package ID value returned in the previous step.

    export CC_PACKAGE_ID=MyPackageID docker exec cli peer lifecycle chaincode approveformyorg \ --orderer $ORDERER --tls --cafile /opt/home/managedblockchain-tls-chain.pem \ --channelID ourchannel --name myjointcc --version v0 --sequence 1 --package-id $CC_PACKAGE_ID
  4. Check the commit readiness of the chaincode definition.

    docker exec cli peer lifecycle chaincode checkcommitreadiness \ --orderer $ORDERER --tls --cafile /opt/home/managedblockchain-tls-chain.pem \ --channelID ourchannel --name myjointcc --version v0 --sequence 1

    The command returns true if the chaincode is ready to be committed.

  5. Commit the chaincode definition on the channel.

    docker exec cli peer lifecycle chaincode commit \ --orderer $ORDERER --tls --cafile /opt/home/managedblockchain-tls-chain.pem \ --channelID ourchannel --name myjointcc --version v0 --sequence 1

Step 8.11: Query Chaincode

Channel members can run the following command to query the chaincode:

docker exec cli peer chaincode query -C ourchannel \ -n myjointcc -c '{"Args":["query","a"]}'

The previous command returns the value of a, which you instantiated to a value of 100.

You may need to wait a brief moment for the instantiation from the previous step to complete before you run the following command to query a value:

Step 8.12: Invoke Chaincode

With the channel created and configured with both members, and the chaincode instantiated with values and an endorsement policy, channel members can invoke chaincode. This example command is similar to the example in Step 7.11: Invoke the Chaincode. However, the command uses the --peerAddresses option to specify the endpoints of peer nodes that belong to members in the endorsement policy. The example specifies Org2PeerNodeEndpoint in addition to Org1PeerEndpoint.

docker exec cli peer chaincode invoke \ -C ourchannel -n myjointcc -c '{"Args":["invoke","a","b","10"]}' \ --peerAddresses Org1PeerEndpoint \ --tlsRootCertFiles /opt/home/managedblockchain-tls-chain.pem \ --peerAddresses Org2PeerNodeEndpoint \ --tlsRootCertFiles /opt/home/managedblockchain-tls-chain.pem \ -o $ORDERER --cafile /opt/home/managedblockchain-tls-chain.pem --tls

When we query again using the following command:

docker exec cli peer chaincode query -C ourchannel \ -n myjointcc -c '{"Args":["query","a"]}'

The command should return the value of a as the new value 90.