multi: make remote signer RPC timeout configurable

This commit is contained in:
Oliver Gugger 2022-01-05 11:04:28 +01:00
parent f3cd383d1f
commit 9601a9ab84
No known key found for this signature in database
GPG Key ID: 8E4256593F177720
5 changed files with 47 additions and 19 deletions

View File

@ -579,7 +579,9 @@ func DefaultConfig() Config {
ChannelCommitInterval: defaultChannelCommitInterval, ChannelCommitInterval: defaultChannelCommitInterval,
ChannelCommitBatchSize: defaultChannelCommitBatchSize, ChannelCommitBatchSize: defaultChannelCommitBatchSize,
CoinSelectionStrategy: defaultCoinSelectionStrategy, CoinSelectionStrategy: defaultCoinSelectionStrategy,
RemoteSigner: &lncfg.RemoteSigner{}, RemoteSigner: &lncfg.RemoteSigner{
Timeout: lncfg.DefaultRemoteSignerRPCTimeout,
},
} }
} }
@ -1554,6 +1556,7 @@ func ValidateConfig(cfg Config, interceptor signal.Interceptor, fileParser,
cfg.Cluster, cfg.Cluster,
cfg.HealthChecks, cfg.HealthChecks,
cfg.RPCMiddleware, cfg.RPCMiddleware,
cfg.RemoteSigner,
) )
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -688,7 +688,6 @@ func (d *RPCSignerWalletImpl) BuildChainControl(
rpcKeyRing, err := rpcwallet.NewRPCKeyRing( rpcKeyRing, err := rpcwallet.NewRPCKeyRing(
baseKeyRing, walletController, baseKeyRing, walletController,
d.DefaultWalletImpl.cfg.RemoteSigner, walletConfig.CoinType, d.DefaultWalletImpl.cfg.RemoteSigner, walletConfig.CoinType,
rpcwallet.DefaultRPCTimeout,
) )
if err != nil { if err != nil {
err := fmt.Errorf("unable to create RPC remote signing wallet "+ err := fmt.Errorf("unable to create RPC remote signing wallet "+

View File

@ -1,9 +1,36 @@
package lncfg package lncfg
import (
"fmt"
"time"
)
const (
// DefaultRemoteSignerRPCTimeout is the default timeout that is used
// when forwarding a request to the remote signer through RPC.
DefaultRemoteSignerRPCTimeout = 5 * time.Second
)
// RemoteSigner holds the configuration options for a remote RPC signer. // RemoteSigner holds the configuration options for a remote RPC signer.
type RemoteSigner struct { type RemoteSigner struct {
Enable bool `long:"enable" description:"Use a remote signer for signing any on-chain related transactions or messages. Only recommended if local wallet is initialized as watch-only. Remote signer must use the same seed/root key as the local watch-only wallet but must have private keys."` Enable bool `long:"enable" description:"Use a remote signer for signing any on-chain related transactions or messages. Only recommended if local wallet is initialized as watch-only. Remote signer must use the same seed/root key as the local watch-only wallet but must have private keys."`
RPCHost string `long:"rpchost" description:"The remote signer's RPC host:port"` RPCHost string `long:"rpchost" description:"The remote signer's RPC host:port"`
MacaroonPath string `long:"macaroonpath" description:"The macaroon to use for authenticating with the remote signer"` MacaroonPath string `long:"macaroonpath" description:"The macaroon to use for authenticating with the remote signer"`
TLSCertPath string `long:"tlscertpath" description:"The TLS certificate to use for establishing the remote signer's identity"` TLSCertPath string `long:"tlscertpath" description:"The TLS certificate to use for establishing the remote signer's identity"`
Timeout time.Duration `long:"timeout" description:"The timeout for connecting to and signing requests with the remote signer. Valid time units are {s, m, h}."`
}
// Validate checks the values configured for our remote RPC signer.
func (r *RemoteSigner) Validate() error {
if !r.Enable {
return nil
}
if r.Timeout < time.Millisecond {
return fmt.Errorf("remote signer: timeout of %v is invalid, "+
"cannot be smaller than %v", r.Timeout,
time.Millisecond)
}
return nil
} }

View File

@ -31,12 +31,6 @@ import (
"gopkg.in/macaroon.v2" "gopkg.in/macaroon.v2"
) )
const (
// DefaultRPCTimeout is the default timeout that is used when forwarding
// a request to the remote signer through RPC.
DefaultRPCTimeout = 5 * time.Second
)
var ( var (
// ErrRemoteSigningPrivateKeyNotAvailable is the error that is returned // ErrRemoteSigningPrivateKeyNotAvailable is the error that is returned
// if an operation is requested from the RPC wallet that is not // if an operation is requested from the RPC wallet that is not
@ -74,12 +68,11 @@ var _ lnwallet.WalletController = (*RPCKeyRing)(nil)
// delegates any signing or ECDH operations to the remove signer through RPC. // delegates any signing or ECDH operations to the remove signer through RPC.
func NewRPCKeyRing(watchOnlyKeyRing keychain.SecretKeyRing, func NewRPCKeyRing(watchOnlyKeyRing keychain.SecretKeyRing,
watchOnlyWalletController lnwallet.WalletController, watchOnlyWalletController lnwallet.WalletController,
remoteSigner *lncfg.RemoteSigner, coinType uint32, remoteSigner *lncfg.RemoteSigner, coinType uint32) (*RPCKeyRing, error) {
rpcTimeout time.Duration) (*RPCKeyRing, error) {
rpcConn, err := connectRPC( rpcConn, err := connectRPC(
remoteSigner.RPCHost, remoteSigner.TLSCertPath, remoteSigner.RPCHost, remoteSigner.TLSCertPath,
remoteSigner.MacaroonPath, remoteSigner.MacaroonPath, remoteSigner.Timeout,
) )
if err != nil { if err != nil {
return nil, fmt.Errorf("error connecting to the remote "+ return nil, fmt.Errorf("error connecting to the remote "+
@ -90,7 +83,7 @@ func NewRPCKeyRing(watchOnlyKeyRing keychain.SecretKeyRing,
WalletController: watchOnlyWalletController, WalletController: watchOnlyWalletController,
watchOnlyKeyRing: watchOnlyKeyRing, watchOnlyKeyRing: watchOnlyKeyRing,
coinType: coinType, coinType: coinType,
rpcTimeout: rpcTimeout, rpcTimeout: remoteSigner.Timeout,
signerClient: signrpc.NewSignerClient(rpcConn), signerClient: signrpc.NewSignerClient(rpcConn),
walletClient: walletrpc.NewWalletKitClient(rpcConn), walletClient: walletrpc.NewWalletKitClient(rpcConn),
}, nil }, nil
@ -708,8 +701,8 @@ func (r *RPCKeyRing) remoteSign(tx *wire.MsgTx, signDesc *input.SignDescriptor,
// connectRPC tries to establish an RPC connection to the given host:port with // connectRPC tries to establish an RPC connection to the given host:port with
// the supplied certificate and macaroon. // the supplied certificate and macaroon.
func connectRPC(hostPort, tlsCertPath, macaroonPath string) (*grpc.ClientConn, func connectRPC(hostPort, tlsCertPath, macaroonPath string,
error) { timeout time.Duration) (*grpc.ClientConn, error) {
certBytes, err := ioutil.ReadFile(tlsCertPath) certBytes, err := ioutil.ReadFile(tlsCertPath)
if err != nil { if err != nil {
@ -743,8 +736,11 @@ func connectRPC(hostPort, tlsCertPath, macaroonPath string) (*grpc.ClientConn,
cp, "", cp, "",
)), )),
grpc.WithPerRPCCredentials(macCred), grpc.WithPerRPCCredentials(macCred),
grpc.WithBlock(),
} }
conn, err := grpc.Dial(hostPort, opts...) ctxt, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
conn, err := grpc.DialContext(ctxt, hostPort, opts...)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to connect to RPC server: %v", return nil, fmt.Errorf("unable to connect to RPC server: %v",
err) err)

View File

@ -1253,6 +1253,9 @@ litecoin.node=ltcd
; The TLS certificate to use for establishing the remote signer's identity. ; The TLS certificate to use for establishing the remote signer's identity.
; remotesigner.tlscertpath=/path/to/remote/signer/tls.cert ; remotesigner.tlscertpath=/path/to/remote/signer/tls.cert
; The timeout for connecting to and signing requests with the remote signer.
; Valid time units are {s, m, h}.
; remotesigner.timeout=5s
[gossip] [gossip]