Skip to content

Commit

Permalink
[FAB-4821] Improve configtxlator reconfig examples
Browse files Browse the repository at this point in the history
This improves the configtxlator README.md to use '.pb' as the suffix for
files contain protobuf messages rather than '.proto' which confuses the
'make protos' target.

It also improves the scripts for the existing examples, to use common
functions and adds an interactive mode which pauses between each step,
so that the user may inspect the file artifacts as they are generated.

It additionally improves error checking on the output of the assorted
commands, as the script would not reliably fail at the error points, but
might continue several statements.

Finally, it adds a new example for adding an organization to a channel.

Change-Id: I5c60cefe364f41dfc0d15c1dc5dd8f9ddc85ea2b
Signed-off-by: Jason Yellick <jyellick@us.ibm.com>
  • Loading branch information
Jason Yellick committed Jun 16, 2017
1 parent 040a9b1 commit 012f721
Show file tree
Hide file tree
Showing 7 changed files with 552 additions and 130 deletions.
118 changes: 97 additions & 21 deletions examples/configtxupdate/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ For extensibility, and because certain fields must be signed over, many proto fi

To convert a proto to its human readable JSON equivalent, simply post the binary proto to the rest target `http://$SERVER:$PORT/protolator/decode/<message.Name>` where `<message.Name>` is the fully qualified proto name of the message.

For instance, to decode a configuration block saved as `configuration_block.proto`, run the command:
For instance, to decode a configuration block saved as `configuration_block.pb`, run the command:

```
curl -X POST --data-binary @configuration_block.proto http://127.0.0.1:7059/protolator/decode/common.Block
curl -X POST --data-binary @configuration_block.pb http://127.0.0.1:7059/protolator/decode/common.Block
```

To convert the human readable JSON version of the proto message, simply post the JSON version to `http://$SERVER:$PORT/protolator/encode/<message.Name` where `<message.Name>` is again the fully qualified proto name of the message.
Expand All @@ -51,10 +51,10 @@ Any of the configuration related protos, including `common.Block`, `common.Envel

Given two different configurations, it is possible to compute the config update which transitions between them. Simply POST the two `common.Config` proto encoded configurations as `multipart/formdata`, with the original as field `original` and the updated as field `updated`, to `http://$SERVER:$PORT/configtxlator/compute/update-from-configs`.

For example, given the original config as the file `original_config.proto` and the updated config as the file `updated_config.proto` for the channel `desiredchannel`
For example, given the original config as the file `original_config.pb` and the updated config as the file `updated_config.pb` for the channel `desiredchannel`:

```
curl -X POST -F channel=desiredchannel -F original=@original_config.proto -F updated=@updated_config.proto http://127.0.0.1:7059/configtxlator/compute/update-from-configs
curl -X POST -F channel=desiredchannel -F original=@original_config.pb -F updated=@updated_config.pb http://127.0.0.1:7059/configtxlator/compute/update-from-configs
```

