Skip to content

Commit 71a3389

Browse files
author
Kostas Christidis
committed
[FAB-1364] Switch to provisional bootstrapper
https://jira.hyperledger.org/browse/FAB-1364 All consenters read several of their config settings (think sharedconfig) from the genesis block that is generated by a bootstrapper. The only bootstrapper available so far is the static one. However, when testing we need to be able to modify several of these config values on the fly. Therefore the bootstrapper should be able to read a config object (which is itself created by reading the orderer.yaml file and -if set- its associated ENV vars). An example of that would be the KafkaBrokers value. For unit tests the "right" value is "127.0.0.1:9092", whereas for the current Docker Compose-based BDD tests the right value is "kafka0:9092". Since this bootstrapper is no longer static, renaming the package seemed appropriate. For production we will need to introduce file-based bootstrapper that reads the genesis block created by the genesis block tool. This changeset allows the bootstrapper to generate the appropriate genesis blocks (with their own custom keys) for all know consenters types: solo, kafka, sbft (though sbft for now just short-circuits to the solo case). The new bootstrapper is built in a way that makes further extensions easier, and minimizes code duplication by creating the appropriate structs and doing the necessary embeddings. The test that inspected the block's Data field was removed. It was a tautological test, serving no good purpose, and was also hard to maintain. Finally, this changeset updates the bootstrap helper signature by removing the error return; while the error return can be useful if the expectation is that the caller will be able to resort to a different bootstrapper if the first one fails, etc. one could that this amount of flexibility is unnecessary, and complicates the code needlessly. The bootstrapper should simply panic if the wrong settings have been passed to it, and the user should read the fine manual. Change-Id: I6aef9b19dbf9a39652d2d6b3ccbefc794e3001df Signed-off-by: Kostas Christidis <kostas@christidis.io>
1 parent b504af9 commit 71a3389

File tree

31 files changed

+412
-445
lines changed

31 files changed

+412
-445
lines changed

orderer/common/bootstrap/bootstrap.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ import (
2020
ab "github.com/hyperledger/fabric/protos/common"
2121
)
2222

