Skip to content

Commit 7dbf685

Browse files
author
Jason Yellick
committed
[FAB-4168] Document configtxlator REST usage
This CR adds a README.md file describing the usage of the configtxlator tool, as well as documenting two basic configuration flows. It includes a script for each of the basic configuration flows which automates the commands documented to produce the artifacts for inspections. Change-Id: I745bb6a567224761edf80a6d9850bf016e0ccbdd Signed-off-by: Jason Yellick <[email protected]>
1 parent c8785e3 commit 7dbf685

File tree

3 files changed

+329
-0
lines changed

3 files changed

+329
-0
lines changed

examples/configtxupdate/README.md

+222
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
# Reconfiguraing with configtxlator
2+
3+
## Overview
4+
5+
The `configtxlator` tool was created to support reconfiguration independent of SDKs. Channel configuration is stored as a transaction in configuration blocks of a channel and may be manipulated directly, such as in the bdd behave tests. However, at the time of this writing, no SDK natively supports manipulating the configuration directly, so the `configtxlator` tool is designed to provide an API which consumers of any SDK may interact with to assist with configuration updates.
6+
7+
The tool name is a portmanteau of *configtx* and *translator* and is intended to convey that the tool simply converts between different equivalent data representations. It does not generate configuration, it does not submit or retrieve configuration, it does not modify configuration itself, it simply provides some bijective operations between different views of the configtx format.
8+
9+
The standard usage is expected to be:
10+
1. SDK retrieves latest config
11+
2. `configtxlator` produces human readable version of config
12+
3. User or application edits the config
13+
4. `configtxlator` used to compute config update representation of changes to the config
14+
5. SDK submits signs and submits config
15+
16+
The `configtxlator` tool exposes a truly stateless REST API for interacting with configuration elements. These REST components support converting the native configuration format to/from a human readable JSON representation, as well as computing computing configuration updates based on the difference between two configurations.
17+
18+
Because the `configtxlator` service deliberately does not contain any crypto material, or otherwise secret information, it does not include any authorization or access control. The anticipated typical deployment would be to operate as a sandboxed container, locally with the application, so that there is a dedicated configtxlator process for each consumer of it.
19+
20+
## Buliding and running the configtxlator
21+
22+
The `configtxlator` binary may be produced by executing `make configtxlator`.
23+
24+
To execute the `configtxlator` simply execute the binary, optionally with the `-serverPort` option to specify a listen port, or accept the default listen port, `7059`.
25+
26+
The binary will start an http server listening on the designated port and is now ready to process requests.
27+
28+
## Proto translation
29+
30+
For extensibility, and because certain fields must be signed over, many proto fields are stored as bytes. This makes the natural proto to JSON translation using the `jsonpb` package ineffective for producing a human readable version of the protobufs. Instead, the `configtxlator` exposes a REST component to do a more sophisticated translation.
31+
32+
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.
33+
34+
For instance, to decode a configuration block saved as `configuration_block.proto`, run the command:
35+
36+
```
37+
curl -X POST --data-binary @configuration_block.proto http://127.0.0.1:7059/protolator/decode/common.Block
38+
```
39+
40+
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.
41+
42+
For instance, re-encode the block saved as `configuration_block.json`, run the command:
43+
44+
```
45+
curl -X POST --data-binary @configuration_block.json http://127.0.0.1:7059/protolator/encode/common.Block
46+
```
47+
48+
Any of the configuration related protos, including `common.Block`, `common.Envelope`, `common.ConfigEnvelope`, `common.ConfigUpdateEnvelope`, `common.Configuration`, and `common.ConfigUpdate` are valid targets for these URLs. In the future, other proto decoding types may be added, such as for endorser transactions.
49+
50+
## Config update computation
51+
52+
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`.
53+
54+
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`
55+
56+
```
57+
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
58+
```
59+
60+
## Bootstraping example
61+
62+
First build and start the `configtxlator`.
63+
64+
```
65+
$ make configtxlator
66+
build/bin/configtxlator
67+
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
68+
Binary available as build/bin/configtxlator
69+
```
70+
```
71+
$ configtxlator
72+
2017-05-31 12:57:22.499 EDT [configtxlator] main -> INFO 001 Serving HTTP requests on port: 7059
73+
```
74+
75+
Then, in another window, build and run the `configtxgen` tool to produce a genesis block for the ordering system channel.
76+
77+
```
78+
$ make configtxgen
79+
build/bin/configtxgen
80+
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
81+
Binary available as build/bin/configtxgen
82+
```
83+
```
84+
$ configtxgen -outputBlock genesis_block.proto
85+
2017-05-31 14:15:16.634 EDT [common/configtx/tool] main -> INFO 001 Loading configuration
86+
2017-05-31 14:15:16.646 EDT [common/configtx/tool] doOutputBlock -> INFO 002 Generating genesis block
87+
2017-05-31 14:15:16.646 EDT [common/configtx/tool] doOutputBlock -> INFO 003 Writing genesis block
88+
```
89+
Decode the genesis block into a human editable form.
90+
```
91+
curl -X POST --data-binary @genesis_block.proto http://127.0.0.1:7059/protolator/decode/common.Block > genesis_block.json
92+
```
93+
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.
94+
```
95+
$ export MAXBATCHSIZEPATH=".data.data[0].payload.data.config.channel_group.groups.Orderer.values.BatchSize.value.maxMessageCount"
96+
# Display the old batch size
97+
$ jq "$MAXBATCHSIZEPATH" genesis_block.json
98+
10
99+
100+
# Set the new batch size
101+
$ jq "$MAXBATCHSIZEPATH = 20" genesis_block.json > updated_genesis_block.json
102+
103+
# Display the new batch size
104+
$ jq "$MAXBATCHSIZEPATH" updated_genesis_block.json
105+
20
106+
```
107+
The genesis block is now ready to be re-encoded into the native proto form to be used for bootstrapping.
108+
```
109+
curl -X POST --data-binary @updated_genesis_block.json http://127.0.0.1:7059/protolator/encode/common.Block > updated_genesis_block.proto
110+
```
111+
The `updated_genesis_block.proto` file may now be used as the genesis block for bootstrapping an ordering system channel.
112+
113+
## Reconfiguration example
114+
115+
Reconfiguring a channel can be performed in a very similar way to modifying a genesis config.
116+
117+
118+
First build and start the `configtxlator`.
119+
120+
```
121+
$ make configtxlator
122+
build/bin/configtxlator
123+
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
124+
Binary available as build/bin/configtxlator
125+
```
126+
```
127+
$ configtxlator
128+
2017-05-31 12:57:22.499 EDT [configtxlator] main -> INFO 001 Serving HTTP requests on port: 7059
129+
```
130+
131+
Then, in another window, build the orderer and peer.
132+
133+
```
134+
$ make peer
135+
Installing chaintool
136+
curl -L https://github.com/hyperledger/fabric-chaintool/releases/download/v0.10.3/chaintool > build/bin/chaintool
137+
...
138+
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
139+
Binary available as build/bin/peer
140+
141+
$ make orderer
142+
build/bin/orderer
143+
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
144+
Binary available as build/bin/orderer
145+
```
146+
147+
Start the orderer using the default options, including the provisional bootstrapper which will create a `testchainid` ordering system channel.
148+
149+
```
150+
ORDERER_GENERAL_LOGLEVEL=debug orderer
151+
```
152+
153+
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.
154+
155+
```
156+
$ peer channel fetch config config_block.proto -o 127.0.0.1:7050 -c testchainid
157+
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]
158+
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]
159+
Received block: 1
160+
Received block: 1
161+
2017-05-31 15:11:37.635 EDT [main] main -> INFO 003 Exiting.....
162+
```
163+
164+
Send the config block to the `configtxlator` service for decoding:
165+
166+
```
167+
curl -X POST --data-binary @config_block.proto http://127.0.0.1:7059/protolator/decode/common.Block > config_block.json
168+
```
169+
170+
Extract the config section from the block:
171+
172+
```
173+
jq .data.data[0].payload.data.config config_block.json > config.json
174+
```
175+
176+
Edit the config, saving it as a new `updated_config.json`. Here, we set the batch size to 30.
177+
178+
```
179+
jq ".channel_group.groups.Orderer.values.BatchSize.value.maxMessageCount = 30" config.json > updated_config.json
180+
```
181+
182+
Re-encode both the original config, and the updated config into proto.
183+
184+
```
185+
curl -X POST --data-binary @config.json http://127.0.0.1:7059/protolator/encode/common.Config > config.proto
186+
```
187+
188+
```
189+
curl -X POST --data-binary @updated_config.json http://127.0.0.1:7059/protolator/encode/common.Config > updated_config.proto
190+
```
191+
192+
Now, with both configs properly encoded, send them to the `configtxlator` service to compute the config update which transitions between the two.
193+
194+
```
195+
curl -X POST -F [email protected] -F updated=@updated_config.proto http://127.0.0.1:7059/configtxlator/compute/update-from-configs -F channel=testchainid > config_update.proto
196+
```
197+
198+
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.
199+
200+
First, we decode the ConfigUpdate so that we may work with it as text.
201+
202+
```
203+
$ curl -X POST --data-binary @config_update.proto http://127.0.0.1:7059/protolator/decode/common.ConfigUpdate > config_update.json
204+
```
205+
206+
Then, we wrap it in an envelope message.
207+
208+
```
209+
echo '{"payload":{"header":{"channel_header":{"channel_id":"testchainid", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' > config_update_as_envelope.json
210+
```
211+
212+
And finally, convert it back into the proto form of a full fledged config transaction.
213+
214+
```
215+
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
216+
```
217+
218+
Finally, submit the config update transaction to ordering to perform a config update.
219+
220+
```
221+
peer channel update -f config_update_as_envelope.proto -c testchainid -o 127.0.0.1:7050
222+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/bin/bash
2+
3+
die() {
4+
echo "$1"
5+
exit 1
6+
}
7+
8+
bigMsg() {
9+
echo
10+
echo "####################################################################################"
11+
echo "$1"
12+
echo "####################################################################################"
13+
echo
14+
}
15+
16+
# set -x
17+
18+
bigMsg "Beginning bootstrap editing example"
19+
20+
CONFIGTXGEN=../../../build/bin/configtxgen
21+
22+
bigMsg "Creating bootstrap block"
23+
24+
$CONFIGTXGEN -outputBlock genesis_block.proto || die "Error generating genesis block"
25+
26+
bigMsg "Decoding genesis block"
27+
28+
curl -X POST --data-binary @genesis_block.proto http://127.0.0.1:7059/protolator/decode/common.Block > genesis_block.json || die "Error decoding genesis block"
29+
30+
bigMsg "Updating genesis config"
31+
32+
jq ".data.data[0].payload.data.config.channel_group.groups.Orderer.values.BatchSize.value.maxMessageCount" genesis_block.json > updated_genesis_block.json
33+
34+
bigMsg "Re-encoding the updated genesis block"
35+
36+
curl -X POST --data-binary @updated_genesis_block.json http://127.0.0.1:7059/protolator/encode/common.Block > updated_genesis_block.proto
37+
38+
bigMsg "Bootstrapping edit complete"
+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#!/bin/bash
2+
3+
die() {
4+
echo "$1"
5+
exit 1
6+
}
7+
8+
bigMsg() {
9+
echo
10+
echo "####################################################################################"
11+
echo "$1"
12+
echo "####################################################################################"
13+
echo
14+
}
15+
16+
# set -x
17+
18+
bigMsg "Beginning config update example"
19+
20+
PEER=../../../build/bin/peer
21+
22+
bigMsg "Fetching current config block"
23+
24+
$PEER channel fetch config config_block.proto -o 127.0.0.1:7050 -c testchainid || die "Unable to fetch config block"
25+
26+
bigMsg "Decoding current config block"
27+
28+
curl -X POST --data-binary @config_block.proto http://127.0.0.1:7059/protolator/decode/common.Block > config_block.json || die "Unable to decode config block"
29+
30+
bigMsg "Isolating current config"
31+
32+
jq .data.data[0].payload.data.config config_block.json > config.json || die "Unable to extract config from config block"
33+
34+
bigMsg "Generating new config"
35+
36+
OLD_BATCH_SIZE=$(jq ".channel_group.groups.Orderer.values.BatchSize.value.maxMessageCount" config.json)
37+
NEW_BATCH_SIZE=$(($OLD_BATCH_SIZE+1))
38+
39+
jq ".channel_group.groups.Orderer.values.BatchSize.value.maxMessageCount = $NEW_BATCH_SIZE" config.json > updated_config.json || die "Error updating batch size"
40+
41+
bigMsg "Translating original config to proto"
42+
43+
curl -X POST --data-binary @config.json http://127.0.0.1:7059/protolator/encode/common.Config > config.proto || die "Error re-encoding config"
44+
45+
bigMsg "Translating updated config to proto"
46+
47+
curl -X POST --data-binary @updated_config.json http://127.0.0.1:7059/protolator/encode/common.Config > updated_config.proto || die "Error re-encoding updated config"
48+
49+
bigMsg "Computing config update"
50+
51+
curl -X POST -F [email protected] -F updated=@updated_config.proto http://127.0.0.1:7059/configtxlator/compute/update-from-configs -F channel=testchainid > config_update.proto || die "Error computing config update"
52+
53+
bigMsg "Decoding config update"
54+
55+
curl -X POST --data-binary @config_update.proto http://127.0.0.1:7059/protolator/decode/common.ConfigUpdate > config_update.json || die "Error decoding config update"
56+
57+
bigMsg "Generating config update envelope"
58+
59+
echo '{"payload":{"header":{"channel_header":{"channel_id":"testchainid", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' > config_update_as_envelope.json || die "Error creating config update envelope"
60+
61+
bigMsg "Encoding config update envelope"
62+
63+
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 || die "Error converting envelope to proto"
64+
65+
bigMsg "Sending config update to channel"
66+
67+
$PEER channel update -f config_update_as_envelope.proto -c testchainid -o 127.0.0.1:7050 || die "Error updating channel"
68+
69+
bigMsg "Config Update Successful!"

0 commit comments

Comments
 (0)