func resolveOrdererAddress(ordererAddress string) string {
	s := strings.Split(ordererAddress, ":")
	if len(s) > 1 {
		return s[0]
	}
	return ordererAddress
}
resolveOrdererAddress resolves order address to remove port from address if present
package channel
import (
	"encoding/pem"
	"regexp"
	"strings"
	"github.com/pkg/errors"
	"github.com/hyperledger/fabric-sdk-go/api/apiconfig"
	fab "github.com/hyperledger/fabric-sdk-go/api/apifabclient"
	"github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/msp"
	"github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/orderer"
	"github.com/hyperledger/fabric-sdk-go/pkg/logging"
	"github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common"
	pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer"
	"github.com/hyperledger/fabric-sdk-go/internal/github.com/tjfoc/gmsm/sm2"
)
var logger = logging.NewLogger("fabric_sdk_go")
type Channel struct {
	name          string  
	peers         map[string]fab.Peer
	orderers      map[string]fab.Orderer
	clientContext fab.Context
	primaryPeer   fab.Peer
	mspManager    msp.MSPManager
	anchorPeers   []*fab.OrgAnchorPeer
	initialized   bool
}
func New(ctx fab.Context, cfg fab.ChannelCfg) (*Channel, error) {
	if ctx == nil {
		return nil, errors.Errorf("client is required")
	}
	p := make(map[string]fab.Peer)
	o := make(map[string]fab.Orderer)
	c := Channel{
		name:          cfg.Name(),
		peers:         p,
		orderers:      o,
		clientContext: ctx,
	}
	mspManager := msp.NewMSPManager()
	if len(cfg.Msps()) > 0 {
		msps, err := loadMSPs(cfg.Msps(), ctx.CryptoSuite())
		if err != nil {
			return nil, errors.WithMessage(err, "load MSPs from config failed")
		}
		if err := mspManager.Setup(msps); err != nil {
			return nil, errors.WithMessage(err, "MSPManager Setup failed")
		}
		for _, msp := range msps {
			for _, cert := range msp.GetTLSRootCerts() {
				addCertsToConfig(ctx.Config(), cert)
			}
			for _, cert := range msp.GetTLSIntermediateCerts() {
				addCertsToConfig(ctx.Config(), cert)
			}
		}
	}
	c.mspManager = mspManager
	c.anchorPeers = cfg.AnchorPeers()
	for _, name := range cfg.Orderers() {
		oCfg, err := getOrdererConfig(ctx.Config(), name)
		if err != nil {
			return nil, errors.Errorf("failed to retrieve orderer config...: %s", err)
		}
		var o *orderer.Orderer
		if oCfg == nil {
			o, err = orderer.New(ctx.Config(), orderer.WithURL(resolveOrdererURL(name)), orderer.WithServerName(resolveOrdererAddress(name)))
		} else {
			o, err = orderer.New(ctx.Config(), orderer.FromOrdererConfig(oCfg))
		}
		if err != nil {
			return nil, errors.WithMessage(err, "failed to create new orderer from config")
		}
		c.orderers[o.URL()] = o
	}
	logger.Debugf("Constructed channel instance for channel %s: %v", c.name, c)
	return &c, nil
}
func (c *Channel) Name() string {
	return c.name
}
func (c *Channel) AddPeer(peer fab.Peer) error {
	url := peer.URL()
	if c.peers[url] != nil {
		return errors.Errorf("peer with URL %s already exists", url)
	}
	c.peers[url] = peer
	return nil
}
func (c *Channel) RemovePeer(peer fab.Peer) {
	url := peer.URL()
	if c.peers[url] != nil {
		delete(c.peers, url)
		logger.Debugf("Removed peer with URL %s", url)
	}
}
func (c *Channel) Peers() []fab.Peer {
	var peersArray []fab.Peer
	for _, v := range c.peers {
		peersArray = append(peersArray, v)
	}
	return peersArray
}
func (c *Channel) AnchorPeers() []fab.OrgAnchorPeer {
	anchors := []fab.OrgAnchorPeer{}
	for _, anchor := range c.anchorPeers {
		anchors = append(anchors, *anchor)
	}
	return anchors
}
func (c *Channel) SetPrimaryPeer(peer fab.Peer) error {
	if !c.isValidPeer(peer) {
		return errors.New("primary peer must be on this channel peer list")
	}
	c.primaryPeer = c.peers[peer.URL()]
	return nil
}
func (c *Channel) PrimaryPeer() fab.Peer {
	if c.primaryPeer != nil {
		return c.primaryPeer
	}
	for _, peer := range c.peers {
		logger.Debugf("Primary peer was not set, using %s", peer.URL())
		return peer
	}
	return nil
}
func (c *Channel) AddOrderer(orderer fab.Orderer) error {
	url := orderer.URL()
	if c.orderers[url] != nil {
		return errors.Errorf("orderer with URL %s already exists", url)
	}
	c.orderers[orderer.URL()] = orderer
	return nil
}
func (c *Channel) RemoveOrderer(orderer fab.Orderer) {
	url := orderer.URL()
	if c.orderers[url] != nil {
		delete(c.orderers, url)
		logger.Debugf("Removed orderer with URL %s", url)
	}
}
func (c *Channel) Orderers() []fab.Orderer {
	var orderersArray []fab.Orderer
	for _, v := range c.orderers {
		orderersArray = append(orderersArray, v)
	}
	return orderersArray
}
func (c *Channel) SetMSPManager(mspManager msp.MSPManager) {
	c.mspManager = mspManager
}
func (c *Channel) MSPManager() msp.MSPManager {
	return c.mspManager
}
func (c *Channel) OrganizationUnits() ([]string, error) {
	channelMSPManager := c.MSPManager()
	msps, err := channelMSPManager.GetMSPs()
	if err != nil {
		logger.Info("Cannot get channel manager")
		return nil, errors.WithMessage(err, "organization units were not set")
	}
	var orgIdentifiers []string
	for _, v := range msps {
		orgName, err := v.GetIdentifier()
		if err != nil {
			logger.Info("Organization does not have an identifier")
		}
		orgIdentifiers = append(orgIdentifiers, orgName)
	}
	return orgIdentifiers, nil
}
func (c *Channel) isValidPeer(peer fab.Peer) bool {
	return peer != nil && c.peers[peer.URL()] != nil
}
func (c *Channel) UpdateChannel() bool {
	return false
}
func (c *Channel) IsReadonly() bool {
	return false  
}
func (c *Channel) IsInitialized() bool {
	return c.initialized
}
func addCertsToConfig(config apiconfig.Config, pemCerts []byte) {
	for len(pemCerts) > 0 {
		var block *pem.Block
		block, pemCerts = pem.Decode(pemCerts)
		if block == nil {
			break
		}
		if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
			continue
		}
		cert, err := sm2.ParseCertificate(block.Bytes)
		if err != nil {
			continue
		}
		config.TLSCACertPool(cert)
	}
}
func getOrdererConfig(config apiconfig.Config, ordererAddress string) (*apiconfig.OrdererConfig, error) {
	return config.OrdererConfig(resolveOrdererAddress(ordererAddress))
}