11package loopin
22
33import (
4+ "bytes"
45 "context"
56 "errors"
67 "testing"
78
9+ "github.com/btcsuite/btcd/btcec/v2/schnorr/musig2"
810 "github.com/btcsuite/btcd/btcutil"
11+ "github.com/btcsuite/btcd/btcutil/psbt"
912 "github.com/btcsuite/btcd/chaincfg/chainhash"
1013 "github.com/btcsuite/btcd/wire"
1114 "github.com/lightninglabs/loop"
@@ -14,6 +17,7 @@ import (
1417 "github.com/lightninglabs/loop/staticaddr/deposit"
1518 "github.com/lightninglabs/loop/staticaddr/script"
1619 "github.com/lightninglabs/loop/swap"
20+ "github.com/lightninglabs/loop/swapserverrpc"
1721 "github.com/lightningnetwork/lnd/lntypes"
1822 "github.com/lightningnetwork/lnd/routing/route"
1923 "github.com/lightningnetwork/lnd/zpay32"
@@ -220,6 +224,80 @@ func TestInitiateLoopInAllowsReservedAutoloopLabel(t *testing.T) {
220224 require .Equal (t , selectedDeposit .Value , quoteGetter .amount )
221225}
222226
227+ // TestHandleLoopInSweepReqRejectsInvalidServerNonce ensures that a malformed
228+ // MuSig2 nonce returned by the server is rejected before it reaches the signer.
229+ func TestHandleLoopInSweepReqRejectsInvalidServerNonce (t * testing.T ) {
230+ ctx := t .Context ()
231+
232+ changeAddr := & script.Parameters {
233+ PkScript : []byte {0xaa , 0xbb },
234+ }
235+
236+ const confirmationHeight = 0
237+ dep := makeDeposit (7 , 0 , 10_000 , confirmationHeight )
238+ depOutpoint := outpointString (dep )
239+
240+ swapHash := lntypes.Hash {9 }
241+ loopIn := & StaticAddressLoopIn {
242+ SwapHash : swapHash ,
243+ DepositOutpoints : []string {depOutpoint },
244+ SelectedAmount : dep .Value ,
245+ }
246+ loopIn .SetState (Succeeded )
247+
248+ sweepTx := makeSweepTx (
249+ []wire.OutPoint {dep .OutPoint },
250+ []* wire.TxOut {{
251+ Value : int64 (dep .Value ),
252+ PkScript : []byte {0xcc , 0xdd },
253+ }},
254+ )
255+ sweepPacket , err := psbt .NewFromUnsignedTx (sweepTx )
256+ require .NoError (t , err )
257+
258+ var psbtBuf bytes.Buffer
259+ require .NoError (t , sweepPacket .Serialize (& psbtBuf ))
260+
261+ mgr := & Manager {
262+ cfg : & Config {
263+ AddressManager : & mockAddressManager {
264+ params : changeAddr ,
265+ },
266+ DepositManager : & mockDepositManager {
267+ byOutpoint : map [string ]* deposit.Deposit {
268+ depOutpoint : dep ,
269+ },
270+ },
271+ Store : & mockStore {
272+ loopIns : map [lntypes.Hash ]* StaticAddressLoopIn {
273+ swapHash : loopIn ,
274+ },
275+ mapIDs : map [lntypes.Hash ][]deposit.ID {
276+ swapHash : {dep .ID },
277+ },
278+ },
279+ },
280+ }
281+
282+ req := & swapserverrpc.ServerStaticLoopInSweepNotification {
283+ SweepTxPsbt : psbtBuf .Bytes (),
284+ SwapHash : swapHash [:],
285+ DepositToNonces : map [string ][]byte {
286+ depOutpoint : make ([]byte , musig2 .PubNonceSize - 1 ),
287+ },
288+ PrevoutInfo : []* swapserverrpc.PrevoutInfo {{
289+ Value : uint64 (dep .Value ),
290+ PkScript : changeAddr .PkScript ,
291+ TxidBytes : dep .Hash [:],
292+ OutputIndex : dep .Index ,
293+ }},
294+ }
295+
296+ err = mgr .handleLoopInSweepReq (ctx , req )
297+ require .ErrorContains (t , err , "invalid server nonce" )
298+ require .ErrorContains (t , err , depOutpoint )
299+ }
300+
223301// mockDepositManager implements DepositManager for tests.
224302type mockDepositManager struct {
225303 // activeDeposits is the set returned by GetActiveDepositsInState.
0 commit comments