@@ -31,6 +31,13 @@ const (
3131 defaultConfTarget = 3
3232)
3333
34+ var (
35+ // ErrFeeTooHigh is returned if the server sets a fee rate for the htlc
36+ // tx that is too high. We prevent here against a low htlc timeout sweep
37+ // amount.
38+ ErrFeeTooHigh = errors .New ("fee is higher than 20% of sweep value" )
39+ )
40+
3441// InitHtlcAction is executed if all loop-in information has been validated. We
3542// assemble a loop-in request and send it to the server.
3643func (f * FSM ) InitHtlcAction (_ fsm.EventContext ) fsm.EventType {
@@ -132,22 +139,53 @@ func (f *FSM) InitHtlcAction(_ fsm.EventContext) fsm.EventType {
132139 }
133140
134141 f .loopIn .HtlcCltvExpiry = loopInResp .HtlcExpiry
142+
143+ // Retrieve htlc tx server nonces.
135144 f .htlcServerNonces , err = toNonces (loopInResp .HtlcServerNonces )
136145 if err != nil {
137146 err = fmt .Errorf ("unable to convert server nonces: %w" , err )
138147 return f .HandleError (err )
139148 }
149+ f .htlcServerNoncesHighFee , err = toNonces (
150+ loopInResp .HtlcServerNoncesHighFee ,
151+ )
152+ if err != nil {
153+ return f .HandleError (err )
154+ }
155+ f .htlcServerNoncesExtremelyHighFee , err = toNonces (
156+ loopInResp .HtlcServerNoncesExtremelyHighFee ,
157+ )
158+ if err != nil {
159+ return f .HandleError (err )
160+ }
140161
141162 // We need to defend against the server setting high fees for the htlc
142163 // tx since we might have to sweep the timeout path. We maximally allow
143164 // 20% of the swap value to be spent on fees.
144- f .loopIn .HtlcTxFeeRate = chainfee .SatPerKWeight (loopInResp .HtlcFeeRate )
145- fee := f .loopIn .HtlcTxFeeRate .FeeForWeight (f .loopIn .htlcWeight ())
165+ maxFee := f .loopIn .TotalDepositAmount () / 5
146166
147- if fee > f .loopIn .TotalDepositAmount ()/ 5 {
148- return f .HandleError (errors .New ("fee is higher than 20% of " +
149- "sweep value" ))
167+ feeRate := chainfee .SatPerKWeight (loopInResp .HtlcFeeRate )
168+ fee := feeRate .FeeForWeight (f .loopIn .htlcWeight ())
169+ if fee > maxFee {
170+ return f .HandleError (ErrFeeTooHigh )
150171 }
172+ f .loopIn .HtlcTxFeeRate = feeRate
173+
174+ highFeeRate := chainfee .SatPerKWeight (loopInResp .HighHtlcFeeRate )
175+ fee = highFeeRate .FeeForWeight (f .loopIn .htlcWeight ())
176+ if fee > maxFee {
177+ return f .HandleError (ErrFeeTooHigh )
178+ }
179+ f .loopIn .HtlcTxHighFeeRate = highFeeRate
180+
181+ extremelyHighFeeRate := chainfee .SatPerKWeight (
182+ loopInResp .ExtremelyHighHtlcFeeRate ,
183+ )
184+ fee = extremelyHighFeeRate .FeeForWeight (f .loopIn .htlcWeight ())
185+ if fee > maxFee {
186+ return f .HandleError (ErrFeeTooHigh )
187+ }
188+ f .loopIn .HtlcTxExtremelyHighFeeRate = extremelyHighFeeRate
151189
152190 // Derive the sweep address for the htlc timeout sweep tx.
153191 sweepAddress , err := f .cfg .WalletKit .NextAddr (
@@ -195,26 +233,51 @@ func (f *FSM) SignHtlcTxAction(_ fsm.EventContext) fsm.EventType {
195233 return f .HandleError (err )
196234 }
197235
198- // Create a musig2 session for each deposit.
236+ // Create a musig2 session for each deposit and different htlc tx fee
237+ // rates.
199238 htlcSessions , clientHtlcNonces , err := f .loopIn .createMusig2Sessions (
200239 f .ctx , f .cfg .Signer ,
201240 )
202241 if err != nil {
203242 err = fmt .Errorf ("unable to create musig2 sessions: %w" , err )
204243 return f .HandleError (err )
205244 }
245+ htlcSessionsHighFee , highFeeNonces , err := f .loopIn .createMusig2Sessions (
246+ f .ctx , f .cfg .Signer ,
247+ )
248+ if err != nil {
249+ return f .HandleError (err )
250+ }
251+ htlcSessionsExtremelyHighFee , extremelyHighNonces , err := f .loopIn .createMusig2Sessions ( //nolint:lll
252+ f .ctx , f .cfg .Signer ,
253+ )
206254 if err != nil {
207255 err = fmt .Errorf ("unable to convert nonces: %w" , err )
208256 return f .HandleError (err )
209257 }
210258
211- htlcTx , err := f .loopIn .createHtlcTx (f .cfg .ChainParams )
259+ // Create the htlc txns for different fee rates.
260+ htlcTx , err := f .loopIn .createHtlcTx (
261+ f .cfg .ChainParams , f .loopIn .HtlcTxFeeRate ,
262+ )
263+ if err != nil {
264+ return f .HandleError (err )
265+ }
266+ htlcTxHighFee , err := f .loopIn .createHtlcTx (
267+ f .cfg .ChainParams , f .loopIn .HtlcTxHighFeeRate ,
268+ )
269+ if err != nil {
270+ return f .HandleError (err )
271+ }
272+ htlcTxExtremelyHighFee , err := f .loopIn .createHtlcTx (
273+ f .cfg .ChainParams , f .loopIn .HtlcTxExtremelyHighFeeRate ,
274+ )
212275 if err != nil {
213276 err = fmt .Errorf ("unable to create the htlc tx: %w" , err )
214277 return f .HandleError (err )
215278 }
216279
217- // Next we'll get our htlc tx signatures.
280+ // Next we'll get our htlc tx signatures for different fee rates .
218281 htlcSigs , err := f .loopIn .signMusig2Tx (
219282 f .ctx , htlcTx , f .cfg .Signer , htlcSessions , f .htlcServerNonces ,
220283 )
@@ -223,11 +286,30 @@ func (f *FSM) SignHtlcTxAction(_ fsm.EventContext) fsm.EventType {
223286 return f .HandleError (err )
224287 }
225288
289+ htlcSigsHighFee , err := f .loopIn .signMusig2Tx (
290+ f .ctx , htlcTxHighFee , f .cfg .Signer , htlcSessionsHighFee ,
291+ f .htlcServerNoncesHighFee ,
292+ )
293+ if err != nil {
294+ return f .HandleError (err )
295+ }
296+ htlcSigsExtremelyHighFee , err := f .loopIn .signMusig2Tx (
297+ f .ctx , htlcTxExtremelyHighFee , f .cfg .Signer ,
298+ htlcSessionsExtremelyHighFee , f .htlcServerNoncesExtremelyHighFee ,
299+ )
300+ if err != nil {
301+ return f .HandleError (err )
302+ }
303+
226304 // Push htlc tx sigs to server.
227305 pushHtlcReq := & looprpc.PushStaticAddressHtlcSigsRequest {
228- SwapHash : f .loopIn .SwapHash [:],
229- HtlcClientNonces : clientHtlcNonces ,
230- HtlcClientSigs : htlcSigs ,
306+ SwapHash : f .loopIn .SwapHash [:],
307+ HtlcClientNonces : clientHtlcNonces ,
308+ HtlcClientNoncesHighFee : highFeeNonces ,
309+ HtlcClientNoncesExtremelyHighFee : extremelyHighNonces ,
310+ HtlcClientSigs : htlcSigs ,
311+ HtlcClientSigsHighFee : htlcSigsHighFee ,
312+ HtlcClientSigsExtremelyHighFee : htlcSigsExtremelyHighFee ,
231313 }
232314 _ , err = f .cfg .Server .PushStaticAddressHtlcSigs (f .ctx , pushHtlcReq )
233315 if err != nil {
0 commit comments