## Bootstraping example
Expand All @@ -72,23 +72,35 @@ $ configtxlator start
2017-05-31 12:57:22.499 EDT [configtxlator] main -> INFO 001 Serving HTTP requests on port: 7059
```

Then, in another window, build and run the `configtxgen` tool to produce a genesis block for the ordering system channel.
Then, in another window, build the `configtxgen` tool.

```
$ make configtxgen
build/bin/configtxgen
CGO_CFLAGS=" " GOBIN=/home/yellickj/go/src/github.com/hyperledger/fabric/build/bin go install -tags "nopkcs11" -ldflags "-X github.com/hyperledger/fabric/common/metadata.Version=1.0.0-alpha3-snapshot-63e0dc80f -X github.com/hyperledger/fabric/common/metadata.BaseVersion=0.3.1 -X github.com/hyperledger/fabric/common/metadata.BaseDockerLabel=org.hyperledger.fabric -X github.com/hyperledger/fabric/common/metadata.DockerNamespace=hyperledger -X github.com/hyperledger/fabric/common/metadata.BaseDockerNamespace=hyperledger" github.com/hyperledger/fabric/common/configtx/tool/configtxgen
Binary available as build/bin/configtxgen
```

It is recommended to run the example by invoking the script `fabric/example/configtxupdate/bootstrap_batchsize/script.sh` as follows:

```
INTERACTIVE=true ./script.sh
```
$ configtxgen -outputBlock genesis_block.proto

This will write out what is happening at each step, pause, and allow you to inspect the artifacts generated before proceeding. Alternatively, you may run the steps below manually.

----
First produce a genesis block for the ordering system channel.

```
$ configtxgen -outputBlock genesis_block.pb
2017-05-31 14:15:16.634 EDT [common/configtx/tool] main -> INFO 001 Loading configuration
2017-05-31 14:15:16.646 EDT [common/configtx/tool] doOutputBlock -> INFO 002 Generating genesis block
2017-05-31 14:15:16.646 EDT [common/configtx/tool] doOutputBlock -> INFO 003 Writing genesis block
```
Decode the genesis block into a human editable form.
```
curl -X POST --data-binary @genesis_block.proto http://127.0.0.1:7059/protolator/decode/common.Block > genesis_block.json
curl -X POST --data-binary @genesis_block.pb http://127.0.0.1:7059/protolator/decode/common.Block > genesis_block.json
```
Edit the `genesis_block.json` file in your favorite JSON editor, or manipulate it programatically, here, we use the JSON CLI tool `jq`. For simplicity, we are editing the batch size for the channel, because it is a single numeric field, but any edits, including policy and MSP edits may be made here.
```
Expand All @@ -106,15 +118,12 @@ $ jq "$MAXBATCHSIZEPATH" updated_genesis_block.json
```
The genesis block is now ready to be re-encoded into the native proto form to be used for bootstrapping.
```
curl -X POST --data-binary @updated_genesis_block.json http://127.0.0.1:7059/protolator/encode/common.Block > updated_genesis_block.proto
curl -X POST --data-binary @updated_genesis_block.json http://127.0.0.1:7059/protolator/encode/common.Block > updated_genesis_block.pb
```
The `updated_genesis_block.proto` file may now be used as the genesis block for bootstrapping an ordering system channel.
The `updated_genesis_block.pb` file may now be used as the genesis block for bootstrapping an ordering system channel.

## Reconfiguration example

Reconfiguring a channel can be performed in a very similar way to modifying a genesis config.


First build and start the `configtxlator`.

```
Expand Down Expand Up @@ -143,17 +152,28 @@ build/bin/orderer
CGO_CFLAGS=" " GOBIN=/home/yellickj/go/src/github.com/hyperledger/fabric/build/bin go install -tags "" -ldflags "-X github.com/hyperledger/fabric/common/metadata.Version=1.0.0-alpha3-snapshot-63e0dc80f -X github.com/hyperledger/fabric/common/metadata.BaseVersion=0.3.1 -X github.com/hyperledger/fabric/common/metadata.BaseDockerLabel=org.hyperledger.fabric -X github.com/hyperledger/fabric/common/metadata.DockerNamespace=hyperledger -X github.com/hyperledger/fabric/common/metadata.BaseDockerNamespace=hyperledger" github.com/hyperledger/fabric/orderer
Binary available as build/bin/orderer
```

Start the orderer using the default options, including the provisional bootstrapper which will create a `testchainid` ordering system channel.

```
ORDERER_GENERAL_LOGLEVEL=debug orderer
```

Reconfiguring a channel can be performed in a very similar way to modifying a genesis config.

The recommended path to proceed with this example is to run the script located at `fabric/example/configtxupdate/reconfigure_batchsize/script.sh` by invoking

```
INTERACTIVE=true ./script.sh
```

This will write out what is happening at each step, pause, and allow you to inspect the artifacts generated before proceeding. Alternatively, you may run the steps below manually.

----

At this point, executing `examples/reconfig/script.sh` in another window will increase the batch size of the ordering system channel by 1, or, you may follow the steps below to do the process interactively.

```
$ peer channel fetch config config_block.proto -o 127.0.0.1:7050 -c testchainid
$ peer channel fetch config config_block.pb -o 127.0.0.1:7050 -c testchainid
2017-05-31 15:11:37.617 EDT [msp] getMspConfig -> INFO 001 intermediate certs folder not found at [/home/yellickj/go/src/github.com/hyperledger/fabric/sampleconfig/msp/intermediatecerts]. Skipping.: [stat /home/yellickj/go/src/github.com/hyperledger/fabric/sampleconfig/msp/intermediatecerts: no such file or directory]
2017-05-31 15:11:37.617 EDT [msp] getMspConfig -> INFO 002 crls folder not found at [/home/yellickj/go/src/github.com/hyperledger/fabric/sampleconfig/msp/intermediatecerts]. Skipping.: [stat /home/yellickj/go/src/github.com/hyperledger/fabric/sampleconfig/msp/crls: no such file or directory]
Received block: 1
Expand All @@ -164,7 +184,7 @@ Received block: 1
Send the config block to the `configtxlator` service for decoding:

```
curl -X POST --data-binary @config_block.proto http://127.0.0.1:7059/protolator/decode/common.Block > config_block.json
curl -X POST --data-binary @config_block.pb http://127.0.0.1:7059/protolator/decode/common.Block > config_block.json
```

Extract the config section from the block:
Expand All @@ -182,25 +202,25 @@ jq ".channel_group.groups.Orderer.values.BatchSize.value.max_message_count = 30"
Re-encode both the original config, and the updated config into proto.

