Skip to content

Commit e057af8

Browse files
author
Jason Yellick
committed
[FAB-1697] Add chain hashing algorithm config
https://jira.hyperledger.org/browse/FAB-1697 This changeset adds the chain hashing algorithm to the configuration proto. It also adds a chain configuration consumer (for configuration items of chain type) which is capable of processing this message once embedded in the genesis block. Actually embedding this and utilizing the chain configuration will come in later changesets. Change-Id: I960ce4c6ca73b988840585364876e970cbf99a47 Signed-off-by: Jason Yellick <jyellick@us.ibm.com>
1 parent 0e0de5c commit e057af8

File tree

5 files changed

+288
-40
lines changed

5 files changed

+288
-40
lines changed

common/chainconfig/chainconfig.go

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
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 chainconfig
18+
19+
import (
20+
"fmt"
21+
22+
"github.com/hyperledger/fabric/common/util"
23+
cb "github.com/hyperledger/fabric/protos/common"
24+
25+
"github.com/golang/protobuf/proto"
26+
"github.com/op/go-logging"
27+
)
28+
29+
// Chain config keys
30+
const (
31+
// HashingAlgorithmKey is the cb.ConfigurationItem type key name for the HashingAlgorithm message
32+
HashingAlgorithmKey = "HashingAlgorithm"
33+
)
34+
35+
// Hashing algorithm types
36+
const (
37+
// SHAKE256 is the algorithm type for the sha3 shake256 hashing algorithm with 512 bits of output
38+
SHA3Shake256 = "SHAKE256"
39+
)
40+
41+
var logger = logging.MustGetLogger("common/chainconfig")
42+
43+
// Descriptor stores the common chain configuration
44+
// It is intended to be the primary accessor of DescriptorImpl
45+
// It is intended to discourage use of the other exported DescriptorImpl methods
46+
// which are used for updating the chain configuration by the configtx.Manager
47+
type Descriptor interface {
48+
// HashingAlgorithm returns the default algorithm to be used when hashing
49+
// such as computing block hashes, and CreationPolicy digests
50+
HashingAlgorithm() func(input []byte) []byte
51+
}
52+
53+
type chainConfig struct {
54+
hashingAlgorithm func(input []byte) []byte
55+
}
56+
57+
// DescriptorImpl is an implementation of Manager and configtx.ConfigHandler
58+
// In general, it should only be referenced as an Impl for the configtx.Manager
59+
type DescriptorImpl struct {
60+
pendingConfig *chainConfig
61+
config *chainConfig
62+
}
63+
64+
// NewDescriptorImpl creates a new DescriptorImpl with the given CryptoHelper
65+
func NewDescriptorImpl() *DescriptorImpl {
66+
return &DescriptorImpl{
67+
config: &chainConfig{},
68+
}
69+
}
70+
71+
// HashingAlgorithm returns a function pointer to the chain hashing algorihtm
72+
func (pm *DescriptorImpl) HashingAlgorithm() func(input []byte) []byte {
73+
return pm.config.hashingAlgorithm
74+
}
75+
76+
// BeginConfig is used to start a new configuration proposal
77+
func (pm *DescriptorImpl) BeginConfig() {
78+
if pm.pendingConfig != nil {
79+
logger.Panicf("Programming error, cannot call begin in the middle of a proposal")
80+
}
81+
pm.pendingConfig = &chainConfig{}
82+
}
83+
84+
// RollbackConfig is used to abandon a new configuration proposal
85+
func (pm *DescriptorImpl) RollbackConfig() {
86+
pm.pendingConfig = nil
87+
}
88+
89+
// CommitConfig is used to commit a new configuration proposal
90+
func (pm *DescriptorImpl) CommitConfig() {
91+
if pm.pendingConfig == nil {
92+
logger.Panicf("Programming error, cannot call commit without an existing proposal")
93+
}
94+
pm.config = pm.pendingConfig
95+
pm.pendingConfig = nil
96+
}
97+
98+
// ProposeConfig is used to add new configuration to the configuration proposal
99+
func (pm *DescriptorImpl) ProposeConfig(configItem *cb.ConfigurationItem) error {
100+
if configItem.Type != cb.ConfigurationItem_Chain {
101+
return fmt.Errorf("Expected type of ConfigurationItem_Chain, got %v", configItem.Type)
102+
}
103+
104+
switch configItem.Key {
105+
case HashingAlgorithmKey:
106+
hashingAlgorithm := &cb.HashingAlgorithm{}
107+
if err := proto.Unmarshal(configItem.Value, hashingAlgorithm); err != nil {
108+
return fmt.Errorf("Unmarshaling error for HashingAlgorithm: %s", err)
109+
}
110+
switch hashingAlgorithm.Name {
111+
case SHA3Shake256:
112+
pm.pendingConfig.hashingAlgorithm = util.ComputeCryptoHash
113+
default:
114+
return fmt.Errorf("Unknown hashing algorithm type: %s", hashingAlgorithm.Name)
115+
}
116+
default:
117+
logger.Warningf("Uknown Chain configuration item with key %s", configItem.Key)
118+
}
119+
return nil
120+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
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 chainconfig
18+
19+
import (
20+
"testing"
21+
22+
cb "github.com/hyperledger/fabric/protos/common"
23+
"github.com/hyperledger/fabric/protos/utils"
24+
25+
logging "github.com/op/go-logging"
26+
)
27+
28+
func init() {
29+
logging.SetLevel(logging.DEBUG, "")
30+
}
31+
32+
func TestDoubleBegin(t *testing.T) {
33+
defer func() {
34+
if err := recover(); err == nil {
35+
t.Fatalf("Should have panicked on multiple begin configs")
36+
}
37+
}()
38+
39+
m := NewDescriptorImpl()
40+
m.BeginConfig()
41+
m.BeginConfig()
42+
}
43+
44+
func TestCommitWithoutBegin(t *testing.T) {
45+
defer func() {
46+
if err := recover(); err == nil {
47+
t.Fatalf("Should have panicked on multiple begin configs")
48+
}
49+
}()
50+
51+
m := NewDescriptorImpl()
52+
m.CommitConfig()
53+
}
54+
55+
func TestRollback(t *testing.T) {
56+
m := NewDescriptorImpl()
57+
m.pendingConfig = &chainConfig{}
58+
m.RollbackConfig()
59+
if m.pendingConfig != nil {
60+
t.Fatalf("Should have cleared pending config on rollback")
61+
}
62+
}
63+
64+
func TestHashingAlgorithm(t *testing.T) {
65+
invalidMessage :=
66+
&cb.ConfigurationItem{
67+
Type: cb.ConfigurationItem_Chain,
68+
Key: HashingAlgorithmKey,
69+
Value: []byte("Garbage Data"),
70+
}
71+
invalidAlgorithm := &cb.ConfigurationItem{
72+
Type: cb.ConfigurationItem_Chain,
73+
Key: HashingAlgorithmKey,
74+
Value: utils.MarshalOrPanic(&cb.HashingAlgorithm{Name: "MD5"}),
75+
}
76+
validAlgorithm := &cb.ConfigurationItem{
77+
Type: cb.ConfigurationItem_Chain,
78+
Key: HashingAlgorithmKey,
79+
Value: utils.MarshalOrPanic(&cb.HashingAlgorithm{Name: SHA3Shake256}),
80+
}
81+
m := NewDescriptorImpl()
82+
m.BeginConfig()
83+
84+
err := m.ProposeConfig(invalidMessage)
85+
if err == nil {
86+
t.Fatalf("Should have failed on invalid message")
87+
}
88+
89+
err = m.ProposeConfig(invalidAlgorithm)
90+
if err == nil {
91+
t.Fatalf("Should have failed on invalid algorithm")
92+
}
93+
94+
err = m.ProposeConfig(validAlgorithm)
95+
if err != nil {
96+
t.Fatalf("Error applying valid config: %s", err)
97+
}
98+
99+
m.CommitConfig()
100+
101+
if m.HashingAlgorithm() == nil {
102+
t.Fatalf("Should have set default hashing algorithm")
103+
}
104+
}

protos/common/common.pb.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

protos/common/configuration.pb.go

Lines changed: 55 additions & 40 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

protos/common/configuration.proto

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,11 @@ message SignaturePolicy {
116116
NOutOf From = 2;
117117
}
118118
}
119+
120+
121+
// HashingAlgorithm is encoded into the configuration transaction as a configuration item of type CHAIN
122+
// with a Key of "HashingAlgorithm" as marshaled protobuf bytes
123+
message HashingAlgorithm {
124+
// Currently supported algorithms are: SHAKE256
125+
string name = 1;
126+
}

0 commit comments

Comments
 (0)