Skip to content

Commit cf3674b

Browse files
accounts: separate account RPC server init & start
In the upcoming actions migration, we need fetch LNDs macaroons prior to initializing the stores, as the macaroons will be required during the migration. This requires that we setup the connection to LND before we initialize the stores, as we can only fetch the macaroons after the LND connection is established. In preparation of doing so, we cannot reference the stores when initializing/creating the accounts RPC server object, as we do so prior to setting up the LND connection. This commit therefore refactors the accounts RPC server so that we separate the initializing from the starting of the RPC server, and only require the store reference during the actual startup of the RPC server. Note that while this commit adds an `active atomic int32` to the RPC server which must be set toggled before the server will process requests, the RPC proxy and status manager will ensure that no requests get sent to the RPC prior to LiT's subserver being set to running. This is added to ensure that we dont introduce any nil pointer panics in future updates though, as the RPC server would panic in requests were actually processed prior to it having the dependencies injected during the `Start` function. Also note that we still keep the init of the accounts RPC server reference prior to setting up the LND connection, as not doing so would require that we'd refactor the registering of `GrpcSubserver`s in a more complex and in a less elegant way.
1 parent ef87c7a commit cf3674b

File tree

2 files changed

+76
-8
lines changed

2 files changed

+76
-8
lines changed

