func NewRemoteSigner(
	logger log.Logger,
	chainID, socketAddr string,
	privVal types.PrivValidator,
	privKey ed25519.PrivKeyEd25519,
) *RemoteSigner {
	rs := &RemoteSigner{
		addr:         socketAddr,
		chainID:      chainID,
		connDeadline: time.Second * defaultConnDeadlineSeconds,
		connRetries:  defaultDialRetries,
		privKey:      privKey,
		privVal:      privVal,
	}
	rs.BaseService = *cmn.NewBaseService(logger, "RemoteSigner", rs)
	return rs
}
NewRemoteSigner returns an instance of RemoteSigner.
package privval
import (
	"errors"
	"fmt"
	"io"
	"net"
	"time"
	"github.com/tendermint/go-amino"
	"github.com/tendermint/tendermint/crypto"
	"github.com/tendermint/tendermint/crypto/ed25519"
	cmn "github.com/tendermint/tendermint/libs/common"
	"github.com/tendermint/tendermint/libs/log"
	p2pconn "github.com/tendermint/tendermint/p2p/conn"
	"github.com/tendermint/tendermint/types"
)
const (
	defaultAcceptDeadlineSeconds = 3
	defaultConnDeadlineSeconds   = 3
	defaultConnHeartBeatSeconds  = 30
	defaultConnWaitSeconds       = 60
	defaultDialRetries           = 10
)
var (
	ErrDialRetryMax    = errors.New("dialed maximum retries")
	ErrConnWaitTimeout = errors.New("waited for remote signer for too long")
	ErrConnTimeout     = errors.New("remote signer timed out")
)
var (
	acceptDeadline = time.Second + defaultAcceptDeadlineSeconds
	connDeadline   = time.Second * defaultConnDeadlineSeconds
	connHeartbeat  = time.Second * defaultConnHeartBeatSeconds
)
type SocketPVOption func(*SocketPV)
func SocketPVAcceptDeadline(deadline time.Duration) SocketPVOption {
	return func(sc *SocketPV) { sc.acceptDeadline = deadline }
}
func SocketPVConnDeadline(deadline time.Duration) SocketPVOption {
	return func(sc *SocketPV) { sc.connDeadline = deadline }
}
func SocketPVHeartbeat(period time.Duration) SocketPVOption {
	return func(sc *SocketPV) { sc.connHeartbeat = period }
}
func SocketPVConnWait(timeout time.Duration) SocketPVOption {
	return func(sc *SocketPV) { sc.connWaitTimeout = timeout }
}
type SocketPV struct {
	cmn.BaseService
	addr            string
	acceptDeadline  time.Duration
	connDeadline    time.Duration
	connHeartbeat   time.Duration
	connWaitTimeout time.Duration
	privKey         ed25519.PrivKeyEd25519
	conn     net.Conn
	listener net.Listener
}
var _ types.PrivValidator = (*SocketPV)(nil)
func NewSocketPV(
	logger log.Logger,
	socketAddr string,
	privKey ed25519.PrivKeyEd25519,
) *SocketPV {
	sc := &SocketPV{
		addr:            socketAddr,
		acceptDeadline:  acceptDeadline,
		connDeadline:    connDeadline,
		connHeartbeat:   connHeartbeat,
		connWaitTimeout: time.Second * defaultConnWaitSeconds,
		privKey:         privKey,
	}
	sc.BaseService = *cmn.NewBaseService(logger, "SocketPV", sc)
	return sc
}
func (sc *SocketPV) GetAddress() types.Address {
	addr, err := sc.getAddress()
	if err != nil {
		panic(err)
	}
	return addr
}
func (sc *SocketPV) getAddress() (cmn.HexBytes, error) {
	p, err := sc.getPubKey()
	if err != nil {
		return nil, err
	}
	return p.Address(), nil
}
func (sc *SocketPV) GetPubKey() crypto.PubKey {
	pubKey, err := sc.getPubKey()
	if err != nil {
		panic(err)
	}
	return pubKey
}
func (sc *SocketPV) getPubKey() (crypto.PubKey, error) {
	err := writeMsg(sc.conn, &PubKeyMsg{})
	if err != nil {
		return nil, err
	}
	res, err := readMsg(sc.conn)
	if err != nil {
		return nil, err
	}
	return res.(*PubKeyMsg).PubKey, nil
}
func (sc *SocketPV) SignVote(chainID string, vote *types.Vote) error {
	err := writeMsg(sc.conn, &SignVoteMsg{Vote: vote})
	if err != nil {
		return err
	}
	res, err := readMsg(sc.conn)
	if err != nil {
		return err
	}
	*vote = *res.(*SignVoteMsg).Vote
	return nil
}
func (sc *SocketPV) SignProposal(
	chainID string,
	proposal *types.Proposal,
) error {
	err := writeMsg(sc.conn, &SignProposalMsg{Proposal: proposal})
	if err != nil {
		return err
	}
	res, err := readMsg(sc.conn)
	if err != nil {
		return err
	}
	*proposal = *res.(*SignProposalMsg).Proposal
	return nil
}
func (sc *SocketPV) SignHeartbeat(
	chainID string,
	heartbeat *types.Heartbeat,
) error {
	err := writeMsg(sc.conn, &SignHeartbeatMsg{Heartbeat: heartbeat})
	if err != nil {
		return err
	}
	res, err := readMsg(sc.conn)
	if err != nil {
		return err
	}
	*heartbeat = *res.(*SignHeartbeatMsg).Heartbeat
	return nil
}
func (sc *SocketPV) OnStart() error {
	if err := sc.listen(); err != nil {
		err = cmn.ErrorWrap(err, "failed to listen")
		sc.Logger.Error(
			"OnStart",
			"err", err,
		)
		return err
	}
	conn, err := sc.waitConnection()
	if err != nil {
		err = cmn.ErrorWrap(err, "failed to accept connection")
		sc.Logger.Error(
			"OnStart",
			"err", err,
		)
		return err
	}
	sc.conn = conn
	return nil
}
func (sc *SocketPV) OnStop() {
	if sc.conn != nil {
		if err := sc.conn.Close(); err != nil {
			err = cmn.ErrorWrap(err, "failed to close connection")
			sc.Logger.Error(
				"OnStop",
				"err", err,
			)
		}
	}
	if sc.listener != nil {
		if err := sc.listener.Close(); err != nil {
			err = cmn.ErrorWrap(err, "failed to close listener")
			sc.Logger.Error(
				"OnStop",
				"err", err,
			)
		}
	}
}
func (sc *SocketPV) acceptConnection() (net.Conn, error) {
	conn, err := sc.listener.Accept()
	if err != nil {
		if !sc.IsRunning() {
			return nil, nil  
		}
		return nil, err
	}
	conn, err = p2pconn.MakeSecretConnection(conn, sc.privKey)
	if err != nil {
		return nil, err
	}
	return conn, nil
}
func (sc *SocketPV) listen() error {
	ln, err := net.Listen(cmn.ProtocolAndAddress(sc.addr))
	if err != nil {
		return err
	}
	sc.listener = newTCPTimeoutListener(
		ln,
		sc.acceptDeadline,
		sc.connDeadline,
		sc.connHeartbeat,
	)
	return nil
}
func (sc *SocketPV) waitConnection() (net.Conn, error) {
	var (
		connc = make(chan net.Conn, 1)
		errc  = make(chan error, 1)
	)
	go func(connc chan<- net.Conn, errc chan<- error) {
		conn, err := sc.acceptConnection()
		if err != nil {
			errc <- err
			return
		}
		connc <- conn
	}(connc, errc)
	select {
	case conn := <-connc:
		return conn, nil
	case err := <-errc:
		if _, ok := err.(timeoutError); ok {
			return nil, cmn.ErrorWrap(ErrConnWaitTimeout, err.Error())
		}
		return nil, err
	case <-time.After(sc.connWaitTimeout):
		return nil, ErrConnWaitTimeout
	}
}
type RemoteSignerOption func(*RemoteSigner)
func RemoteSignerConnDeadline(deadline time.Duration) RemoteSignerOption {
	return func(ss *RemoteSigner) { ss.connDeadline = deadline }
}
func RemoteSignerConnRetries(retries int) RemoteSignerOption {
	return func(ss *RemoteSigner) { ss.connRetries = retries }
}
type RemoteSigner struct {
	cmn.BaseService
	addr         string
	chainID      string
	connDeadline time.Duration
	connRetries  int
	privKey      ed25519.PrivKeyEd25519
	privVal      types.PrivValidator
	conn net.Conn
}