/ 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 }