github.com/ewagmig/fabric@v2.1.1+incompatible/common/channelconfig/util.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package channelconfig
     8  
     9  import (
    10  	"fmt"
    11  	"io/ioutil"
    12  	"math"
    13  
    14  	"github.com/golang/protobuf/proto"
    15  	cb "github.com/hyperledger/fabric-protos-go/common"
    16  	mspprotos "github.com/hyperledger/fabric-protos-go/msp"
    17  	ab "github.com/hyperledger/fabric-protos-go/orderer"
    18  	"github.com/hyperledger/fabric-protos-go/orderer/etcdraft"
    19  	pb "github.com/hyperledger/fabric-protos-go/peer"
    20  	"github.com/hyperledger/fabric/bccsp"
    21  	"github.com/hyperledger/fabric/protoutil"
    22  	"github.com/pkg/errors"
    23  )
    24  
    25  const (
    26  	// ReadersPolicyKey is the key used for the read policy
    27  	ReadersPolicyKey = "Readers"
    28  
    29  	// WritersPolicyKey is the key used for the read policy
    30  	WritersPolicyKey = "Writers"
    31  
    32  	// AdminsPolicyKey is the key used for the read policy
    33  	AdminsPolicyKey = "Admins"
    34  
    35  	defaultHashingAlgorithm = bccsp.SHA256
    36  
    37  	defaultBlockDataHashingStructureWidth = math.MaxUint32
    38  )
    39  
    40  // ConfigValue defines a common representation for different *cb.ConfigValue values.
    41  type ConfigValue interface {
    42  	// Key is the key this value should be stored in the *cb.ConfigGroup.Values map.
    43  	Key() string
    44  
    45  	// Value is the message which should be marshaled to opaque bytes for the *cb.ConfigValue.value.
    46  	Value() proto.Message
    47  }
    48  
    49  // StandardConfigValue implements the ConfigValue interface.
    50  type StandardConfigValue struct {
    51  	key   string
    52  	value proto.Message
    53  }
    54  
    55  // Key is the key this value should be stored in the *cb.ConfigGroup.Values map.
    56  func (scv *StandardConfigValue) Key() string {
    57  	return scv.key
    58  }
    59  
    60  // Value is the message which should be marshaled to opaque bytes for the *cb.ConfigValue.value.
    61  func (scv *StandardConfigValue) Value() proto.Message {
    62  	return scv.value
    63  }
    64  
    65  // ConsortiumValue returns the config definition for the consortium name.
    66  // It is a value for the channel group.
    67  func ConsortiumValue(name string) *StandardConfigValue {
    68  	return &StandardConfigValue{
    69  		key: ConsortiumKey,
    70  		value: &cb.Consortium{
    71  			Name: name,
    72  		},
    73  	}
    74  }
    75  
    76  // HashingAlgorithm returns the only currently valid hashing algorithm.
    77  // It is a value for the /Channel group.
    78  func HashingAlgorithmValue() *StandardConfigValue {
    79  	return &StandardConfigValue{
    80  		key: HashingAlgorithmKey,
    81  		value: &cb.HashingAlgorithm{
    82  			Name: defaultHashingAlgorithm,
    83  		},
    84  	}
    85  }
    86  
    87  // BlockDataHashingStructureValue returns the only currently valid block data hashing structure.
    88  // It is a value for the /Channel group.
    89  func BlockDataHashingStructureValue() *StandardConfigValue {
    90  	return &StandardConfigValue{
    91  		key: BlockDataHashingStructureKey,
    92  		value: &cb.BlockDataHashingStructure{
    93  			Width: defaultBlockDataHashingStructureWidth,
    94  		},
    95  	}
    96  }
    97  
    98  // OrdererAddressesValue returns the a config definition for the orderer addresses.
    99  // It is a value for the /Channel group.
   100  func OrdererAddressesValue(addresses []string) *StandardConfigValue {
   101  	return &StandardConfigValue{
   102  		key: OrdererAddressesKey,
   103  		value: &cb.OrdererAddresses{
   104  			Addresses: addresses,
   105  		},
   106  	}
   107  }
   108  
   109  // ConsensusTypeValue returns the config definition for the orderer consensus type.
   110  // It is a value for the /Channel/Orderer group.
   111  func ConsensusTypeValue(consensusType string, consensusMetadata []byte) *StandardConfigValue {
   112  	return &StandardConfigValue{
   113  		key: ConsensusTypeKey,
   114  		value: &ab.ConsensusType{
   115  			Type:     consensusType,
   116  			Metadata: consensusMetadata,
   117  		},
   118  	}
   119  }
   120  
   121  // BatchSizeValue returns the config definition for the orderer batch size.
   122  // It is a value for the /Channel/Orderer group.
   123  func BatchSizeValue(maxMessages, absoluteMaxBytes, preferredMaxBytes uint32) *StandardConfigValue {
   124  	return &StandardConfigValue{
   125  		key: BatchSizeKey,
   126  		value: &ab.BatchSize{
   127  			MaxMessageCount:   maxMessages,
   128  			AbsoluteMaxBytes:  absoluteMaxBytes,
   129  			PreferredMaxBytes: preferredMaxBytes,
   130  		},
   131  	}
   132  }
   133  
   134  // BatchTimeoutValue returns the config definition for the orderer batch timeout.
   135  // It is a value for the /Channel/Orderer group.
   136  func BatchTimeoutValue(timeout string) *StandardConfigValue {
   137  	return &StandardConfigValue{
   138  		key: BatchTimeoutKey,
   139  		value: &ab.BatchTimeout{
   140  			Timeout: timeout,
   141  		},
   142  	}
   143  }
   144  
   145  // ChannelRestrictionsValue returns the config definition for the orderer channel restrictions.
   146  // It is a value for the /Channel/Orderer group.
   147  func ChannelRestrictionsValue(maxChannelCount uint64) *StandardConfigValue {
   148  	return &StandardConfigValue{
   149  		key: ChannelRestrictionsKey,
   150  		value: &ab.ChannelRestrictions{
   151  			MaxCount: maxChannelCount,
   152  		},
   153  	}
   154  }
   155  
   156  // KafkaBrokersValue returns the config definition for the addresses of the ordering service's Kafka brokers.
   157  // It is a value for the /Channel/Orderer group.
   158  func KafkaBrokersValue(brokers []string) *StandardConfigValue {
   159  	return &StandardConfigValue{
   160  		key: KafkaBrokersKey,
   161  		value: &ab.KafkaBrokers{
   162  			Brokers: brokers,
   163  		},
   164  	}
   165  }
   166  
   167  // MSPValue returns the config definition for an MSP.
   168  // It is a value for the /Channel/Orderer/*, /Channel/Application/*, and /Channel/Consortiums/*/*/* groups.
   169  func MSPValue(mspDef *mspprotos.MSPConfig) *StandardConfigValue {
   170  	return &StandardConfigValue{
   171  		key:   MSPKey,
   172  		value: mspDef,
   173  	}
   174  }
   175  
   176  // CapabilitiesValue returns the config definition for a a set of capabilities.
   177  // It is a value for the /Channel/Orderer, Channel/Application/, and /Channel groups.
   178  func CapabilitiesValue(capabilities map[string]bool) *StandardConfigValue {
   179  	c := &cb.Capabilities{
   180  		Capabilities: make(map[string]*cb.Capability),
   181  	}
   182  
   183  	for capability, required := range capabilities {
   184  		if !required {
   185  			continue
   186  		}
   187  		c.Capabilities[capability] = &cb.Capability{}
   188  	}
   189  
   190  	return &StandardConfigValue{
   191  		key:   CapabilitiesKey,
   192  		value: c,
   193  	}
   194  }
   195  
   196  // EndpointsValue returns the config definition for the orderer addresses at an org scoped level.
   197  // It is a value for the /Channel/Orderer/<OrgName> group.
   198  func EndpointsValue(addresses []string) *StandardConfigValue {
   199  	return &StandardConfigValue{
   200  		key: EndpointsKey,
   201  		value: &cb.OrdererAddresses{
   202  			Addresses: addresses,
   203  		},
   204  	}
   205  }
   206  
   207  // AnchorPeersValue returns the config definition for an org's anchor peers.
   208  // It is a value for the /Channel/Application/*.
   209  func AnchorPeersValue(anchorPeers []*pb.AnchorPeer) *StandardConfigValue {
   210  	return &StandardConfigValue{
   211  		key:   AnchorPeersKey,
   212  		value: &pb.AnchorPeers{AnchorPeers: anchorPeers},
   213  	}
   214  }
   215  
   216  // ChannelCreationPolicyValue returns the config definition for a consortium's channel creation policy
   217  // It is a value for the /Channel/Consortiums/*/*.
   218  func ChannelCreationPolicyValue(policy *cb.Policy) *StandardConfigValue {
   219  	return &StandardConfigValue{
   220  		key:   ChannelCreationPolicyKey,
   221  		value: policy,
   222  	}
   223  }
   224  
   225  // ACLValues returns the config definition for an applications resources based ACL definitions.
   226  // It is a value for the /Channel/Application/.
   227  func ACLValues(acls map[string]string) *StandardConfigValue {
   228  	a := &pb.ACLs{
   229  		Acls: make(map[string]*pb.APIResource),
   230  	}
   231  
   232  	for apiResource, policyRef := range acls {
   233  		a.Acls[apiResource] = &pb.APIResource{PolicyRef: policyRef}
   234  	}
   235  
   236  	return &StandardConfigValue{
   237  		key:   ACLsKey,
   238  		value: a,
   239  	}
   240  }
   241  
   242  // ValidateCapabilities validates whether the peer can meet the capabilities requirement in the given config block
   243  func ValidateCapabilities(block *cb.Block, bccsp bccsp.BCCSP) error {
   244  	envelopeConfig, err := protoutil.ExtractEnvelope(block, 0)
   245  	if err != nil {
   246  		return errors.Errorf("failed to %s", err)
   247  	}
   248  
   249  	configEnv := &cb.ConfigEnvelope{}
   250  	_, err = protoutil.UnmarshalEnvelopeOfType(envelopeConfig, cb.HeaderType_CONFIG, configEnv)
   251  	if err != nil {
   252  		return errors.Errorf("malformed configuration envelope: %s", err)
   253  	}
   254  
   255  	if configEnv.Config == nil {
   256  		return errors.New("nil config envelope Config")
   257  	}
   258  
   259  	if configEnv.Config.ChannelGroup == nil {
   260  		return errors.New("no channel configuration was found in the config block")
   261  	}
   262  
   263  	if configEnv.Config.ChannelGroup.Groups == nil {
   264  		return errors.New("no channel configuration groups are available")
   265  	}
   266  
   267  	_, exists := configEnv.Config.ChannelGroup.Groups[ApplicationGroupKey]
   268  	if !exists {
   269  		return errors.Errorf("invalid configuration block, missing %s "+
   270  			"configuration group", ApplicationGroupKey)
   271  	}
   272  
   273  	cc, err := NewChannelConfig(configEnv.Config.ChannelGroup, bccsp)
   274  	if err != nil {
   275  		return errors.Errorf("no valid channel configuration found due to %s", err)
   276  	}
   277  
   278  	// Check the channel top-level capabilities
   279  	if err := cc.Capabilities().Supported(); err != nil {
   280  		return err
   281  	}
   282  
   283  	// Check the application capabilities
   284  	if err := cc.ApplicationConfig().Capabilities().Supported(); err != nil {
   285  		return err
   286  	}
   287  
   288  	return nil
   289  }
   290  
   291  // MarshalEtcdRaftMetadata serializes etcd RAFT metadata.
   292  func MarshalEtcdRaftMetadata(md *etcdraft.ConfigMetadata) ([]byte, error) {
   293  	copyMd := proto.Clone(md).(*etcdraft.ConfigMetadata)
   294  	for _, c := range copyMd.Consenters {
   295  		// Expect the user to set the config value for client/server certs to the
   296  		// path where they are persisted locally, then load these files to memory.
   297  		clientCert, err := ioutil.ReadFile(string(c.GetClientTlsCert()))
   298  		if err != nil {
   299  			return nil, fmt.Errorf("cannot load client cert for consenter %s:%d: %s", c.GetHost(), c.GetPort(), err)
   300  		}
   301  		c.ClientTlsCert = clientCert
   302  
   303  		serverCert, err := ioutil.ReadFile(string(c.GetServerTlsCert()))
   304  		if err != nil {
   305  			return nil, fmt.Errorf("cannot load server cert for consenter %s:%d: %s", c.GetHost(), c.GetPort(), err)
   306  		}
   307  		c.ServerTlsCert = serverCert
   308  	}
   309  	return proto.Marshal(copyMd)
   310  }