Skip to content

Commit 275a882

Browse files
committed
firewall: obfuscate BatchOpenChannel
We obfuscate fields from the batch channel open requests and responses.
1 parent e797abd commit 275a882

File tree

2 files changed

+193
-0
lines changed

2 files changed

+193
-0
lines changed

firewall/privacy_mapper.go

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"strings"
1313
"time"
1414

15+
"github.com/btcsuite/btcd/chaincfg/chainhash"
1516
"github.com/lightninglabs/lightning-terminal/firewalldb"
1617
mid "github.com/lightninglabs/lightning-terminal/rpcmiddleware"
1718
"github.com/lightninglabs/lightning-terminal/session"
@@ -296,6 +297,14 @@ func (p *PrivacyMapper) checkers(db firewalldb.PrivacyMapDB,
296297
handlePendingChannelsResponse(db, flags, p.randIntn),
297298
mid.PassThroughErrorHandler,
298299
),
300+
301+
"/lnrpc.Lightning/BatchOpenChannel": mid.NewFullRewriter(
302+
&lnrpc.BatchOpenChannelRequest{},
303+
&lnrpc.BatchOpenChannelResponse{},
304+
handleBatchOpenChannelRequest(db, flags),
305+
handleBatchOpenChannelResponse(db, flags),
306+
mid.PassThroughErrorHandler,
307+
),
299308
}
300309
}
301310

@@ -1317,6 +1326,134 @@ func handlePendingChannelsResponse(db firewalldb.PrivacyMapDB,
13171326
}
13181327
}
13191328

