Skip to content

Commit 9f07b96

Browse files
author
Jason Yellick
committed
[FAB-1851] Add peer sharedconfig
https://jira.hyperledger.org/browse/FAB-1851 This changeset adds a peer sharedconfig package. The sharedconfig is named as such, because it is configuration which is shared across all peers for a channel, as opposed to the local configuration which the peer sources from its yaml file. Change-Id: I46bc408ed15a065020722666ee8e50d9f679e665 Signed-off-by: Jason Yellick <[email protected]>
1 parent e111bac commit 9f07b96

File tree

4 files changed

+259
-1
lines changed

4 files changed

+259
-1
lines changed

core/peer/peer.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import (
3535
"github.com/hyperledger/fabric/core/ledger/ledgermgmt"
3636
"github.com/hyperledger/fabric/gossip/service"
3737
mspmgmt "github.com/hyperledger/fabric/msp/mgmt"
38+
"github.com/hyperledger/fabric/peer/sharedconfig"
3839
"github.com/hyperledger/fabric/protos/common"
3940
"github.com/hyperledger/fabric/protos/utils"
4041
)
@@ -160,8 +161,10 @@ func createChain(cid string, ledger ledger.PeerLedger, cb *common.Block) error {
160161
return err
161162
}
162163

164+
sharedConfigHandler := sharedconfig.NewDescriptorImpl()
165+
163166
configtxInitializer := configtx.NewInitializer()
164-
// TODO Hook peer shared config manager in here once it exists
167+
configtxInitializer.Handlers()[common.ConfigurationItem_Peer] = sharedConfigHandler
165168
configtxManager, err := configtx.NewManagerImpl(configEnvelope, configtxInitializer)
166169
if err != nil {
167170
return err

peer/sharedconfig/sharedconfig.go

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
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 sharedconfig
18+
19+
import (
20+
"fmt"
21+
22+
cb "github.com/hyperledger/fabric/protos/common"
23+
pb "github.com/hyperledger/fabric/protos/peer"
24+
25+
"github.com/golang/protobuf/proto"
26+
"github.com/op/go-logging"
27+
)
28+
29+
// Peer config keys
30+
const (
31+
// AnchorPeersKey is the cb.ConfigurationItem type key name for the AnchorPeers message
32+
AnchorPeersKey = "AnchorPeers"
33+
)
34+
35+
var logger = logging.MustGetLogger("peer/sharedconfig")
36+
37+
// Descriptor stores the common peer configuration
38+
// It is intended to be the primary accessor of DescriptorImpl
39+
// It is intended to discourage use of the other exported DescriptorImpl methods
40+
// which are used for updating the chain configuration by the configtx.Manager
41+
type Descriptor interface {
42+
// AnchorPeers returns the list of anchor peers for the channel
43+
AnchorPeers() []*pb.AnchorPeer
44+
}
45+
46+
type sharedConfig struct {
47+
anchorPeers []*pb.AnchorPeer
48+
}
49+
50+
// DescriptorImpl is an implementation of Manager and configtx.ConfigHandler
51+
// In general, it should only be referenced as an Impl for the configtx.Manager
52+
type DescriptorImpl struct {
53+
pendingConfig *sharedConfig
54+
config *sharedConfig
55+
}
56+
57+
// NewDescriptorImpl creates a new DescriptorImpl with the given CryptoHelper
58+
func NewDescriptorImpl() *DescriptorImpl {
59+
return &DescriptorImpl{
60+
config: &sharedConfig{},
61+
}
62+
}
63+
64+
// AnchorPeers returns the list of valid orderer addresses to connect to to invoke Broadcast/Deliver
65+
func (di *DescriptorImpl) AnchorPeers() []*pb.AnchorPeer {
66+
return di.config.anchorPeers
67+
}
68+
69+
// BeginConfig is used to start a new configuration proposal
70+
func (di *DescriptorImpl) BeginConfig() {
71+
logger.Debugf("Beginning a possible new peer shared configuration")
72+
if di.pendingConfig != nil {
73+
logger.Panicf("Programming error, cannot call begin in the middle of a proposal")
74+
}
75+
di.pendingConfig = &sharedConfig{}
76+
}
77+
78+
// RollbackConfig is used to abandon a new configuration proposal
79+
func (di *DescriptorImpl) RollbackConfig() {
80+
logger.Debugf("Rolling back proposed peer shared configuration")
81+
di.pendingConfig = nil
82+
}
83+
84+
// CommitConfig is used to commit a new configuration proposal
85+
func (di *DescriptorImpl) CommitConfig() {
86+
logger.Debugf("Committing new peer shared configuration")
87+
if di.pendingConfig == nil {
88+
logger.Panicf("Programming error, cannot call commit without an existing proposal")
89+
}
90+
di.config = di.pendingConfig
91+
di.pendingConfig = nil
92+
}
93+
94+
// ProposeConfig is used to add new configuration to the configuration proposal
95+
func (di *DescriptorImpl) ProposeConfig(configItem *cb.ConfigurationItem) error {
96+
if configItem.Type != cb.ConfigurationItem_Peer {
97+
return fmt.Errorf("Expected type of ConfigurationItem_Peer, got %v", configItem.Type)
98+
}
99+
100+
switch configItem.Key {
101+
case AnchorPeersKey:
102+
anchorPeers := &pb.AnchorPeers{}
103+
if err := proto.Unmarshal(configItem.Value, anchorPeers); err != nil {
104+
return fmt.Errorf("Unmarshaling error for %s: %s", configItem.Key, err)
105+
}
106+
if logger.IsEnabledFor(logging.DEBUG) {
107+
logger.Debugf("Setting %s to %v", configItem.Key, anchorPeers.AnchorPeers)
108+
}
109+
di.pendingConfig.anchorPeers = anchorPeers.AnchorPeers
110+
default:
111+
logger.Warningf("Uknown Peer configuration item with key %s", configItem.Key)
112+
}
113+
return nil
114+
}
+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
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 sharedconfig
18+
19+
import (
20+
"reflect"
21+
"testing"
22+
23+
cb "github.com/hyperledger/fabric/protos/common"
24+
pb "github.com/hyperledger/fabric/protos/peer"
25+
26+
logging "github.com/op/go-logging"
27+
)
28+
29+
func init() {
30+
logging.SetLevel(logging.DEBUG, "")
31+
}
32+
33+
func makeInvalidConfigItem(key string) *cb.ConfigurationItem {
34+
return &cb.ConfigurationItem{
35+
Type: cb.ConfigurationItem_Peer,
36+
Key: key,
37+
Value: []byte("Garbage Data"),
38+
}
39+
}
40+
41+
func TestInterface(t *testing.T) {
42+
_ = Descriptor(NewDescriptorImpl())
43+
}
44+
45+
func TestDoubleBegin(t *testing.T) {
46+
defer func() {
47+
if err := recover(); err == nil {
48+
t.Fatalf("Should have panicked on multiple begin configs")
49+
}
50+
}()
51+
52+
m := NewDescriptorImpl()
53+
m.BeginConfig()
54+
m.BeginConfig()
55+
}
56+
57+
func TestCommitWithoutBegin(t *testing.T) {
58+
defer func() {
59+
if err := recover(); err == nil {
60+
t.Fatalf("Should have panicked on multiple begin configs")
61+
}
62+
}()
63+
64+
m := NewDescriptorImpl()
65+
m.CommitConfig()
66+
}
67+
68+
func TestRollback(t *testing.T) {
69+
m := NewDescriptorImpl()
70+
m.pendingConfig = &sharedConfig{}
71+
m.RollbackConfig()
72+
if m.pendingConfig != nil {
73+
t.Fatalf("Should have cleared pending config on rollback")
74+
}
75+
}
76+
77+
func TestAnchorPeers(t *testing.T) {
78+
endVal := []*pb.AnchorPeer{
79+
&pb.AnchorPeer{Host: "foo", Port: 234, Cert: []byte("foocert")},
80+
&pb.AnchorPeer{Host: "bar", Port: 237, Cert: []byte("barcert")},
81+
}
82+
invalidMessage := makeInvalidConfigItem(AnchorPeersKey)
83+
validMessage := TemplateAnchorPeers(endVal)
84+
m := NewDescriptorImpl()
85+
m.BeginConfig()
86+
87+
err := m.ProposeConfig(invalidMessage)
88+
if err == nil {
89+
t.Fatalf("Should have failed on invalid message")
90+
}
91+
92+
err = m.ProposeConfig(validMessage)
93+
if err != nil {
94+
t.Fatalf("Error applying valid config: %s", err)
95+
}
96+
97+
m.CommitConfig()
98+
99+
if newVal := m.AnchorPeers(); !reflect.DeepEqual(newVal, endVal) {
100+
t.Fatalf("Unexpected anchor peers, got %v expected %v", newVal, endVal)
101+
}
102+
}
+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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 sharedconfig
18+
19+
import (
20+
cb "github.com/hyperledger/fabric/protos/common"
21+
pb "github.com/hyperledger/fabric/protos/peer"
22+
"github.com/hyperledger/fabric/protos/utils"
23+
)
24+
25+
var defaultAnchorPeers = []*pb.AnchorPeer{}
26+
27+
// TemplateAnchorPeers creates a headerless configuration item representing the anchor peers
28+
func TemplateAnchorPeers(anchorPeers []*pb.AnchorPeer) *cb.ConfigurationItem {
29+
return &cb.ConfigurationItem{
30+
Type: cb.ConfigurationItem_Peer,
31+
Key: AnchorPeersKey,
32+
Value: utils.MarshalOrPanic(&pb.AnchorPeers{AnchorPeers: anchorPeers}),
33+
}
34+
}
35+
36+
// DefaultAnchorPeers creates a headerless configuration item for the default orderer addresses
37+
func DefaultAnchorPeers() *cb.ConfigurationItem {
38+
return TemplateAnchorPeers(defaultAnchorPeers)
39+
}

0 commit comments

Comments
 (0)