216 lines
6.7 KiB
Go
216 lines
6.7 KiB
Go
/*
|
|
Copyright IBM Corp. All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package channelconfig
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
|
|
cb "github.com/hyperledger/fabric-protos-go/common"
|
|
"github.com/hyperledger/fabric/bccsp"
|
|
"github.com/hyperledger/fabric/common/capabilities"
|
|
"github.com/hyperledger/fabric/common/util"
|
|
"github.com/hyperledger/fabric/msp"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// Channel config keys
|
|
const (
|
|
// ConsortiumKey is the key for the cb.ConfigValue for the Consortium message
|
|
ConsortiumKey = "Consortium"
|
|
|
|
// HashingAlgorithmKey is the cb.ConfigItem type key name for the HashingAlgorithm message
|
|
HashingAlgorithmKey = "HashingAlgorithm"
|
|
|
|
// BlockDataHashingStructureKey is the cb.ConfigItem type key name for the BlockDataHashingStructure message
|
|
BlockDataHashingStructureKey = "BlockDataHashingStructure"
|
|
|
|
// OrdererAddressesKey is the cb.ConfigItem type key name for the OrdererAddresses message
|
|
OrdererAddressesKey = "OrdererAddresses"
|
|
|
|
// ChannelGroupKey is the name of the channel group
|
|
ChannelGroupKey = "Channel"
|
|
|
|
OrderersKey = "Orderers"
|
|
|
|
// CapabilitiesKey is the name of the key which refers to capabilities, it appears at the channel,
|
|
// application, and orderer levels and this constant is used for all three.
|
|
CapabilitiesKey = "Capabilities"
|
|
)
|
|
|
|
// ChannelValues gives read only access to the channel configuration
|
|
type ChannelValues interface {
|
|
// HashingAlgorithm returns the default algorithm to be used when hashing
|
|
// such as computing block hashes, and CreationPolicy digests
|
|
HashingAlgorithm() func(input []byte) []byte
|
|
|
|
// BlockDataHashingStructureWidth returns the width to use when constructing the
|
|
// Merkle tree to compute the BlockData hash
|
|
BlockDataHashingStructureWidth() uint32
|
|
|
|
// OrdererAddresses returns the list of valid orderer addresses to connect to invoke Broadcast/Deliver
|
|
OrdererAddresses() []string
|
|
}
|
|
|
|
// ChannelProtos is where the proposed configuration is unmarshaled into
|
|
type ChannelProtos struct {
|
|
HashingAlgorithm *cb.HashingAlgorithm
|
|
BlockDataHashingStructure *cb.BlockDataHashingStructure
|
|
OrdererAddresses *cb.OrdererAddresses
|
|
Orderers *cb.Orderers
|
|
Consortium *cb.Consortium
|
|
Capabilities *cb.Capabilities
|
|
}
|
|
|
|
// ChannelConfig stores the channel configuration
|
|
type ChannelConfig struct {
|
|
protos *ChannelProtos
|
|
|
|
hashingAlgorithm func(input []byte) []byte
|
|
|
|
mspManager msp.MSPManager
|
|
|
|
appConfig *ApplicationConfig
|
|
ordererConfig *OrdererConfig
|
|
consortiumsConfig *ConsortiumsConfig
|
|
}
|
|
|
|
// NewChannelConfig creates a new ChannelConfig
|
|
func NewChannelConfig(channelGroup *cb.ConfigGroup, bccsp bccsp.BCCSP) (*ChannelConfig, error) {
|
|
cc := &ChannelConfig{
|
|
protos: &ChannelProtos{},
|
|
}
|
|
|
|
if err := DeserializeProtoValuesFromGroup(channelGroup, cc.protos); err != nil {
|
|
return nil, errors.Wrap(err, "failed to deserialize values")
|
|
}
|
|
|
|
channelCapabilities := cc.Capabilities()
|
|
|
|
if err := cc.Validate(channelCapabilities); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
mspConfigHandler := NewMSPConfigHandler(channelCapabilities.MSPVersion(), bccsp)
|
|
|
|
var err error
|
|
for groupName, group := range channelGroup.Groups {
|
|
switch groupName {
|
|
case ApplicationGroupKey:
|
|
cc.appConfig, err = NewApplicationConfig(group, mspConfigHandler)
|
|
case OrdererGroupKey:
|
|
cc.ordererConfig, err = NewOrdererConfig(group, mspConfigHandler, channelCapabilities)
|
|
case ConsortiumsGroupKey:
|
|
cc.consortiumsConfig, err = NewConsortiumsConfig(group, mspConfigHandler)
|
|
default:
|
|
return nil, fmt.Errorf("Disallowed channel group: %s", group)
|
|
}
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "could not create channel %s sub-group config", groupName)
|
|
}
|
|
}
|
|
|
|
if cc.mspManager, err = mspConfigHandler.CreateMSPManager(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return cc, nil
|
|
}
|
|
|
|
// MSPManager returns the MSP manager for this config
|
|
func (cc *ChannelConfig) MSPManager() msp.MSPManager {
|
|
return cc.mspManager
|
|
}
|
|
|
|
// OrdererConfig returns the orderer config associated with this channel
|
|
func (cc *ChannelConfig) OrdererConfig() *OrdererConfig {
|
|
return cc.ordererConfig
|
|
}
|
|
|
|
// ApplicationConfig returns the application config associated with this channel
|
|
func (cc *ChannelConfig) ApplicationConfig() *ApplicationConfig {
|
|
return cc.appConfig
|
|
}
|
|
|
|
// ConsortiumsConfig returns the consortium config associated with this channel if it exists
|
|
func (cc *ChannelConfig) ConsortiumsConfig() *ConsortiumsConfig {
|
|
return cc.consortiumsConfig
|
|
}
|
|
|
|
// HashingAlgorithm returns a function pointer to the chain hashing algorithm
|
|
func (cc *ChannelConfig) HashingAlgorithm() func(input []byte) []byte {
|
|
return cc.hashingAlgorithm
|
|
}
|
|
|
|
// BlockDataHashingStructureWidth returns the width to use when forming the block data hashing structure
|
|
func (cc *ChannelConfig) BlockDataHashingStructureWidth() uint32 {
|
|
return cc.protos.BlockDataHashingStructure.Width
|
|
}
|
|
|
|
// OrdererAddresses returns the list of valid orderer addresses to connect to invoke Broadcast/Deliver
|
|
func (cc *ChannelConfig) OrdererAddresses() []string {
|
|
return cc.protos.OrdererAddresses.Addresses
|
|
}
|
|
|
|
// ConsortiumName returns the name of the consortium this channel was created under
|
|
func (cc *ChannelConfig) ConsortiumName() string {
|
|
return cc.protos.Consortium.Name
|
|
}
|
|
|
|
// Capabilities returns information about the available capabilities for this channel
|
|
func (cc *ChannelConfig) Capabilities() ChannelCapabilities {
|
|
_ = cc.protos
|
|
_ = cc.protos.Capabilities
|
|
_ = cc.protos.Capabilities.Capabilities
|
|
return capabilities.NewChannelProvider(cc.protos.Capabilities.Capabilities)
|
|
}
|
|
|
|
// Validate inspects the generated configuration protos and ensures that the values are correct
|
|
func (cc *ChannelConfig) Validate(channelCapabilities ChannelCapabilities) error {
|
|
for _, validator := range []func() error{
|
|
cc.validateHashingAlgorithm,
|
|
cc.validateBlockDataHashingStructure,
|
|
} {
|
|
if err := validator(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if !channelCapabilities.OrgSpecificOrdererEndpoints() {
|
|
return cc.validateOrdererAddresses()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (cc *ChannelConfig) validateHashingAlgorithm() error {
|
|
switch cc.protos.HashingAlgorithm.Name {
|
|
case bccsp.SHA256:
|
|
cc.hashingAlgorithm = util.ComputeSHA256
|
|
case bccsp.SHA3_256:
|
|
cc.hashingAlgorithm = util.ComputeSHA3256
|
|
default:
|
|
return fmt.Errorf("Unknown hashing algorithm type: %s", cc.protos.HashingAlgorithm.Name)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (cc *ChannelConfig) validateBlockDataHashingStructure() error {
|
|
if cc.protos.BlockDataHashingStructure.Width != math.MaxUint32 {
|
|
return fmt.Errorf("BlockDataHashStructure width only supported at MaxUint32 in this version")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (cc *ChannelConfig) validateOrdererAddresses() error {
|
|
if len(cc.protos.OrdererAddresses.Addresses) == 0 {
|
|
return fmt.Errorf("Must set some OrdererAddresses")
|
|
}
|
|
return nil
|
|
}
|