/ subrpcserver_config.go
subrpcserver_config.go
  1  package lnd
  2  
  3  import (
  4  	"context"
  5  	"fmt"
  6  	"net"
  7  	"reflect"
  8  
  9  	"github.com/btcsuite/btcd/chaincfg"
 10  	"github.com/btcsuite/btclog/v2"
 11  	"github.com/lightningnetwork/lnd/aliasmgr"
 12  	"github.com/lightningnetwork/lnd/autopilot"
 13  	"github.com/lightningnetwork/lnd/chainreg"
 14  	"github.com/lightningnetwork/lnd/channeldb"
 15  	"github.com/lightningnetwork/lnd/fn/v2"
 16  	graphdb "github.com/lightningnetwork/lnd/graph/db"
 17  	"github.com/lightningnetwork/lnd/htlcswitch"
 18  	"github.com/lightningnetwork/lnd/invoices"
 19  	"github.com/lightningnetwork/lnd/lncfg"
 20  	"github.com/lightningnetwork/lnd/lnrpc/autopilotrpc"
 21  	"github.com/lightningnetwork/lnd/lnrpc/chainrpc"
 22  	"github.com/lightningnetwork/lnd/lnrpc/devrpc"
 23  	"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
 24  	"github.com/lightningnetwork/lnd/lnrpc/neutrinorpc"
 25  	"github.com/lightningnetwork/lnd/lnrpc/peersrpc"
 26  	"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
 27  	"github.com/lightningnetwork/lnd/lnrpc/signrpc"
 28  	"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
 29  	"github.com/lightningnetwork/lnd/lnrpc/watchtowerrpc"
 30  	"github.com/lightningnetwork/lnd/lnrpc/wtclientrpc"
 31  	"github.com/lightningnetwork/lnd/lnwire"
 32  	"github.com/lightningnetwork/lnd/macaroons"
 33  	"github.com/lightningnetwork/lnd/netann"
 34  	"github.com/lightningnetwork/lnd/routing"
 35  	"github.com/lightningnetwork/lnd/sweep"
 36  	"github.com/lightningnetwork/lnd/watchtower"
 37  	"github.com/lightningnetwork/lnd/watchtower/wtclient"
 38  	"google.golang.org/protobuf/proto"
 39  )
 40  
 41  // subRPCServerConfigs is special sub-config in the main configuration that
 42  // houses the configuration for the optional sub-servers. These sub-RPC servers
 43  // are meant to house experimental new features that may eventually make it
 44  // into the main RPC server that lnd exposes. Special methods are present on
 45  // this struct to allow the main RPC server to create and manipulate the
 46  // sub-RPC servers in a generalized manner.
 47  type subRPCServerConfigs struct {
 48  	// SignRPC is a sub-RPC server that exposes signing of arbitrary inputs
 49  	// as a gRPC service.
 50  	SignRPC *signrpc.Config `group:"signrpc" namespace:"signrpc"`
 51  
 52  	// WalletKitRPC is a sub-RPC server that exposes functionality allowing
 53  	// a client to send transactions through a wallet, publish them, and
 54  	// also requests keys and addresses under control of the backing
 55  	// wallet.
 56  	WalletKitRPC *walletrpc.Config `group:"walletrpc" namespace:"walletrpc"`
 57  
 58  	// AutopilotRPC is a sub-RPC server that exposes methods on the running
 59  	// autopilot as a gRPC service.
 60  	AutopilotRPC *autopilotrpc.Config `group:"autopilotrpc" namespace:"autopilotrpc"`
 61  
 62  	// ChainRPC is a sub-RPC server that exposes functionality allowing a
 63  	// client to be notified of certain on-chain events (new blocks,
 64  	// confirmations, spends).
 65  	ChainRPC *chainrpc.Config `group:"chainrpc" namespace:"chainrpc"`
 66  
 67  	// InvoicesRPC is a sub-RPC server that exposes invoice related methods
 68  	// as a gRPC service.
 69  	InvoicesRPC *invoicesrpc.Config `group:"invoicesrpc" namespace:"invoicesrpc"`
 70  
 71  	// PeersRPC is a sub-RPC server that exposes peer related methods
 72  	// as a gRPC service.
 73  	PeersRPC *peersrpc.Config `group:"peersrpc" namespace:"peersrpc"`
 74  
 75  	// NeutrinoKitRPC is a sub-RPC server that exposes functionality allowing
 76  	// a client to interact with a running neutrino node.
 77  	NeutrinoKitRPC *neutrinorpc.Config `group:"neutrinorpc" namespace:"neutrinorpc"`
 78  
 79  	// RouterRPC is a sub-RPC server the exposes functionality that allows
 80  	// clients to send payments on the network, and perform Lightning
 81  	// payment related queries such as requests for estimates of off-chain
 82  	// fees.
 83  	RouterRPC *routerrpc.Config `group:"routerrpc" namespace:"routerrpc"`
 84  
 85  	// WatchtowerRPC is a sub-RPC server that exposes functionality allowing
 86  	// clients to monitor and control their embedded watchtower.
 87  	WatchtowerRPC *watchtowerrpc.Config `group:"watchtowerrpc" namespace:"watchtowerrpc"`
 88  
 89  	// WatchtowerClientRPC is a sub-RPC server that exposes functionality
 90  	// that allows clients to interact with the active watchtower client
 91  	// instance within lnd in order to add, remove, list registered client
 92  	// towers, etc.
 93  	WatchtowerClientRPC *wtclientrpc.Config `group:"wtclientrpc" namespace:"wtclientrpc"`
 94  
 95  	// DevRPC is a sub-RPC server that exposes functionality that allows
 96  	// developers manipulate LND state that is normally not possible.
 97  	// Should only be used for development purposes.
 98  	DevRPC *devrpc.Config `group:"devrpc" namespace:"devrpc"`
 99  }
