@@ -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 * looprpc.StaticAddressSummaryResponse
765+ amount := btcutil .Amount (req .Amt )
766+ if len (req .DepositOutpoints ) > 0 {
767+ summary , err = s .GetStaticAddressSummary (
768+ ctx , & looprpc.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
@@ -1725,7 +1766,13 @@ func validateConfTarget(target, defaultTarget int32) (int32, error) {
17251766
17261767// validateLoopInRequest fails if the mutually exclusive conf target and
17271768// external parameters are both set.
1728- func validateLoopInRequest (htlcConfTarget int32 , external bool ) (int32 , error ) {
1769+ func validateLoopInRequest (htlcConfTarget int32 , external bool ,
1770+ numDeposits uint32 , amount int64 ) (int32 , error ) {
1771+
1772+ if amount == 0 && numDeposits == 0 {
1773+ return 0 , errors .New ("either amount or deposits must be set" )
1774+ }
1775+
17291776 // If the htlc is going to be externally set, the htlcConfTarget should
17301777 // not be set, because it has no relevance when the htlc is external.
17311778 if external && htlcConfTarget != 0 {
@@ -1739,6 +1786,12 @@ func validateLoopInRequest(htlcConfTarget int32, external bool) (int32, error) {
17391786 return 0 , nil
17401787 }
17411788
1789+ // If the loop in uses static address deposits, we do not need to set a
1790+ // confirmation target since the HTLC won't be published by the client.
1791+ if numDeposits > 0 {
1792+ return 0 , nil
1793+ }
1794+
17421795 return validateConfTarget (htlcConfTarget , loop .DefaultHtlcConfTarget )
17431796}
17441797
0 commit comments