```
curl -X POST --data-binary @config.json http://127.0.0.1:7059/protolator/encode/common.Config > config.proto
curl -X POST --data-binary @config.json http://127.0.0.1:7059/protolator/encode/common.Config > config.pb
```

```
curl -X POST --data-binary @updated_config.json http://127.0.0.1:7059/protolator/encode/common.Config > updated_config.proto
curl -X POST --data-binary @updated_config.json http://127.0.0.1:7059/protolator/encode/common.Config > updated_config.pb
```

Now, with both configs properly encoded, send them to the `configtxlator` service to compute the config update which transitions between the two.

```
curl -X POST -F original=@config.proto -F updated=@updated_config.proto http://127.0.0.1:7059/configtxlator/compute/update-from-configs -F channel=testchainid > config_update.proto
curl -X POST -F original=@config.pb -F updated=@updated_config.pb http://127.0.0.1:7059/configtxlator/compute/update-from-configs -F channel=testchainid > config_update.pb
```

At this point, the computed config update is now prepared, and traditionally, an SDK would be used to sign and wrap this message, but in the interest of using only the peer cli, the `configtxlator` can also be used for this task.

First, we decode the ConfigUpdate so that we may work with it as text.

```
$ curl -X POST --data-binary @config_update.proto http://127.0.0.1:7059/protolator/decode/common.ConfigUpdate > config_update.json
$ curl -X POST --data-binary @config_update.pb http://127.0.0.1:7059/protolator/decode/common.ConfigUpdate > config_update.json
```

Then, we wrap it in an envelope message.
Expand All @@ -212,11 +232,67 @@ echo '{"payload":{"header":{"channel_header":{"channel_id":"testchainid", "type"
And finally, convert it back into the proto form of a full fledged config transaction.

```
curl -X POST --data-binary @config_update_as_envelope.json http://127.0.0.1:7059/protolator/encode/common.Envelope > config_update_as_envelope.proto
curl -X POST --data-binary @config_update_as_envelope.json http://127.0.0.1:7059/protolator/encode/common.Envelope > config_update_as_envelope.pb
```

Finally, submit the config update transaction to ordering to perform a config update.

```
peer channel update -f config_update_as_envelope.proto -c testchainid -o 127.0.0.1:7050
peer channel update -f config_update_as_envelope.pb -c testchainid -o 127.0.0.1:7050
```

## Adding an organization

First build and start the `configtxlator`.

```
$ make configtxlator
build/bin/configtxlator
CGO_CFLAGS=" " GOBIN=/home/yellickj/go/src/github.com/hyperledger/fabric/build/bin go install -tags "" -ldflags "-X github.com/hyperledger/fabric/common/metadata.Version=1.0.0-alpha3-snapshot-42434e60f -X github.com/hyperledger/fabric/common/metadata.BaseVersion=0.3.1 -X github.com/hyperledger/fabric/common/metadata.BaseDockerLabel=org.hyperledger.fabric -X github.com/hyperledger/fabric/common/metadata.DockerNamespace=hyperledger -X github.com/hyperledger/fabric/common/metadata.BaseDockerNamespace=hyperledger" github.com/hyperledger/fabric/common/tools/configtxlator
Binary available as build/bin/configtxlator
```
```
$ configtxlator start
2017-05-31 12:57:22.499 EDT [configtxlator] main -> INFO 001 Serving HTTP requests on port: 7059
```

Then, in another window, build the `configtxgen` tool.

```
$ make configtxgen
build/bin/configtxgen
CGO_CFLAGS=" " GOBIN=/home/yellickj/go/src/github.com/hyperledger/fabric/build/bin go install -tags "nopkcs11" -ldflags "-X github.com/hyperledger/fabric/common/metadata.Version=1.0.0-alpha3-snapshot-63e0dc80f -X github.com/hyperledger/fabric/common/metadata.BaseVersion=0.3.1 -X github.com/hyperledger/fabric/common/metadata.BaseDockerLabel=org.hyperledger.fabric -X github.com/hyperledger/fabric/common/metadata.DockerNamespace=hyperledger -X github.com/hyperledger/fabric/common/metadata.BaseDockerNamespace=hyperledger" github.com/hyperledger/fabric/common/configtx/tool/configtxgen
Binary available as build/bin/configtxgen
```

Then, build the orderer and peer.