100  
101  // PopulateDependencies attempts to iterate through all the sub-server configs
102  // within this struct, and populate the items it requires based on the main
103  // configuration file, and the chain control.
104  //
105  // NOTE: This MUST be called before any callers are permitted to execute the
106  // FetchConfig method.
107  func (s *subRPCServerConfigs) PopulateDependencies(cfg *Config,
108  	cc *chainreg.ChainControl,
109  	networkDir string, macService *macaroons.Service,
110  	atpl *autopilot.Manager,
111  	invoiceRegistry *invoices.InvoiceRegistry,
112  	htlcSwitch *htlcswitch.Switch,
113  	activeNetParams *chaincfg.Params,
114  	chanRouter *routing.ChannelRouter,
115  	routerBackend *routerrpc.RouterBackend,
116  	nodeSigner *netann.NodeSigner,
117  	graphDB *graphdb.ChannelGraph,
118  	chanStateDB *channeldb.ChannelStateDB,
119  	sweeper *sweep.UtxoSweeper,
120  	tower *watchtower.Standalone,
121  	towerClientMgr *wtclient.Manager,
122  	tcpResolver lncfg.TCPResolver,
123  	genInvoiceFeatures func() *lnwire.FeatureVector,
124  	genAmpInvoiceFeatures func() *lnwire.FeatureVector,
125  	getNodeAnnouncement func() lnwire.NodeAnnouncement1,
126  	updateNodeAnnouncement func(ctx context.Context,
127  		features *lnwire.RawFeatureVector,
128  		modifiers ...netann.NodeAnnModifier) error,
129  	parseAddr func(addr string) (net.Addr, error),
130  	rpcLogger btclog.Logger, aliasMgr *aliasmgr.Manager,
131  	auxDataParser fn.Option[AuxDataParser],
132  	invoiceHtlcModifier *invoices.HtlcModificationInterceptor) error {
133  
134  	// First, we'll use reflect to obtain a version of the config struct
135  	// that allows us to programmatically inspect its fields.
136  	selfVal := extractReflectValue(s)
137  	selfType := selfVal.Type()
138  
139  	numFields := selfVal.NumField()
140  	for i := 0; i < numFields; i++ {
141  		field := selfVal.Field(i)
142  		fieldElem := field.Elem()
143  		fieldName := selfType.Field(i).Name
144  
145  		ltndLog.Debugf("Populating dependencies for sub RPC "+
146  			"server: %v", fieldName)
147  
148  		// If this sub-config doesn't actually have any fields, then we
149  		// can skip it, as the build tag for it is likely off.
150  		if fieldElem.NumField() == 0 {
151  			continue
152  		}
153  		if !fieldElem.CanSet() {
154  			continue
155  		}
156  
157  		switch subCfg := field.Interface().(type) {
158  		case *signrpc.Config:
159  			subCfgValue := extractReflectValue(subCfg)
160  
161  			subCfgValue.FieldByName("MacService").Set(
162  				reflect.ValueOf(macService),
163  			)
164  			subCfgValue.FieldByName("NetworkDir").Set(
165  				reflect.ValueOf(networkDir),
166  			)
167  			subCfgValue.FieldByName("Signer").Set(
168  				reflect.ValueOf(cc.Signer),
169  			)
170  			subCfgValue.FieldByName("KeyRing").Set(
171  				reflect.ValueOf(cc.KeyRing),
172  			)
173  
174  		case *walletrpc.Config:
175  			subCfgValue := extractReflectValue(subCfg)
176  
177  			subCfgValue.FieldByName("NetworkDir").Set(
178  				reflect.ValueOf(networkDir),
179  			)
180  			subCfgValue.FieldByName("MacService").Set(
181  				reflect.ValueOf(macService),
182  			)
183  			subCfgValue.FieldByName("FeeEstimator").Set(
184  				reflect.ValueOf(cc.FeeEstimator),
185  			)
186  			subCfgValue.FieldByName("Wallet").Set(
187  				reflect.ValueOf(cc.Wallet),
188  			)
189  			subCfgValue.FieldByName("CoinSelectionLocker").Set(
190  				reflect.ValueOf(cc.Wallet),
191  			)
192  			subCfgValue.FieldByName("KeyRing").Set(
193  				reflect.ValueOf(cc.KeyRing),
194  			)
195  			subCfgValue.FieldByName("Sweeper").Set(
196  				reflect.ValueOf(sweeper),
197  			)
198  			subCfgValue.FieldByName("Chain").Set(
199  				reflect.ValueOf(cc.ChainIO),
200  			)
201  			subCfgValue.FieldByName("ChainParams").Set(
202  				reflect.ValueOf(activeNetParams),
203  			)
204  			subCfgValue.FieldByName("CurrentNumAnchorChans").Set(
205  				reflect.ValueOf(cc.Wallet.CurrentNumAnchorChans),
206  			)
207  			subCfgValue.FieldByName("CoinSelectionStrategy").Set(
208  				reflect.ValueOf(
209  					cc.Wallet.Cfg.CoinSelectionStrategy,
210  				),
211  			)
212  			subCfgValue.FieldByName("ChanStateDB").Set(
213  				reflect.ValueOf(chanStateDB),
214  			)
215  
216  		case *autopilotrpc.Config:
217  			subCfgValue := extractReflectValue(subCfg)
218  
219  			subCfgValue.FieldByName("Manager").Set(
220  				reflect.ValueOf(atpl),
221  			)
222  
223  		case *chainrpc.Config:
224  			subCfgValue := extractReflectValue(subCfg)
225  
226  			subCfgValue.FieldByName("NetworkDir").Set(
227  				reflect.ValueOf(networkDir),
228  			)
229  			subCfgValue.FieldByName("MacService").Set(
230  				reflect.ValueOf(macService),
231  			)
232  			subCfgValue.FieldByName("ChainNotifier").Set(
233  				reflect.ValueOf(cc.ChainNotifier),
234  			)
235  			subCfgValue.FieldByName("Chain").Set(
236  				reflect.ValueOf(cc.ChainIO),
237  			)
238  
239  		case *invoicesrpc.Config:
240  			subCfgValue := extractReflectValue(subCfg)
241  
242  			subCfgValue.FieldByName("NetworkDir").Set(
243  				reflect.ValueOf(networkDir),
244  			)
245  			subCfgValue.FieldByName("MacService").Set(
246  				reflect.ValueOf(macService),
247  			)
248  			subCfgValue.FieldByName("InvoiceRegistry").Set(
249  				reflect.ValueOf(invoiceRegistry),
250  			)
251  			subCfgValue.FieldByName("HtlcModifier").Set(
252  				reflect.ValueOf(invoiceHtlcModifier),
253  			)
254  			subCfgValue.FieldByName("IsChannelActive").Set(
255  				reflect.ValueOf(htlcSwitch.HasActiveLink),
256  			)
257  			subCfgValue.FieldByName("ChainParams").Set(
258  				reflect.ValueOf(activeNetParams),
259  			)
260  			subCfgValue.FieldByName("NodeSigner").Set(
261  				reflect.ValueOf(nodeSigner),
262  			)
263  			defaultDelta := cfg.Bitcoin.TimeLockDelta
264  			subCfgValue.FieldByName("DefaultCLTVExpiry").Set(
265  				reflect.ValueOf(defaultDelta),
266  			)
267  			subCfgValue.FieldByName("Graph").Set(
268  				reflect.ValueOf(graphDB),
269  			)
270  			subCfgValue.FieldByName("ChanStateDB").Set(
271  				reflect.ValueOf(chanStateDB),
272  			)
273  			subCfgValue.FieldByName("GenInvoiceFeatures").Set(
274  				reflect.ValueOf(genInvoiceFeatures),
275  			)
276  			subCfgValue.FieldByName("GenAmpInvoiceFeatures").Set(
277  				reflect.ValueOf(genAmpInvoiceFeatures),
278  			)
279  			subCfgValue.FieldByName("GetAlias").Set(
280  				reflect.ValueOf(aliasMgr.GetPeerAlias),
281  			)
282  
283  			parseAuxData := func(m proto.Message) error {
284  				return fn.MapOptionZ(
285  					auxDataParser,
286  					func(p AuxDataParser) error {
287  						return p.InlineParseCustomData(
288  							m,
289  						)
290  					},
291  				)
292  			}
293  			subCfgValue.FieldByName("ParseAuxData").Set(
294  				reflect.ValueOf(parseAuxData),
295  			)
296  
297  		case *neutrinorpc.Config:
298  			subCfgValue := extractReflectValue(subCfg)
299  
300  			subCfgValue.FieldByName("NeutrinoCS").Set(
301  				reflect.ValueOf(cc.Cfg.NeutrinoCS),
302  			)
303  
304  		// RouterRPC isn't conditionally compiled and doesn't need to be
305  		// populated using reflection.
306  		case *routerrpc.Config:
307  			subCfgValue := extractReflectValue(subCfg)
308  
309  			subCfgValue.FieldByName("AliasMgr").Set(
310  				reflect.ValueOf(aliasMgr),
311  			)
312  
313  		case *watchtowerrpc.Config:
314  			subCfgValue := extractReflectValue(subCfg)
315  
316  			subCfgValue.FieldByName("Active").Set(
317  				reflect.ValueOf(tower != nil),
318  			)
319  			subCfgValue.FieldByName("Tower").Set(
320  				reflect.ValueOf(tower),
321  			)
322  
323  		case *wtclientrpc.Config:
324  			subCfgValue := extractReflectValue(subCfg)
325  
326  			if towerClientMgr != nil {
327  				subCfgValue.FieldByName("Active").Set(
328  					reflect.ValueOf(towerClientMgr != nil),
329  				)
330  				subCfgValue.FieldByName("ClientMgr").Set(
331  					reflect.ValueOf(towerClientMgr),
332  				)
333  			}
334  			subCfgValue.FieldByName("Resolver").Set(
335  				reflect.ValueOf(tcpResolver),
336  			)
337  			subCfgValue.FieldByName("Log").Set(
338  				reflect.ValueOf(rpcLogger),
339  			)
340  
341  		case *devrpc.Config:
342  			subCfgValue := extractReflectValue(subCfg)
343  
344  			subCfgValue.FieldByName("ActiveNetParams").Set(
345  				reflect.ValueOf(activeNetParams),
346  			)
347  
348  			subCfgValue.FieldByName("GraphDB").Set(
349  				reflect.ValueOf(graphDB),
350  			)
351  
352  			subCfgValue.FieldByName("Switch").Set(
353  				reflect.ValueOf(htlcSwitch),
354  			)
355  
356  		case *peersrpc.Config:
357  			subCfgValue := extractReflectValue(subCfg)
358  
359  			subCfgValue.FieldByName("GetNodeAnnouncement").Set(
360  				reflect.ValueOf(getNodeAnnouncement),
361  			)
362  
363  			subCfgValue.FieldByName("ParseAddr").Set(
364  				reflect.ValueOf(parseAddr),
365  			)
366  
367  			subCfgValue.FieldByName("UpdateNodeAnnouncement").Set(
368  				reflect.ValueOf(updateNodeAnnouncement),
369  			)
370  
371  		default:
372  			return fmt.Errorf("unknown field: %v, %T", fieldName,
373  				cfg)
374  		}
375  	}
376  
377  	// Populate routerrpc dependencies.
378  	s.RouterRPC.NetworkDir = networkDir
379  	s.RouterRPC.MacService = macService
380  	s.RouterRPC.Router = chanRouter
381  	s.RouterRPC.RouterBackend = routerBackend
382  
383  	return nil
384  }
385  
386  // FetchConfig attempts to locate an existing configuration file mapped to the
387  // target sub-server. If we're unable to find a config file matching the
388  // subServerName name, then false will be returned for the second parameter.
389  //
390  // NOTE: Part of the lnrpc.SubServerConfigDispatcher interface.
391  func (s *subRPCServerConfigs) FetchConfig(subServerName string) (interface{}, bool) {
392  	// First, we'll use reflect to obtain a version of the config struct
393  	// that allows us to programmatically inspect its fields.
394  	selfVal := extractReflectValue(s)
395  
396  	// Now that we have the value of the struct, we can check to see if it
397  	// has an attribute with the same name as the subServerName.
398  	configVal := selfVal.FieldByName(subServerName)
399  
400  	// We'll now ensure that this field actually exists in this value. If
401  	// not, then we'll return false for the ok value to indicate to the
402  	// caller that this field doesn't actually exist.
403  	if !configVal.IsValid() {
404  		return nil, false
405  	}
406  
407  	configValElem := configVal.Elem()
408  
409  	// If a config of this type is found, it doesn't have any fields, then
410  	// it's the same as if it wasn't present. This can happen if the build
411  	// tag for the sub-server is inactive.
412  	if configValElem.NumField() == 0 {
413  		return nil, false
414  	}
415  
416  	// At this pint, we know that the field is actually present in the
417  	// config struct, so we can return it directly.
418  	return configVal.Interface(), true
419  }
420  
421  // extractReflectValue attempts to extract the value from an interface using
422  // the reflect package. The resulting reflect.Value allows the caller to
423  // programmatically examine and manipulate the underlying value.
424  func extractReflectValue(instance interface{}) reflect.Value {
425  	var val reflect.Value
426  
427  	// If the type of the instance is a pointer, then we need to deference
428  	// the pointer one level to get its value. Otherwise, we can access the
429  	// value directly.
430  	if reflect.TypeOf(instance).Kind() == reflect.Ptr {
431  		val = reflect.ValueOf(instance).Elem()
432  	} else {
433  		val = reflect.ValueOf(instance)
434  	}
435  
436  	return val
437  }