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