mirror of
https://github.com/lightninglabs/lightning-terminal.git
synced 2026-08-13 12:33:36 +02:00
firewall: obfuscate PendingChannels
Only obfuscate pending open channels for now.
This commit is contained in:
parent
ef84753f6b
commit
e797abd2a8
2 changed files with 465 additions and 0 deletions
|
|
@ -290,6 +290,12 @@ func (p *PrivacyMapper) checkers(db firewalldb.PrivacyMapDB,
|
|||
handleClosedChannelsResponse(db, flags, p.randIntn),
|
||||
mid.PassThroughErrorHandler,
|
||||
),
|
||||
"/lnrpc.Lightning/PendingChannels": mid.NewResponseRewriter(
|
||||
&lnrpc.PendingChannelsRequest{},
|
||||
&lnrpc.PendingChannelsResponse{},
|
||||
handlePendingChannelsResponse(db, flags, p.randIntn),
|
||||
mid.PassThroughErrorHandler,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1006,6 +1012,311 @@ func handleClosedChannelsResponse(db firewalldb.PrivacyMapDB,
|
|||
}
|
||||
}
|
||||
|
||||
// obfuscatePendingChannel is a helper to obfuscate the fields of a pending
|
||||
// channel.
|
||||
func obfuscatePendingChannel(c *lnrpc.PendingChannelsResponse_PendingChannel,
|
||||
tx firewalldb.PrivacyMapTx, randIntn func(int) (int, error),
|
||||
flags session.PrivacyFlags) (
|
||||
*lnrpc.PendingChannelsResponse_PendingChannel, error) {
|
||||
|
||||
var err error
|
||||
|
||||
remotePub := c.RemoteNodePub
|
||||
if !flags.Contains(session.ClearPubkeys) {
|
||||
remotePub, err = firewalldb.HideString(
|
||||
tx, remotePub,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
capacity, err := maybeHideAmount(
|
||||
flags, randIntn, c.Capacity,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// We randomize local/remote balances.
|
||||
localBalance, err := maybeHideAmount(
|
||||
flags, randIntn, c.LocalBalance,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// We may have a too large value for the local
|
||||
// balance, restrict it to the capacity.
|
||||
if localBalance > capacity {
|
||||
localBalance = capacity
|
||||
}
|
||||
|
||||
// The remote balance is set constently to the local balance.
|
||||
remoteBalance := c.RemoteBalance
|
||||
if !flags.Contains(session.ClearAmounts) {
|
||||
remoteBalance = capacity - localBalance
|
||||
}
|
||||
|
||||
chanPoint := c.ChannelPoint
|
||||
if !flags.Contains(session.ClearChanIDs) {
|
||||
chanPoint, err = firewalldb.HideChanPointStr(
|
||||
tx, c.ChannelPoint,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &lnrpc.PendingChannelsResponse_PendingChannel{
|
||||
// Obfuscated fields.
|
||||
ChannelPoint: chanPoint,
|
||||
RemoteNodePub: remotePub,
|
||||
Capacity: capacity,
|
||||
LocalBalance: localBalance,
|
||||
RemoteBalance: remoteBalance,
|
||||
|
||||
// Non-obfuscated fields.
|
||||
ChanStatusFlags: c.ChanStatusFlags,
|
||||
Private: c.Private,
|
||||
CommitmentType: c.CommitmentType,
|
||||
Initiator: c.Initiator,
|
||||
NumForwardingPackages: c.NumForwardingPackages,
|
||||
Memo: c.Memo,
|
||||
|
||||
// Omitted fields.
|
||||
// LocalChanReserveSat
|
||||
// RemoteChanReserveSat
|
||||
}, nil
|
||||
}
|
||||
|
||||
func handlePendingChannelsResponse(db firewalldb.PrivacyMapDB,
|
||||
flags session.PrivacyFlags,
|
||||
randIntn func(int) (int, error)) func(ctx context.Context,
|
||||
r *lnrpc.PendingChannelsResponse) (proto.Message, error) {
|
||||
|
||||
return func(_ context.Context, r *lnrpc.PendingChannelsResponse) (
|
||||
proto.Message, error) {
|
||||
|
||||
pendingOpens := make(
|
||||
[]*lnrpc.PendingChannelsResponse_PendingOpenChannel,
|
||||
len(r.PendingOpenChannels),
|
||||
)
|
||||
|
||||
pendingCloses := make(
|
||||
[]*lnrpc.PendingChannelsResponse_ClosedChannel,
|
||||
len(r.PendingClosingChannels),
|
||||
)
|
||||
|
||||
pendingForceCloses := make(
|
||||
[]*lnrpc.PendingChannelsResponse_ForceClosedChannel,
|
||||
len(r.PendingForceClosingChannels),
|
||||
)
|
||||
|
||||
waitingCloses := make(
|
||||
[]*lnrpc.PendingChannelsResponse_WaitingCloseChannel,
|
||||
len(r.WaitingCloseChannels),
|
||||
)
|
||||
|
||||
err := db.Update(func(tx firewalldb.PrivacyMapTx) error {
|
||||
for i, c := range r.PendingOpenChannels {
|
||||
var err error
|
||||
|
||||
pendingChannel, err := obfuscatePendingChannel(
|
||||
c.Channel, tx, randIntn, flags,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pendingOpen := lnrpc.PendingChannelsResponse_PendingOpenChannel{
|
||||
// Non-obfuscated fields.
|
||||
CommitFee: c.CommitFee,
|
||||
CommitWeight: c.CommitWeight,
|
||||
FeePerKw: c.FeePerKw,
|
||||
FundingExpiryBlocks: c.FundingExpiryBlocks,
|
||||
|
||||
// Obfuscated fields.
|
||||
Channel: pendingChannel,
|
||||
}
|
||||
|
||||
pendingOpens[i] = &pendingOpen
|
||||
}
|
||||
|
||||
for i, c := range r.PendingClosingChannels {
|
||||
var err error
|
||||
|
||||
pendingChannel, err := obfuscatePendingChannel(
|
||||
c.Channel, tx, randIntn, flags,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
closingTxid := c.ClosingTxid
|
||||
if !flags.Contains(session.ClearClosingTxIds) {
|
||||
closingTxid, err = firewalldb.HideString(
|
||||
tx, c.ClosingTxid,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
pendingClose := lnrpc.PendingChannelsResponse_ClosedChannel{
|
||||
// Obfuscated fields.
|
||||
ClosingTxid: closingTxid,
|
||||
Channel: pendingChannel,
|
||||
}
|
||||
|
||||
pendingCloses[i] = &pendingClose
|
||||
}
|
||||
|
||||
for i, c := range r.PendingForceClosingChannels {
|
||||
var err error
|
||||
|
||||
pendingChannel, err := obfuscatePendingChannel(
|
||||
c.Channel, tx, randIntn, flags,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
closingTxid := c.ClosingTxid
|
||||
if !flags.Contains(session.ClearClosingTxIds) {
|
||||
closingTxid, err = firewalldb.HideString(
|
||||
tx, c.ClosingTxid,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
limboBalance, err := maybeHideAmount(
|
||||
flags, randIntn, c.LimboBalance,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if limboBalance > pendingChannel.Capacity {
|
||||
limboBalance = pendingChannel.Capacity
|
||||
}
|
||||
|
||||
recoveredBalance, err := maybeHideAmount(
|
||||
flags, randIntn, c.RecoveredBalance,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if recoveredBalance > pendingChannel.Capacity {
|
||||
limboBalance = pendingChannel.Capacity
|
||||
}
|
||||
|
||||
pendingForceClose := lnrpc.PendingChannelsResponse_ForceClosedChannel{
|
||||
// Obfuscated fields.
|
||||
ClosingTxid: closingTxid,
|
||||
LimboBalance: limboBalance,
|
||||
RecoveredBalance: recoveredBalance,
|
||||
Channel: pendingChannel,
|
||||
|
||||
// Non-obfuscated fields.
|
||||
MaturityHeight: c.MaturityHeight,
|
||||
BlocksTilMaturity: c.BlocksTilMaturity,
|
||||
Anchor: c.Anchor,
|
||||
|
||||
// Omitted fields.
|
||||
PendingHtlcs: []*lnrpc.PendingHTLC{},
|
||||
}
|
||||
|
||||
pendingForceCloses[i] = &pendingForceClose
|
||||
}
|
||||
|
||||
for i, c := range r.WaitingCloseChannels {
|
||||
var err error
|
||||
|
||||
pendingChannel, err := obfuscatePendingChannel(
|
||||
c.Channel, tx, randIntn, flags,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
limboBalance, err := maybeHideAmount(
|
||||
flags, randIntn, c.LimboBalance,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if limboBalance > pendingChannel.Capacity {
|
||||
limboBalance = pendingChannel.Capacity
|
||||
}
|
||||
|
||||
closingTxid := c.ClosingTxid
|
||||
if !flags.Contains(session.ClearClosingTxIds) {
|
||||
closingTxid, err = firewalldb.HideString(
|
||||
tx, closingTxid,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// The closing tx hash is constrained by the
|
||||
// request, see docstring, which is why we only
|
||||
// obfuscate if a value is set.
|
||||
closingTxHex := c.ClosingTxHex
|
||||
if c.ClosingTxHex != "" &&
|
||||
!flags.Contains(
|
||||
session.ClearClosingTxIds,
|
||||
) {
|
||||
|
||||
closingTxHex, err = firewalldb.HideString(
|
||||
tx, closingTxHex,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
waitingCloseChannel := lnrpc.PendingChannelsResponse_WaitingCloseChannel{
|
||||
Channel: pendingChannel,
|
||||
LimboBalance: limboBalance,
|
||||
ClosingTxid: closingTxid,
|
||||
ClosingTxHex: closingTxHex,
|
||||
|
||||
// Omitted.
|
||||
Commitments: &lnrpc.PendingChannelsResponse_Commitments{},
|
||||
}
|
||||
|
||||
waitingCloses[i] = &waitingCloseChannel
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
totalLimbo, err := maybeHideAmount(
|
||||
flags, randIntn, r.TotalLimboBalance,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &lnrpc.PendingChannelsResponse{
|
||||
TotalLimboBalance: totalLimbo,
|
||||
PendingOpenChannels: pendingOpens,
|
||||
PendingClosingChannels: pendingCloses,
|
||||
PendingForceClosingChannels: pendingForceCloses,
|
||||
WaitingCloseChannels: waitingCloses,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// maybeHideAmount hides an amount if the privacy flag is not set.
|
||||
func maybeHideAmount(flags session.PrivacyFlags, randIntn func(int) (int,
|
||||
error), a int64) (int64, error) {
|
||||
|
|
|
|||
|
|
@ -36,6 +36,33 @@ func TestPrivacyMapper(t *testing.T) {
|
|||
obfusTxID1 := "45ec471bfccb0b7b9a8bc4008248931c59ad994903e07b54f54821ea3ef5cc5c"
|
||||
obfusOut1 := uint32(1642614131)
|
||||
|
||||
clearPending := &lnrpc.PendingChannelsResponse_PendingChannel{
|
||||
RemoteNodePub: "01020304",
|
||||
LocalBalance: 100_000,
|
||||
RemoteBalance: 20_000,
|
||||
LocalChanReserveSat: 1_000,
|
||||
RemoteChanReserveSat: 1_000,
|
||||
Capacity: 120_000,
|
||||
ChannelPoint: outPoint(
|
||||
clearTxID, 0,
|
||||
),
|
||||
Initiator: lnrpc.Initiator_INITIATOR_LOCAL,
|
||||
Memo: "something",
|
||||
}
|
||||
|
||||
obfuscatedPending := &lnrpc.PendingChannelsResponse_PendingChannel{
|
||||
RemoteNodePub: "c8134495",
|
||||
LocalBalance: 95_100,
|
||||
RemoteBalance: 19_000,
|
||||
Capacity: 114_100,
|
||||
ChannelPoint: outPoint(
|
||||
obfusTxID0,
|
||||
obfusOut0,
|
||||
),
|
||||
Initiator: lnrpc.Initiator_INITIATOR_LOCAL,
|
||||
Memo: "something",
|
||||
}
|
||||
|
||||
// Define some preexisting mappings for the privacy mapper.
|
||||
mapPreloadRealToPseudo := map[string]string{
|
||||
"Tinker Bell's pub key": "a44ef01c3bff970ef495c",
|
||||
|
|
@ -518,6 +545,133 @@ func TestPrivacyMapper(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "PendingChannels Response",
|
||||
uri: "/lnrpc.Lightning/PendingChannels",
|
||||
msgType: rpcperms.TypeResponse,
|
||||
msg: &lnrpc.PendingChannelsResponse{
|
||||
PendingOpenChannels: []*lnrpc.PendingChannelsResponse_PendingOpenChannel{
|
||||
{
|
||||
CommitFee: 123,
|
||||
Channel: clearPending,
|
||||
},
|
||||
},
|
||||
PendingClosingChannels: []*lnrpc.PendingChannelsResponse_ClosedChannel{
|
||||
{
|
||||
Channel: clearPending,
|
||||
ClosingTxid: clearTxID,
|
||||
},
|
||||
},
|
||||
PendingForceClosingChannels: []*lnrpc.PendingChannelsResponse_ForceClosedChannel{
|
||||
{
|
||||
Channel: clearPending,
|
||||
ClosingTxid: clearTxID,
|
||||
LimboBalance: 100_000,
|
||||
MaturityHeight: 123,
|
||||
BlocksTilMaturity: 123,
|
||||
RecoveredBalance: 100_000,
|
||||
PendingHtlcs: []*lnrpc.PendingHTLC{
|
||||
{
|
||||
Incoming: true,
|
||||
},
|
||||
},
|
||||
Anchor: 1,
|
||||
},
|
||||
},
|
||||
WaitingCloseChannels: []*lnrpc.PendingChannelsResponse_WaitingCloseChannel{
|
||||
{
|
||||
Channel: clearPending,
|
||||
LimboBalance: 100_000,
|
||||
Commitments: &lnrpc.PendingChannelsResponse_Commitments{
|
||||
LocalTxid: clearTxID,
|
||||
},
|
||||
ClosingTxid: clearTxID,
|
||||
ClosingTxHex: clearTxID,
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedReplacement: &lnrpc.PendingChannelsResponse{
|
||||
PendingOpenChannels: []*lnrpc.PendingChannelsResponse_PendingOpenChannel{
|
||||
{
|
||||
CommitFee: 123,
|
||||
Channel: obfuscatedPending,
|
||||
},
|
||||
},
|
||||
PendingClosingChannels: []*lnrpc.PendingChannelsResponse_ClosedChannel{
|
||||
{
|
||||
Channel: obfuscatedPending,
|
||||
ClosingTxid: obfusTxID0,
|
||||
},
|
||||
},
|
||||
PendingForceClosingChannels: []*lnrpc.PendingChannelsResponse_ForceClosedChannel{
|
||||
{
|
||||
Channel: obfuscatedPending,
|
||||
ClosingTxid: obfusTxID0,
|
||||
LimboBalance: 95_100,
|
||||
MaturityHeight: 123,
|
||||
BlocksTilMaturity: 123,
|
||||
RecoveredBalance: 95_100,
|
||||
PendingHtlcs: []*lnrpc.PendingHTLC{},
|
||||
Anchor: 1,
|
||||
},
|
||||
},
|
||||
WaitingCloseChannels: []*lnrpc.PendingChannelsResponse_WaitingCloseChannel{
|
||||
{
|
||||
Channel: obfuscatedPending,
|
||||
LimboBalance: 95_100,
|
||||
Commitments: &lnrpc.PendingChannelsResponse_Commitments{},
|
||||
ClosingTxid: obfusTxID0,
|
||||
ClosingTxHex: obfusTxID0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "PendingChannels Response clear",
|
||||
uri: "/lnrpc.Lightning/PendingChannels",
|
||||
msgType: rpcperms.TypeResponse,
|
||||
msg: &lnrpc.PendingChannelsResponse{
|
||||
PendingOpenChannels: []*lnrpc.PendingChannelsResponse_PendingOpenChannel{
|
||||
{
|
||||
CommitFee: 123,
|
||||
Channel: &lnrpc.PendingChannelsResponse_PendingChannel{
|
||||
RemoteNodePub: "01020304",
|
||||
LocalBalance: 100_000,
|
||||
RemoteBalance: 100_000,
|
||||
Capacity: 120_000,
|
||||
ChannelPoint: outPoint(
|
||||
clearTxID, 0,
|
||||
),
|
||||
Initiator: lnrpc.Initiator_INITIATOR_LOCAL,
|
||||
Memo: "something",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
privacyFlags: []session.PrivacyFlag{
|
||||
session.ClearPubkeys,
|
||||
session.ClearAmounts,
|
||||
session.ClearChanIDs,
|
||||
},
|
||||
expectedReplacement: &lnrpc.PendingChannelsResponse{
|
||||
PendingOpenChannels: []*lnrpc.PendingChannelsResponse_PendingOpenChannel{
|
||||
{
|
||||
CommitFee: 123,
|
||||
Channel: &lnrpc.PendingChannelsResponse_PendingChannel{
|
||||
RemoteNodePub: "01020304",
|
||||
LocalBalance: 100_000,
|
||||
RemoteBalance: 100_000,
|
||||
Capacity: 120_000,
|
||||
ChannelPoint: outPoint(
|
||||
clearTxID, 0,
|
||||
),
|
||||
Initiator: lnrpc.Initiator_INITIATOR_LOCAL,
|
||||
Memo: "something",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
decodedID := &lnrpc.MacaroonId{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue