func (o *Orderer) SendBroadcast(envelope *fab.SignedEnvelope) (*common.Status, error) {
	ctx := context.Background()
	ctx, _ = context.WithTimeout(ctx, o.dialTimeout)
	conn, err := grpc.DialContext(ctx, o.url, o.grpcDialOption...)
	if err != nil {
		return nil, status.New(status.OrdererClientStatus, status.ConnectionFailed.ToInt32(), err.Error(), nil)
	}
	defer conn.Close()
	broadcastStream, err := ab.NewAtomicBroadcastClient(conn).Broadcast(ctx)
	if err != nil {
		rpcStatus, ok := grpcstatus.FromError(err)
		if ok {
			err = status.NewFromGRPCStatus(rpcStatus)
		}
		return nil, errors.Wrap(err, "NewAtomicBroadcastClient failed")
	}
	done := make(chan bool)
	var broadcastErr error
	var broadcastStatus *common.Status
	go func() {
		for {
			broadcastResponse, err := broadcastStream.Recv()
			logger.Debugf("Orderer.broadcastStream - response:%v, error:%v\n", broadcastResponse, err)
			if err != nil {
				rpcStatus, ok := grpcstatus.FromError(err)
				if ok {
					err = status.NewFromGRPCStatus(rpcStatus)
				}
				broadcastErr = errors.Wrap(err, "broadcast recv failed")
				done <- true
				return
			}
			broadcastStatus = &broadcastResponse.Status
			if broadcastResponse.Status == common.Status_SUCCESS {
				done <- true
				return
			}
			if broadcastResponse.Status != common.Status_SUCCESS {
				broadcastErr = status.New(status.OrdererServerStatus, int32(broadcastResponse.Status), broadcastResponse.Info, nil)
				done <- true
				return
			}
		}
	}()
	if err := broadcastStream.Send(&common.Envelope{
		Payload:   envelope.Payload,
		Signature: envelope.Signature,
	}); err != nil {
		return nil, errors.Wrap(err, "failed to send envelope to orderer")
	}
	broadcastStream.CloseSend()
	<-done
	return broadcastStatus, broadcastErr
}
SendBroadcast Send the created transaction to Orderer.
package orderer
import (
	"time"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/keepalive"
	grpcstatus "google.golang.org/grpc/status"
	"github.com/hyperledger/fabric-sdk-go/api/apiconfig"
	fab "github.com/hyperledger/fabric-sdk-go/api/apifabclient"
	ab "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/protos/orderer"
	"github.com/hyperledger/fabric-sdk-go/pkg/config/comm"
	"github.com/hyperledger/fabric-sdk-go/pkg/config/urlutil"
	"github.com/hyperledger/fabric-sdk-go/pkg/errors/status"
	"github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common"
	"github.com/spf13/cast"
	"github.com/hyperledger/fabric-sdk-go/pkg/logging"
	"github.com/pkg/errors"
	"github.com/hyperledger/fabric-sdk-go/internal/github.com/tjfoc/gmsm/sm2"
	credentials "github.com/hyperledger/fabric-sdk-go/internal/github.com/tjfoc/gmtls/gmcredentials"
)
var logger = logging.NewLogger("fabric_sdk_go")
type Orderer struct {
	config         apiconfig.Config
	url            string
	tlsCACert      *sm2.Certificate
	serverName     string
	grpcDialOption []grpc.DialOption
	kap            keepalive.ClientParameters
	dialTimeout    time.Duration
	failFast       bool
}
type Option func(*Orderer) error
func New(config apiconfig.Config, opts ...Option) (*Orderer, error) {
	orderer := &Orderer{config: config}
	for _, opt := range opts {
		err := opt(orderer)
		if err != nil {
			return nil, err
		}
	}
	var grpcOpts []grpc.DialOption
	if orderer.kap.Time > 0 {
		grpcOpts = append(grpcOpts, grpc.WithKeepaliveParams(orderer.kap))
	}
	grpcOpts = append(grpcOpts, grpc.WithDefaultCallOptions(grpc.FailFast(orderer.failFast)))
	orderer.dialTimeout = config.TimeoutOrDefault(apiconfig.OrdererConnection)
	if urlutil.IsTLSEnabled(orderer.url) {
		tlsConfig, err := comm.TLSConfig(orderer.tlsCACert, orderer.serverName, config)
		if err != nil {
			return nil, err
		}
		grpcOpts = append(grpcOpts, grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)))
	} else {
		grpcOpts = append(grpcOpts, grpc.WithInsecure())
	}
	orderer.url = urlutil.ToAddress(orderer.url)
	orderer.grpcDialOption = grpcOpts
	return orderer, nil
}
func WithURL(url string) Option {
	return func(o *Orderer) error {
		o.url = url
		return nil
	}
}
func WithTLSCert(tlsCACert *sm2.Certificate) Option {
	return func(o *Orderer) error {
		o.tlsCACert = tlsCACert
		return nil
	}
}
func WithServerName(serverName string) Option {
	return func(o *Orderer) error {
		o.serverName = serverName
		return nil
	}
}
func FromOrdererConfig(ordererCfg *apiconfig.OrdererConfig) Option {
	return func(o *Orderer) error {
		o.url = ordererCfg.URL
		var err error
		if urlutil.IsTLSEnabled(ordererCfg.URL) {
			o.tlsCACert, err = ordererCfg.TLSCACerts.TLSCert()
			if err != nil {
				return err
			}
		}
		o.serverName = getServerNameOverride(ordererCfg)
		o.kap = getKeepAliveOptions(ordererCfg)
		o.failFast = getFailFast(ordererCfg)
		return nil
	}
}
func FromOrdererName(name string) Option {
	return func(o *Orderer) error {
		ordererCfg, err := o.config.OrdererConfig(name)
		if err != nil {
			return err
		}
		return FromOrdererConfig(ordererCfg)(o)
	}
}
func getServerNameOverride(ordererCfg *apiconfig.OrdererConfig) string {
	serverNameOverride := ""
	if str, ok := ordererCfg.GRPCOptions["ssl-target-name-override"].(string); ok {
		serverNameOverride = str
	}
	return serverNameOverride
}
func getFailFast(ordererCfg *apiconfig.OrdererConfig) bool {
	var failFast = true
	if ff, ok := ordererCfg.GRPCOptions["fail-fast"].(bool); ok {
		failFast = cast.ToBool(ff)
	}
	return failFast
}
func getKeepAliveOptions(ordererCfg *apiconfig.OrdererConfig) keepalive.ClientParameters {
	var kap keepalive.ClientParameters
	if kaTime, ok := ordererCfg.GRPCOptions["keep-alive-time"].(time.Duration); ok {
		kap.Time = cast.ToDuration(kaTime)
	}
	if kaTimeout, ok := ordererCfg.GRPCOptions["keep-alive-timeout"].(time.Duration); ok {
		kap.Timeout = cast.ToDuration(kaTimeout)
	}
	if kaPermit, ok := ordererCfg.GRPCOptions["keep-alive-permit"].(time.Duration); ok {
		kap.PermitWithoutStream = cast.ToBool(kaPermit)
	}
	return kap
}
func (o *Orderer) URL() string {
	return o.url
}