accounts/rpcserver.go

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ package accounts
33
import (
44
"context"
55
"encoding/hex"
6+
"errors"
67
"fmt"
8+
"sync/atomic"
79
"time"
810

911
"github.com/btcsuite/btcd/btcutil"
@@ -16,8 +18,17 @@ import (
1618
"gopkg.in/macaroon.v2"
1719
)
1820

21+
var (
22+
// ErrServerNotActive indicates that the server has started but hasn't
23+
// fully finished the startup process.
24+
ErrServerNotActive = errors.New("accounts server is still in the " +
25+
"process of starting")
26+
)
27+
1928
// RPCServer is the main server that implements the Accounts gRPC service.
2029
type RPCServer struct {
30+
active int32 // atomic
31+
2132
litrpc.UnimplementedAccountsServer
2233

2334
service *InterceptorService
@@ -26,13 +37,29 @@ type RPCServer struct {
2637
}
2738

2839
// NewRPCServer returns a new RPC server for the given service.
29-
func NewRPCServer(service *InterceptorService,
30-
superMacBaker litmac.Baker) *RPCServer {
40+
func NewRPCServer() *RPCServer {
41+
return &RPCServer{}
42+
}
43+
44+
// started returns true if the server has been started, and false otherwise.
45+
// NOTE: This function is safe for concurrent access.
46+
func (s *RPCServer) started() bool {
47+
return atomic.LoadInt32(&s.active) != 0
48+
}
3149

32-
return &RPCServer{
33-
service: service,
34-
superMacBaker: superMacBaker,
50+
// Start adds the necessary dependencies for the RPCServer to be able to process
51+
// requests, and starts the RPCServer.
52+
func (s *RPCServer) Start(service *InterceptorService,
53+
superMacBaker litmac.Baker) error {
54+
55+
if s.started() {
56+
return errors.New("accounts rpc server is already started")
3557
}
58+
59+
s.service = service
60+
s.superMacBaker = superMacBaker
61+
62+
atomic.StoreInt32(&s.active, 1)
3663
}
3764

3865
// CreateAccount adds an entry to the account database. This entry represents
@@ -50,6 +77,10 @@ func (s *RPCServer) CreateAccount(ctx context.Context,
5077
req *litrpc.CreateAccountRequest) (*litrpc.CreateAccountResponse,
5178
error) {
5279

80+
if !s.started() {
81+
return nil, ErrServerNotActive
82+
}
83+
5384
log.Infof("[createaccount] label=%v, balance=%d, expiration=%d",
5485
req.Label, req.AccountBalance, req.ExpirationDate)
5586

@@ -110,6 +141,10 @@ func (s *RPCServer) CreateAccount(ctx context.Context,
110141
func (s *RPCServer) UpdateAccount(ctx context.Context,
111142
req *litrpc.UpdateAccountRequest) (*litrpc.Account, error) {
112143

144+
if !s.started() {
145+
return nil, ErrServerNotActive
146+
}
147+
113148
log.Infof("[updateaccount] id=%s, label=%v, balance=%d, expiration=%d",
114149
req.Id, req.Label, req.AccountBalance, req.ExpirationDate)
115150

@@ -136,6 +171,10 @@ func (s *RPCServer) CreditAccount(ctx context.Context,
136171
req *litrpc.CreditAccountRequest) (*litrpc.CreditAccountResponse,
137172
error) {
138173

174+
if !s.started() {
175+
return nil, ErrServerNotActive
176+
}
177+
139178
if req.GetAccount() == nil {
140179
return nil, fmt.Errorf("account param must be specified")
141180
}
@@ -174,6 +213,10 @@ func (s *RPCServer) CreditAccount(ctx context.Context,
174213
func (s *RPCServer) DebitAccount(ctx context.Context,
175214
req *litrpc.DebitAccountRequest) (*litrpc.DebitAccountResponse, error) {
176215

216+
if !s.started() {
217+
return nil, ErrServerNotActive
218+
}
219+
177220
if req.GetAccount() == nil {
178221
return nil, fmt.Errorf("account param must be specified")
179222
}
@@ -212,6 +255,10 @@ func (s *RPCServer) DebitAccount(ctx context.Context,
212255
func (s *RPCServer) ListAccounts(ctx context.Context,
213256
_ *litrpc.ListAccountsRequest) (*litrpc.ListAccountsResponse, error) {
214257

258+
if !s.started() {
259+
return nil, ErrServerNotActive
260+
}
261+
215262
log.Info("[listaccounts]")
216263

217264
// Retrieve all accounts from the macaroon account store.
@@ -237,6 +284,10 @@ func (s *RPCServer) ListAccounts(ctx context.Context,
237284
func (s *RPCServer) AccountInfo(ctx context.Context,
238285
req *litrpc.AccountInfoRequest) (*litrpc.Account, error) {
239286

287+
if !s.started() {
288+
return nil, ErrServerNotActive
289+
}
290+
240291
log.Infof("[accountinfo] id=%v, label=%v", req.Id, req.Label)
241292

242293
accountID, err := s.findAccount(ctx, req.Id, req.Label)
@@ -257,6 +308,10 @@ func (s *RPCServer) RemoveAccount(ctx context.Context,
257308
req *litrpc.RemoveAccountRequest) (*litrpc.RemoveAccountResponse,
258309
error) {
259310

311+
if !s.started() {
312+
return nil, ErrServerNotActive
313+
}
314+
260315
log.Infof("[removeaccount] id=%v, label=%v", req.Id, req.Label)
261316

262317
accountID, err := s.findAccount(ctx, req.Id, req.Label)

terminal.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -471,9 +471,7 @@ func (g *LightningTerminal) start(ctx context.Context) error {
471471
)
472472
}
473473

474-
g.accountRpcServer = accounts.NewRPCServer(
475-
g.accountService, superMacBaker,
476-
)
474+
g.accountRpcServer = accounts.NewRPCServer()
477475

478476
g.ruleMgrs = rules.NewRuleManagerSet()
479477

@@ -1025,6 +1023,21 @@ func (g *LightningTerminal) startInternalSubServers(ctx context.Context,
10251023
}
10261024
g.macaroonServiceStarted = true
10271025

1026+
superMacBaker := func(ctx context.Context, rootKeyID uint64,
1027+
perms []bakery.Op, caveats []macaroon.Caveat) (string, error) {
1028+
1029+
return litmac.BakeSuperMacaroon(
1030+
ctx, g.basicClient, rootKeyID, perms, caveats,
1031+
)
1032+
}
1033+
1034+
log.Infof("Starting LiT accounts server")
1035+
1036+
err = g.accountRpcServer.Start(g.accountService, superMacBaker)
1037+
if err != nil {
1038+
return err
1039+
}
1040+
10281041
if !g.cfg.Autopilot.Disable {
10291042
withLndVersion := func(cfg *autopilotserver.Config) {
10301043
cfg.LndVersion = autopilotserver.Version{

0 commit comments

Comments
 (0)