@@ -748,13 +748,31 @@ func (s *swapClientServer) GetLoopInQuote(ctx context.Context,
748748
749749 log .Infof ("Loop in quote request received" )
750750
751+ var (
752+ numDeposits = uint32 (len (req .DepositOutpoints ))
753+ err error
754+ )
755+
751756 htlcConfTarget , err := validateLoopInRequest (
752- req .ConfTarget , req .ExternalHtlc ,
757+ req .ConfTarget , req .ExternalHtlc , numDeposits , req . Amt ,
753758 )
754759 if err != nil {
755760 return nil , err
756761 }
757762
763+ // Retrieve deposits to calculate their total value.
764+ var summary * clientrpc.StaticAddressSummaryResponse
765+ if len (req .DepositOutpoints ) > 0 {
766+ summary , err = s .GetStaticAddressSummary (
767+ ctx , & clientrpc.StaticAddressSummaryRequest {
768+ Outpoints : req .DepositOutpoints ,
769+ },
770+ )
771+ if err != nil {
772+ return nil , err
773+ }
774+ }
775+
758776 var (
759777 routeHints [][]zpay32.HopHint
760778 lastHop * route.Vertex
@@ -777,14 +795,26 @@ func (s *swapClientServer) GetLoopInQuote(ctx context.Context,
777795 }
778796 }
779797
798+ // The requested amount is 0 here if the request contained deposit
799+ // outpoints. In case we quote for deposits we send the server both the
800+ // total value and the number of deposits. This is so the server can
801+ // probe the total amount and calculate the per input fee.
802+ amount := btcutil .Amount (req .Amt )
803+ if amount == 0 && len (summary .FilteredDeposits ) > 0 {
804+ for _ , deposit := range summary .FilteredDeposits {
805+ amount += btcutil .Amount (deposit .Value )
806+ }
807+ }
808+
780809 quote , err := s .impl .LoopInQuote (ctx , & loop.LoopInQuoteRequest {
781- Amount : btcutil . Amount ( req . Amt ) ,
810+ Amount : amount ,
782811 HtlcConfTarget : htlcConfTarget ,
783812 ExternalHtlc : req .ExternalHtlc ,
784813 LastHop : lastHop ,
785814 RouteHints : routeHints ,
786815 Private : req .Private ,
787816 Initiator : defaultLoopdInitiator ,
817+ NumDeposits : numDeposits ,
788818 })
789819 if err != nil {
790820 return nil , err
@@ -881,7 +911,7 @@ func (s *swapClientServer) LoopIn(ctx context.Context,
881911 log .Infof ("Loop in request received" )
882912
883913 htlcConfTarget , err := validateLoopInRequest (
884- in .HtlcConfTarget , in .ExternalHtlc ,
914+ in .HtlcConfTarget , in .ExternalHtlc , 0 , in . Amt ,
885915 )
886916 if err != nil {
887917 return nil , err
@@ -1710,7 +1740,13 @@ func validateConfTarget(target, defaultTarget int32) (int32, error) {
17101740
17111741// validateLoopInRequest fails if the mutually exclusive conf target and
17121742// external parameters are both set.
1713- func validateLoopInRequest (htlcConfTarget int32 , external bool ) (int32 , error ) {
1743+ func validateLoopInRequest (htlcConfTarget int32 , external bool ,
1744+ numDeposits uint32 , amount int64 ) (int32 , error ) {
1745+
1746+ if amount == 0 && numDeposits == 0 {
1747+ return 0 , errors .New ("either amount or deposits must be set" )
1748+ }
1749+
17141750 // If the htlc is going to be externally set, the htlcConfTarget should
17151751 // not be set, because it has no relevance when the htlc is external.
17161752 if external && htlcConfTarget != 0 {
@@ -1724,6 +1760,12 @@ func validateLoopInRequest(htlcConfTarget int32, external bool) (int32, error) {
17241760 return 0 , nil
17251761 }
17261762
1763+ // If the loop in uses static address deposits, we do not need to set a
1764+ // confirmation target since the HTLC won't be published by the client.
1765+ if numDeposits > 0 {
1766+ return 0 , nil
1767+ }
1768+
17271769 return validateConfTarget (htlcConfTarget , loop .DefaultHtlcConfTarget )
17281770}
17291771
0 commit comments