Skip to content

Commit 639dc87

Browse files
author
Jason Yellick
committed
[FAB-1679] Initial config tran inspector
https://jira.hyperledger.org/browse/FAB-1679 This is an initial and incomplete pass at inspecting a configuration transaction. It is currently oriented very much towards developers as it produces a lot of redundant and or extraneous information, but is being written with an eye towards being utilized by other tools. Change-Id: I39f1ef869a2b1d2c24407aaa4d2071a07fce6f9d Signed-off-by: Jason Yellick <[email protected]>
1 parent 6da52bc commit 639dc87

File tree

6 files changed

+510
-0
lines changed

6 files changed

+510
-0
lines changed
+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
Copyright IBM Corp. 2017 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package inspector
18+
19+
import (
20+
"fmt"
21+
cb "github.com/hyperledger/fabric/protos/common"
22+
23+
"github.com/golang/protobuf/proto"
24+
)
25+
26+
func viewableConfigurationEnvelope(name string, configEnvelope *cb.ConfigurationEnvelope) Viewable {
27+
return &field{
28+
name: name,
29+
values: []Viewable{viewableSignedConfigurationItemSlice("Items", configEnvelope.Items)},
30+
}
31+
}
32+
33+
func viewableSignedConfigurationItemSlice(name string, signedConfigItems []*cb.SignedConfigurationItem) Viewable {
34+
values := make([]Viewable, len(signedConfigItems))
35+
for i, item := range signedConfigItems {
36+
values[i] = viewableSignedConfigurationItem(fmt.Sprintf("Element %d", i), item)
37+
}
38+
return &field{
39+
name: name,
40+
values: values,
41+
}
42+
}
43+
44+
func viewableSignedConfigurationItem(name string, signedConfigItem *cb.SignedConfigurationItem) Viewable {
45+
var viewableConfigItem Viewable
46+
47+
configItem := &cb.ConfigurationItem{}
48+
49+
if err := proto.Unmarshal(signedConfigItem.ConfigurationItem, configItem); err != nil {
50+
viewableConfigItem = viewableError(name, err)
51+
} else {
52+
viewableConfigItem = viewableConfigurationItem("ConfigurationItem", configItem)
53+
}
54+
55+
return &field{
56+
name: name,
57+
values: []Viewable{viewableConfigItem, viewableConfigurationSignatureSlice("Signatures", signedConfigItem.Signatures)},
58+
}
59+
}
60+
61+
func viewableConfigurationSignatureSlice(name string, configSigs []*cb.ConfigurationSignature) Viewable {
62+
values := make([]Viewable, len(configSigs))
63+
for i, item := range configSigs {
64+
values[i] = viewableConfigurationSignature(fmt.Sprintf("Element %d", i), item)
65+
}
66+
return &field{
67+
name: name,
68+
values: values,
69+
}
70+
}
71+
72+
func viewableConfigurationSignature(name string, configSig *cb.ConfigurationSignature) Viewable {
73+
children := make([]Viewable, 2)
74+
75+
sigHeader := &cb.SignatureHeader{}
76+
err := proto.Unmarshal(configSig.SignatureHeader, sigHeader)
77+
if err == nil {
78+
children[0] = viewableSignatureHeader("SignatureHeader", sigHeader)
79+
} else {
80+
children[0] = viewableError("SignatureHeader", err)
81+
}
82+
83+
children[1] = viewableBytes("Signature", configSig.Signature)
84+
85+
return &field{
86+
name: name,
87+
values: children,
88+
}
89+
}
90+
91+
func viewableSignatureHeader(name string, sh *cb.SignatureHeader) Viewable {
92+
return &field{
93+
name: name,
94+
values: []Viewable{viewableBytes("Creator", sh.Creator), viewableBytes("Nonce", sh.Nonce)},
95+
}
96+
}
97+
98+
func viewableConfigurationItem(name string, ci *cb.ConfigurationItem) Viewable {
99+
100+
values := make([]Viewable, 6) // Type, Key, Header, LastModified, ModificationPolicy, Value
101+
values[0] = viewableString("Type", fmt.Sprintf("%v", ci.Type))
102+
values[1] = viewableString("Key", ci.Key)
103+
values[2] = viewableString("Header", "TODO")
104+
values[3] = viewableString("LastModified", fmt.Sprintf("%d", ci.LastModified))
105+
values[4] = viewableString("ModificationPolicy", ci.ModificationPolicy)
106+
107+
typeFactory, ok := typeMap[ci.Type]
108+
if ok {
109+
values[5] = typeFactory.Value(ci)
110+
} else {
111+
values[5] = viewableError("Value", fmt.Errorf("Unknown message type: %v", ci.Type))
112+
}
113+
return &field{
114+
name: name,
115+
values: values,
116+
}
117+
}
+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
Copyright IBM Corp. 2017 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package inspector
18+
19+
import (
20+
"fmt"
21+
cb "github.com/hyperledger/fabric/protos/common"
22+
)
23+
24+
var typeMap map[cb.ConfigurationItem_ConfigurationType]ConfigurationItemValueLens = make(map[cb.ConfigurationItem_ConfigurationType]ConfigurationItemValueLens)
25+
26+
type ConfigurationItemValueLens interface {
27+
// Value takes a config item and returns a Viewable version of its value
28+
Value(configItem *cb.ConfigurationItem) Viewable
29+
}
30+
31+
type Viewable interface {
32+
Value() string
33+
Children() []Viewable
34+
}
35+
36+
type field struct {
37+
name string
38+
values []Viewable
39+
}
40+
41+
func (f *field) Value() string {
42+
return fmt.Sprintf("%s:", f.name)
43+
}
44+
45+
func (f *field) Children() []Viewable {
46+
return f.values
47+
}
48+
49+
const indent = 4
50+
51+
func printViewable(viewable Viewable, curDepth int) {
52+
fmt.Printf(fmt.Sprintf("%%%ds%%s\n", curDepth*indent), "", viewable.Value())
53+
for _, child := range viewable.Children() {
54+
printViewable(child, curDepth+1)
55+
}
56+
}
57+
58+
func PrintConfiguration(configEnvelope *cb.ConfigurationEnvelope) {
59+
viewable := viewableConfigurationEnvelope("ConfigurationEnvelope", configEnvelope)
60+
printViewable(viewable, 0)
61+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
Copyright IBM Corp. 2017 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package inspector
18+
19+
import (
20+
"testing"
21+
22+
configtxtest "github.com/hyperledger/fabric/common/configtx/test"
23+
cb "github.com/hyperledger/fabric/protos/common"
24+
)
25+
26+
func TestFromTemplate(t *testing.T) {
27+
ordererTemplate := configtxtest.GetOrdererTemplate()
28+
signedItems, err := ordererTemplate.Items("SampleChainID")
29+
if err != nil {
30+
t.Fatalf("Error creating signed items: %s", err)
31+
}
32+
configEnvelope := &cb.ConfigurationEnvelope{
33+
Items: signedItems,
34+
}
35+
PrintConfiguration(configEnvelope)
36+
}
+152
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/*
2+
Copyright IBM Corp. 2017 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package inspector
18+
19+
import (
20+
"fmt"
21+
22+
"github.com/golang/protobuf/proto"
23+
cb "github.com/hyperledger/fabric/protos/common"
24+
ab "github.com/hyperledger/fabric/protos/orderer"
25+
)
26+
27+
// This file contains the functions needed to create Viewables for protos defined in
28+
// the orderer configuration proto
29+
30+
type ordererTypes struct{}
31+
32+
func (ot ordererTypes) Value(configItem *cb.ConfigurationItem) Viewable {
33+
name := "Value"
34+
switch configItem.Key {
35+
case "ConsensusType":
36+
value := &ab.ConsensusType{}
37+
if err := proto.Unmarshal(configItem.Value, value); err != nil {
38+
return viewableError(name, err)
39+
}
40+
return viewableConsensusType(configItem.Key, value)
41+
case "BatchSize":
42+
value := &ab.BatchSize{}
43+
if err := proto.Unmarshal(configItem.Value, value); err != nil {
44+
return viewableError(name, err)
45+
}
46+
return viewableBatchSize(configItem.Key, value)
47+
case "BatchTimeout":
48+
value := &ab.BatchTimeout{}
49+
if err := proto.Unmarshal(configItem.Value, value); err != nil {
50+
return viewableError(name, err)
51+
}
52+
return viewableBatchTimeout(configItem.Key, value)
53+
case "CreationPolicy":
54+
value := &ab.CreationPolicy{}
55+
if err := proto.Unmarshal(configItem.Value, value); err != nil {
56+
return viewableError(name, err)
57+
}
58+
return viewableCreationPolicy(configItem.Key, value)
59+
case "IngressPolicy":
60+
value := &ab.IngressPolicy{}
61+
if err := proto.Unmarshal(configItem.Value, value); err != nil {
62+
return viewableError(name, err)
63+
}
64+
return viewableIngressPolicy(configItem.Key, value)
65+
case "EgressPolicy":
66+
value := &ab.EgressPolicy{}
67+
if err := proto.Unmarshal(configItem.Value, value); err != nil {
68+
return viewableError(name, err)
69+
}
70+
return viewableEgressPolicy(configItem.Key, value)
71+
case "ChainCreators":
72+
value := &ab.ChainCreators{}
73+
if err := proto.Unmarshal(configItem.Value, value); err != nil {
74+
return viewableError(name, err)
75+
}
76+
return viewableChainCreators(configItem.Key, value)
77+
case "KafkaBrokers":
78+
value := &ab.KafkaBrokers{}
79+
if err := proto.Unmarshal(configItem.Value, value); err != nil {
80+
return viewableError(name, err)
81+
}
82+
return viewableKafkaBrokers(configItem.Key, value)
83+
default:
84+
}
85+
return viewableError(name, fmt.Errorf("Unknown key: %s", configItem.Key))
86+
}
87+
88+
func viewableConsensusType(name string, consensusType *ab.ConsensusType) Viewable {
89+
return &field{
90+
name: name,
91+
values: []Viewable{viewableString("Type", consensusType.Type)},
92+
}
93+
}
94+
95+
func viewableBatchTimeout(name string, batchTimeout *ab.BatchTimeout) Viewable {
96+
return &field{
97+
name: name,
98+
values: []Viewable{viewableString("Timeout", batchTimeout.Timeout)},
99+
}
100+
}
101+
102+
func viewableIngressPolicy(name string, ingressPolicy *ab.IngressPolicy) Viewable {
103+
return &field{
104+
name: name,
105+
values: []Viewable{viewableString("Name", ingressPolicy.Name)},
106+
}
107+
}
108+
109+
func viewableEgressPolicy(name string, egressPolicy *ab.EgressPolicy) Viewable {
110+
return &field{
111+
name: name,
112+
values: []Viewable{viewableString("Name", egressPolicy.Name)},
113+
}
114+
}
115+
116+
func viewableChainCreators(name string, creators *ab.ChainCreators) Viewable {
117+
return &field{
118+
name: name,
119+
values: []Viewable{viewableStringSlice("Policies", creators.Policies)},
120+
}
121+
}
122+
123+
func viewableKafkaBrokers(name string, brokers *ab.KafkaBrokers) Viewable {
124+
return &field{
125+
name: name,
126+
values: []Viewable{viewableStringSlice("Brokers", brokers.Brokers)},
127+
}
128+
}
129+
130+
func viewableCreationPolicy(name string, creationPolicy *ab.CreationPolicy) Viewable {
131+
return &field{
132+
name: name,
133+
values: []Viewable{
134+
viewableString("Policy", creationPolicy.Policy),
135+
viewableBytes("Digest", creationPolicy.Digest),
136+
},
137+
}
138+
}
139+
140+
func viewableBatchSize(name string, batchSize *ab.BatchSize) Viewable {
141+
return &field{
142+
name: name,
143+
values: []Viewable{
144+
viewableUint32("MaxMessageCount", batchSize.MaxMessageCount),
145+
viewableUint32("AbsoluteMaxBytes", batchSize.AbsoluteMaxBytes),
146+
},
147+
}
148+
}
149+
150+
func init() {
151+
typeMap[cb.ConfigurationItem_Orderer] = ordererTypes{}
152+
}

0 commit comments

Comments
 (0)