```
$ make peer
Installing chaintool
curl -L https://github.com/hyperledger/fabric-chaintool/releases/download/v0.10.3/chaintool > build/bin/chaintool
...
CGO_CFLAGS=" " GOBIN=/home/yellickj/go/src/github.com/hyperledger/fabric/build/bin go install -tags "" -ldflags "-X github.com/hyperledger/fabric/common/metadata.Version=1.0.0-alpha3-snapshot-63e0dc80f -X github.com/hyperledger/fabric/common/metadata.BaseVersion=0.3.1 -X github.com/hyperledger/fabric/common/metadata.BaseDockerLabel=org.hyperledger.fabric -X github.com/hyperledger/fabric/common/metadata.DockerNamespace=hyperledger -X github.com/hyperledger/fabric/common/metadata.BaseDockerNamespace=hyperledger" github.com/hyperledger/fabric/peer
Binary available as build/bin/peer
$ make orderer
build/bin/orderer
CGO_CFLAGS=" " GOBIN=/home/yellickj/go/src/github.com/hyperledger/fabric/build/bin go install -tags "" -ldflags "-X github.com/hyperledger/fabric/common/metadata.Version=1.0.0-alpha3-snapshot-63e0dc80f -X github.com/hyperledger/fabric/common/metadata.BaseVersion=0.3.1 -X github.com/hyperledger/fabric/common/metadata.BaseDockerLabel=org.hyperledger.fabric -X github.com/hyperledger/fabric/common/metadata.DockerNamespace=hyperledger -X github.com/hyperledger/fabric/common/metadata.BaseDockerNamespace=hyperledger" github.com/hyperledger/fabric/orderer
Binary available as build/bin/orderer
```

Start the orderer using the `SampleDevModSolo` profile option.

```
ORDERER_GENERAL_LOGLEVEL=debug ORDERER_GENERAL_GENESISPROFILE=SampleDevModeSolo orderer
```

The process to add an organization then follows exactly like the batch size example, but, instead of setting the batch size, a new org is defined at the application level. Adding an organization is slightly more involved, because we must first create a channel, then modify its membership set.

To see this example run the script `fabric/examples/configtxupdate/reconfig_membership/script.sh` by:

```
INTERACTIVE=true ./script.sh
```

Running the script interactively (as above), you may inspect the artifacts produced as they appear in the `example_output` directory.
40 changes: 40 additions & 0 deletions examples/configtxupdate/bootstrap_batchsize/script.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/bin/bash

CDIR=$(dirname $(basename "$0"))

: ${OUTDIR:="example_output"}
mkdir -p ${OUTDIR} || die "could not create output dir ${OUTDIR}"

GENESIS_BLOCK_PB="${OUTDIR}/genesis_block.pb"
GENESIS_BLOCK_JSON="${OUTDIR}/genesis_block.json"
UPDATED_GENESIS_BLOCK_JSON="${OUTDIR}/updated_genesis_block.json"
UPDATED_GENESIS_BLOCK_PB="${OUTDIR}/updated_genesis_block.pb"

. ${CDIR}/../common_scripts/common.sh

findConfigtxgen || die "no configtxgen present"

bigMsg "Creating bootstrap block"

echo -e "Executing:\n\tconfigtxgen -outputBlock '${GENESIS_BLOCK_PB}' -profile SampleSingleMSPSolo"
$CONFIGTXGEN -outputBlock "${GENESIS_BLOCK_PB}" -profile SampleSingleMSPSolo 2>/dev/null || die "Error generating genesis block"

pauseIfInteractive

bigMsg "Decoding genesis block"
decode common.Block "${GENESIS_BLOCK_PB}" "${GENESIS_BLOCK_JSON}"

bigMsg "Updating the genesis config"
ORIGINAL_BATCHSIZE=$(jq ".data.data[0].payload.data.config.channel_group.groups.Orderer.values.BatchSize.value.max_message_count" genesis_block.json)
NEW_BATCHSIZE=$(( ${ORIGINAL_BATCHSIZE} + 1 ))
echo "Updating batch size from ${ORIGINAL_BATCHSIZE} to ${NEW_BATCHSIZE}."
echo -e "Executing\n\tjq '.data.data[0].payload.data.config.channel_group.groups.Orderer.values.BatchSize.value.max_message_count = ${NEW_BATCHSIZE}' '${GENESIS_BLOCK_JSON}' > '${UPDATED_GENESIS_BLOCK_JSON}'"
jq ".data.data[0].payload.data.config.channel_group.groups.Orderer.values.BatchSize.value.max_message_count = ${NEW_BATCHSIZE}" "${GENESIS_BLOCK_JSON}" > "${UPDATED_GENESIS_BLOCK_JSON}"

pauseIfInteractive

bigMsg "Re-encoding the updated genesis block"

encode common.Block "${UPDATED_GENESIS_BLOCK_JSON}" "${UPDATED_GENESIS_BLOCK_PB}"

bigMsg "Bootstrapping edit complete"
38 changes: 0 additions & 38 deletions examples/configtxupdate/bootstrapping/script.sh

This file was deleted.

Loading

0 comments on commit 012f721

Please sign in to comment.