github.com/decred/dcrlnd@v0.7.6/lnrpc/routerrpc/router_server.go (about) 1 package routerrpc 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "io/ioutil" 8 "os" 9 "path/filepath" 10 "sync/atomic" 11 "time" 12 13 "github.com/decred/dcrd/dcrutil/v4" 14 "github.com/decred/dcrd/wire" 15 "github.com/decred/dcrlnd/channeldb" 16 "github.com/decred/dcrlnd/lnrpc" 17 "github.com/decred/dcrlnd/lntypes" 18 "github.com/decred/dcrlnd/lnwire" 19 "github.com/decred/dcrlnd/macaroons" 20 "github.com/decred/dcrlnd/routing" 21 "github.com/decred/dcrlnd/routing/route" 22 "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 23 "google.golang.org/grpc" 24 "google.golang.org/grpc/codes" 25 "google.golang.org/grpc/status" 26 "gopkg.in/macaroon-bakery.v2/bakery" 27 ) 28 29 const ( 30 // subServerName is the name of the sub rpc server. We'll use this name 31 // to register ourselves, and we also require that the main 32 // SubServerConfigDispatcher instance recognize as the name of our 33 subServerName = "RouterRPC" 34 ) 35 36 var ( 37 errServerShuttingDown = errors.New("routerrpc server shutting down") 38 39 // ErrInterceptorAlreadyExists is an error returned when the a new stream 40 // is opened and there is already one active interceptor. 41 // The user must disconnect prior to open another stream. 42 ErrInterceptorAlreadyExists = errors.New("interceptor already exists") 43 44 // macaroonOps are the set of capabilities that our minted macaroon (if 45 // it doesn't already exist) will have. 46 macaroonOps = []bakery.Op{ 47 { 48 Entity: "offchain", 49 Action: "read", 50 }, 51 { 52 Entity: "offchain", 53 Action: "write", 54 }, 55 } 56 57 // macPermissions maps RPC calls to the permissions they require. 58 macPermissions = map[string][]bakery.Op{ 59 "/routerrpc.Router/SendPaymentV2": {{ 60 Entity: "offchain", 61 Action: "write", 62 }}, 63 "/routerrpc.Router/SendToRouteV2": {{ 64 Entity: "offchain", 65 Action: "write", 66 }}, 67 "/routerrpc.Router/SendToRoute": {{ 68 Entity: "offchain", 69 Action: "write", 70 }}, 71 "/routerrpc.Router/TrackPaymentV2": {{ 72 Entity: "offchain", 73 Action: "read", 74 }}, 75 "/routerrpc.Router/EstimateRouteFee": {{ 76 Entity: "offchain", 77 Action: "read", 78 }}, 79 "/routerrpc.Router/QueryMissionControl": {{ 80 Entity: "offchain", 81 Action: "read", 82 }}, 83 "/routerrpc.Router/XImportMissionControl": {{ 84 Entity: "offchain", 85 Action: "write", 86 }}, 87 "/routerrpc.Router/GetMissionControlConfig": {{ 88 Entity: "offchain", 89 Action: "read", 90 }}, 91 "/routerrpc.Router/SetMissionControlConfig": {{ 92 Entity: "offchain", 93 Action: "write", 94 }}, 95 "/routerrpc.Router/QueryProbability": {{ 96 Entity: "offchain", 97 Action: "read", 98 }}, 99 "/routerrpc.Router/ResetMissionControl": {{ 100 Entity: "offchain", 101 Action: "write", 102 }}, 103 "/routerrpc.Router/BuildRoute": {{ 104 Entity: "offchain", 105 Action: "read", 106 }}, 107 "/routerrpc.Router/SubscribeHtlcEvents": {{ 108 Entity: "offchain", 109 Action: "read", 110 }}, 111 "/routerrpc.Router/SendPayment": {{ 112 Entity: "offchain", 113 Action: "write", 114 }}, 115 "/routerrpc.Router/TrackPayment": {{ 116 Entity: "offchain", 117 Action: "read", 118 }}, 119 "/routerrpc.Router/HtlcInterceptor": {{ 120 Entity: "offchain", 121 Action: "write", 122 }}, 123 "/routerrpc.Router/UpdateChanStatus": {{ 124 Entity: "offchain", 125 Action: "write", 126 }}, 127 } 128 129 // DefaultRouterMacFilename is the default name of the router macaroon 130 // that we expect to find via a file handle within the main 131 // configuration file in this package. 132 DefaultRouterMacFilename = "router.macaroon" 133 ) 134 135 // ServerShell a is shell struct holding a reference to the actual sub-server. 136 // It is used to register the gRPC sub-server with the root server before we 137 // have the necessary dependencies to populate the actual sub-server. 138 type ServerShell struct { 139 RouterServer 140 } 141 142 // Server is a stand alone sub RPC server which exposes functionality that 143 // allows clients to route arbitrary payment through the Lightning Network. 144 type Server struct { 145 started int32 // To be used atomically. 146 shutdown int32 // To be used atomically. 147 forwardInterceptorActive int32 // To be used atomically. 148 149 cfg *Config 150 151 quit chan struct{} 152 } 153 154 // A compile time check to ensure that Server fully implements the RouterServer 155 // gRPC service. 156 var _ RouterServer = (*Server)(nil) 157 158 // New creates a new instance of the RouterServer given a configuration struct 159 // that contains all external dependencies. If the target macaroon exists, and 160 // we're unable to create it, then an error will be returned. We also return 161 // the set of permissions that we require as a server. At the time of writing 162 // of this documentation, this is the same macaroon as as the admin macaroon. 163 func New(cfg *Config) (*Server, lnrpc.MacaroonPerms, error) { 164 // If the path of the router macaroon wasn't generated, then we'll 165 // assume that it's found at the default network directory. 166 if cfg.RouterMacPath == "" { 167 cfg.RouterMacPath = filepath.Join( 168 cfg.NetworkDir, DefaultRouterMacFilename, 169 ) 170 } 171 172 // Now that we know the full path of the router macaroon, we can check 173 // to see if we need to create it or not. If stateless_init is set 174 // then we don't write the macaroons. 175 macFilePath := cfg.RouterMacPath 176 if cfg.MacService != nil && !cfg.MacService.StatelessInit && 177 !lnrpc.FileExists(macFilePath) { 178 179 log.Infof("Making macaroons for Router RPC Server at: %v", 180 macFilePath) 181 182 // At this point, we know that the router macaroon doesn't yet, 183 // exist, so we need to create it with the help of the main 184 // macaroon service. 185 routerMac, err := cfg.MacService.NewMacaroon( 186 context.Background(), macaroons.DefaultRootKeyID, 187 macaroonOps..., 188 ) 189 if err != nil { 190 return nil, nil, err 191 } 192 routerMacBytes, err := routerMac.M().MarshalBinary() 193 if err != nil { 194 return nil, nil, err 195 } 196 err = ioutil.WriteFile(macFilePath, routerMacBytes, 0644) 197 if err != nil { 198 _ = os.Remove(macFilePath) 199 return nil, nil, err 200 } 201 } 202 203 routerServer := &Server{ 204 cfg: cfg, 205 quit: make(chan struct{}), 206 } 207 208 return routerServer, macPermissions, nil 209 } 210 211 // Start launches any helper goroutines required for the rpcServer to function. 212 // 213 // NOTE: This is part of the lnrpc.SubServer interface. 214 func (s *Server) Start() error { 215 if atomic.AddInt32(&s.started, 1) != 1 { 216 return nil 217 } 218 219 return nil 220 } 221 222 // Stop signals any active goroutines for a graceful closure. 223 // 224 // NOTE: This is part of the lnrpc.SubServer interface. 225 func (s *Server) Stop() error { 226 if atomic.AddInt32(&s.shutdown, 1) != 1 { 227 return nil 228 } 229 230 close(s.quit) 231 return nil 232 } 233 234 // Name returns a unique string representation of the sub-server. This can be 235 // used to identify the sub-server and also de-duplicate them. 236 // 237 // NOTE: This is part of the lnrpc.SubServer interface. 238 func (s *Server) Name() string { 239 return subServerName 240 } 241 242 // RegisterWithRootServer will be called by the root gRPC server to direct a 243 // sub RPC server to register itself with the main gRPC root server. Until this 244 // is called, each sub-server won't be able to have requests routed towards it. 245 // 246 // NOTE: This is part of the lnrpc.GrpcHandler interface. 247 func (r *ServerShell) RegisterWithRootServer(grpcServer *grpc.Server) error { 248 // We make sure that we register it with the main gRPC server to ensure 249 // all our methods are routed properly. 250 RegisterRouterServer(grpcServer, r) 251 252 log.Debugf("Router RPC server successfully register with root gRPC " + 253 "server") 254 255 return nil 256 } 257 258 // RegisterWithRestServer will be called by the root REST mux to direct a sub 259 // RPC server to register itself with the main REST mux server. Until this is 260 // called, each sub-server won't be able to have requests routed towards it. 261 // 262 // NOTE: This is part of the lnrpc.GrpcHandler interface. 263 func (r *ServerShell) RegisterWithRestServer(ctx context.Context, 264 mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error { 265 266 // We make sure that we register it with the main REST server to ensure 267 // all our methods are routed properly. 268 err := RegisterRouterHandlerFromEndpoint(ctx, mux, dest, opts) 269 if err != nil { 270 log.Errorf("Could not register Router REST server "+ 271 "with root REST server: %v", err) 272 return err 273 } 274 275 log.Debugf("Router REST server successfully registered with " + 276 "root REST server") 277 return nil 278 } 279 280 // CreateSubServer populates the subserver's dependencies using the passed 281 // SubServerConfigDispatcher. This method should fully initialize the 282 // sub-server instance, making it ready for action. It returns the macaroon 283 // permissions that the sub-server wishes to pass on to the root server for all 284 // methods routed towards it. 285 // 286 // NOTE: This is part of the lnrpc.GrpcHandler interface. 287 func (r *ServerShell) CreateSubServer(configRegistry lnrpc.SubServerConfigDispatcher) ( 288 lnrpc.SubServer, lnrpc.MacaroonPerms, error) { 289 290 subServer, macPermissions, err := createNewSubServer(configRegistry) 291 if err != nil { 292 return nil, nil, err 293 } 294 295 r.RouterServer = subServer 296 return subServer, macPermissions, nil 297 } 298 299 // SendPaymentV2 attempts to route a payment described by the passed 300 // PaymentRequest to the final destination. If we are unable to route the 301 // payment, or cannot find a route that satisfies the constraints in the 302 // PaymentRequest, then an error will be returned. Otherwise, the payment 303 // pre-image, along with the final route will be returned. 304 func (s *Server) SendPaymentV2(req *SendPaymentRequest, 305 stream Router_SendPaymentV2Server) error { 306 307 payment, err := s.cfg.RouterBackend.extractIntentFromSendRequest(req) 308 if err != nil { 309 return err 310 } 311 312 err = s.cfg.Router.SendPaymentAsync(payment) 313 if err != nil { 314 // Transform user errors to grpc code. 315 if err == channeldb.ErrPaymentInFlight || 316 err == channeldb.ErrAlreadyPaid { 317 318 log.Debugf("SendPayment async result for payment %x: %v", 319 payment.Identifier(), err) 320 321 return status.Error( 322 codes.AlreadyExists, err.Error(), 323 ) 324 } 325 326 log.Errorf("SendPayment async error for payment %x: %v", 327 payment.Identifier(), err) 328 329 return err 330 } 331 332 return s.trackPayment(payment.Identifier(), stream, req.NoInflightUpdates) 333 } 334 335 // EstimateRouteFee allows callers to obtain a lower bound w.r.t how much it 336 // may cost to send an HTLC to the target end destination. 337 func (s *Server) EstimateRouteFee(ctx context.Context, 338 req *RouteFeeRequest) (*RouteFeeResponse, error) { 339 340 if len(req.Dest) != 33 { 341 return nil, errors.New("invalid length destination key") 342 } 343 var destNode route.Vertex 344 copy(destNode[:], req.Dest) 345 346 // Next, we'll convert the amount in satoshis to mSAT, which are the 347 // native unit of LN. 348 amtMat := lnwire.NewMAtomsFromAtoms(dcrutil.Amount(req.AmtAtoms)) 349 350 // Pick a fee limit 351 // 352 // TODO: Change this into behaviour that makes more sense. 353 feeLimit := lnwire.NewMAtomsFromAtoms(dcrutil.AtomsPerCoin) 354 355 // Finally, we'll query for a route to the destination that can carry 356 // that target amount, we'll only request a single route. Set a 357 // restriction for the default CLTV limit, otherwise we can find a route 358 // that exceeds it and is useless to us. 359 mc := s.cfg.RouterBackend.MissionControl 360 route, err := s.cfg.Router.FindRoute( 361 s.cfg.RouterBackend.SelfNode, destNode, amtMat, 362 &routing.RestrictParams{ 363 FeeLimit: feeLimit, 364 CltvLimit: s.cfg.RouterBackend.MaxTotalTimelock, 365 ProbabilitySource: mc.GetProbability, 366 }, nil, nil, s.cfg.RouterBackend.DefaultFinalCltvDelta, 367 ) 368 if err != nil { 369 return nil, err 370 } 371 372 return &RouteFeeResponse{ 373 RoutingFeeMatoms: int64(route.TotalFees()), 374 TimeLockDelay: int64(route.TotalTimeLock), 375 }, nil 376 } 377 378 // SendToRouteV2 sends a payment through a predefined route. The response of this 379 // call contains structured error information. 380 func (s *Server) SendToRouteV2(ctx context.Context, 381 req *SendToRouteRequest) (*lnrpc.HTLCAttempt, error) { 382 383 if req.Route == nil { 384 return nil, fmt.Errorf("unable to send, no routes provided") 385 } 386 387 route, err := s.cfg.RouterBackend.UnmarshallRoute(req.Route) 388 if err != nil { 389 return nil, err 390 } 391 392 hash, err := lntypes.MakeHash(req.PaymentHash) 393 if err != nil { 394 return nil, err 395 } 396 397 // Pass route to the router. This call returns the full htlc attempt 398 // information as it is stored in the database. It is possible that both 399 // the attempt return value and err are non-nil. This can happen when 400 // the attempt was already initiated before the error happened. In that 401 // case, we give precedence to the attempt information as stored in the 402 // db. 403 attempt, err := s.cfg.Router.SendToRoute(hash, route) 404 if attempt != nil { 405 rpcAttempt, err := s.cfg.RouterBackend.MarshalHTLCAttempt( 406 *attempt, 407 ) 408 if err != nil { 409 return nil, err 410 } 411 return rpcAttempt, nil 412 } 413 414 // Transform user errors to grpc code. 415 if err == channeldb.ErrPaymentInFlight || 416 err == channeldb.ErrAlreadyPaid { 417 418 return nil, status.Error(codes.AlreadyExists, err.Error()) 419 } 420 421 return nil, err 422 } 423 424 // ResetMissionControl clears all mission control state and starts with a clean 425 // slate. 426 func (s *Server) ResetMissionControl(ctx context.Context, 427 req *ResetMissionControlRequest) (*ResetMissionControlResponse, error) { 428 429 err := s.cfg.RouterBackend.MissionControl.ResetHistory() 430 if err != nil { 431 return nil, err 432 } 433 434 return &ResetMissionControlResponse{}, nil 435 } 436 437 // GetMissionControlConfig returns our current mission control config. 438 func (s *Server) GetMissionControlConfig(ctx context.Context, 439 req *GetMissionControlConfigRequest) (*GetMissionControlConfigResponse, 440 error) { 441 442 cfg := s.cfg.RouterBackend.MissionControl.GetConfig() 443 return &GetMissionControlConfigResponse{ 444 Config: &MissionControlConfig{ 445 HalfLifeSeconds: uint64(cfg.PenaltyHalfLife.Seconds()), 446 HopProbability: float32(cfg.AprioriHopProbability), 447 Weight: float32(cfg.AprioriWeight), 448 MaximumPaymentResults: uint32(cfg.MaxMcHistory), 449 MinimumFailureRelaxInterval: uint64(cfg.MinFailureRelaxInterval.Seconds()), 450 }, 451 }, nil 452 } 453 454 // SetMissionControlConfig returns our current mission control config. 455 func (s *Server) SetMissionControlConfig(ctx context.Context, 456 req *SetMissionControlConfigRequest) (*SetMissionControlConfigResponse, 457 error) { 458 459 cfg := &routing.MissionControlConfig{ 460 ProbabilityEstimatorCfg: routing.ProbabilityEstimatorCfg{ 461 PenaltyHalfLife: time.Duration( 462 req.Config.HalfLifeSeconds, 463 ) * time.Second, 464 AprioriHopProbability: float64(req.Config.HopProbability), 465 AprioriWeight: float64(req.Config.Weight), 466 }, 467 MaxMcHistory: int(req.Config.MaximumPaymentResults), 468 MinFailureRelaxInterval: time.Duration( 469 req.Config.MinimumFailureRelaxInterval, 470 ) * time.Second, 471 } 472 473 return &SetMissionControlConfigResponse{}, 474 s.cfg.RouterBackend.MissionControl.SetConfig(cfg) 475 } 476 477 // QueryMissionControl exposes the internal mission control state to callers. It 478 // is a development feature. 479 func (s *Server) QueryMissionControl(ctx context.Context, 480 req *QueryMissionControlRequest) (*QueryMissionControlResponse, error) { 481 482 snapshot := s.cfg.RouterBackend.MissionControl.GetHistorySnapshot() 483 484 rpcPairs := make([]*PairHistory, 0, len(snapshot.Pairs)) 485 for _, p := range snapshot.Pairs { 486 // Prevent binding to loop variable. 487 pair := p 488 489 rpcPair := PairHistory{ 490 NodeFrom: pair.Pair.From[:], 491 NodeTo: pair.Pair.To[:], 492 History: toRPCPairData(&pair.TimedPairResult), 493 } 494 495 rpcPairs = append(rpcPairs, &rpcPair) 496 } 497 498 response := QueryMissionControlResponse{ 499 Pairs: rpcPairs, 500 } 501 502 return &response, nil 503 } 504 505 // toRPCPairData marshalls mission control pair data to the rpc struct. 506 func toRPCPairData(data *routing.TimedPairResult) *PairData { 507 rpcData := PairData{ 508 FailAmtAtoms: int64(data.FailAmt.ToAtoms()), 509 FailAmtMAtoms: int64(data.FailAmt), 510 SuccessAmtAtoms: int64(data.SuccessAmt.ToAtoms()), 511 SuccessAmtMAtoms: int64(data.SuccessAmt), 512 } 513 514 if !data.FailTime.IsZero() { 515 rpcData.FailTime = data.FailTime.Unix() 516 } 517 518 if !data.SuccessTime.IsZero() { 519 rpcData.SuccessTime = data.SuccessTime.Unix() 520 } 521 522 return &rpcData 523 } 524 525 // XImportMissionControl imports the state provided to our internal mission 526 // control. Only entries that are fresher than our existing state will be used. 527 func (s *Server) XImportMissionControl(ctx context.Context, 528 req *XImportMissionControlRequest) (*XImportMissionControlResponse, 529 error) { 530 531 if len(req.Pairs) == 0 { 532 return nil, errors.New("at least one pair required for import") 533 } 534 535 snapshot := &routing.MissionControlSnapshot{ 536 Pairs: make( 537 []routing.MissionControlPairSnapshot, len(req.Pairs), 538 ), 539 } 540 541 for i, pairResult := range req.Pairs { 542 pairSnapshot, err := toPairSnapshot(pairResult) 543 if err != nil { 544 return nil, err 545 } 546 547 snapshot.Pairs[i] = *pairSnapshot 548 } 549 550 err := s.cfg.RouterBackend.MissionControl.ImportHistory( 551 snapshot, req.Force, 552 ) 553 if err != nil { 554 return nil, err 555 } 556 557 return &XImportMissionControlResponse{}, nil 558 } 559 560 func toPairSnapshot(pairResult *PairHistory) (*routing.MissionControlPairSnapshot, 561 error) { 562 563 from, err := route.NewVertexFromBytes(pairResult.NodeFrom) 564 if err != nil { 565 return nil, err 566 } 567 568 to, err := route.NewVertexFromBytes(pairResult.NodeTo) 569 if err != nil { 570 return nil, err 571 } 572 573 pairPrefix := fmt.Sprintf("pair: %v -> %v:", from, to) 574 575 if from == to { 576 return nil, fmt.Errorf("%v source and destination node must "+ 577 "differ", pairPrefix) 578 } 579 580 failAmt, failTime, err := getPair( 581 lnwire.MilliAtom(pairResult.History.FailAmtMAtoms), 582 dcrutil.Amount(pairResult.History.FailAmtAtoms), 583 pairResult.History.FailTime, 584 ) 585 if err != nil { 586 return nil, fmt.Errorf("%v invalid failure: %v", pairPrefix, 587 err) 588 } 589 590 successAmt, successTime, err := getPair( 591 lnwire.MilliAtom(pairResult.History.SuccessAmtMAtoms), 592 dcrutil.Amount(pairResult.History.SuccessAmtAtoms), 593 pairResult.History.SuccessTime, 594 ) 595 if err != nil { 596 return nil, fmt.Errorf("%v invalid success: %v", pairPrefix, 597 err) 598 } 599 600 if successAmt == 0 && failAmt == 0 { 601 return nil, fmt.Errorf("%v: either success or failure result "+ 602 "required", pairPrefix) 603 } 604 605 pair := routing.NewDirectedNodePair(from, to) 606 607 result := &routing.TimedPairResult{ 608 FailAmt: failAmt, 609 FailTime: failTime, 610 SuccessAmt: successAmt, 611 SuccessTime: successTime, 612 } 613 614 return &routing.MissionControlPairSnapshot{ 615 Pair: pair, 616 TimedPairResult: *result, 617 }, nil 618 } 619 620 // getPair validates the values provided for a mission control result and 621 // returns the msat amount and timestamp for it. 622 func getPair(amtMAtoms lnwire.MilliAtom, amtAtoms dcrutil.Amount, 623 timestamp int64) (lnwire.MilliAtom, time.Time, error) { 624 625 amt, err := getMsatPairValue(amtMAtoms, amtAtoms) 626 if err != nil { 627 return 0, time.Time{}, err 628 } 629 630 var ( 631 timeSet = timestamp != 0 632 amountSet = amt != 0 633 ) 634 635 switch { 636 case timeSet && amountSet: 637 return amt, time.Unix(timestamp, 0), nil 638 639 case timeSet && !amountSet: 640 return 0, time.Time{}, errors.New("non-zero timestamp " + 641 "requires non-zero amount") 642 643 case !timeSet && amountSet: 644 return 0, time.Time{}, errors.New("non-zero amount requires " + 645 "non-zero timestamp") 646 647 default: 648 return 0, time.Time{}, nil 649 } 650 } 651 652 // getMsatPairValue checks the msat and sat values set for a pair and ensures 653 // that the values provided are either the same, or only a single value is set. 654 func getMsatPairValue(msatValue lnwire.MilliAtom, 655 satValue dcrutil.Amount) (lnwire.MilliAtom, error) { 656 657 // If our msat value converted to sats equals our sat value, we just 658 // return the msat value, since the values are the same. 659 if msatValue.ToAtoms() == satValue { 660 return msatValue, nil 661 } 662 663 // If we have no msatValue, we can just return our sate value even if 664 // it is zero, because it's impossible that we have mismatched values. 665 if msatValue == 0 { 666 return lnwire.MilliAtom(satValue * 1000), nil 667 } 668 669 // Likewise, we can just use msat value if we have no sat value set. 670 if satValue == 0 { 671 return msatValue, nil 672 } 673 674 // If our values are non-zero but not equal, we have invalid amounts 675 // set, so we fail. 676 return 0, fmt.Errorf("msat: %v and sat: %v values not equal", msatValue, 677 satValue) 678 } 679 680 // QueryProbability returns the current success probability estimate for a 681 // given node pair and amount. 682 func (s *Server) QueryProbability(ctx context.Context, 683 req *QueryProbabilityRequest) (*QueryProbabilityResponse, error) { 684 685 fromNode, err := route.NewVertexFromBytes(req.FromNode) 686 if err != nil { 687 return nil, err 688 } 689 690 toNode, err := route.NewVertexFromBytes(req.ToNode) 691 if err != nil { 692 return nil, err 693 } 694 695 amt := lnwire.MilliAtom(req.AmtMAtoms) 696 697 mc := s.cfg.RouterBackend.MissionControl 698 prob := mc.GetProbability(fromNode, toNode, amt) 699 history := mc.GetPairHistorySnapshot(fromNode, toNode) 700 701 return &QueryProbabilityResponse{ 702 Probability: prob, 703 History: toRPCPairData(&history), 704 }, nil 705 } 706 707 // TrackPaymentV2 returns a stream of payment state updates. The stream is 708 // closed when the payment completes. 709 func (s *Server) TrackPaymentV2(request *TrackPaymentRequest, 710 stream Router_TrackPaymentV2Server) error { 711 712 paymentHash, err := lntypes.MakeHash(request.PaymentHash) 713 if err != nil { 714 return err 715 } 716 717 log.Debugf("TrackPayment called for payment %v", paymentHash) 718 719 return s.trackPayment(paymentHash, stream, request.NoInflightUpdates) 720 } 721 722 // trackPayment writes payment status updates to the provided stream. 723 func (s *Server) trackPayment(identifier lntypes.Hash, 724 stream Router_TrackPaymentV2Server, noInflightUpdates bool) error { 725 726 router := s.cfg.RouterBackend 727 728 // Subscribe to the outcome of this payment. 729 subscription, err := router.Tower.SubscribePayment( 730 identifier, 731 ) 732 switch { 733 case err == channeldb.ErrPaymentNotInitiated: 734 return status.Error(codes.NotFound, err.Error()) 735 case err != nil: 736 return err 737 } 738 defer subscription.Close() 739 740 // Stream updates back to the client. The first update is always the 741 // current state of the payment. 742 for { 743 select { 744 case item, ok := <-subscription.Updates: 745 if !ok { 746 // No more payment updates. 747 return nil 748 } 749 result := item.(*channeldb.MPPayment) 750 751 // Skip in-flight updates unless requested. 752 if noInflightUpdates && 753 result.Status == channeldb.StatusInFlight { 754 755 continue 756 } 757 758 rpcPayment, err := router.MarshallPayment(result) 759 if err != nil { 760 return err 761 } 762 763 // Send event to the client. 764 err = stream.Send(rpcPayment) 765 if err != nil { 766 return err 767 } 768 769 case <-s.quit: 770 return errServerShuttingDown 771 772 case <-stream.Context().Done(): 773 log.Debugf("Payment status stream %v canceled", identifier) 774 return stream.Context().Err() 775 } 776 } 777 } 778 779 // BuildRoute builds a route from a list of hop addresses. 780 func (s *Server) BuildRoute(ctx context.Context, 781 req *BuildRouteRequest) (*BuildRouteResponse, error) { 782 783 // Unmarshall hop list. 784 hops := make([]route.Vertex, len(req.HopPubkeys)) 785 for i, pubkeyBytes := range req.HopPubkeys { 786 pubkey, err := route.NewVertexFromBytes(pubkeyBytes) 787 if err != nil { 788 return nil, err 789 } 790 hops[i] = pubkey 791 } 792 793 // Prepare BuildRoute call parameters from rpc request. 794 var amt *lnwire.MilliAtom 795 if req.AmtMAtoms != 0 { 796 rpcAmt := lnwire.MilliAtom(req.AmtMAtoms) 797 amt = &rpcAmt 798 } 799 800 var outgoingChan *uint64 801 if req.OutgoingChanId != 0 { 802 outgoingChan = &req.OutgoingChanId 803 } 804 805 var payAddr *[32]byte 806 if len(req.PaymentAddr) != 0 { 807 var backingPayAddr [32]byte 808 copy(backingPayAddr[:], req.PaymentAddr) 809 810 payAddr = &backingPayAddr 811 } 812 813 // Build the route and return it to the caller. 814 route, err := s.cfg.Router.BuildRoute( 815 amt, hops, outgoingChan, req.FinalCltvDelta, payAddr, 816 ) 817 if err != nil { 818 return nil, err 819 } 820 821 rpcRoute, err := s.cfg.RouterBackend.MarshallRoute(route) 822 if err != nil { 823 return nil, err 824 } 825 826 routeResp := &BuildRouteResponse{ 827 Route: rpcRoute, 828 } 829 830 return routeResp, nil 831 } 832 833 // SubscribeHtlcEvents creates a uni-directional stream from the server to 834 // the client which delivers a stream of htlc events. 835 func (s *Server) SubscribeHtlcEvents(req *SubscribeHtlcEventsRequest, 836 stream Router_SubscribeHtlcEventsServer) error { 837 838 htlcClient, err := s.cfg.RouterBackend.SubscribeHtlcEvents() 839 if err != nil { 840 return err 841 } 842 defer htlcClient.Cancel() 843 844 for { 845 select { 846 case event := <-htlcClient.Updates(): 847 rpcEvent, err := rpcHtlcEvent(event) 848 if err != nil { 849 return err 850 } 851 852 if err := stream.Send(rpcEvent); err != nil { 853 return err 854 } 855 856 // If the stream's context is cancelled, return an error. 857 case <-stream.Context().Done(): 858 log.Debugf("htlc event stream cancelled") 859 return stream.Context().Err() 860 861 // If the subscribe client terminates, exit with an error. 862 case <-htlcClient.Quit(): 863 return errors.New("htlc event subscription terminated") 864 865 // If the server has been signalled to shut down, exit. 866 case <-s.quit: 867 return errServerShuttingDown 868 } 869 } 870 } 871 872 // HtlcInterceptor is a bidirectional stream for streaming interception 873 // requests to the caller. 874 // Upon connection it does the following: 875 // 1. Check if there is already a live stream, if yes it rejects the request. 876 // 2. Regsitered a ForwardInterceptor 877 // 3. Delivers to the caller every √√ and detect his answer. 878 // It uses a local implementation of holdForwardsStore to keep all the hold 879 // forwards and find them when manual resolution is later needed. 880 func (s *Server) HtlcInterceptor(stream Router_HtlcInterceptorServer) error { 881 // We ensure there is only one interceptor at a time. 882 if !atomic.CompareAndSwapInt32(&s.forwardInterceptorActive, 0, 1) { 883 return ErrInterceptorAlreadyExists 884 } 885 defer atomic.CompareAndSwapInt32(&s.forwardInterceptorActive, 1, 0) 886 887 // run the forward interceptor. 888 return newForwardInterceptor(s, stream).run() 889 } 890 891 func extractOutPoint(req *UpdateChanStatusRequest) (*wire.OutPoint, error) { 892 chanPoint := req.GetChanPoint() 893 txid, err := lnrpc.GetChanPointFundingTxid(chanPoint) 894 if err != nil { 895 return nil, err 896 } 897 index := chanPoint.OutputIndex 898 return wire.NewOutPoint(txid, index, wire.TxTreeRegular), nil 899 } 900 901 // UpdateChanStatus allows channel state to be set manually. 902 func (s *Server) UpdateChanStatus(ctx context.Context, 903 req *UpdateChanStatusRequest) (*UpdateChanStatusResponse, error) { 904 905 outPoint, err := extractOutPoint(req) 906 if err != nil { 907 return nil, err 908 } 909 910 action := req.GetAction() 911 912 log.Debugf("UpdateChanStatus called for channel(%v) with "+ 913 "action %v", outPoint, action) 914 915 switch action { 916 case ChanStatusAction_ENABLE: 917 err = s.cfg.RouterBackend.SetChannelEnabled(*outPoint) 918 case ChanStatusAction_DISABLE: 919 err = s.cfg.RouterBackend.SetChannelDisabled(*outPoint) 920 case ChanStatusAction_AUTO: 921 err = s.cfg.RouterBackend.SetChannelAuto(*outPoint) 922 default: 923 err = fmt.Errorf("unrecognized ChannelStatusAction %v", action) 924 } 925 926 if err != nil { 927 return nil, err 928 } 929 return &UpdateChanStatusResponse{}, nil 930 }