diff --git a/common/genesis/genesis.go b/common/genesis/genesis.go new file mode 100644 index 00000000000..a6be46d5585 --- /dev/null +++ b/common/genesis/genesis.go @@ -0,0 +1,64 @@ +/* +Copyright IBM Corp. 2016 All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package genesis + +import ( + "github.com/hyperledger/fabric/common/configtx" + cb "github.com/hyperledger/fabric/protos/common" + "github.com/hyperledger/fabric/protos/utils" +) + +const ( + msgVersion = int32(1) + + // These values are fixed for the genesis block. + lastModified = 0 + epoch = 0 +) + +type Factory interface { + Block(chainID string) (*cb.Block, error) +} + +type factory struct { + template configtx.Template +} + +func NewFactoryImpl(template configtx.Template) Factory { + return &factory{template: template} +} + +func (f *factory) Block(chainID string) (*cb.Block, error) { + items, err := f.template.Items(chainID) + if err != nil { + return nil, err + } + + payloadChainHeader := utils.MakeChainHeader(cb.HeaderType_CONFIGURATION_TRANSACTION, msgVersion, chainID, epoch) + payloadSignatureHeader := utils.MakeSignatureHeader(nil, utils.CreateNonceOrPanic()) + payloadHeader := utils.MakePayloadHeader(payloadChainHeader, payloadSignatureHeader) + payload := &cb.Payload{Header: payloadHeader, Data: utils.MarshalOrPanic(&cb.ConfigurationEnvelope{Items: items})} + envelope := &cb.Envelope{Payload: utils.MarshalOrPanic(payload), Signature: nil} + + block := cb.NewBlock(0, nil) + block.Data = &cb.BlockData{Data: [][]byte{utils.MarshalOrPanic(envelope)}} + block.Header.DataHash = block.Data.Hash() + block.Metadata.Metadata[cb.BlockMetadataIndex_LAST_CONFIGURATION] = utils.MarshalOrPanic(&cb.Metadata{ + Value: utils.MarshalOrPanic(&cb.LastConfiguration{Index: 0}), + }) + return block, nil +} diff --git a/common/genesis/genesis_test.go b/common/genesis/genesis_test.go new file mode 100644 index 00000000000..3e2661ca51e --- /dev/null +++ b/common/genesis/genesis_test.go @@ -0,0 +1,32 @@ +/* +Copyright IBM Corp. 2016 All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package genesis + +import ( + "testing" + + "github.com/hyperledger/fabric/common/configtx" + cb "github.com/hyperledger/fabric/protos/common" +) + +func TestSanity(t *testing.T) { + impl := NewFactoryImpl(configtx.NewSimpleTemplate(&cb.ConfigurationItem{})) + _, err := impl.Block("TestChainID") + if err != nil { + t.Fatalf("Basic sanity fails") + } +} diff --git a/orderer/common/bootstrap/provisional/item.go b/orderer/common/bootstrap/provisional/item.go index d7e205c23f7..9811e257bad 100644 --- a/orderer/common/bootstrap/provisional/item.go +++ b/orderer/common/bootstrap/provisional/item.go @@ -25,93 +25,84 @@ import ( "github.com/hyperledger/fabric/protos/utils" ) -func (cbs *commonBootstrapper) encodeConsensusType() *cb.SignedConfigurationItem { +func (cbs *commonBootstrapper) encodeConsensusType() *cb.ConfigurationItem { configItemKey := sharedconfig.ConsensusTypeKey configItemValue := utils.MarshalOrPanic(&ab.ConsensusType{Type: cbs.consensusType}) modPolicy := configtx.DefaultModificationPolicyID configItemChainHeader := utils.MakeChainHeader(cb.HeaderType_CONFIGURATION_ITEM, msgVersion, cbs.chainID, epoch) - configItem := utils.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Orderer, lastModified, modPolicy, configItemKey, configItemValue) - return &cb.SignedConfigurationItem{ConfigurationItem: utils.MarshalOrPanic(configItem), Signatures: nil} + return utils.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Orderer, lastModified, modPolicy, configItemKey, configItemValue) } -func (cbs *commonBootstrapper) encodeBatchSize() *cb.SignedConfigurationItem { +func (cbs *commonBootstrapper) encodeBatchSize() *cb.ConfigurationItem { configItemKey := sharedconfig.BatchSizeKey configItemValue := utils.MarshalOrPanic(cbs.batchSize) modPolicy := configtx.DefaultModificationPolicyID configItemChainHeader := utils.MakeChainHeader(cb.HeaderType_CONFIGURATION_ITEM, msgVersion, cbs.chainID, epoch) - configItem := utils.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Orderer, lastModified, modPolicy, configItemKey, configItemValue) - return &cb.SignedConfigurationItem{ConfigurationItem: utils.MarshalOrPanic(configItem), Signatures: nil} + return utils.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Orderer, lastModified, modPolicy, configItemKey, configItemValue) } -func (cbs *commonBootstrapper) encodeBatchTimeout() *cb.SignedConfigurationItem { +func (cbs *commonBootstrapper) encodeBatchTimeout() *cb.ConfigurationItem { configItemKey := sharedconfig.BatchTimeoutKey configItemValue := utils.MarshalOrPanic(&ab.BatchTimeout{Timeout: cbs.batchTimeout}) modPolicy := configtx.DefaultModificationPolicyID configItemChainHeader := utils.MakeChainHeader(cb.HeaderType_CONFIGURATION_ITEM, msgVersion, cbs.chainID, epoch) - configItem := utils.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Orderer, lastModified, modPolicy, configItemKey, configItemValue) - return &cb.SignedConfigurationItem{ConfigurationItem: utils.MarshalOrPanic(configItem), Signatures: nil} + return utils.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Orderer, lastModified, modPolicy, configItemKey, configItemValue) } -func (cbs *commonBootstrapper) encodeChainCreators() *cb.SignedConfigurationItem { +func (cbs *commonBootstrapper) encodeChainCreators() *cb.ConfigurationItem { configItemKey := sharedconfig.ChainCreatorsKey configItemValue := utils.MarshalOrPanic(&ab.ChainCreators{Policies: DefaultChainCreators}) modPolicy := configtx.DefaultModificationPolicyID configItemChainHeader := utils.MakeChainHeader(cb.HeaderType_CONFIGURATION_ITEM, msgVersion, cbs.chainID, epoch) - configItem := utils.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Orderer, lastModified, modPolicy, configItemKey, configItemValue) - return &cb.SignedConfigurationItem{ConfigurationItem: utils.MarshalOrPanic(configItem), Signatures: nil} + return utils.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Orderer, lastModified, modPolicy, configItemKey, configItemValue) } -func (cbs *commonBootstrapper) encodeAcceptAllPolicy() *cb.SignedConfigurationItem { +func (cbs *commonBootstrapper) encodeAcceptAllPolicy() *cb.ConfigurationItem { configItemKey := AcceptAllPolicyKey configItemValue := utils.MarshalOrPanic(utils.MakePolicyOrPanic(cauthdsl.AcceptAllPolicy)) modPolicy := configtx.DefaultModificationPolicyID configItemChainHeader := utils.MakeChainHeader(cb.HeaderType_CONFIGURATION_ITEM, msgVersion, cbs.chainID, epoch) - configItem := utils.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Policy, lastModified, modPolicy, configItemKey, configItemValue) - return &cb.SignedConfigurationItem{ConfigurationItem: utils.MarshalOrPanic(configItem), Signatures: nil} + return utils.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Policy, lastModified, modPolicy, configItemKey, configItemValue) } -func (cbs *commonBootstrapper) encodeIngressPolicy() *cb.SignedConfigurationItem { +func (cbs *commonBootstrapper) encodeIngressPolicy() *cb.ConfigurationItem { configItemKey := sharedconfig.IngressPolicyKey configItemValue := utils.MarshalOrPanic(&ab.IngressPolicy{Name: AcceptAllPolicyKey}) modPolicy := configtx.DefaultModificationPolicyID configItemChainHeader := utils.MakeChainHeader(cb.HeaderType_CONFIGURATION_ITEM, msgVersion, cbs.chainID, epoch) - configItem := utils.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Orderer, lastModified, modPolicy, configItemKey, configItemValue) - return &cb.SignedConfigurationItem{ConfigurationItem: utils.MarshalOrPanic(configItem), Signatures: nil} + return utils.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Orderer, lastModified, modPolicy, configItemKey, configItemValue) } -func (cbs *commonBootstrapper) encodeEgressPolicy() *cb.SignedConfigurationItem { +func (cbs *commonBootstrapper) encodeEgressPolicy() *cb.ConfigurationItem { configItemKey := sharedconfig.EgressPolicyKey configItemValue := utils.MarshalOrPanic(&ab.EgressPolicy{Name: AcceptAllPolicyKey}) modPolicy := configtx.DefaultModificationPolicyID configItemChainHeader := utils.MakeChainHeader(cb.HeaderType_CONFIGURATION_ITEM, msgVersion, cbs.chainID, epoch) - configItem := utils.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Orderer, lastModified, modPolicy, configItemKey, configItemValue) - return &cb.SignedConfigurationItem{ConfigurationItem: utils.MarshalOrPanic(configItem), Signatures: nil} + return utils.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Orderer, lastModified, modPolicy, configItemKey, configItemValue) } -func (cbs *commonBootstrapper) lockDefaultModificationPolicy() *cb.SignedConfigurationItem { +func (cbs *commonBootstrapper) lockDefaultModificationPolicy() *cb.ConfigurationItem { // Lock down the default modification policy to prevent any further policy modifications configItemKey := configtx.DefaultModificationPolicyID configItemValue := utils.MarshalOrPanic(utils.MakePolicyOrPanic(cauthdsl.RejectAllPolicy)) modPolicy := configtx.DefaultModificationPolicyID configItemChainHeader := utils.MakeChainHeader(cb.HeaderType_CONFIGURATION_ITEM, msgVersion, cbs.chainID, epoch) - configItem := utils.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Policy, lastModified, modPolicy, configItemKey, configItemValue) - return &cb.SignedConfigurationItem{ConfigurationItem: utils.MarshalOrPanic(configItem), Signatures: nil} + return utils.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Policy, lastModified, modPolicy, configItemKey, configItemValue) } -func (kbs *kafkaBootstrapper) encodeKafkaBrokers() *cb.SignedConfigurationItem { +func (kbs *kafkaBootstrapper) encodeKafkaBrokers() *cb.ConfigurationItem { configItemKey := sharedconfig.KafkaBrokersKey configItemValue := utils.MarshalOrPanic(&ab.KafkaBrokers{Brokers: kbs.kafkaBrokers}) modPolicy := configtx.DefaultModificationPolicyID configItemChainHeader := utils.MakeChainHeader(cb.HeaderType_CONFIGURATION_ITEM, msgVersion, kbs.chainID, epoch) - configItem := utils.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Orderer, lastModified, modPolicy, configItemKey, configItemValue) - return &cb.SignedConfigurationItem{ConfigurationItem: utils.MarshalOrPanic(configItem), Signatures: nil} + return utils.MakeConfigurationItem(configItemChainHeader, cb.ConfigurationItem_Orderer, lastModified, modPolicy, configItemKey, configItemValue) } diff --git a/orderer/common/bootstrap/provisional/provisional.go b/orderer/common/bootstrap/provisional/provisional.go index 61ac3972251..fd84135b9ca 100644 --- a/orderer/common/bootstrap/provisional/provisional.go +++ b/orderer/common/bootstrap/provisional/provisional.go @@ -19,13 +19,22 @@ package provisional import ( "fmt" + "github.com/hyperledger/fabric/common/configtx" + "github.com/hyperledger/fabric/common/genesis" "github.com/hyperledger/fabric/orderer/common/bootstrap" "github.com/hyperledger/fabric/orderer/localconfig" cb "github.com/hyperledger/fabric/protos/common" ab "github.com/hyperledger/fabric/protos/orderer" - "github.com/hyperledger/fabric/protos/utils" ) +// Generator can either create an orderer genesis block or configuration template +type Generator interface { + bootstrap.Helper + + // TemplateItems returns a set of configuration items which can be used to initialize a template + TemplateItems() []*cb.ConfigurationItem +} + const ( msgVersion = int32(1) @@ -70,7 +79,7 @@ type kafkaBootstrapper struct { } // New returns a new provisional bootstrap helper. -func New(conf *config.TopLevel) bootstrap.Helper { +func New(conf *config.TopLevel) Generator { cbs := &commonBootstrapper{ chainID: TestChainID, consensusType: conf.Genesis.OrdererType, @@ -95,30 +104,26 @@ func New(conf *config.TopLevel) bootstrap.Helper { } } +func (cbs *commonBootstrapper) genesisBlock(minimalTemplateItems func() []*cb.ConfigurationItem) *cb.Block { + block, err := genesis.NewFactoryImpl( + configtx.NewCompositeTemplate( + configtx.NewSimpleTemplate(minimalTemplateItems()...), + configtx.NewSimpleTemplate(cbs.makeOrdererSystemChainConfig()...), + ), + ).Block(TestChainID) + + if err != nil { + panic(err) + } + return block +} + // GenesisBlock returns the genesis block to be used for bootstrapping. func (cbs *commonBootstrapper) GenesisBlock() *cb.Block { - return cbs.makeGenesisBlock(cbs.makeGenesisConfigEnvelope()) + return cbs.genesisBlock(cbs.TemplateItems) } // GenesisBlock returns the genesis block to be used for bootstrapping. func (kbs *kafkaBootstrapper) GenesisBlock() *cb.Block { - return kbs.makeGenesisBlock(kbs.makeGenesisConfigEnvelope()) -} - -func (cbs *commonBootstrapper) makeGenesisBlock(configEnvelope *cb.ConfigurationEnvelope) *cb.Block { - configItemChainHeader := utils.MakeChainHeader(cb.HeaderType_CONFIGURATION_ITEM, msgVersion, cbs.chainID, epoch) - payloadChainHeader := utils.MakeChainHeader(cb.HeaderType_CONFIGURATION_TRANSACTION, configItemChainHeader.Version, cbs.chainID, epoch) - payloadSignatureHeader := utils.MakeSignatureHeader(nil, utils.CreateNonceOrPanic()) - payloadHeader := utils.MakePayloadHeader(payloadChainHeader, payloadSignatureHeader) - payload := &cb.Payload{Header: payloadHeader, Data: utils.MarshalOrPanic(configEnvelope)} - envelope := &cb.Envelope{Payload: utils.MarshalOrPanic(payload), Signature: nil} - - block := cb.NewBlock(0, nil) - block.Data = &cb.BlockData{Data: [][]byte{utils.MarshalOrPanic(envelope)}} - block.Header.DataHash = block.Data.Hash() - block.Metadata.Metadata[cb.BlockMetadataIndex_LAST_CONFIGURATION] = utils.MarshalOrPanic(&cb.Metadata{ - Value: utils.MarshalOrPanic(&cb.LastConfiguration{Index: 0}), - }) - - return block + return kbs.genesisBlock(kbs.TemplateItems) } diff --git a/orderer/common/bootstrap/provisional/envelope.go b/orderer/common/bootstrap/provisional/templates.go similarity index 59% rename from orderer/common/bootstrap/provisional/envelope.go rename to orderer/common/bootstrap/provisional/templates.go index cfe360abf63..bce5371080b 100644 --- a/orderer/common/bootstrap/provisional/envelope.go +++ b/orderer/common/bootstrap/provisional/templates.go @@ -18,32 +18,24 @@ package provisional import ( cb "github.com/hyperledger/fabric/protos/common" - "github.com/hyperledger/fabric/protos/utils" ) -func (cbs *commonBootstrapper) makeGenesisConfigEnvelope() *cb.ConfigurationEnvelope { - return utils.MakeConfigurationEnvelope( +func (cbs *commonBootstrapper) makeOrdererSystemChainConfig() []*cb.ConfigurationItem { + return []*cb.ConfigurationItem{cbs.encodeChainCreators()} +} + +func (cbs *commonBootstrapper) TemplateItems() []*cb.ConfigurationItem { + return []*cb.ConfigurationItem{ cbs.encodeConsensusType(), cbs.encodeBatchSize(), cbs.encodeBatchTimeout(), - cbs.encodeChainCreators(), cbs.encodeAcceptAllPolicy(), cbs.encodeIngressPolicy(), cbs.encodeEgressPolicy(), cbs.lockDefaultModificationPolicy(), - ) + } } -func (kbs *kafkaBootstrapper) makeGenesisConfigEnvelope() *cb.ConfigurationEnvelope { - return utils.MakeConfigurationEnvelope( - kbs.encodeConsensusType(), - kbs.encodeBatchSize(), - kbs.encodeBatchTimeout(), - kbs.encodeKafkaBrokers(), - kbs.encodeChainCreators(), - kbs.encodeAcceptAllPolicy(), - kbs.encodeIngressPolicy(), - kbs.encodeEgressPolicy(), - kbs.lockDefaultModificationPolicy(), - ) +func (kbs *kafkaBootstrapper) TemplateItems() []*cb.ConfigurationItem { + return append(kbs.commonBootstrapper.TemplateItems(), kbs.encodeKafkaBrokers()) }