Skip to content

Commit e6d3b99

Browse files
author
Jason Yellick
committed
Introduce orderer sharedconfig mechanism
The configtx.Manager supports maintaining configuration updates based on configuration transactions, but today, the only interpretation of these configuration updates is the policies.Manager which handles configuration updates of type Policy. There are other types of configuration, such as Orderer type configuration which are currently ignored. This changeset adds an orderer shared config manager. It is called sharedconfig to make it explicit that this configuration is common to and available to all orderers. This is different from the notion of localconfig which could include things like machine dependent paths and buffer sizes. This changeset also establishes a convention for encoding orderer configuration by creating a proto message with name equal to the Key field which is set in the orderer config. This changeset hooks the shared config into the XXX points of the multichain ChainSupport. In the future, the batchSize and consensusType will be removed from the localconfig once the other consensus plugins have been migrated to the new shared multichain infrastructure. Change-Id: Ia68f5a83bf816317609b7df4c9ad0d1bed1bb800 Signed-off-by: Jason Yellick <[email protected]>
1 parent 8e97791 commit e6d3b99

File tree

9 files changed

+482
-20
lines changed

9 files changed

+482
-20
lines changed

orderer/common/bootstrap/static/static.go

+47-11
Original file line numberDiff line numberDiff line change
@@ -20,38 +20,74 @@ import (
2020
"github.com/hyperledger/fabric/orderer/common/bootstrap"
2121
"github.com/hyperledger/fabric/orderer/common/cauthdsl"
2222
"github.com/hyperledger/fabric/orderer/common/configtx"
23+
"github.com/hyperledger/fabric/orderer/common/sharedconfig"
2324
"github.com/hyperledger/fabric/orderer/common/util"
2425
cb "github.com/hyperledger/fabric/protos/common"
26+
ab "github.com/hyperledger/fabric/protos/orderer"
2527
)
2628

2729
var TestChainID = "**TEST_CHAINID**"
2830

2931
const msgVersion = int32(1)
3032

3133
type bootstrapper struct {
32-
chainID string
34+
chainID string
35+
lastModified uint64
36+
epoch uint64
37+
consensusType string
38+
batchSize int32
3339
}
3440

3541
// New returns a new static bootstrap helper.
3642
func New() bootstrap.Helper {
37-
return &bootstrapper{chainID: TestChainID}
43+
return &bootstrapper{
44+
chainID: TestChainID,
45+
consensusType: "solo",
46+
batchSize: 10,
47+
}
3848
}
3949

