Skip to content

Commit

Permalink
[FAB-2342] Encode MSPs via configtxgen tool
Browse files Browse the repository at this point in the history
https://jira.hyperledger.org/browse/FAB-2342

This CR adds utilizes the MSP and anchor peer information in the
genesis.yaml to additional encode these parameters into a genesis block.

This additionally adds sample configtx profiles which may be specified
when using the configtx tool to generate a genesis config.

Change-Id: I57a5caf5f02f510ef4bf6e4799403dbfa40d8478
Signed-off-by: Jason Yellick <jyellick@us.ibm.com>
  • Loading branch information
Jason Yellick committed Feb 18, 2017
1 parent 6f4a391 commit b78e929
Show file tree
Hide file tree
Showing 24 changed files with 237 additions and 116 deletions.
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -178,16 +178,16 @@ build/image/javaenv/payload: build/javashim.tar.bz2 \
build/image/peer/payload: build/docker/bin/peer \
peer/core.yaml \
build/msp-sampleconfig.tar.bz2 \
common/configtx/tool/genesis.yaml
common/configtx/tool/configtx.yaml
build/image/orderer/payload: build/docker/bin/orderer \
build/msp-sampleconfig.tar.bz2 \
orderer/orderer.yaml \
common/configtx/tool/genesis.yaml
common/configtx/tool/configtx.yaml
build/image/buildenv/payload: build/gotools.tar.bz2 \
build/docker/gotools/bin/protoc-gen-go
build/image/testenv/payload: build/docker/bin/orderer \
orderer/orderer.yaml \
common/configtx/tool/genesis.yaml \
common/configtx/tool/configtx.yaml \
build/docker/bin/peer \
peer/core.yaml \
build/msp-sampleconfig.tar.bz2 \
Expand Down
2 changes: 1 addition & 1 deletion common/configtx/test/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func MakeGenesisBlock(chainID string) (*cb.Block, error) {

// OrderererTemplate returns the test orderer template
func OrdererTemplate() configtx.Template {
genConf := genesisconfig.Load()
genConf := genesisconfig.Load(genesisconfig.SampleInsecureProfile)
return provisional.New(genConf).ChannelTemplate()
}

Expand Down
7 changes: 7 additions & 0 deletions common/configtx/test/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,19 @@ limitations under the License.
package test

import (
"os"
"path/filepath"
"testing"

logging "github.com/op/go-logging"
)

func init() {
// Configuration is always specified relative to $GOPATH/github.com/hyperledger/fabric
// This test will fail with the default configuration if executed in the package dir
// We are in common/configtx/test
os.Chdir(filepath.Join("..", "..", ".."))

logging.SetLevel(logging.DEBUG, "")
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,34 @@
---
################################################################################
#
# Profile
#
# - Different configuration profiles may be encoded here to be specified
# as parameters to the configtxgen tool
#
################################################################################
Profiles:

# SampleInsecureSol defines a configuration which contains no MSP definitions
# and allows all transactions and channel creation requests
SampleInsecureSolo:
Orderer:
<<: *OrdererDefaults
Application:
<<: *ApplicationDefaults

# SampleSingleMSPSolo defines a configuration which contains a single MSP
# definition (the MSP sampleconfig).
SampleSingleMSPSolo:
Orderer:
<<: *OrdererDefaults
Organizations:
- *SampleOrg
Application:
<<: *ApplicationDefaults
Organizations:
- *SampleOrg

################################################################################
#
# Section: Organizations
Expand All @@ -9,18 +39,19 @@
################################################################################
Organizations:

- &defaultOrg
# SampleOrg defines an MSP using the sampleconfig. It should never be used
# in production but may be used as a template for other definitions
- &SampleOrg
# DefaultOrg defines the organization which is used in the sampleconfig
# of the fabric.git development environment
Name: defaultOrg
Name: SampleOrg

# ID to load the MSP definition as
ID: DEFAULT

# MSPDir is the filesystem path which contains the MSP configuration
MSPDir: msp/sampleconfig


AnchorPeers:
# AnchorPeers defines the location of peers which can be used
# for cross org gossip communication. Note, this value is only
Expand All @@ -36,7 +67,7 @@ Organizations:
# genesis block for orderer related parameters
#
################################################################################
Orderer:
Orderer: &OrdererDefaults

# Orderer Type: The orderer implementation to start
# Available types are "solo" and "kafka"
Expand Down Expand Up @@ -73,9 +104,6 @@ Orderer:
# the orderer side of the network
Organizations:

# The default organization as defined in the organization section
- *defaultOrg

################################################################################
#
# SECTION: Application
Expand All @@ -84,11 +112,8 @@ Orderer:
# genesis block for application related parameters
#
################################################################################
Application:
Application: &ApplicationDefaults

# Organizations is the list of orgs which are defined as participants on
# the application side of the network
Organizations:

# The default organization as defined in the organization section
- *defaultOrg
42 changes: 31 additions & 11 deletions common/configtx/tool/localconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ import (
"github.com/spf13/viper"
)

const (
// SampleInsecureProfile references the sample profile which does not include any MSPs and uses solo for consensus
SampleInsecureProfile = "SampleInsecureSolo"

// SampleSingleMSPSoloProfile references the sample profile which includes only the sample MSP and uses solo for consensus
SampleSingleMSPSoloProfile = "SampleSingleMSPSolo"
)

var logger = logging.MustGetLogger("configtx/tool/localconfig")

func init() {
Expand All @@ -40,11 +48,19 @@ const Prefix string = "CONFIGTX"

// TopLevel contains the genesis structures for use by the provisional bootstrapper
type TopLevel struct {
Application Application
Profiles map[string]*Profile
Organizations []*Organization
Orderer Orderer
Application *Application
Orderer *Orderer
}

// TopLevel contains the genesis structures for use by the provisional bootstrapper
type Profile struct {
Application *Application
Orderer *Orderer
}

// Application encodes the configuration needed for the config transaction
type Application struct {
Organizations []*Organization
}
Expand Down Expand Up @@ -92,7 +108,7 @@ type Kafka struct {
}

var genesisDefaults = TopLevel{
Orderer: Orderer{
Orderer: &Orderer{
OrdererType: "solo",
Addresses: []string{"127.0.0.1:7050"},
BatchTimeout: 10 * time.Second,
Expand All @@ -107,7 +123,7 @@ var genesisDefaults = TopLevel{
},
}

func (g *TopLevel) completeInitialization() {
func (g *Profile) completeInitialization() {
for {
switch {
case g.Orderer.OrdererType == "":
Expand Down Expand Up @@ -140,10 +156,10 @@ func (g *TopLevel) completeInitialization() {
}
}

func Load() *TopLevel {
func Load(profile string) *Profile {
config := viper.New()

config.SetConfigName("genesis")
config.SetConfigName("configtx")
var cfgPath string

// Path to look for the config file in based on GOPATH
Expand All @@ -157,16 +173,16 @@ func Load() *TopLevel {
}

for _, genesisPath := range searchPath {
logger.Infof("Checking for genesis.yaml at: %s", genesisPath)
if _, err := os.Stat(filepath.Join(genesisPath, "genesis.yaml")); err != nil {
logger.Infof("Checking for configtx.yaml at: %s", genesisPath)
if _, err := os.Stat(filepath.Join(genesisPath, "configtx.yaml")); err != nil {
// The yaml file does not exist in this component of the path
continue
}
cfgPath = genesisPath
}

if cfgPath == "" {
logger.Fatalf("Could not find genesis.yaml in paths of %s. Try setting ORDERER_CFG_PATH, PEER_CFG_PATH, or GOPATH correctly", searchPath)
logger.Fatalf("Could not find configtx.yaml in paths of %s. Try setting ORDERER_CFG_PATH, PEER_CFG_PATH, or GOPATH correctly", searchPath)
}
config.AddConfigPath(cfgPath) // Path to look for the config file in

Expand All @@ -188,7 +204,11 @@ func Load() *TopLevel {
panic(fmt.Errorf("Error unmarshaling into structure: %s", err))
}

uconf.completeInitialization()
result, ok := uconf.Profiles[profile]
if !ok {
logger.Panicf("Could not find profile %s", profile)
}
result.completeInitialization()

return &uconf
return result
}
91 changes: 64 additions & 27 deletions common/configtx/tool/provisional/provisional.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,16 @@ import (
configvaluesmsp "github.com/hyperledger/fabric/common/configvalues/msp"
"github.com/hyperledger/fabric/common/genesis"
"github.com/hyperledger/fabric/common/policies"
"github.com/hyperledger/fabric/msp"
"github.com/hyperledger/fabric/orderer/common/bootstrap"
cb "github.com/hyperledger/fabric/protos/common"
ab "github.com/hyperledger/fabric/protos/orderer"

logging "github.com/op/go-logging"
)

var logger = logging.MustGetLogger("common/configtx/tool/provisional")

// Generator can either create an orderer genesis block or config template
type Generator interface {
bootstrap.Helper
Expand Down Expand Up @@ -63,19 +68,33 @@ const (
var DefaultChainCreationPolicyNames = []string{AcceptAllPolicyKey}

type bootstrapper struct {
minimalGroups []*cb.ConfigGroup
systemChainGroups []*cb.ConfigGroup
channelGroups []*cb.ConfigGroup
ordererGroups []*cb.ConfigGroup
applicationGroups []*cb.ConfigGroup
ordererSystemChannelGroups []*cb.ConfigGroup
}

// New returns a new provisional bootstrap helper.
func New(conf *genesisconfig.TopLevel) Generator {
func New(conf *genesisconfig.Profile) Generator {
bs := &bootstrapper{
minimalGroups: []*cb.ConfigGroup{
channelGroups: []*cb.ConfigGroup{
// Chain Config Types
configtxchannel.DefaultHashingAlgorithm(),
configtxchannel.DefaultBlockDataHashingStructure(),
configtxchannel.TemplateOrdererAddresses(conf.Orderer.Addresses),
configtxchannel.TemplateOrdererAddresses(conf.Orderer.Addresses), // TODO, move to conf.Channel when it exists

// Default policies
policies.TemplateImplicitMetaAnyPolicy([]string{}, configvaluesmsp.ReadersPolicyKey),
policies.TemplateImplicitMetaAnyPolicy([]string{}, configvaluesmsp.WritersPolicyKey),
policies.TemplateImplicitMetaMajorityPolicy([]string{}, configvaluesmsp.AdminsPolicyKey),

// Temporary AcceptAllPolicy XXX, remove
cauthdsl.TemplatePolicy(AcceptAllPolicyKey, cauthdsl.AcceptAllPolicy),
},
}

if conf.Orderer != nil {
bs.ordererGroups = []*cb.ConfigGroup{
// Orderer Config Types
configtxorderer.TemplateConsensusType(conf.Orderer.OrdererType),
configtxorderer.TemplateBatchSize(&ab.BatchSize{
Expand All @@ -87,49 +106,67 @@ func New(conf *genesisconfig.TopLevel) Generator {
configtxorderer.TemplateIngressPolicyNames([]string{AcceptAllPolicyKey}),
configtxorderer.TemplateEgressPolicyNames([]string{AcceptAllPolicyKey}),

// Policies
cauthdsl.TemplatePolicy(AcceptAllPolicyKey, cauthdsl.AcceptAllPolicy),

// Initialize the default Reader/Writer/Admins channel policies
policies.TemplateImplicitMetaAnyPolicy([]string{}, configvaluesmsp.ReadersPolicyKey),
policies.TemplateImplicitMetaAnyPolicy([]string{}, configvaluesmsp.WritersPolicyKey),
policies.TemplateImplicitMetaMajorityPolicy([]string{}, configvaluesmsp.AdminsPolicyKey),

// Initialize the default Reader/Writer/Admins orderer policies
policies.TemplateImplicitMetaAnyPolicy([]string{configtxorderer.GroupKey}, configvaluesmsp.ReadersPolicyKey),
policies.TemplateImplicitMetaAnyPolicy([]string{configtxorderer.GroupKey}, configvaluesmsp.WritersPolicyKey),
policies.TemplateImplicitMetaMajorityPolicy([]string{configtxorderer.GroupKey}, configvaluesmsp.AdminsPolicyKey),
}

for _, org := range conf.Orderer.Organizations {
mspConfig, err := msp.GetLocalMspConfig(org.MSPDir, org.ID)
if err != nil {
logger.Panicf("Error loading MSP configuration for org %s: %s", org.Name, err)
}
bs.ordererGroups = append(bs.ordererGroups, configvaluesmsp.TemplateGroupMSP([]string{configtxorderer.GroupKey, org.Name}, mspConfig))
}

switch conf.Orderer.OrdererType {
case ConsensusTypeSolo, ConsensusTypeSbft:
case ConsensusTypeKafka:
bs.ordererGroups = append(bs.ordererGroups, configtxorderer.TemplateKafkaBrokers(conf.Orderer.Kafka.Brokers))
default:
panic(fmt.Errorf("Wrong consenter type value given: %s", conf.Orderer.OrdererType))
}

bs.ordererSystemChannelGroups = []*cb.ConfigGroup{
// Policies
configtxorderer.TemplateChainCreationPolicyNames(DefaultChainCreationPolicyNames),
}
}

if conf.Application != nil {

bs.applicationGroups = []*cb.ConfigGroup{
// Initialize the default Reader/Writer/Admins application policies
policies.TemplateImplicitMetaAnyPolicy([]string{configtxapplication.GroupKey}, configvaluesmsp.ReadersPolicyKey),
policies.TemplateImplicitMetaAnyPolicy([]string{configtxapplication.GroupKey}, configvaluesmsp.WritersPolicyKey),
policies.TemplateImplicitMetaMajorityPolicy([]string{configtxapplication.GroupKey}, configvaluesmsp.AdminsPolicyKey),
},

systemChainGroups: []*cb.ConfigGroup{
configtxorderer.TemplateChainCreationPolicyNames(DefaultChainCreationPolicyNames),
},
}
}
for _, org := range conf.Application.Organizations {
mspConfig, err := msp.GetLocalMspConfig(org.MSPDir, org.ID)
if err != nil {
logger.Panicf("Error loading MSP configuration for org %s: %s", org.Name, err)
}
bs.ordererGroups = append(bs.ordererGroups, configvaluesmsp.TemplateGroupMSP([]string{configtxapplication.GroupKey, org.Name}, mspConfig))
}

switch conf.Orderer.OrdererType {
case ConsensusTypeSolo, ConsensusTypeSbft:
case ConsensusTypeKafka:
bs.minimalGroups = append(bs.minimalGroups, configtxorderer.TemplateKafkaBrokers(conf.Orderer.Kafka.Brokers))
default:
panic(fmt.Errorf("Wrong consenter type value given: %s", conf.Orderer.OrdererType))
}

return bs
}

func (bs *bootstrapper) ChannelTemplate() configtx.Template {
return configtx.NewSimpleTemplate(bs.minimalGroups...)
return configtx.NewCompositeTemplate(
configtx.NewSimpleTemplate(bs.channelGroups...),
configtx.NewSimpleTemplate(bs.ordererGroups...),
configtx.NewSimpleTemplate(bs.applicationGroups...),
)
}

func (bs *bootstrapper) GenesisBlock() *cb.Block {
block, err := genesis.NewFactoryImpl(
configtx.NewCompositeTemplate(
configtx.NewSimpleTemplate(bs.systemChainGroups...),
configtx.NewSimpleTemplate(bs.ordererSystemChannelGroups...),
bs.ChannelTemplate(),
),
).Block(TestChainID)
Expand Down
Loading

0 comments on commit b78e929

Please sign in to comment.