1329+
func handleBatchOpenChannelRequest(db firewalldb.PrivacyMapDB,
1330+
flags session.PrivacyFlags) func(ctx context.Context,
1331+
r *lnrpc.BatchOpenChannelRequest) (proto.Message, error) {
1332+
1333+
return func(_ context.Context, r *lnrpc.BatchOpenChannelRequest) (
1334+
proto.Message, error) {
1335+
1336+
var reqs = make([]*lnrpc.BatchOpenChannel, len(r.Channels))
1337+
1338+
err := db.View(func(tx firewalldb.PrivacyMapTx) error {
1339+
for i, c := range r.Channels {
1340+
var err error
1341+
1342+
// Note, this only works if the obfuscated
1343+
// pubkey was already created via other
1344+
// calls, e.g. via ListChannels or
1345+
// GetInfo or the like.
1346+
nodePubkey := c.NodePubkey
1347+
if !flags.Contains(session.ClearPubkeys) {
1348+
nodePubkey, err = firewalldb.RevealBytes(
1349+
tx, c.NodePubkey,
1350+
)
1351+
if err != nil {
1352+
return err
1353+
}
1354+
}
1355+
1356+
reqs[i] = &lnrpc.BatchOpenChannel{
1357+
// Obfuscated fields.
1358+
NodePubkey: nodePubkey,
1359+
1360+
// Non-obfuscated fields.
1361+
LocalFundingAmount: c.LocalFundingAmount,
1362+
PushSat: c.PushSat,
1363+
Private: c.Private,
1364+
MinHtlcMsat: c.MinHtlcMsat,
1365+
RemoteCsvDelay: c.RemoteCsvDelay,
1366+
CloseAddress: c.CloseAddress,
1367+
PendingChanId: c.PendingChanId,
1368+
CommitmentType: c.CommitmentType,
1369+
RemoteMaxValueInFlightMsat: c.RemoteMaxValueInFlightMsat,
1370+
RemoteMaxHtlcs: c.RemoteMaxHtlcs,
1371+
MaxLocalCsv: c.MaxLocalCsv,
1372+
ZeroConf: c.ZeroConf,
1373+
ScidAlias: c.ScidAlias,
1374+
BaseFee: c.BaseFee,
1375+
FeeRate: c.FeeRate,
1376+
UseBaseFee: c.UseBaseFee,
1377+
UseFeeRate: c.UseFeeRate,
1378+
RemoteChanReserveSat: c.RemoteChanReserveSat,
1379+
Memo: c.Memo,
1380+
}
1381+
}
1382+
1383+
return nil
1384+
})
1385+
if err != nil {
1386+
return nil, err
1387+
}
1388+
1389+
return &lnrpc.BatchOpenChannelRequest{
1390+
Channels: reqs,
1391+
TargetConf: r.TargetConf,
1392+
SatPerVbyte: r.SatPerVbyte,
1393+
MinConfs: r.MinConfs,
1394+
SpendUnconfirmed: r.SpendUnconfirmed,
1395+
Label: r.Label,
1396+
}, nil
1397+
}
1398+
}
1399+
1400+
func handleBatchOpenChannelResponse(db firewalldb.PrivacyMapDB,
1401+
flags session.PrivacyFlags) func(ctx context.Context,
1402+
r *lnrpc.BatchOpenChannelResponse) (proto.Message, error) {
1403+
1404+
return func(_ context.Context, r *lnrpc.BatchOpenChannelResponse) (
1405+
proto.Message, error) {
1406+
1407+
resps := make([]*lnrpc.PendingUpdate, len(r.PendingChannels))
1408+
1409+
err := db.Update(func(tx firewalldb.PrivacyMapTx) error {
1410+
for i, p := range r.PendingChannels {
1411+
var (
1412+
txIdBytes = p.Txid
1413+
outputIndex = p.OutputIndex
1414+
)
1415+
1416+
if !flags.Contains(session.ClearChanIDs) {
1417+
txId, err := chainhash.NewHash(p.Txid)
1418+
if err != nil {
1419+
return err
1420+
}
1421+
1422+
txID, outIdx, err := firewalldb.HideChanPoint(
1423+
tx, txId.String(), p.OutputIndex,
1424+
)
1425+
if err != nil {
1426+
return err
1427+
}
1428+
outputIndex = outIdx
1429+
1430+
txHash, err := chainhash.NewHashFromStr(
1431+
txID,
1432+
)
1433+
if err != nil {
1434+
return err
1435+
}
1436+
txIdBytes = txHash[:]
1437+
}
1438+
1439+
resps[i] = &lnrpc.PendingUpdate{
1440+
Txid: txIdBytes,
1441+
OutputIndex: outputIndex,
1442+
}
1443+
}
1444+
1445+
return nil
1446+
})
1447+
if err != nil {
1448+
return nil, err
1449+
}
1450+
1451+
return &lnrpc.BatchOpenChannelResponse{
1452+
PendingChannels: resps,
1453+
}, nil
1454+
}
1455+
}
1456+
13201457
// maybeHideAmount hides an amount if the privacy flag is not set.
13211458
func maybeHideAmount(flags session.PrivacyFlags, randIntn func(int) (int,
13221459
error), a int64) (int64, error) {

firewall/privacy_mapper_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@ func TestPrivacyMapper(t *testing.T) {
2727

2828
// Define some transaction outpoints used for mapping.
2929
clearTxID := "abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd"
30+
clearTxIDReveresed, err := chainhash.NewHashFromStr(clearTxID)
31+
require.NoError(t, err)
3032

3133
obfusTxID0 := "097ef666a61919ff3413b3b701eae3a5cbac08f70c0ca567806e1fa6acbfe384"
34+
require.NoError(t, err)
3235
obfusOut0 := uint32(2161781494)
3336
obfusTxID0Reversed, err := chainhash.NewHashFromStr(obfusTxID0)
3437
require.NoError(t, err)
@@ -672,6 +675,59 @@ func TestPrivacyMapper(t *testing.T) {
672675
},
673676
},
674677
},
678+
{
679+
name: "BatchOpenChannel Request",
680+
uri: "/lnrpc.Lightning/BatchOpenChannel",
681+
msgType: rpcperms.TypeRequest,
682+
msg: &lnrpc.BatchOpenChannelRequest{
683+
TargetConf: 6,
684+
Channels: []*lnrpc.BatchOpenChannel{
685+
{
686+
NodePubkey: []byte{
687+
200, 19, 68, 149,
688+
},
689+
LocalFundingAmount: 1_000_000,
690+
PushSat: 1_000_000,
691+
MinHtlcMsat: 100,
692+
},
693+
},
694+
},
695+
expectedReplacement: &lnrpc.BatchOpenChannelRequest{
696+
TargetConf: 6,
697+
Channels: []*lnrpc.BatchOpenChannel{
698+
{
699+
NodePubkey: []byte{
700+
1, 2, 3, 4,
701+
},
702+
LocalFundingAmount: 1_000_000,
703+
PushSat: 1_000_000,
704+
MinHtlcMsat: 100,
705+
},
706+
},
707+
},
708+
},
709+
{
710+
name: "BatchOpenChannel Response",
711+
uri: "/lnrpc.Lightning/BatchOpenChannel",
712+
msgType: rpcperms.TypeResponse,
713+
msg: &lnrpc.BatchOpenChannelResponse{
714+
PendingChannels: []*lnrpc.PendingUpdate{
715+
{
716+
717+
Txid: clearTxIDReveresed[:],
718+
OutputIndex: 0,
719+
},
720+
},
721+
},
722+
expectedReplacement: &lnrpc.BatchOpenChannelResponse{
723+
PendingChannels: []*lnrpc.PendingUpdate{
724+
{
725+
Txid: obfusTxID0Reversed[:],
726+
OutputIndex: obfusOut0,
727+
},
728+
},
729+
},
730+
},
675731
}
676732

677733
decodedID := &lnrpc.MacaroonId{

0 commit comments

Comments
 (0)