@@ -3774,8 +3774,10 @@ func (r *rpcServer) ChannelBalance(ctx context.Context,
3774
3774
}
3775
3775
3776
3776
type (
3777
+ pendingForceClose * lnrpc.PendingChannelsResponse_ForceClosedChannel
3778
+
3777
3779
pendingOpenChannels []* lnrpc.PendingChannelsResponse_PendingOpenChannel
3778
- pendingForceClose []* lnrpc.PendingChannelsResponse_ForceClosedChannel
3780
+ pendingForceCloses []* lnrpc.PendingChannelsResponse_ForceClosedChannel
3779
3781
waitingCloseChannels []* lnrpc.PendingChannelsResponse_WaitingCloseChannel
3780
3782
)
3781
3783
@@ -3861,7 +3863,7 @@ func (r *rpcServer) fetchPendingOpenChannels() (pendingOpenChannels, error) {
3861
3863
// fetchPendingForceCloseChannels queries the database for a list of channels
3862
3864
// that have their closing transactions confirmed but not fully resolved yet.
3863
3865
// The returned result is used in the response of the PendingChannels RPC.
3864
- func (r * rpcServer ) fetchPendingForceCloseChannels () (pendingForceClose ,
3866
+ func (r * rpcServer ) fetchPendingForceCloseChannels () (pendingForceCloses ,
3865
3867
int64 , error ) {
3866
3868
3867
3869
_ , currentHeight , err := r .server .cc .ChainIO .GetBestBlock ()
@@ -3877,7 +3879,7 @@ func (r *rpcServer) fetchPendingForceCloseChannels() (pendingForceClose,
3877
3879
return nil , 0 , err
3878
3880
}
3879
3881
3880
- result := make (pendingForceClose , 0 )
3882
+ result := make (pendingForceCloses , 0 )
3881
3883
limboBalance := int64 (0 )
3882
3884
3883
3885
for _ , pendingClose := range channels {
@@ -3992,13 +3994,47 @@ func (r *rpcServer) fetchPendingForceCloseChannels() (pendingForceClose,
3992
3994
}
3993
3995
3994
3996
limboBalance += forceClose .LimboBalance
3997
+
3998
+ // Dedup pending HTLCs.
3999
+ dedupPendingHTLCs (forceClose )
3995
4000
result = append (result , forceClose )
3996
4001
}
3997
4002
}
3998
4003
3999
4004
return result , limboBalance , nil
4000
4005
}
4001
4006
4007
+ // dedupPendingHTLCs takes a pending force close response and removes the
4008
+ // duplicated HTLCs found in the report.
4009
+ //
4010
+ // TODO(yy): remove the utxo nursery so there won't be duplicate reports.
4011
+ func dedupPendingHTLCs (forceClose pendingForceClose ) {
4012
+ // Make an outpoint map for lookup.
4013
+ ops := make (map [string ]struct {}, len (forceClose .PendingHtlcs ))
4014
+
4015
+ // Create a set to store the result.
4016
+ htlcSet := make ([]* lnrpc.PendingHTLC , 0 , len (forceClose .PendingHtlcs ))
4017
+
4018
+ // Go through each pending HTLC, if it's outpoint hasn't been seen
4019
+ // before, it will be added to the set.
4020
+ for _ , htlc := range forceClose .PendingHtlcs {
4021
+ op := htlc .Outpoint
4022
+ _ , found := ops [op ]
4023
+
4024
+ // Already seen, skip.
4025
+ if found {
4026
+ continue
4027
+ }
4028
+
4029
+ // Otherwise save it to the set.
4030
+ ops [op ] = struct {}{}
4031
+ htlcSet = append (htlcSet , htlc )
4032
+ }
4033
+
4034
+ // Attach the dedupped set.
4035
+ forceClose .PendingHtlcs = htlcSet
4036
+ }
4037
+
4002
4038
// fetchWaitingCloseChannels queries the database for a list of channels
4003
4039
// that have their closing transactions broadcast but not confirmed yet.
4004
4040
// The returned result is used in the response of the PendingChannels RPC.
0 commit comments