40-
// GenesisBlock returns the genesis block to be used for bootstrapping
41-
func (b *bootstrapper) GenesisBlock() (*cb.Block, error) {
50+
func (b *bootstrapper) encodeConsensusType() *cb.SignedConfigurationItem {
51+
configItemKey := sharedconfig.ConsensusTypeKey
52+
configItemValue := util.MarshalOrPanic(&ab.ConsensusType{Type: b.consensusType})
53+
modPolicy := configtx.DefaultModificationPolicyID
54+
55+
configItemChainHeader := util.MakeChainHeader(cb.HeaderType_CONFIGURATION_ITEM, msgVersion, b.chainID, b.epoch)
56+
configItem := util.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Orderer, b.lastModified, modPolicy, configItemKey, configItemValue)
57+
return &cb.SignedConfigurationItem{ConfigurationItem: util.MarshalOrPanic(configItem), Signatures: nil}
58+
}
59+
60+
func (b *bootstrapper) encodeBatchSize() *cb.SignedConfigurationItem {
61+
configItemKey := sharedconfig.BatchSizeKey
62+
configItemValue := util.MarshalOrPanic(&ab.BatchSize{Messages: b.batchSize})
63+
modPolicy := configtx.DefaultModificationPolicyID
64+
65+
configItemChainHeader := util.MakeChainHeader(cb.HeaderType_CONFIGURATION_ITEM, msgVersion, b.chainID, b.epoch)
66+
configItem := util.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Orderer, b.lastModified, modPolicy, configItemKey, configItemValue)
67+
return &cb.SignedConfigurationItem{ConfigurationItem: util.MarshalOrPanic(configItem), Signatures: nil}
68+
}
69+
70+
func (b *bootstrapper) lockDefaultModificationPolicy() *cb.SignedConfigurationItem {
4271
// Lock down the default modification policy to prevent any further policy modifications
4372
configItemKey := configtx.DefaultModificationPolicyID
4473
configItemValue := util.MarshalOrPanic(util.MakePolicyOrPanic(cauthdsl.RejectAllPolicy))
4574
modPolicy := configtx.DefaultModificationPolicyID
4675

47-
lastModified := uint64(0)
48-
epoch := uint64(0)
49-
configItemChainHeader := util.MakeChainHeader(cb.HeaderType_CONFIGURATION_ITEM, msgVersion, b.chainID, epoch)
50-
configItem := util.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Policy, lastModified, modPolicy, configItemKey, configItemValue)
51-
signedConfigItem := &cb.SignedConfigurationItem{ConfigurationItem: util.MarshalOrPanic(configItem), Signatures: nil}
76+
configItemChainHeader := util.MakeChainHeader(cb.HeaderType_CONFIGURATION_ITEM, msgVersion, b.chainID, b.epoch)
77+
configItem := util.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Policy, b.lastModified, modPolicy, configItemKey, configItemValue)
78+
return &cb.SignedConfigurationItem{ConfigurationItem: util.MarshalOrPanic(configItem), Signatures: nil}
79+
}
80+
81+
// GenesisBlock returns the genesis block to be used for bootstrapping
82+
func (b *bootstrapper) GenesisBlock() (*cb.Block, error) {
83+
configItemChainHeader := util.MakeChainHeader(cb.HeaderType_CONFIGURATION_ITEM, msgVersion, b.chainID, b.epoch)
5284

53-
configEnvelope := util.MakeConfigurationEnvelope(signedConfigItem)
54-
payloadChainHeader := util.MakeChainHeader(cb.HeaderType_CONFIGURATION_TRANSACTION, configItemChainHeader.Version, b.chainID, epoch)
85+
configEnvelope := util.MakeConfigurationEnvelope(
86+
b.encodeConsensusType(),
87+
b.encodeBatchSize(),
88+
b.lockDefaultModificationPolicy(),
89+
)
90+
payloadChainHeader := util.MakeChainHeader(cb.HeaderType_CONFIGURATION_TRANSACTION, configItemChainHeader.Version, b.chainID, b.epoch)
5591
payloadSignatureHeader := util.MakeSignatureHeader(nil, util.CreateNonceOrPanic())
5692
payloadHeader := util.MakePayloadHeader(payloadChainHeader, payloadSignatureHeader)
5793
payload := &cb.Payload{Header: payloadHeader, Data: util.MarshalOrPanic(configEnvelope)}

orderer/common/bootstrap/static/static_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func TestGenesisBlockData(t *testing.T) {
5959
expectedPayloadChainHeaderType := int32(cb.HeaderType_CONFIGURATION_TRANSACTION)
6060
expectedChainHeaderVersion := msgVersion
6161
expectedChainHeaderEpoch := uint64(0)
62-
expectedConfigEnvelopeItemsLength := 1
62+
expectedConfigEnvelopeItemsLength := 3
6363
expectedConfigurationItemChainHeaderType := int32(cb.HeaderType_CONFIGURATION_ITEM)
6464
expectedConfigurationItemChainHeaderVersion := msgVersion
6565
expectedConfigurationItemType := cb.ConfigurationItem_Policy
@@ -110,7 +110,7 @@ func TestGenesisBlockData(t *testing.T) {
110110
t.Fatalf("Expected configuration envelope to have %d configuration item(s), got %d", expectedConfigEnvelopeItemsLength, len(configurationEnvelope.Items))
111111
}
112112

113-
signedConfigurationItem := configurationEnvelope.Items[0]
113+
signedConfigurationItem := configurationEnvelope.Items[2]
114114
marshaledConfigurationItem := signedConfigurationItem.ConfigurationItem
115115
configurationItem := &cb.ConfigurationItem{}
116116
if err := proto.Unmarshal(marshaledConfigurationItem, configurationItem); err != nil {
+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/*
2+
Copyright IBM Corp. 2016 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+
ab "github.com/hyperledger/fabric/protos/orderer"
24+
25+
"github.com/golang/protobuf/proto"
26+
"github.com/op/go-logging"
27+
)
28+
29+
// ConsensusTypeKey is the cb.ConfigurationItem type key name for the ConsensusType message
30+
const ConsensusTypeKey = "ConsensusType"
31+
32+
// BatchSizeKey is the cb.ConfigurationItem type key name for the BatchSize message
33+
const BatchSizeKey = "BatchSize"
34+
35+
var logger = logging.MustGetLogger("orderer/common/sharedconfig")
36+
37+
func init() {
38+
logging.SetLevel(logging.DEBUG, "")
39+
}
40+
41+
// Manager stores the common shared orderer configuration
42+
// It is intended to be the primary accessor of ManagerImpl
43+
// It is intended to discourage use of the other exported ManagerImpl methods
44+
// which are used for updating the orderer configuration by the ConfigManager
45+
type Manager interface {
46+
// ConsensusType returns the configured consensus type
47+
ConsensusType() string
48+
49+
// BatchSize returns the maximum number of messages to include in a block
50+
BatchSize() int
51+
}
52+
53+
type ordererConfig struct {
54+
consensusType string
55+
batchSize int
56+
}
57+
58+
// ManagerImpl is an implementation of Manager and configtx.ConfigHandler
59+
// In general, it should only be referenced as an Impl for the configtx.ConfigManager
60+
type ManagerImpl struct {
61+
pendingConfig *ordererConfig
62+
config *ordererConfig
63+
}
64+
65+
// NewManagerImpl creates a new ManagerImpl with the given CryptoHelper
66+
func NewManagerImpl() *ManagerImpl {
67+
return &ManagerImpl{
68+
config: &ordererConfig{},
69+
}
70+
}
71+
72+
// ConsensusType returns the configured consensus type
73+
func (pm *ManagerImpl) ConsensusType() string {
74+
return pm.config.consensusType
75+
}
76+
77+
// BatchSize returns the maximum number of messages to include in a block
78+
func (pm *ManagerImpl) BatchSize() int {
79+
return pm.config.batchSize
80+
}
81+
82+
// BeginConfig is used to start a new configuration proposal
83+
func (pm *ManagerImpl) BeginConfig() {
84+
if pm.pendingConfig != nil {
85+
logger.Fatalf("Programming error, cannot call begin in the middle of a proposal")
86+
}
87+
pm.pendingConfig = &ordererConfig{}
88+
}
89+
90+
// RollbackConfig is used to abandon a new configuration proposal
91+
func (pm *ManagerImpl) RollbackConfig() {
92+
pm.pendingConfig = nil
93+
}
94+
95+
// CommitConfig is used to commit a new configuration proposal
96+
func (pm *ManagerImpl) CommitConfig() {
97+
if pm.pendingConfig == nil {
98+
logger.Fatalf("Programming error, cannot call commit without an existing proposal")
99+
}
100+
pm.config = pm.pendingConfig
101+
pm.pendingConfig = nil
102+
}
103+
104+
// ProposeConfig is used to add new configuration to the configuration proposal
105+
func (pm *ManagerImpl) ProposeConfig(configItem *cb.ConfigurationItem) error {
106+
if configItem.Type != cb.ConfigurationItem_Orderer {
107+
return fmt.Errorf("Expected type of ConfigurationItem_Orderer, got %v", configItem.Type)
108+
}
109+
110+
switch configItem.Key {
111+
case ConsensusTypeKey:
112+
consensusType := &ab.ConsensusType{}
113+
err := proto.Unmarshal(configItem.Value, consensusType)
114+
if err != nil {
115+
return fmt.Errorf("Unmarshaling error for ConsensusType: %s", err)
116+
}
117+
if pm.config.consensusType == "" {
118+
// The first configuration we accept the consensus type regardless
119+
pm.config.consensusType = consensusType.Type
120+
}
121+
if consensusType.Type != pm.config.consensusType {
122+
return fmt.Errorf("Attempted to change the consensus type from %s to %s after init", pm.config.consensusType, consensusType.Type)
123+
}
124+
125+
pm.pendingConfig.consensusType = consensusType.Type
126+
case BatchSizeKey:
127+
batchSize := &ab.BatchSize{}
128+
err := proto.Unmarshal(configItem.Value, batchSize)
129+
if err != nil {
130+
return fmt.Errorf("Unmarshaling error for BatchSize: %s", err)
131+
}
132+
133+
if batchSize.Messages <= 0 {
134+
return fmt.Errorf("Attempted to set the batch size to %d which is less than or equal to 0", batchSize.Messages)
135+
}
136+
137+
pm.pendingConfig.batchSize = int(batchSize.Messages)
138+
}
139+
140+
return nil
141+
}

0 commit comments

Comments
 (0)