From 006dff12073225aa95f58de4f06f7518369085d2 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 2 Aug 2017 20:59:43 -0700 Subject: [PATCH] rpc: ensure that calls that depend server are rejected if server not active MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds a bit of a guard to a set of RPC calls. If an RPC call needs to interact with the server but it hasn’t yet been started. Then we’ll exit early in order to avoid blocking the call until the server itself has started. A recent change to the initialization order of sub-systems within lnd results in a state where the daemon will wait for the wallet itself to finish syncing _before_ the server is started. This was interpreted as a bug by some users, so we’ll make the state of the server more explicit by returning an error. --- rpcserver.go | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/rpcserver.go b/rpcserver.go index 62f3a414..ceb33c6d 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -247,13 +247,23 @@ func (r *rpcServer) VerifyMessage(ctx context.Context, return nil, fmt.Errorf("failed to query graph: %v", err) } - return &lnrpc.VerifyMessageResponse{Valid: active, Pubkey: pubKeyHex}, nil + return &lnrpc.VerifyMessageResponse{ + Valid: active, + Pubkey: pubKeyHex, + }, nil } // ConnectPeer attempts to establish a connection to a remote peer. func (r *rpcServer) ConnectPeer(ctx context.Context, in *lnrpc.ConnectPeerRequest) (*lnrpc.ConnectPeerResponse, error) { + // The server hasn't yet started, so it won't be able to service any of + // our requests, so we'll bail early here. + if !r.server.Started() { + return nil, fmt.Errorf("chain backend is still syncing, server " + + "not active yet") + } + if in.Addr == nil { return nil, fmt.Errorf("need: lnc pubkeyhash@hostname") } @@ -310,6 +320,11 @@ func (r *rpcServer) DisconnectPeer(ctx context.Context, rpcsLog.Debugf("[disconnectpeer] from peer(%s)", in.PubKey) + if !r.server.Started() { + return nil, fmt.Errorf("chain backend is still syncing, server " + + "not active yet") + } + // First we'll validate the string passed in within the request to // ensure that it's a valid hex-string, and also a valid compressed // public key. @@ -356,6 +371,11 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest, "allocation(us=%v, them=%v)", in.TargetPeerId, in.LocalFundingAmount, in.PushSat) + if !r.server.Started() { + return fmt.Errorf("chain backend is still syncing, server " + + "not active yet") + } + localFundingAmt := btcutil.Amount(in.LocalFundingAmount) remoteInitialBalance := btcutil.Amount(in.PushSat) @@ -463,6 +483,14 @@ func (r *rpcServer) OpenChannelSync(ctx context.Context, "allocation(us=%v, them=%v)", in.TargetPeerId, in.LocalFundingAmount, in.PushSat) + // We don't allow new channels to be open while the server is still + // syncing, as otherwise we may not be able to obtain the relevant + // notifications. + if !r.server.Started() { + return nil, fmt.Errorf("chain backend is still syncing, server " + + "not active yet") + } + // Creation of channels before the wallet syncs up is currently // disallowed. isSynced, err := r.server.cc.wallet.IsSynced() @@ -1136,6 +1164,14 @@ func (r *rpcServer) SendPayment(paymentStream lnrpc.Lightning_SendPaymentServer) errChan := make(chan error, 1) payChan := make(chan *lnrpc.SendRequest) + // We don't allow payments to be sent while the daemon itself is still + // syncing as we may be trying to sent a payment over a "stale" + // channel. + if !r.server.Started() { + return fmt.Errorf("chain backend is still syncing, server " + + "not active yet") + } + // TODO(roasbeef): check payment filter to see if already used? // In order to limit the level of concurrency and prevent a client from @@ -1285,6 +1321,14 @@ func (r *rpcServer) SendPayment(paymentStream lnrpc.Lightning_SendPaymentServer) func (r *rpcServer) SendPaymentSync(ctx context.Context, nextPayment *lnrpc.SendRequest) (*lnrpc.SendResponse, error) { + // We don't allow payments to be sent while the daemon itself is still + // syncing as we may be trying to sent a payment over a "stale" + // channel. + if !r.server.Started() { + return nil, fmt.Errorf("chain backend is still syncing, server " + + "not active yet") + } + var ( destPub *btcec.PublicKey amt btcutil.Amount