23-
// Helper defines the functions a bootstrapping implementation to provide
23+
// Helper defines the functions a bootstrapping implementation should provide.
2424
type Helper interface {
25-
// GenesisBlock should return the genesis block required to bootstrap the ledger (be it reading from the filesystem, generating it, etc.)
26-
GenesisBlock() (*ab.Block, error)
25+
// GenesisBlock should return the genesis block required to bootstrap
26+
// the ledger (be it reading from the filesystem, generating it, etc.)
27+
GenesisBlock() *ab.Block
2728
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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 provisional
18+
19+
import (
20+
cb "github.com/hyperledger/fabric/protos/common"
21+
"github.com/hyperledger/fabric/protos/utils"
22+
)
23+
24+
func (cbs *commonBootstrapper) makeGenesisConfigEnvelope() *cb.ConfigurationEnvelope {
25+
return utils.MakeConfigurationEnvelope(
26+
cbs.encodeConsensusType(),
27+
cbs.encodeBatchSize(),
28+
cbs.encodeChainCreators(),
29+
cbs.encodeAcceptAllPolicy(),
30+
cbs.lockDefaultModificationPolicy(),
31+
)
32+
}
33+
34+
func (kbs *kafkaBootstrapper) makeGenesisConfigEnvelope() *cb.ConfigurationEnvelope {
35+
return utils.MakeConfigurationEnvelope(
36+
kbs.encodeConsensusType(),
37+
kbs.encodeBatchSize(),
38+
kbs.encodeKafkaBrokers(),
39+
kbs.encodeChainCreators(),
40+
kbs.encodeAcceptAllPolicy(),
41+
kbs.lockDefaultModificationPolicy(),
42+
)
43+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
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 provisional
18+
19+
import (
20+
"github.com/hyperledger/fabric/common/cauthdsl"
21+
"github.com/hyperledger/fabric/common/configtx"
22+
"github.com/hyperledger/fabric/orderer/common/sharedconfig"
23+
cb "github.com/hyperledger/fabric/protos/common"
24+
ab "github.com/hyperledger/fabric/protos/orderer"
25+
"github.com/hyperledger/fabric/protos/utils"
26+
)
27+
28+
func (cbs *commonBootstrapper) encodeConsensusType() *cb.SignedConfigurationItem {
29+
configItemKey := sharedconfig.ConsensusTypeKey
30+
configItemValue := utils.MarshalOrPanic(&ab.ConsensusType{Type: cbs.consensusType})
31+
modPolicy := configtx.DefaultModificationPolicyID
32+
33+
configItemChainHeader := utils.MakeChainHeader(cb.HeaderType_CONFIGURATION_ITEM, msgVersion, cbs.chainID, epoch)
34+
configItem := utils.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Orderer, lastModified, modPolicy, configItemKey, configItemValue)
35+
return &cb.SignedConfigurationItem{ConfigurationItem: utils.MarshalOrPanic(configItem), Signatures: nil}
36+
}
37+
38+
func (cbs *commonBootstrapper) encodeBatchSize() *cb.SignedConfigurationItem {
39+
configItemKey := sharedconfig.BatchSizeKey
40+
configItemValue := utils.MarshalOrPanic(&ab.BatchSize{Messages: cbs.batchSize})
41+
modPolicy := configtx.DefaultModificationPolicyID
42+
43+
configItemChainHeader := utils.MakeChainHeader(cb.HeaderType_CONFIGURATION_ITEM, msgVersion, cbs.chainID, epoch)
44+
configItem := utils.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Orderer, lastModified, modPolicy, configItemKey, configItemValue)
45+
return &cb.SignedConfigurationItem{ConfigurationItem: utils.MarshalOrPanic(configItem), Signatures: nil}
46+
}
47+
48+
func (cbs *commonBootstrapper) encodeChainCreators() *cb.SignedConfigurationItem {
49+
configItemKey := sharedconfig.ChainCreatorsKey
50+
configItemValue := utils.MarshalOrPanic(&ab.ChainCreators{Policies: DefaultChainCreators})
51+
modPolicy := configtx.DefaultModificationPolicyID
52+
53+
configItemChainHeader := utils.MakeChainHeader(cb.HeaderType_CONFIGURATION_ITEM, msgVersion, cbs.chainID, epoch)
54+
configItem := utils.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Orderer, lastModified, modPolicy, configItemKey, configItemValue)
55+
return &cb.SignedConfigurationItem{ConfigurationItem: utils.MarshalOrPanic(configItem), Signatures: nil}
56+
}
57+
58+
func (cbs *commonBootstrapper) encodeAcceptAllPolicy() *cb.SignedConfigurationItem {
59+
configItemKey := AcceptAllPolicyKey
60+
configItemValue := utils.MarshalOrPanic(utils.MakePolicyOrPanic(cauthdsl.AcceptAllPolicy))
61+
modPolicy := configtx.DefaultModificationPolicyID
62+
63+
configItemChainHeader := utils.MakeChainHeader(cb.HeaderType_CONFIGURATION_ITEM, msgVersion, cbs.chainID, epoch)
64+
configItem := utils.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Policy, lastModified, modPolicy, configItemKey, configItemValue)
65+
return &cb.SignedConfigurationItem{ConfigurationItem: utils.MarshalOrPanic(configItem), Signatures: nil}
66+
}
67+
68+
func (cbs *commonBootstrapper) lockDefaultModificationPolicy() *cb.SignedConfigurationItem {
69+
// Lock down the default modification policy to prevent any further policy modifications
70+
configItemKey := configtx.DefaultModificationPolicyID
71+
configItemValue := utils.MarshalOrPanic(utils.MakePolicyOrPanic(cauthdsl.RejectAllPolicy))
72+
modPolicy := configtx.DefaultModificationPolicyID
73+
74+
configItemChainHeader := utils.MakeChainHeader(cb.HeaderType_CONFIGURATION_ITEM, msgVersion, cbs.chainID, epoch)
75+
configItem := utils.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Policy, lastModified, modPolicy, configItemKey, configItemValue)
76+
return &cb.SignedConfigurationItem{ConfigurationItem: utils.MarshalOrPanic(configItem), Signatures: nil}
77+
}
78+
79+
func (kbs *kafkaBootstrapper) encodeKafkaBrokers() *cb.SignedConfigurationItem {
80+
configItemKey := sharedconfig.KafkaBrokersKey
81+
configItemValue := utils.MarshalOrPanic(&ab.KafkaBrokers{Brokers: kbs.kafkaBrokers})
82+
modPolicy := configtx.DefaultModificationPolicyID
83+
84+
configItemChainHeader := utils.MakeChainHeader(cb.HeaderType_CONFIGURATION_ITEM, msgVersion, kbs.chainID, epoch)
85+
configItem := utils.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Orderer, lastModified, modPolicy, configItemKey, configItemValue)
86+
return &cb.SignedConfigurationItem{ConfigurationItem: utils.MarshalOrPanic(configItem), Signatures: nil}
87+
}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
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 provisional
18+
19+
import (
20+
"fmt"
21+
22+
"github.com/hyperledger/fabric/orderer/common/bootstrap"
23+
"github.com/hyperledger/fabric/orderer/localconfig"
24+
cb "github.com/hyperledger/fabric/protos/common"
25+
"github.com/hyperledger/fabric/protos/utils"
26+
)
27+
28+
const (
29+
msgVersion = int32(1)
30+
31+
// ConsensusTypeSolo identifies the solo consensus implementation.
32+
ConsensusTypeSolo = "solo"
33+
// ConsensusTypeKafka identifies the Kafka-based consensus implementation.
34+
ConsensusTypeKafka = "kafka"
35+
// ConsensusTypeSbft identifies the SBFT consensus implementation.
36+
ConsensusTypeSbft = "sbft"
37+
38+
// TestChainID is the default value of ChainID. It is used by all testing
39+
// networks. It it necessary to set and export this variable so that test
40+
// clients can connect without being rejected for targetting a chain which
41+
// does not exist.
42+
TestChainID = "**TEST_CHAINID**"
43+
44+
// AcceptAllPolicyKey is the key of the AcceptAllPolicy.
45+
AcceptAllPolicyKey = "AcceptAllPolicy"
46+
47+
// These values are fixed for the genesis block.
48+
lastModified = 0
49+
epoch = 0
50+
)
51+
52+
// DefaultChainCreators is the default value of ChainCreatorsKey.
53+
var DefaultChainCreators = []string{AcceptAllPolicyKey}
54+
55+
type commonBootstrapper struct {
56+
chainID string
57+
consensusType string
58+
batchSize uint32
59+
}
60+
61+
type soloBootstrapper struct {
62+
commonBootstrapper
63+
}
64+
65+
type kafkaBootstrapper struct {
66+
commonBootstrapper
67+
kafkaBrokers []string
68+
}
69+
70+
// New returns a new provisional bootstrap helper.
71+
func New(conf *config.TopLevel) bootstrap.Helper {
72+
cbs := &commonBootstrapper{
73+
chainID: TestChainID,
74+
consensusType: conf.General.OrdererType,
75+
batchSize: conf.General.BatchSize,
76+
}
77+
78+
switch conf.General.OrdererType {
79+
case ConsensusTypeSolo, ConsensusTypeSbft:
80+
return &soloBootstrapper{
81+
commonBootstrapper: *cbs,
82+
}
83+
case ConsensusTypeKafka:
84+
return &kafkaBootstrapper{
85+
commonBootstrapper: *cbs,
86+
kafkaBrokers: conf.Kafka.Brokers,
87+
}
88+
default:
89+
panic(fmt.Errorf("Wrong consenter type value given: %s", conf.General.OrdererType))
90+
}
91+
}
92+
93+
// GenesisBlock returns the genesis block to be used for bootstrapping.
94+
func (cbs *commonBootstrapper) GenesisBlock() *cb.Block {
95+
return cbs.makeGenesisBlock(cbs.makeGenesisConfigEnvelope())
96+
}
97+
98+
// GenesisBlock returns the genesis block to be used for bootstrapping.
99+
func (kbs *kafkaBootstrapper) GenesisBlock() *cb.Block {
100+
return kbs.makeGenesisBlock(kbs.makeGenesisConfigEnvelope())
101+
}
102+
103+
func (cbs *commonBootstrapper) makeGenesisBlock(configEnvelope *cb.ConfigurationEnvelope) *cb.Block {
104+
configItemChainHeader := utils.MakeChainHeader(cb.HeaderType_CONFIGURATION_ITEM, msgVersion, cbs.chainID, epoch)
105+
payloadChainHeader := utils.MakeChainHeader(cb.HeaderType_CONFIGURATION_TRANSACTION, configItemChainHeader.Version, cbs.chainID, epoch)
106+
payloadSignatureHeader := utils.MakeSignatureHeader(nil, utils.CreateNonceOrPanic())
107+
payloadHeader := utils.MakePayloadHeader(payloadChainHeader, payloadSignatureHeader)
108+
payload := &cb.Payload{Header: payloadHeader, Data: utils.MarshalOrPanic(configEnvelope)}
109+
envelope := &cb.Envelope{Payload: utils.MarshalOrPanic(payload), Signature: nil}
110+
111+
blockData := &cb.BlockData{Data: [][]byte{utils.MarshalOrPanic(envelope)}}
112+
113+
return &cb.Block{
114+
Header: &cb.BlockHeader{
115+
Number: 0,
116+
PreviousHash: nil,
117+
DataHash: blockData.Hash(),
118+
},
119+
Data: blockData,
120+
Metadata: nil,
121+
}
122+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
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 provisional
18+
19+
import (
20+
"bytes"
21+
"testing"
22+
23+
"github.com/hyperledger/fabric/orderer/localconfig"
24+
)
25+
26+
var confSolo, confKafka *config.TopLevel
27+
var testCases []*config.TopLevel
28+
29+
func init() {
30+
confSolo = config.Load()
31+
confKafka = config.Load()
32+
confKafka.General.OrdererType = ConsensusTypeKafka
33+
testCases = []*config.TopLevel{confSolo, confKafka}
34+
}
35+
36+
func TestGenesisBlockHeader(t *testing.T) {
37+
expectedHeaderNumber := uint64(0)
38+
39+
for _, tc := range testCases {
40+
genesisBlock := New(tc).GenesisBlock()
41+
if genesisBlock.Header.Number != expectedHeaderNumber {
42+
t.Fatalf("Case %s: Expected header number %d, got %d", tc.General.OrdererType, expectedHeaderNumber, genesisBlock.Header.Number)
43+
}
44+
if !bytes.Equal(genesisBlock.Header.PreviousHash, nil) {
45+
t.Fatalf("Case %s: Expected header previousHash to be nil, got %x", tc.General.OrdererType, genesisBlock.Header.PreviousHash)
46+
}
47+
}
48+
}
49+
50+
func TestGenesisMetadata(t *testing.T) {
51+
for _, tc := range testCases {
52+
genesisBlock := New(tc).GenesisBlock()
53+
if genesisBlock.Metadata != nil {
54+
t.Fatalf("Expected metadata nil, got %x", genesisBlock.Metadata)
55+
}
56+
}
57+
}

0 commit comments

Comments
 (0)