@@ -290,6 +290,12 @@ func (p *PrivacyMapper) checkers(db firewalldb.PrivacyMapDB,
290
290
handleClosedChannelsResponse (db , flags , p .randIntn ),
291
291
mid .PassThroughErrorHandler ,
292
292
),
293
+ "/lnrpc.Lightning/PendingChannels" : mid .NewResponseRewriter (
294
+ & lnrpc.PendingChannelsRequest {},
295
+ & lnrpc.PendingChannelsResponse {},
296
+ handlePendingChannelsResponse (db , flags , p .randIntn ),
297
+ mid .PassThroughErrorHandler ,
298
+ ),
293
299
}
294
300
}
295
301
@@ -1006,6 +1012,311 @@ func handleClosedChannelsResponse(db firewalldb.PrivacyMapDB,
1006
1012
}
1007
1013
}
1008
1014
1015
+ // obfuscatePendingChannel is a helper to obfuscate the fields of a pending
1016
+ // channel.
1017
+ func obfuscatePendingChannel (c * lnrpc.PendingChannelsResponse_PendingChannel ,
1018
+ tx firewalldb.PrivacyMapTx , randIntn func (int ) (int , error ),
1019
+ flags session.PrivacyFlags ) (
1020
+ * lnrpc.PendingChannelsResponse_PendingChannel , error ) {
1021
+
1022
+ var err error
1023
+
1024
+ remotePub := c .RemoteNodePub
1025
+ if ! flags .Contains (session .ClearPubkeys ) {
1026
+ remotePub , err = firewalldb .HideString (
1027
+ tx , remotePub ,
1028
+ )
1029
+ if err != nil {
1030
+ return nil , err
1031
+ }
1032
+ }
1033
+
1034
+ capacity , err := maybeHideAmount (
1035
+ flags , randIntn , c .Capacity ,
1036
+ )
1037
+ if err != nil {
1038
+ return nil , err
1039
+ }
1040
+
1041
+ // We randomize local/remote balances.
1042
+ localBalance , err := maybeHideAmount (
1043
+ flags , randIntn , c .LocalBalance ,
1044
+ )
1045
+ if err != nil {
1046
+ return nil , err
1047
+ }
1048
+
1049
+ // We may have a too large value for the local
1050
+ // balance, restrict it to the capacity.
1051
+ if localBalance > capacity {
1052
+ localBalance = capacity
1053
+ }
1054
+
1055
+ // The remote balance is set constently to the local balance.
1056
+ remoteBalance := c .RemoteBalance
1057
+ if ! flags .Contains (session .ClearAmounts ) {
1058
+ remoteBalance = capacity - localBalance
1059
+ }
1060
+
1061
+ chanPoint := c .ChannelPoint
1062
+ if ! flags .Contains (session .ClearChanIDs ) {
1063
+ chanPoint , err = firewalldb .HideChanPointStr (
1064
+ tx , c .ChannelPoint ,
1065
+ )
1066
+ if err != nil {
1067
+ return nil , err
1068
+ }
1069
+ }
1070
+
1071
+ return & lnrpc.PendingChannelsResponse_PendingChannel {
1072
+ // Obfuscated fields.
1073
+ ChannelPoint : chanPoint ,
1074
+ RemoteNodePub : remotePub ,
1075
+ Capacity : capacity ,
1076
+ LocalBalance : localBalance ,
1077
+ RemoteBalance : remoteBalance ,
1078
+
1079
+ // Non-obfuscated fields.
1080
+ ChanStatusFlags : c .ChanStatusFlags ,
1081
+ Private : c .Private ,
1082
+ CommitmentType : c .CommitmentType ,
1083
+ Initiator : c .Initiator ,
1084
+ NumForwardingPackages : c .NumForwardingPackages ,
1085
+ Memo : c .Memo ,
1086
+
1087
+ // Omitted fields.
1088
+ // LocalChanReserveSat
1089
+ // RemoteChanReserveSat
1090
+ }, nil
1091
+ }
1092
+
1093
+ func handlePendingChannelsResponse (db firewalldb.PrivacyMapDB ,
1094
+ flags session.PrivacyFlags ,
1095
+ randIntn func (int ) (int , error )) func (ctx context.Context ,
1096
+ r * lnrpc.PendingChannelsResponse ) (proto.Message , error ) {
1097
+
1098
+ return func (_ context.Context , r * lnrpc.PendingChannelsResponse ) (
1099
+ proto.Message , error ) {
1100
+
1101
+ pendingOpens := make (
1102
+ []* lnrpc.PendingChannelsResponse_PendingOpenChannel ,
1103
+ len (r .PendingOpenChannels ),
1104
+ )
1105
+
1106
+ pendingCloses := make (
1107
+ []* lnrpc.PendingChannelsResponse_ClosedChannel ,
1108
+ len (r .PendingClosingChannels ),
1109
+ )
1110
+
1111
+ pendingForceCloses := make (
1112
+ []* lnrpc.PendingChannelsResponse_ForceClosedChannel ,
1113
+ len (r .PendingForceClosingChannels ),
1114
+ )
1115
+
1116
+ waitingCloses := make (
1117
+ []* lnrpc.PendingChannelsResponse_WaitingCloseChannel ,
1118
+ len (r .WaitingCloseChannels ),
1119
+ )
1120
+
1121
+ err := db .Update (func (tx firewalldb.PrivacyMapTx ) error {
1122
+ for i , c := range r .PendingOpenChannels {
1123
+ var err error
1124
+
1125
+ pendingChannel , err := obfuscatePendingChannel (
1126
+ c .Channel , tx , randIntn , flags ,
1127
+ )
1128
+ if err != nil {
1129
+ return err
1130
+ }
1131
+
1132
+ pendingOpen := lnrpc.PendingChannelsResponse_PendingOpenChannel {
1133
+ // Non-obfuscated fields.
1134
+ CommitFee : c .CommitFee ,
1135
+ CommitWeight : c .CommitWeight ,
1136
+ FeePerKw : c .FeePerKw ,
1137
+ FundingExpiryBlocks : c .FundingExpiryBlocks ,
1138
+
1139
+ // Obfuscated fields.
1140
+ Channel : pendingChannel ,
1141
+ }
1142
+
1143
+ pendingOpens [i ] = & pendingOpen
1144
+ }
1145
+
1146
+ for i , c := range r .PendingClosingChannels {
1147
+ var err error
1148
+
1149
+ pendingChannel , err := obfuscatePendingChannel (
1150
+ c .Channel , tx , randIntn , flags ,
1151
+ )
1152
+ if err != nil {
1153
+ return err
1154
+ }
1155
+
1156
+ closingTxid := c .ClosingTxid
1157
+ if ! flags .Contains (session .ClearClosingTxIds ) {
1158
+ closingTxid , err = firewalldb .HideString (
1159
+ tx , c .ClosingTxid ,
1160
+ )
1161
+ if err != nil {
1162
+ return err
1163
+ }
1164
+ }
1165
+
1166
+ pendingClose := lnrpc.PendingChannelsResponse_ClosedChannel {
1167
+ // Obfuscated fields.
1168
+ ClosingTxid : closingTxid ,
1169
+ Channel : pendingChannel ,
1170
+ }
1171
+
1172
+ pendingCloses [i ] = & pendingClose
1173
+ }
1174
+
1175
+ for i , c := range r .PendingForceClosingChannels {
1176
+ var err error
1177
+
1178
+ pendingChannel , err := obfuscatePendingChannel (
1179
+ c .Channel , tx , randIntn , flags ,
1180
+ )
1181
+ if err != nil {
1182
+ return err
1183
+ }
1184
+
1185
+ closingTxid := c .ClosingTxid
1186
+ if ! flags .Contains (session .ClearClosingTxIds ) {
1187
+ closingTxid , err = firewalldb .HideString (
1188
+ tx , c .ClosingTxid ,
1189
+ )
1190
+ if err != nil {
1191
+ return err
1192
+ }
1193
+ }
1194
+
1195
+ limboBalance , err := maybeHideAmount (
1196
+ flags , randIntn , c .LimboBalance ,
1197
+ )
1198
+ if err != nil {
1199
+ return err
1200
+ }
1201
+
1202
+ if limboBalance > pendingChannel .Capacity {
1203
+ limboBalance = pendingChannel .Capacity
1204
+ }
1205
+
1206
+ recoveredBalance , err := maybeHideAmount (
1207
+ flags , randIntn , c .RecoveredBalance ,
1208
+ )
1209
+ if err != nil {
1210
+ return err
1211
+ }
1212
+
1213
+ if recoveredBalance > pendingChannel .Capacity {
1214
+ limboBalance = pendingChannel .Capacity
1215
+ }
1216
+
1217
+ pendingForceClose := lnrpc.PendingChannelsResponse_ForceClosedChannel {
1218
+ // Obfuscated fields.
1219
+ ClosingTxid : closingTxid ,
1220
+ LimboBalance : limboBalance ,
1221
+ RecoveredBalance : recoveredBalance ,
1222
+ Channel : pendingChannel ,
1223
+
1224
+ // Non-obfuscated fields.
1225
+ MaturityHeight : c .MaturityHeight ,
1226
+ BlocksTilMaturity : c .BlocksTilMaturity ,
1227
+ Anchor : c .Anchor ,
1228
+
1229
+ // Omitted fields.
1230
+ PendingHtlcs : []* lnrpc.PendingHTLC {},
1231
+ }
1232
+
1233
+ pendingForceCloses [i ] = & pendingForceClose
1234
+ }
1235
+
1236
+ for i , c := range r .WaitingCloseChannels {
1237
+ var err error
1238
+
1239
+ pendingChannel , err := obfuscatePendingChannel (
1240
+ c .Channel , tx , randIntn , flags ,
1241
+ )
1242
+ if err != nil {
1243
+ return err
1244
+ }
1245
+
1246
+ limboBalance , err := maybeHideAmount (
1247
+ flags , randIntn , c .LimboBalance ,
1248
+ )
1249
+ if err != nil {
1250
+ return err
1251
+ }
1252
+
1253
+ if limboBalance > pendingChannel .Capacity {
1254
+ limboBalance = pendingChannel .Capacity
1255
+ }
1256
+
1257
+ closingTxid := c .ClosingTxid
1258
+ if ! flags .Contains (session .ClearClosingTxIds ) {
1259
+ closingTxid , err = firewalldb .HideString (
1260
+ tx , closingTxid ,
1261
+ )
1262
+ if err != nil {
1263
+ return err
1264
+ }
1265
+ }
1266
+
1267
+ // The closing tx hash is constrained by the
1268
+ // request, see docstring, which is why we only
1269
+ // obfuscate if a value is set.
1270
+ closingTxHex := c .ClosingTxHex
1271
+ if c .ClosingTxHex != "" &&
1272
+ ! flags .Contains (
1273
+ session .ClearClosingTxIds ,
1274
+ ) {
1275
+
1276
+ closingTxHex , err = firewalldb .HideString (
1277
+ tx , closingTxHex ,
1278
+ )
1279
+ if err != nil {
1280
+ return err
1281
+ }
1282
+ }
1283
+
1284
+ waitingCloseChannel := lnrpc.PendingChannelsResponse_WaitingCloseChannel {
1285
+ Channel : pendingChannel ,
1286
+ LimboBalance : limboBalance ,
1287
+ ClosingTxid : closingTxid ,
1288
+ ClosingTxHex : closingTxHex ,
1289
+
1290
+ // Omitted.
1291
+ Commitments : & lnrpc.PendingChannelsResponse_Commitments {},
1292
+ }
1293
+
1294
+ waitingCloses [i ] = & waitingCloseChannel
1295
+ }
1296
+
1297
+ return nil
1298
+ })
1299
+ if err != nil {
1300
+ return nil , err
1301
+ }
1302
+
1303
+ totalLimbo , err := maybeHideAmount (
1304
+ flags , randIntn , r .TotalLimboBalance ,
1305
+ )
1306
+ if err != nil {
1307
+ return nil , err
1308
+ }
1309
+
1310
+ return & lnrpc.PendingChannelsResponse {
1311
+ TotalLimboBalance : totalLimbo ,
1312
+ PendingOpenChannels : pendingOpens ,
1313
+ PendingClosingChannels : pendingCloses ,
1314
+ PendingForceClosingChannels : pendingForceCloses ,
1315
+ WaitingCloseChannels : waitingCloses ,
1316
+ }, nil
1317
+ }
1318
+ }
1319
+
1009
1320
// maybeHideAmount hides an amount if the privacy flag is not set.
1010
1321
func maybeHideAmount (flags session.PrivacyFlags , randIntn func (int ) (int ,
1011
1322
error ), a int64 ) (int64 , error ) {
0 commit comments