@@ -748,13 +748,53 @@ 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+ amount := btcutil .Amount (req .Amt )
766+ if len (req .DepositOutpoints ) > 0 {
767+ summary , err = s .GetStaticAddressSummary (
768+ ctx , & clientrpc.StaticAddressSummaryRequest {
769+ Outpoints : req .DepositOutpoints ,
770+ },
771+ )
772+ if err != nil {
773+ return nil , err
774+ }
775+
776+ if summary == nil {
777+ return nil , fmt .Errorf ("no summary returned for " +
778+ "deposit outpoints" )
779+ }
780+
781+ // The requested amount should be 0 here if the request
782+ // contained deposit outpoints.
783+ if amount != 0 && len (summary .FilteredDeposits ) > 0 {
784+ return nil , fmt .Errorf ("amount should be 0 for " +
785+ "deposit quotes" )
786+ }
787+
788+ // In case we quote for deposits we send the server both the
789+ // total value and the number of deposits. This is so the server
790+ // can probe the total amount and calculate the per input fee.
791+ if amount == 0 && len (summary .FilteredDeposits ) > 0 {
792+ for _ , deposit := range summary .FilteredDeposits {
793+ amount += btcutil .Amount (deposit .Value )
794+ }
795+ }
796+ }
797+
758798 var (
759799 routeHints [][]zpay32.HopHint
760800 lastHop * route.Vertex
@@ -778,13 +818,14 @@ func (s *swapClientServer) GetLoopInQuote(ctx context.Context,
778818 }
779819
780820 quote , err := s .impl .LoopInQuote (ctx , & loop.LoopInQuoteRequest {
781- Amount : btcutil . Amount ( req . Amt ) ,
821+ Amount : amount ,
782822 HtlcConfTarget : htlcConfTarget ,
783823 ExternalHtlc : req .ExternalHtlc ,
784824 LastHop : lastHop ,
785825 RouteHints : routeHints ,
786826 Private : req .Private ,
787827 Initiator : defaultLoopdInitiator ,
828+ NumDeposits : numDeposits ,
788829 })
789830 if err != nil {
790831 return nil , err
@@ -881,7 +922,7 @@ func (s *swapClientServer) LoopIn(ctx context.Context,
881922 log .Infof ("Loop in request received" )
882923
883924 htlcConfTarget , err := validateLoopInRequest (
884- in .HtlcConfTarget , in .ExternalHtlc ,
925+ in .HtlcConfTarget , in .ExternalHtlc , 0 , in . Amt ,
885926 )
886927 if err != nil {
887928 return nil , err
@@ -1710,7 +1751,13 @@ func validateConfTarget(target, defaultTarget int32) (int32, error) {
17101751
17111752// validateLoopInRequest fails if the mutually exclusive conf target and
17121753// external parameters are both set.
1713- func validateLoopInRequest (htlcConfTarget int32 , external bool ) (int32 , error ) {
1754+ func validateLoopInRequest (htlcConfTarget int32 , external bool ,
1755+ numDeposits uint32 , amount int64 ) (int32 , error ) {
1756+
1757+ if amount == 0 && numDeposits == 0 {
1758+ return 0 , errors .New ("either amount or deposits must be set" )
1759+ }
1760+
17141761 // If the htlc is going to be externally set, the htlcConfTarget should
17151762 // not be set, because it has no relevance when the htlc is external.
17161763 if external && htlcConfTarget != 0 {
@@ -1724,6 +1771,12 @@ func validateLoopInRequest(htlcConfTarget int32, external bool) (int32, error) {
17241771 return 0 , nil
17251772 }
17261773
1774+ // If the loop in uses static address deposits, we do not need to set a
1775+ // confirmation target since the HTLC won't be published by the client.
1776+ if numDeposits > 0 {
1777+ return 0 , nil
1778+ }
1779+
17271780 return validateConfTarget (htlcConfTarget , loop .DefaultHtlcConfTarget )
17281781}
17291782
0 commit comments