From 07e5ed4490ff1177d9a196d33dcb1928142fb763 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20A=2EP?= <53834183+Jossec101@users.noreply.github.com> Date: Thu, 18 Sep 2025 15:52:12 +0200 Subject: [PATCH 1/3] feat: refactor swap provider to support per-channel locking - Add ChannelId field to submarine swap requests - Replace global swap locks with per-channel lock maps - Update lock acquisition/release methods to accept channel ID - Fix pointer dereference for swap status in fee recording - Simplify reverse swap request to use single ChannelId instead of ChannelSet --- liquidator.go | 7 +- provider/loop_provider.go | 111 ++++++++++++-------- provider/loop_provider_test.go | 186 +++++++++++++++++++++++++++++---- provider/provider.go | 8 +- 4 files changed, 239 insertions(+), 73 deletions(-) diff --git a/liquidator.go b/liquidator.go index 9667d15..e18e518 100644 --- a/liquidator.go +++ b/liquidator.go @@ -580,6 +580,7 @@ func performSwap(info ManageChannelLiquidityInfo, channel *lnrpc.Channel, swapAm swapRequest := provider.SubmarineSwapRequest{ SatsAmount: swapAmount, LastHopPubkey: channel.RemotePubkey, + ChannelId: channel.GetChanId(), } //Log including channel.GetChanId() and swapAmount @@ -700,7 +701,7 @@ func performSwap(info ManageChannelLiquidityInfo, channel *lnrpc.Channel, swapAm swapType := "swap" //Add fees to counter - recordSwapFees(swapStatus, info, swapType, channel) + recordSwapFees(*swapStatus, info, swapType, channel) } return nil } @@ -728,7 +729,7 @@ func performReverseSwap(info ManageChannelLiquidityInfo, channel *lnrpc.Channel, //Perform the swap swapRequest := provider.ReverseSubmarineSwapRequest{ SatsAmount: swapAmount, - ChannelSet: []uint64{channel.GetChanId()}, + ChannelId: channel.GetChanId(), ReceiverBTCAddress: address, } @@ -790,7 +791,7 @@ func performReverseSwap(info ManageChannelLiquidityInfo, channel *lnrpc.Channel, swapType := "rswap" //Add fees to counter - recordSwapFees(swapStatus, info, swapType, channel) + recordSwapFees(*swapStatus, info, swapType, channel) } return nil } diff --git a/provider/loop_provider.go b/provider/loop_provider.go index 344b3af..8b89f75 100644 --- a/provider/loop_provider.go +++ b/provider/loop_provider.go @@ -17,72 +17,91 @@ import ( ) type LoopProvider struct { - // Timestamp of when submarine swap lock was acquired - submarineSwapLockTime *time.Time + // Maps channel ID to timestamp of when submarine swap lock was acquired for that channel + submarineSwapLocks map[uint64]*time.Time - // Timestamp of when reverse submarine swap lock was acquired - reverseSwapLockTime *time.Time + // Maps channel ID to timestamp of when reverse submarine swap lock was acquired for that channel + reverseSwapLocks map[uint64]*time.Time // General mutex for managing lock state stateMutex sync.RWMutex } -// acquireSubmarineSwapLock tries to acquire the submarine swap lock -func (l *LoopProvider) acquireSubmarineSwapLock() error { +// acquireSubmarineSwapLock tries to acquire the submarine swap lock for a specific channel +func (l *LoopProvider) acquireSubmarineSwapLock(channelId uint64) error { l.stateMutex.Lock() defer l.stateMutex.Unlock() - // Check if there's an active lock and if it has expired - if l.submarineSwapLockTime != nil { + // Initialize the maps if they don't exist + if l.submarineSwapLocks == nil { + l.submarineSwapLocks = make(map[uint64]*time.Time) + } + + // Check if there's an active lock for this channel and if it has expired + if lockTime, exists := l.submarineSwapLocks[channelId]; exists && lockTime != nil { swapLockTimeout := viper.GetDuration("swapLockTimeout") - if time.Since(*l.submarineSwapLockTime) < swapLockTimeout { + if time.Since(*lockTime) < swapLockTimeout { return &customerrors.SwapInProgressError{ - Message: fmt.Sprintf("submarine swap is locked, started at %s, will expire at %s", - l.submarineSwapLockTime.Format(time.RFC3339), - l.submarineSwapLockTime.Add(swapLockTimeout).Format(time.RFC3339)), + Message: fmt.Sprintf("submarine swap is locked for channel %d, started at %s, will expire at %s", + channelId, + lockTime.Format(time.RFC3339), + lockTime.Add(swapLockTimeout).Format(time.RFC3339)), } } } - // Acquire the lock + // Acquire the lock for this channel now := time.Now() - l.submarineSwapLockTime = &now - log.Infof("Acquired submarine swap lock at %s", now.Format(time.RFC3339)) + l.submarineSwapLocks[channelId] = &now + log.Infof("Acquired submarine swap lock for channel %d at %s", channelId, now.Format(time.RFC3339)) return nil } -// acquireReverseSwapLock tries to acquire the reverse swap lock -func (l *LoopProvider) acquireReverseSwapLock() error { +// acquireReverseSwapLock tries to acquire the reverse swap lock for a specific channel +func (l *LoopProvider) acquireReverseSwapLock(channelId uint64) error { l.stateMutex.Lock() defer l.stateMutex.Unlock() - // Check if there's an active lock and if it has expired - if l.reverseSwapLockTime != nil { - swapLockTimeout := viper.GetDuration("swapLockTimeout") - if time.Since(*l.reverseSwapLockTime) < swapLockTimeout { + // Initialize the maps if they don't exist + if l.reverseSwapLocks == nil { + l.reverseSwapLocks = make(map[uint64]*time.Time) + } + + swapLockTimeout := viper.GetDuration("swapLockTimeout") + + // Check if there's an active lock for this channel and if it has expired + if lockTime, exists := l.reverseSwapLocks[channelId]; exists && lockTime != nil { + if time.Since(*lockTime) < swapLockTimeout { return &customerrors.SwapInProgressError{ - Message: fmt.Sprintf("reverse submarine swap is locked, started at %s, will expire at %s", - l.reverseSwapLockTime.Format(time.RFC3339), - l.reverseSwapLockTime.Add(swapLockTimeout).Format(time.RFC3339)), + Message: fmt.Sprintf("reverse submarine swap is locked for channel %d, started at %s, will expire at %s", + channelId, + lockTime.Format(time.RFC3339), + lockTime.Add(swapLockTimeout).Format(time.RFC3339)), } } } - // Acquire the lock + // Acquire the lock for this channel now := time.Now() - l.reverseSwapLockTime = &now - log.Infof("Acquired reverse swap lock at %s", now.Format(time.RFC3339)) + l.reverseSwapLocks[channelId] = &now + log.Infof("Acquired reverse swap lock for channel %d at %s", channelId, now.Format(time.RFC3339)) return nil } -// releaseReverseSwapLock releases the reverse swap lock -func (l *LoopProvider) releaseReverseSwapLock() { +// releaseReverseSwapLock releases the reverse swap lock for a specific channel +func (l *LoopProvider) releaseReverseSwapLock(channelId uint64) { l.stateMutex.Lock() defer l.stateMutex.Unlock() - if l.reverseSwapLockTime != nil { - log.Infof("Released reverse swap lock that was acquired at %s", l.reverseSwapLockTime.Format(time.RFC3339)) - l.reverseSwapLockTime = nil + // Initialize the maps if they don't exist + if l.reverseSwapLocks == nil { + l.reverseSwapLocks = make(map[uint64]*time.Time) + return + } + + if lockTime, exists := l.reverseSwapLocks[channelId]; exists && lockTime != nil { + log.Infof("Released reverse swap lock for channel %d that was acquired at %s", channelId, lockTime.Format(time.RFC3339)) + delete(l.reverseSwapLocks, channelId) } } @@ -90,7 +109,7 @@ func (l *LoopProvider) releaseReverseSwapLock() { func (l *LoopProvider) RequestSubmarineSwap(ctx context.Context, request SubmarineSwapRequest, client looprpc.SwapClientClient) (SubmarineSwapResponse, error) { //Check that no sub swap is already in progress and acquire lock (rate limiting) - err := l.acquireSubmarineSwapLock() + err := l.acquireSubmarineSwapLock(request.ChannelId) if err != nil { log.Error(err) return SubmarineSwapResponse{}, err @@ -198,7 +217,7 @@ func (l *LoopProvider) RequestSubmarineSwap(ctx context.Context, request Submari func (l *LoopProvider) RequestReverseSubmarineSwap(ctx context.Context, request ReverseSubmarineSwapRequest, client looprpc.SwapClientClient) (ReverseSubmarineSwapResponse, error) { //Check that no other swap is in progress and acquire lock (rate limiting) - err := l.acquireReverseSwapLock() + err := l.acquireReverseSwapLock(request.ChannelId) if err != nil { log.Error(err) return ReverseSubmarineSwapResponse{}, err @@ -262,12 +281,12 @@ func (l *LoopProvider) RequestReverseSubmarineSwap(ctx context.Context, request MaxSwapFee: int64(limits.maxSwapFee), MaxPrepayRoutingFee: int64(limits.maxPrepayRoutingFee), MaxSwapRoutingFee: maxSwapRoutingFee, - // OutgoingChanSet: request.ChannelSet, Disabled, evidence indicates this is not needed + // OutgoingChanSet: []uint64{request.ChannelId}, Disabled, evidence indicates this is not needed SweepConfTarget: viper.GetInt32("sweepConfTarget"), HtlcConfirmations: 3, //The publication deadline is maximum the offset of the swap deadline conf plus the current time SwapPublicationDeadline: uint64(time.Now().Add(viper.GetDuration("swapPublicationOffset") * time.Minute).Unix()), - Label: fmt.Sprintf("Reverse submarine swap %d sats on date %s for channels: %v", request.SatsAmount, time.Now().Format(time.RFC3339), request.ChannelSet), + Label: fmt.Sprintf("Reverse submarine swap %d sats on date %s for channel: %d", request.SatsAmount, time.Now().Format(time.RFC3339), request.ChannelId), Initiator: "Liquidator", }) @@ -293,7 +312,7 @@ func (l *LoopProvider) RequestReverseSubmarineSwap(ctx context.Context, request } // Get the status of a swap by invoking SwapInfo method from the client -func (l *LoopProvider) GetSwapStatus(ctx context.Context, swapId string, client looprpc.SwapClientClient) (looprpc.SwapStatus, error) { +func (l *LoopProvider) GetSwapStatus(ctx context.Context, swapId string, client looprpc.SwapClientClient) (*looprpc.SwapStatus, error) { log.Infof("getting swap status for swapId: %s", swapId) @@ -303,7 +322,7 @@ func (l *LoopProvider) GetSwapStatus(ctx context.Context, swapId string, client //Log error log.Error(err) - return looprpc.SwapStatus{}, err + return nil, err } //Decode swapId from hex string to bytes @@ -312,7 +331,7 @@ func (l *LoopProvider) GetSwapStatus(ctx context.Context, swapId string, client if err != nil { //Log error log.Errorf("error decoding swapId: %s", err) - return looprpc.SwapStatus{}, err + return nil, err } //Get swap info @@ -323,7 +342,7 @@ func (l *LoopProvider) GetSwapStatus(ctx context.Context, swapId string, client if err != nil { //Log error log.Errorf("error getting swap info: %s", err) - return looprpc.SwapStatus{}, err + return nil, err } //Log response @@ -332,17 +351,17 @@ func (l *LoopProvider) GetSwapStatus(ctx context.Context, swapId string, client //Log success log.Infof("swap status for swapId: %s is %s", swapId, swapInfo.State.String()) - return *swapInfo, nil + return swapInfo, nil } // Monitor a swap status changes and stops when the swap is completed or failed -func (l *LoopProvider) MonitorSwap(ctx context.Context, swapId string, swapClient looprpc.SwapClientClient) (looprpc.SwapStatus, error) { +func (l *LoopProvider) MonitorSwap(ctx context.Context, swapId string, swapClient looprpc.SwapClientClient) (*looprpc.SwapStatus, error) { if swapId == "" { err := fmt.Errorf("swapId is empty") log.Error(err) - return looprpc.SwapStatus{}, err + return nil, err } //Decode swapId from hex string to bytes @@ -350,7 +369,7 @@ func (l *LoopProvider) MonitorSwap(ctx context.Context, swapId string, swapClien if err != nil { //Log error log.Errorf("error decoding swapId: %s", err) - return looprpc.SwapStatus{}, err + return nil, err } for { @@ -363,7 +382,7 @@ func (l *LoopProvider) MonitorSwap(ctx context.Context, swapId string, swapClien if err != nil { //Log error log.Errorf("error getting swap info: %s", err) - return looprpc.SwapStatus{}, err + return nil, err } //Log response @@ -371,7 +390,7 @@ func (l *LoopProvider) MonitorSwap(ctx context.Context, swapId string, swapClien //If the swap is completed or failed, return the response if swapInfo.State == looprpc.SwapState_SUCCESS || swapInfo.State == looprpc.SwapState_FAILED { - return *swapInfo, nil + return swapInfo, nil } time.Sleep(1 * time.Second) diff --git a/provider/loop_provider_test.go b/provider/loop_provider_test.go index f6265db..c7f422b 100644 --- a/provider/loop_provider_test.go +++ b/provider/loop_provider_test.go @@ -3,6 +3,7 @@ package provider import ( "context" "encoding/hex" + "fmt" "reflect" "strings" "sync" @@ -255,7 +256,7 @@ func TestLoopProvider_RequestReverseSubmarineSwap(t *testing.T) { request: ReverseSubmarineSwapRequest{ ReceiverBTCAddress: "", SatsAmount: 100000000, - ChannelSet: []uint64{}, + ChannelId: 12345, }, client: swapClient, }, @@ -325,7 +326,7 @@ func TestLoopProvider_GetSwapStatus(t *testing.T) { name string l *LoopProvider args args - want looprpc.SwapStatus + want *looprpc.SwapStatus wantErr bool }{ { @@ -336,7 +337,7 @@ func TestLoopProvider_GetSwapStatus(t *testing.T) { request: "", client: nil, }, - want: looprpc.SwapStatus{}, + want: nil, wantErr: true, }, @@ -348,7 +349,7 @@ func TestLoopProvider_GetSwapStatus(t *testing.T) { request: "1234", client: client, }, - want: status, + want: &status, wantErr: false, }, } @@ -432,7 +433,7 @@ func TestLoopProvider_MonitorSwap(t *testing.T) { name string l *LoopProvider args args - want looprpc.SwapStatus + want *looprpc.SwapStatus wantErr bool }{ { @@ -443,7 +444,7 @@ func TestLoopProvider_MonitorSwap(t *testing.T) { swapId: "1234", swapClient: mockSwapClientSuccess, }, - want: *swapStatusSuccess, + want: swapStatusSuccess, wantErr: false, }, { @@ -454,7 +455,7 @@ func TestLoopProvider_MonitorSwap(t *testing.T) { swapId: "1234", swapClient: mockSwapClientFailure, }, - want: *swapStatusFailure, + want: swapStatusFailure, wantErr: false, }, } @@ -479,15 +480,16 @@ func TestLoopProvider_LockFunctionality(t *testing.T) { // Test submarine swap lock functionality t.Run("SubmarineSwapLock", func(t *testing.T) { l := &LoopProvider{} + testChannelId := uint64(12345) // Test acquiring lock for the first time - err := l.acquireSubmarineSwapLock() + err := l.acquireSubmarineSwapLock(testChannelId) if err != nil { t.Errorf("Expected no error when acquiring submarine swap lock for the first time, got: %v", err) } // Test that lock is active - should fail to acquire again - err = l.acquireSubmarineSwapLock() + err = l.acquireSubmarineSwapLock(testChannelId) if err == nil { t.Error("Expected error when trying to acquire submarine swap lock while already locked") } @@ -503,15 +505,16 @@ func TestLoopProvider_LockFunctionality(t *testing.T) { // Test reverse swap lock functionality t.Run("ReverseSwapLock", func(t *testing.T) { l := &LoopProvider{} + testChannelId := uint64(67890) // Test acquiring lock for the first time - err := l.acquireReverseSwapLock() + err := l.acquireReverseSwapLock(testChannelId) if err != nil { t.Errorf("Expected no error when acquiring reverse swap lock for the first time, got: %v", err) } // Test that lock is active - should fail to acquire again - err = l.acquireReverseSwapLock() + err = l.acquireReverseSwapLock(testChannelId) if err == nil { t.Error("Expected error when trying to acquire reverse swap lock while already locked") } @@ -527,15 +530,17 @@ func TestLoopProvider_LockFunctionality(t *testing.T) { // Test that submarine and reverse swap locks are independent t.Run("IndependentLocks", func(t *testing.T) { l := &LoopProvider{} + testChannelId1 := uint64(11111) + testChannelId2 := uint64(22222) // Acquire submarine swap lock - err := l.acquireSubmarineSwapLock() + err := l.acquireSubmarineSwapLock(testChannelId1) if err != nil { t.Errorf("Expected no error when acquiring submarine swap lock, got: %v", err) } - // Should still be able to acquire reverse swap lock - err = l.acquireReverseSwapLock() + // Should still be able to acquire reverse swap lock on different channel + err = l.acquireReverseSwapLock(testChannelId2) if err != nil { t.Errorf("Expected no error when acquiring reverse swap lock while submarine swap is locked, got: %v", err) } @@ -553,15 +558,16 @@ func TestLoopProvider_LockTimeout(t *testing.T) { t.Run("SubmarineSwapLockTimeout", func(t *testing.T) { l := &LoopProvider{} + testChannelId := uint64(33333) // Acquire lock - err := l.acquireSubmarineSwapLock() + err := l.acquireSubmarineSwapLock(testChannelId) if err != nil { t.Errorf("Expected no error when acquiring submarine swap lock, got: %v", err) } // Immediately try to acquire again - should fail - err = l.acquireSubmarineSwapLock() + err = l.acquireSubmarineSwapLock(testChannelId) if err == nil { t.Error("Expected error when trying to acquire submarine swap lock while already locked") } @@ -570,7 +576,7 @@ func TestLoopProvider_LockTimeout(t *testing.T) { time.Sleep(150 * time.Millisecond) // Should be able to acquire again after timeout - err = l.acquireSubmarineSwapLock() + err = l.acquireSubmarineSwapLock(testChannelId) if err != nil { t.Errorf("Expected no error when acquiring submarine swap lock after timeout, got: %v", err) } @@ -580,15 +586,16 @@ func TestLoopProvider_LockTimeout(t *testing.T) { t.Run("ReverseSwapLockTimeout", func(t *testing.T) { l := &LoopProvider{} + testChannelId := uint64(44444) // Acquire lock - err := l.acquireReverseSwapLock() + err := l.acquireReverseSwapLock(testChannelId) if err != nil { t.Errorf("Expected no error when acquiring reverse swap lock, got: %v", err) } // Immediately try to acquire again - should fail - err = l.acquireReverseSwapLock() + err = l.acquireReverseSwapLock(testChannelId) if err == nil { t.Error("Expected error when trying to acquire reverse swap lock while already locked") } @@ -597,7 +604,7 @@ func TestLoopProvider_LockTimeout(t *testing.T) { time.Sleep(150 * time.Millisecond) // Should be able to acquire again after timeout - err = l.acquireReverseSwapLock() + err = l.acquireReverseSwapLock(testChannelId) if err != nil { t.Errorf("Expected no error when acquiring reverse swap lock after timeout, got: %v", err) } @@ -611,6 +618,7 @@ func TestLoopProvider_ConcurrentLockAccess(t *testing.T) { l := &LoopProvider{} t.Run("ConcurrentSubmarineSwapLock", func(t *testing.T) { + testChannelId := uint64(55555) successCount := 0 errorCount := 0 var mu sync.Mutex @@ -621,7 +629,7 @@ func TestLoopProvider_ConcurrentLockAccess(t *testing.T) { wg.Add(1) go func() { defer wg.Done() - err := l.acquireSubmarineSwapLock() + err := l.acquireSubmarineSwapLock(testChannelId) mu.Lock() if err == nil { successCount++ @@ -646,6 +654,142 @@ func TestLoopProvider_ConcurrentLockAccess(t *testing.T) { }) } +// TestLoopProvider_PerChannelLocking tests the per-channel locking behavior +func TestLoopProvider_PerChannelLocking(t *testing.T) { + + t.Run("DifferentChannelsCanSwapSimultaneously", func(t *testing.T) { + l := &LoopProvider{} + channel1 := uint64(12345) + channel2 := uint64(67890) + + // Both channels should be able to acquire submarine swap locks + err1 := l.acquireSubmarineSwapLock(channel1) + if err1 != nil { + t.Errorf("Expected no error for channel1 submarine swap lock, got: %v", err1) + } + + err2 := l.acquireSubmarineSwapLock(channel2) + if err2 != nil { + t.Errorf("Expected no error for channel2 submarine swap lock, got: %v", err2) + } + + // Both channels should be able to acquire reverse swap locks + err3 := l.acquireReverseSwapLock(channel1) + if err3 != nil { + t.Errorf("Expected no error for channel1 reverse swap lock, got: %v", err3) + } + + err4 := l.acquireReverseSwapLock(channel2) + if err4 != nil { + t.Errorf("Expected no error for channel2 reverse swap lock, got: %v", err4) + } + }) + + t.Run("SameChannelCannotHaveDuplicateSubmarineSwaps", func(t *testing.T) { + l := &LoopProvider{} + channelId := uint64(11111) + + // First submarine swap should succeed + err1 := l.acquireSubmarineSwapLock(channelId) + if err1 != nil { + t.Errorf("Expected no error for first submarine swap lock, got: %v", err1) + } + + // Second submarine swap on same channel should fail + err2 := l.acquireSubmarineSwapLock(channelId) + if err2 == nil { + t.Error("Expected error for second submarine swap lock on same channel") + } + + // Error should mention the channel ID + if !contains(err2.Error(), fmt.Sprintf("channel %d", channelId)) { + t.Errorf("Expected error message to contain channel ID %d, got: %s", channelId, err2.Error()) + } + }) + + t.Run("SameChannelCannotHaveDuplicateReverseSwaps", func(t *testing.T) { + l := &LoopProvider{} + channelId := uint64(22222) + + // First reverse swap should succeed + err1 := l.acquireReverseSwapLock(channelId) + if err1 != nil { + t.Errorf("Expected no error for first reverse swap lock, got: %v", err1) + } + + // Second reverse swap on same channel should fail + err2 := l.acquireReverseSwapLock(channelId) + if err2 == nil { + t.Error("Expected error for second reverse swap lock on same channel") + } + + // Error should mention the channel ID + if !contains(err2.Error(), fmt.Sprintf("channel %d", channelId)) { + t.Errorf("Expected error message to contain channel ID %d, got: %s", channelId, err2.Error()) + } + }) + + t.Run("SameChannelCanHaveBothSubmarineAndReverseSwaps", func(t *testing.T) { + l := &LoopProvider{} + channelId := uint64(33333) + + // Submarine swap should succeed + err1 := l.acquireSubmarineSwapLock(channelId) + if err1 != nil { + t.Errorf("Expected no error for submarine swap lock, got: %v", err1) + } + + // Reverse swap on same channel should also succeed (different lock types) + err2 := l.acquireReverseSwapLock(channelId) + if err2 != nil { + t.Errorf("Expected no error for reverse swap lock on same channel, got: %v", err2) + } + + // But duplicate submarine swap should fail + err3 := l.acquireSubmarineSwapLock(channelId) + if err3 == nil { + t.Error("Expected error for duplicate submarine swap lock") + } + + // And duplicate reverse swap should fail + err4 := l.acquireReverseSwapLock(channelId) + if err4 == nil { + t.Error("Expected error for duplicate reverse swap lock") + } + }) + + t.Run("ChannelLockTimeout", func(t *testing.T) { + // Set a short timeout for testing + originalTimeout := viper.GetString("swapLockTimeout") + viper.Set("swapLockTimeout", "50ms") + defer viper.Set("swapLockTimeout", originalTimeout) + + l := &LoopProvider{} + channelId := uint64(44444) + + // Acquire lock + err1 := l.acquireSubmarineSwapLock(channelId) + if err1 != nil { + t.Errorf("Expected no error for initial lock, got: %v", err1) + } + + // Immediate retry should fail + err2 := l.acquireSubmarineSwapLock(channelId) + if err2 == nil { + t.Error("Expected error for immediate retry") + } + + // Wait for timeout + time.Sleep(100 * time.Millisecond) + + // Should be able to acquire again after timeout + err3 := l.acquireSubmarineSwapLock(channelId) + if err3 != nil { + t.Errorf("Expected no error after timeout, got: %v", err3) + } + }) +} + // Helper function to check if a string contains a substring func contains(s, substr string) bool { return strings.Contains(s, substr) diff --git a/provider/provider.go b/provider/provider.go index 71c3d16..baaf6c9 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -18,10 +18,10 @@ type Provider interface { RequestReverseSubmarineSwap(context.Context, ReverseSubmarineSwapRequest, looprpc.SwapClientClient) (ReverseSubmarineSwapResponse, error) //Swap info - GetSwapStatus(context.Context, string, looprpc.SwapClientClient) (looprpc.SwapStatus, error) + GetSwapStatus(context.Context, string, looprpc.SwapClientClient) (*looprpc.SwapStatus, error) //Monitor Swap by waiting for it to complete or fail - MonitorSwap(context.Context, string, looprpc.SwapClientClient) (looprpc.SwapStatus, error) + MonitorSwap(context.Context, string, looprpc.SwapClientClient) (*looprpc.SwapStatus, error) } // Provider-agnostic request for a submarine swap @@ -29,6 +29,8 @@ type SubmarineSwapRequest struct { SatsAmount int64 //Last hop node to identify which channel to use, if multiple channels are with this node then there is no way to know which one will be used LastHopPubkey string + //Channel ID for per-channel locking + ChannelId uint64 } // Provider-agnostic response for a submarine swap @@ -43,7 +45,7 @@ type ReverseSubmarineSwapRequest struct { //L1 Address to receive L2 funds ReceiverBTCAddress string SatsAmount int64 - ChannelSet []uint64 + ChannelId uint64 } // Provider-agnostic response for a reverse submarine swap From 8dfb806e85653c47c8ea1ed4b85711abc261f5f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20A=2EP?= <53834183+Jossec101@users.noreply.github.com> Date: Thu, 18 Sep 2025 16:18:40 +0200 Subject: [PATCH 2/3] feat: add mutual exclusion between submarine and reverse swaps per channel Implement cross-type swap locking to prevent simultaneous submarine and reverse swaps on the same channel. Add validation logic to check for existing locks of opposite swap types before acquiring new locks --- provider/loop_provider.go | 37 ++++++++++++++++++-- provider/loop_provider_test.go | 63 +++++++++++++++++++++------------- 2 files changed, 74 insertions(+), 26 deletions(-) diff --git a/provider/loop_provider.go b/provider/loop_provider.go index 8b89f75..67e0f66 100644 --- a/provider/loop_provider.go +++ b/provider/loop_provider.go @@ -36,10 +36,26 @@ func (l *LoopProvider) acquireSubmarineSwapLock(channelId uint64) error { if l.submarineSwapLocks == nil { l.submarineSwapLocks = make(map[uint64]*time.Time) } + if l.reverseSwapLocks == nil { + l.reverseSwapLocks = make(map[uint64]*time.Time) + } + + swapLockTimeout := viper.GetDuration("swapLockTimeout") + + // Check if there's an active reverse swap lock for this channel (cannot have both types) + if lockTime, exists := l.reverseSwapLocks[channelId]; exists && lockTime != nil { + if time.Since(*lockTime) < swapLockTimeout { + return &customerrors.SwapInProgressError{ + Message: fmt.Sprintf("reverse submarine swap is in progress for channel %d, cannot start submarine swap, started at %s, will expire at %s", + channelId, + lockTime.Format(time.RFC3339), + lockTime.Add(swapLockTimeout).Format(time.RFC3339)), + } + } + } - // Check if there's an active lock for this channel and if it has expired + // Check if there's an active submarine swap lock for this channel and if it has expired if lockTime, exists := l.submarineSwapLocks[channelId]; exists && lockTime != nil { - swapLockTimeout := viper.GetDuration("swapLockTimeout") if time.Since(*lockTime) < swapLockTimeout { return &customerrors.SwapInProgressError{ Message: fmt.Sprintf("submarine swap is locked for channel %d, started at %s, will expire at %s", @@ -66,10 +82,25 @@ func (l *LoopProvider) acquireReverseSwapLock(channelId uint64) error { if l.reverseSwapLocks == nil { l.reverseSwapLocks = make(map[uint64]*time.Time) } + if l.submarineSwapLocks == nil { + l.submarineSwapLocks = make(map[uint64]*time.Time) + } swapLockTimeout := viper.GetDuration("swapLockTimeout") - // Check if there's an active lock for this channel and if it has expired + // Check if there's an active submarine swap lock for this channel (cannot have both types) + if lockTime, exists := l.submarineSwapLocks[channelId]; exists && lockTime != nil { + if time.Since(*lockTime) < swapLockTimeout { + return &customerrors.SwapInProgressError{ + Message: fmt.Sprintf("submarine swap is in progress for channel %d, cannot start reverse swap, started at %s, will expire at %s", + channelId, + lockTime.Format(time.RFC3339), + lockTime.Add(swapLockTimeout).Format(time.RFC3339)), + } + } + } + + // Check if there's an active reverse swap lock for this channel and if it has expired if lockTime, exists := l.reverseSwapLocks[channelId]; exists && lockTime != nil { if time.Since(*lockTime) < swapLockTimeout { return &customerrors.SwapInProgressError{ diff --git a/provider/loop_provider_test.go b/provider/loop_provider_test.go index c7f422b..8a96194 100644 --- a/provider/loop_provider_test.go +++ b/provider/loop_provider_test.go @@ -661,8 +661,10 @@ func TestLoopProvider_PerChannelLocking(t *testing.T) { l := &LoopProvider{} channel1 := uint64(12345) channel2 := uint64(67890) + channel3 := uint64(11111) + channel4 := uint64(22222) - // Both channels should be able to acquire submarine swap locks + // Different channels should be able to acquire submarine swap locks err1 := l.acquireSubmarineSwapLock(channel1) if err1 != nil { t.Errorf("Expected no error for channel1 submarine swap lock, got: %v", err1) @@ -673,21 +675,21 @@ func TestLoopProvider_PerChannelLocking(t *testing.T) { t.Errorf("Expected no error for channel2 submarine swap lock, got: %v", err2) } - // Both channels should be able to acquire reverse swap locks - err3 := l.acquireReverseSwapLock(channel1) + // Different channels should be able to acquire reverse swap locks + err3 := l.acquireReverseSwapLock(channel3) if err3 != nil { - t.Errorf("Expected no error for channel1 reverse swap lock, got: %v", err3) + t.Errorf("Expected no error for channel3 reverse swap lock, got: %v", err3) } - err4 := l.acquireReverseSwapLock(channel2) + err4 := l.acquireReverseSwapLock(channel4) if err4 != nil { - t.Errorf("Expected no error for channel2 reverse swap lock, got: %v", err4) + t.Errorf("Expected no error for channel4 reverse swap lock, got: %v", err4) } }) t.Run("SameChannelCannotHaveDuplicateSubmarineSwaps", func(t *testing.T) { l := &LoopProvider{} - channelId := uint64(11111) + channelId := uint64(99999) // First submarine swap should succeed err1 := l.acquireSubmarineSwapLock(channelId) @@ -709,7 +711,7 @@ func TestLoopProvider_PerChannelLocking(t *testing.T) { t.Run("SameChannelCannotHaveDuplicateReverseSwaps", func(t *testing.T) { l := &LoopProvider{} - channelId := uint64(22222) + channelId := uint64(88888) // First reverse swap should succeed err1 := l.acquireReverseSwapLock(channelId) @@ -729,32 +731,47 @@ func TestLoopProvider_PerChannelLocking(t *testing.T) { } }) - t.Run("SameChannelCanHaveBothSubmarineAndReverseSwaps", func(t *testing.T) { + t.Run("SameChannelCannotHaveBothSubmarineAndReverseSwaps", func(t *testing.T) { l := &LoopProvider{} - channelId := uint64(33333) + channelId := uint64(77777) - // Submarine swap should succeed + // First submarine swap should succeed err1 := l.acquireSubmarineSwapLock(channelId) if err1 != nil { t.Errorf("Expected no error for submarine swap lock, got: %v", err1) } - // Reverse swap on same channel should also succeed (different lock types) + // Reverse swap on same channel should fail err2 := l.acquireReverseSwapLock(channelId) - if err2 != nil { - t.Errorf("Expected no error for reverse swap lock on same channel, got: %v", err2) + if err2 == nil { + t.Error("Expected error for reverse swap lock on same channel as submarine swap") } - // But duplicate submarine swap should fail - err3 := l.acquireSubmarineSwapLock(channelId) - if err3 == nil { - t.Error("Expected error for duplicate submarine swap lock") + // Error should mention conflicting swap + if !contains(err2.Error(), "submarine swap") { + t.Errorf("Expected error message to mention submarine swap conflict, got: %s", err2.Error()) + } + }) + + t.Run("ReverseSwapBlocksSubmarineSwap", func(t *testing.T) { + l := &LoopProvider{} + channelId := uint64(66666) + + // First reverse swap should succeed + err1 := l.acquireReverseSwapLock(channelId) + if err1 != nil { + t.Errorf("Expected no error for reverse swap lock, got: %v", err1) + } + + // Submarine swap on same channel should fail + err2 := l.acquireSubmarineSwapLock(channelId) + if err2 == nil { + t.Error("Expected error for submarine swap lock on same channel as reverse swap") } - // And duplicate reverse swap should fail - err4 := l.acquireReverseSwapLock(channelId) - if err4 == nil { - t.Error("Expected error for duplicate reverse swap lock") + // Error should mention conflicting swap + if !contains(err2.Error(), "reverse submarine swap") { + t.Errorf("Expected error message to mention reverse submarine swap conflict, got: %s", err2.Error()) } }) @@ -765,7 +782,7 @@ func TestLoopProvider_PerChannelLocking(t *testing.T) { defer viper.Set("swapLockTimeout", originalTimeout) l := &LoopProvider{} - channelId := uint64(44444) + channelId := uint64(55555) // Acquire lock err1 := l.acquireSubmarineSwapLock(channelId) From 937bd2939bec3f3fb6287663bf6512a43b05b741 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20A=2EP?= <53834183+Jossec101@users.noreply.github.com> Date: Thu, 18 Sep 2025 16:52:50 +0200 Subject: [PATCH 3/3] fix: update mock methods to return pointers for SwapStatus - Change MonitorSwap mock returns from value to pointer types - Remove unused MockNodeGuardServiceServer from generated mock file - Update mock generation command to use interface-based approach --- liquidator_test.go | 4 +- nodeguard/nodeguard_mock.go | 331 +----------------------------------- provider/provider_mock.go | 8 +- 3 files changed, 8 insertions(+), 335 deletions(-) diff --git a/liquidator_test.go b/liquidator_test.go index c7499e4..c296a62 100644 --- a/liquidator_test.go +++ b/liquidator_test.go @@ -362,7 +362,7 @@ func createMockProviderValidSwap(mockCtrl *gomock.Controller) *provider.MockProv InvoiceBTCAddress: "bcrt1q6zszlnxhlq0lsmfc42nkwgqedy9kvmvmxhkvme", }, nil).AnyTimes() - mockProvider.EXPECT().MonitorSwap(gomock.Any(), gomock.Any(), gomock.Any()).Return(looprpc.SwapStatus{ + mockProvider.EXPECT().MonitorSwap(gomock.Any(), gomock.Any(), gomock.Any()).Return(&looprpc.SwapStatus{ Amt: 0, Id: "", IdBytes: []byte{}, @@ -396,7 +396,7 @@ func createMockProviderInvalidSwap(mockCtrl *gomock.Controller) *provider.MockPr InvoiceBTCAddress: "bcrt1q6zszlnxhlq0lsmfc42nkwgqedy9kvmvmxhkvme", }, nil).AnyTimes() - mockProviderInvalid.EXPECT().MonitorSwap(gomock.Any(), gomock.Any(), gomock.Any()).Return(looprpc.SwapStatus{ + mockProviderInvalid.EXPECT().MonitorSwap(gomock.Any(), gomock.Any(), gomock.Any()).Return(&looprpc.SwapStatus{ Amt: 0, Id: "", IdBytes: []byte{}, diff --git a/nodeguard/nodeguard_mock.go b/nodeguard/nodeguard_mock.go index 7fb5604..bcdac61 100644 --- a/nodeguard/nodeguard_mock.go +++ b/nodeguard/nodeguard_mock.go @@ -1,9 +1,9 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: nodeguard/nodeguard_grpc.pb.go +// Source: github.com/Elenpay/liquidator/nodeguard (interfaces: NodeGuardServiceClient) // // Generated by this command: // -// mockgen -destination ./nodeguard/nodeguard_mock.go -source nodeguard/nodeguard_grpc.pb.go -package nodeguard +// mockgen -destination ./nodeguard/nodeguard_mock.go -package nodeguard github.com/Elenpay/liquidator/nodeguard NodeGuardServiceClient // // Package nodeguard is a generated GoMock package. @@ -380,330 +380,3 @@ func (mr *MockNodeGuardServiceClientMockRecorder) RequestWithdrawal(ctx, in any, varargs := append([]any{ctx, in}, opts...) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RequestWithdrawal", reflect.TypeOf((*MockNodeGuardServiceClient)(nil).RequestWithdrawal), varargs...) } - -// MockNodeGuardServiceServer is a mock of NodeGuardServiceServer interface. -type MockNodeGuardServiceServer struct { - ctrl *gomock.Controller - recorder *MockNodeGuardServiceServerMockRecorder - isgomock struct{} -} - -// MockNodeGuardServiceServerMockRecorder is the mock recorder for MockNodeGuardServiceServer. -type MockNodeGuardServiceServerMockRecorder struct { - mock *MockNodeGuardServiceServer -} - -// NewMockNodeGuardServiceServer creates a new mock instance. -func NewMockNodeGuardServiceServer(ctrl *gomock.Controller) *MockNodeGuardServiceServer { - mock := &MockNodeGuardServiceServer{ctrl: ctrl} - mock.recorder = &MockNodeGuardServiceServerMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockNodeGuardServiceServer) EXPECT() *MockNodeGuardServiceServerMockRecorder { - return m.recorder -} - -// AddLiquidityRule mocks base method. -func (m *MockNodeGuardServiceServer) AddLiquidityRule(arg0 context.Context, arg1 *AddLiquidityRuleRequest) (*AddLiquidityRuleResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddLiquidityRule", arg0, arg1) - ret0, _ := ret[0].(*AddLiquidityRuleResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// AddLiquidityRule indicates an expected call of AddLiquidityRule. -func (mr *MockNodeGuardServiceServerMockRecorder) AddLiquidityRule(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddLiquidityRule", reflect.TypeOf((*MockNodeGuardServiceServer)(nil).AddLiquidityRule), arg0, arg1) -} - -// AddNode mocks base method. -func (m *MockNodeGuardServiceServer) AddNode(arg0 context.Context, arg1 *AddNodeRequest) (*AddNodeResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddNode", arg0, arg1) - ret0, _ := ret[0].(*AddNodeResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// AddNode indicates an expected call of AddNode. -func (mr *MockNodeGuardServiceServerMockRecorder) AddNode(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddNode", reflect.TypeOf((*MockNodeGuardServiceServer)(nil).AddNode), arg0, arg1) -} - -// AddTags mocks base method. -func (m *MockNodeGuardServiceServer) AddTags(arg0 context.Context, arg1 *AddTagsRequest) (*AddTagsResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddTags", arg0, arg1) - ret0, _ := ret[0].(*AddTagsResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// AddTags indicates an expected call of AddTags. -func (mr *MockNodeGuardServiceServerMockRecorder) AddTags(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddTags", reflect.TypeOf((*MockNodeGuardServiceServer)(nil).AddTags), arg0, arg1) -} - -// CloseChannel mocks base method. -func (m *MockNodeGuardServiceServer) CloseChannel(arg0 context.Context, arg1 *CloseChannelRequest) (*CloseChannelResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CloseChannel", arg0, arg1) - ret0, _ := ret[0].(*CloseChannelResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// CloseChannel indicates an expected call of CloseChannel. -func (mr *MockNodeGuardServiceServerMockRecorder) CloseChannel(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CloseChannel", reflect.TypeOf((*MockNodeGuardServiceServer)(nil).CloseChannel), arg0, arg1) -} - -// GetAvailableUtxos mocks base method. -func (m *MockNodeGuardServiceServer) GetAvailableUtxos(arg0 context.Context, arg1 *GetAvailableUtxosRequest) (*GetUtxosResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetAvailableUtxos", arg0, arg1) - ret0, _ := ret[0].(*GetUtxosResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetAvailableUtxos indicates an expected call of GetAvailableUtxos. -func (mr *MockNodeGuardServiceServerMockRecorder) GetAvailableUtxos(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAvailableUtxos", reflect.TypeOf((*MockNodeGuardServiceServer)(nil).GetAvailableUtxos), arg0, arg1) -} - -// GetAvailableWallets mocks base method. -func (m *MockNodeGuardServiceServer) GetAvailableWallets(arg0 context.Context, arg1 *GetAvailableWalletsRequest) (*GetAvailableWalletsResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetAvailableWallets", arg0, arg1) - ret0, _ := ret[0].(*GetAvailableWalletsResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetAvailableWallets indicates an expected call of GetAvailableWallets. -func (mr *MockNodeGuardServiceServerMockRecorder) GetAvailableWallets(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAvailableWallets", reflect.TypeOf((*MockNodeGuardServiceServer)(nil).GetAvailableWallets), arg0, arg1) -} - -// GetChannel mocks base method. -func (m *MockNodeGuardServiceServer) GetChannel(arg0 context.Context, arg1 *GetChannelRequest) (*GetChannelResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetChannel", arg0, arg1) - ret0, _ := ret[0].(*GetChannelResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetChannel indicates an expected call of GetChannel. -func (mr *MockNodeGuardServiceServerMockRecorder) GetChannel(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChannel", reflect.TypeOf((*MockNodeGuardServiceServer)(nil).GetChannel), arg0, arg1) -} - -// GetChannelOperationRequest mocks base method. -func (m *MockNodeGuardServiceServer) GetChannelOperationRequest(arg0 context.Context, arg1 *GetChannelOperationRequestRequest) (*GetChannelOperationRequestResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetChannelOperationRequest", arg0, arg1) - ret0, _ := ret[0].(*GetChannelOperationRequestResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetChannelOperationRequest indicates an expected call of GetChannelOperationRequest. -func (mr *MockNodeGuardServiceServerMockRecorder) GetChannelOperationRequest(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChannelOperationRequest", reflect.TypeOf((*MockNodeGuardServiceServer)(nil).GetChannelOperationRequest), arg0, arg1) -} - -// GetLiquidityRules mocks base method. -func (m *MockNodeGuardServiceServer) GetLiquidityRules(arg0 context.Context, arg1 *GetLiquidityRulesRequest) (*GetLiquidityRulesResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetLiquidityRules", arg0, arg1) - ret0, _ := ret[0].(*GetLiquidityRulesResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetLiquidityRules indicates an expected call of GetLiquidityRules. -func (mr *MockNodeGuardServiceServerMockRecorder) GetLiquidityRules(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLiquidityRules", reflect.TypeOf((*MockNodeGuardServiceServer)(nil).GetLiquidityRules), arg0, arg1) -} - -// GetNewWalletAddress mocks base method. -func (m *MockNodeGuardServiceServer) GetNewWalletAddress(arg0 context.Context, arg1 *GetNewWalletAddressRequest) (*GetNewWalletAddressResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetNewWalletAddress", arg0, arg1) - ret0, _ := ret[0].(*GetNewWalletAddressResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetNewWalletAddress indicates an expected call of GetNewWalletAddress. -func (mr *MockNodeGuardServiceServerMockRecorder) GetNewWalletAddress(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNewWalletAddress", reflect.TypeOf((*MockNodeGuardServiceServer)(nil).GetNewWalletAddress), arg0, arg1) -} - -// GetNodes mocks base method. -func (m *MockNodeGuardServiceServer) GetNodes(arg0 context.Context, arg1 *GetNodesRequest) (*GetNodesResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetNodes", arg0, arg1) - ret0, _ := ret[0].(*GetNodesResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetNodes indicates an expected call of GetNodes. -func (mr *MockNodeGuardServiceServerMockRecorder) GetNodes(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNodes", reflect.TypeOf((*MockNodeGuardServiceServer)(nil).GetNodes), arg0, arg1) -} - -// GetUtxos mocks base method. -func (m *MockNodeGuardServiceServer) GetUtxos(arg0 context.Context, arg1 *GetUtxosRequest) (*GetUtxosResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetUtxos", arg0, arg1) - ret0, _ := ret[0].(*GetUtxosResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetUtxos indicates an expected call of GetUtxos. -func (mr *MockNodeGuardServiceServerMockRecorder) GetUtxos(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUtxos", reflect.TypeOf((*MockNodeGuardServiceServer)(nil).GetUtxos), arg0, arg1) -} - -// GetWalletBalance mocks base method. -func (m *MockNodeGuardServiceServer) GetWalletBalance(arg0 context.Context, arg1 *GetWalletBalanceRequest) (*GetWalletBalanceResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetWalletBalance", arg0, arg1) - ret0, _ := ret[0].(*GetWalletBalanceResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetWalletBalance indicates an expected call of GetWalletBalance. -func (mr *MockNodeGuardServiceServerMockRecorder) GetWalletBalance(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWalletBalance", reflect.TypeOf((*MockNodeGuardServiceServer)(nil).GetWalletBalance), arg0, arg1) -} - -// GetWithdrawalsRequestStatus mocks base method. -func (m *MockNodeGuardServiceServer) GetWithdrawalsRequestStatus(arg0 context.Context, arg1 *GetWithdrawalsRequestStatusRequest) (*GetWithdrawalsRequestStatusResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetWithdrawalsRequestStatus", arg0, arg1) - ret0, _ := ret[0].(*GetWithdrawalsRequestStatusResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetWithdrawalsRequestStatus indicates an expected call of GetWithdrawalsRequestStatus. -func (mr *MockNodeGuardServiceServerMockRecorder) GetWithdrawalsRequestStatus(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWithdrawalsRequestStatus", reflect.TypeOf((*MockNodeGuardServiceServer)(nil).GetWithdrawalsRequestStatus), arg0, arg1) -} - -// GetWithdrawalsRequestStatusByReferenceIds mocks base method. -func (m *MockNodeGuardServiceServer) GetWithdrawalsRequestStatusByReferenceIds(arg0 context.Context, arg1 *GetWithdrawalsRequestStatusByReferenceIdsRequest) (*GetWithdrawalsRequestStatusResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetWithdrawalsRequestStatusByReferenceIds", arg0, arg1) - ret0, _ := ret[0].(*GetWithdrawalsRequestStatusResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetWithdrawalsRequestStatusByReferenceIds indicates an expected call of GetWithdrawalsRequestStatusByReferenceIds. -func (mr *MockNodeGuardServiceServerMockRecorder) GetWithdrawalsRequestStatusByReferenceIds(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWithdrawalsRequestStatusByReferenceIds", reflect.TypeOf((*MockNodeGuardServiceServer)(nil).GetWithdrawalsRequestStatusByReferenceIds), arg0, arg1) -} - -// OpenChannel mocks base method. -func (m *MockNodeGuardServiceServer) OpenChannel(arg0 context.Context, arg1 *OpenChannelRequest) (*OpenChannelResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "OpenChannel", arg0, arg1) - ret0, _ := ret[0].(*OpenChannelResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// OpenChannel indicates an expected call of OpenChannel. -func (mr *MockNodeGuardServiceServerMockRecorder) OpenChannel(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OpenChannel", reflect.TypeOf((*MockNodeGuardServiceServer)(nil).OpenChannel), arg0, arg1) -} - -// RequestWithdrawal mocks base method. -func (m *MockNodeGuardServiceServer) RequestWithdrawal(arg0 context.Context, arg1 *RequestWithdrawalRequest) (*RequestWithdrawalResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RequestWithdrawal", arg0, arg1) - ret0, _ := ret[0].(*RequestWithdrawalResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// RequestWithdrawal indicates an expected call of RequestWithdrawal. -func (mr *MockNodeGuardServiceServerMockRecorder) RequestWithdrawal(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RequestWithdrawal", reflect.TypeOf((*MockNodeGuardServiceServer)(nil).RequestWithdrawal), arg0, arg1) -} - -// mustEmbedUnimplementedNodeGuardServiceServer mocks base method. -func (m *MockNodeGuardServiceServer) mustEmbedUnimplementedNodeGuardServiceServer() { - m.ctrl.T.Helper() - m.ctrl.Call(m, "mustEmbedUnimplementedNodeGuardServiceServer") -} - -// mustEmbedUnimplementedNodeGuardServiceServer indicates an expected call of mustEmbedUnimplementedNodeGuardServiceServer. -func (mr *MockNodeGuardServiceServerMockRecorder) mustEmbedUnimplementedNodeGuardServiceServer() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "mustEmbedUnimplementedNodeGuardServiceServer", reflect.TypeOf((*MockNodeGuardServiceServer)(nil).mustEmbedUnimplementedNodeGuardServiceServer)) -} - -// MockUnsafeNodeGuardServiceServer is a mock of UnsafeNodeGuardServiceServer interface. -type MockUnsafeNodeGuardServiceServer struct { - ctrl *gomock.Controller - recorder *MockUnsafeNodeGuardServiceServerMockRecorder - isgomock struct{} -} - -// MockUnsafeNodeGuardServiceServerMockRecorder is the mock recorder for MockUnsafeNodeGuardServiceServer. -type MockUnsafeNodeGuardServiceServerMockRecorder struct { - mock *MockUnsafeNodeGuardServiceServer -} - -// NewMockUnsafeNodeGuardServiceServer creates a new mock instance. -func NewMockUnsafeNodeGuardServiceServer(ctrl *gomock.Controller) *MockUnsafeNodeGuardServiceServer { - mock := &MockUnsafeNodeGuardServiceServer{ctrl: ctrl} - mock.recorder = &MockUnsafeNodeGuardServiceServerMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockUnsafeNodeGuardServiceServer) EXPECT() *MockUnsafeNodeGuardServiceServerMockRecorder { - return m.recorder -} - -// mustEmbedUnimplementedNodeGuardServiceServer mocks base method. -func (m *MockUnsafeNodeGuardServiceServer) mustEmbedUnimplementedNodeGuardServiceServer() { - m.ctrl.T.Helper() - m.ctrl.Call(m, "mustEmbedUnimplementedNodeGuardServiceServer") -} - -// mustEmbedUnimplementedNodeGuardServiceServer indicates an expected call of mustEmbedUnimplementedNodeGuardServiceServer. -func (mr *MockUnsafeNodeGuardServiceServerMockRecorder) mustEmbedUnimplementedNodeGuardServiceServer() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "mustEmbedUnimplementedNodeGuardServiceServer", reflect.TypeOf((*MockUnsafeNodeGuardServiceServer)(nil).mustEmbedUnimplementedNodeGuardServiceServer)) -} diff --git a/provider/provider_mock.go b/provider/provider_mock.go index 4aca144..91cb125 100644 --- a/provider/provider_mock.go +++ b/provider/provider_mock.go @@ -42,10 +42,10 @@ func (m *MockProvider) EXPECT() *MockProviderMockRecorder { } // GetSwapStatus mocks base method. -func (m *MockProvider) GetSwapStatus(arg0 context.Context, arg1 string, arg2 looprpc.SwapClientClient) (looprpc.SwapStatus, error) { +func (m *MockProvider) GetSwapStatus(arg0 context.Context, arg1 string, arg2 looprpc.SwapClientClient) (*looprpc.SwapStatus, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetSwapStatus", arg0, arg1, arg2) - ret0, _ := ret[0].(looprpc.SwapStatus) + ret0, _ := ret[0].(*looprpc.SwapStatus) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -57,10 +57,10 @@ func (mr *MockProviderMockRecorder) GetSwapStatus(arg0, arg1, arg2 any) *gomock. } // MonitorSwap mocks base method. -func (m *MockProvider) MonitorSwap(arg0 context.Context, arg1 string, arg2 looprpc.SwapClientClient) (looprpc.SwapStatus, error) { +func (m *MockProvider) MonitorSwap(arg0 context.Context, arg1 string, arg2 looprpc.SwapClientClient) (*looprpc.SwapStatus, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "MonitorSwap", arg0, arg1, arg2) - ret0, _ := ret[0].(looprpc.SwapStatus) + ret0, _ := ret[0].(*looprpc.SwapStatus) ret1, _ := ret[1].(error) return ret0, ret1 }