Skip to content

Commit a7246e1

Browse files
committed
firewall: obfuscate WalletBalance
1 parent 203d0b7 commit a7246e1

File tree

2 files changed

+179
-20
lines changed

2 files changed

+179
-20
lines changed

firewall/privacy_mapper.go

Lines changed: 113 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,12 @@ func (p *PrivacyMapper) checkers(db firewalldb.PrivacyMapDB,
278278
handleUpdatePolicyResponse(db, flags),
279279
mid.PassThroughErrorHandler,
280280
),
281+
"/lnrpc.Lightning/WalletBalance": mid.NewResponseRewriter(
282+
&lnrpc.WalletBalanceRequest{},
283+
&lnrpc.WalletBalanceResponse{},
284+
handleWalletBalanceResponse(db, flags, p.randIntn),
285+
mid.PassThroughErrorHandler,
286+
),
281287
}
282288
}
283289

@@ -535,21 +541,6 @@ func handleListChannelsResponse(db firewalldb.PrivacyMapDB,
535541
return func(_ context.Context, r *lnrpc.ListChannelsResponse) (
536542
proto.Message, error) {
537543

538-
hideAmount := func(a int64) (int64, error) {
539-
if !flags.Contains(session.ClearAmounts) {
540-
hiddenAmount, err := hideAmount(
541-
randIntn, amountVariation, uint64(a),
542-
)
543-
if err != nil {
544-
return 0, err
545-
}
546-
547-
return int64(hiddenAmount), nil
548-
}
549-
550-
return a, nil
551-
}
552-
553544
hidePubkeys := !flags.Contains(session.ClearPubkeys)
554545
hideChanIds := !flags.Contains(session.ClearChanIDs)
555546

@@ -606,7 +597,9 @@ func handleListChannelsResponse(db firewalldb.PrivacyMapDB,
606597
// state as a non-funder.
607598

608599
// We randomize local/remote balances.
609-
localBalance, err := hideAmount(c.LocalBalance)
600+
localBalance, err := maybeHideAmount(
601+
flags, randIntn, c.LocalBalance,
602+
)
610603
if err != nil {
611604
return err
612605
}
@@ -625,15 +618,16 @@ func handleListChannelsResponse(db firewalldb.PrivacyMapDB,
625618
}
626619

627620
// We hide the total sats sent and received.
628-
satsReceived, err := hideAmount(
621+
satsReceived, err := maybeHideAmount(
622+
flags, randIntn,
629623
c.TotalSatoshisReceived,
630624
)
631625
if err != nil {
632626
return err
633627
}
634628

635-
satsSent, err := hideAmount(
636-
c.TotalSatoshisSent,
629+
satsSent, err := maybeHideAmount(
630+
flags, randIntn, c.TotalSatoshisSent,
637631
)
638632
if err != nil {
639633
return err
@@ -651,7 +645,9 @@ func handleListChannelsResponse(db firewalldb.PrivacyMapDB,
651645
}
652646

653647
// We hide the unsettled balance.
654-
unsettled, err := hideAmount(c.UnsettledBalance)
648+
unsettled, err := maybeHideAmount(
649+
flags, randIntn, c.UnsettledBalance,
650+
)
655651
if err != nil {
656652
return err
657653
}
@@ -812,6 +808,103 @@ func handleUpdatePolicyResponse(db firewalldb.PrivacyMapDB,
812808
}
813809
}
814810

811+
func handleWalletBalanceResponse(_ firewalldb.PrivacyMapDB,
812+
flags session.PrivacyFlags,
813+
randIntn func(int) (int, error)) func(ctx context.Context,
814+
r *lnrpc.WalletBalanceResponse) (proto.Message, error) {
815+
816+
return func(_ context.Context, r *lnrpc.WalletBalanceResponse) (
817+
proto.Message, error) {
818+
819+
totalBalance, err := maybeHideAmount(
820+
flags, randIntn, r.TotalBalance,
821+
)
822+
if err != nil {
823+
return nil, err
824+
}
825+
826+
confirmedBalance, err := maybeHideAmount(
827+
flags, randIntn, r.ConfirmedBalance,
828+
)
829+
if err != nil {
830+
return nil, err
831+
}
832+
833+
unconfirmedBalance, err := maybeHideAmount(
834+
flags, randIntn, r.UnconfirmedBalance,
835+
)
836+
if err != nil {
837+
return nil, err
838+
}
839+
840+
lockedBalance, err := maybeHideAmount(
841+
flags, randIntn, r.LockedBalance,
842+
)
843+
if err != nil {
844+
return nil, err
845+
}
846+
847+
reservedBalanceAnchorChan, err := maybeHideAmount(
848+
flags, randIntn, r.ReservedBalanceAnchorChan,
849+
)
850+
if err != nil {
851+
return nil, err
852+
}
853+
854+
accountBalance := make(
855+
map[string]*lnrpc.WalletAccountBalance,
856+
len(r.AccountBalance),
857+
)
858+
for k, v := range r.AccountBalance {
859+
confirmed, err := maybeHideAmount(
860+
flags, randIntn, v.ConfirmedBalance,
861+
)
862+
if err != nil {
863+
return nil, err
864+
}
865+
866+
unconfirmed, err := maybeHideAmount(
867+
flags, randIntn, v.UnconfirmedBalance,
868+
)
869+
if err != nil {
870+
return nil, err
871+
}
872+
873+
accountBalance[k] = &lnrpc.WalletAccountBalance{
874+
ConfirmedBalance: confirmed,
875+
UnconfirmedBalance: unconfirmed,
876+
}
877+
}
878+
879+
return &lnrpc.WalletBalanceResponse{
880+
TotalBalance: totalBalance,
881+
ConfirmedBalance: confirmedBalance,
882+
UnconfirmedBalance: unconfirmedBalance,
883+
LockedBalance: lockedBalance,
884+
ReservedBalanceAnchorChan: reservedBalanceAnchorChan,
885+
AccountBalance: accountBalance,
886+
}, nil
887+
}
888+
}
889+
890+
// maybeHideAmount hides an amount if the privacy flag is not set.
891+
func maybeHideAmount(flags session.PrivacyFlags, randIntn func(int) (int,
892+
error), a int64) (int64, error) {
893+
894+
if !flags.Contains(session.ClearAmounts) {
895+
hiddenAmount, err := hideAmount(
896+
randIntn, amountVariation, uint64(a),
897+
)
898+
if err != nil {
899+
return 0, err
900+
}
901+
902+
return int64(hiddenAmount), nil
903+
}
904+
905+
return a, nil
906+
}
907+
815908
// hideAmount symmetrically randomizes an amount around a given relative
816909
// variation interval. relativeVariation should be between 0 and 1.
817910
func hideAmount(randIntn func(n int) (int, error), relativeVariation float64,

firewall/privacy_mapper_test.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,72 @@ func TestPrivacyMapper(t *testing.T) {
353353
},
354354
},
355355
},
356+
{
357+
name: "WalletBalance Response",
358+
uri: "/lnrpc.Lightning/WalletBalance",
359+
msgType: rpcperms.TypeResponse,
360+
msg: &lnrpc.WalletBalanceResponse{
361+
TotalBalance: 1_000_000,
362+
ConfirmedBalance: 1_000_000,
363+
UnconfirmedBalance: 1_000_000,
364+
LockedBalance: 1_000_000,
365+
ReservedBalanceAnchorChan: 1_000_000,
366+
AccountBalance: map[string]*lnrpc.WalletAccountBalance{
367+
"first": {
368+
ConfirmedBalance: 1_000_000,
369+
UnconfirmedBalance: 1_000_000,
370+
},
371+
},
372+
},
373+
374+
expectedReplacement: &lnrpc.WalletBalanceResponse{
375+
TotalBalance: 950_100,
376+
ConfirmedBalance: 950_100,
377+
UnconfirmedBalance: 950_100,
378+
LockedBalance: 950_100,
379+
ReservedBalanceAnchorChan: 950_100,
380+
AccountBalance: map[string]*lnrpc.WalletAccountBalance{
381+
"first": {
382+
ConfirmedBalance: 950_100,
383+
UnconfirmedBalance: 950_100,
384+
},
385+
},
386+
},
387+
},
388+
{
389+
name: "WalletBalance Response clear",
390+
uri: "/lnrpc.Lightning/WalletBalance",
391+
msgType: rpcperms.TypeResponse,
392+
msg: &lnrpc.WalletBalanceResponse{
393+
TotalBalance: 1_000_000,
394+
ConfirmedBalance: 1_000_000,
395+
UnconfirmedBalance: 1_000_000,
396+
LockedBalance: 1_000_000,
397+
ReservedBalanceAnchorChan: 1_000_000,
398+
AccountBalance: map[string]*lnrpc.WalletAccountBalance{
399+
"first": {
400+
ConfirmedBalance: 1_000_000,
401+
UnconfirmedBalance: 1_000_000,
402+
},
403+
},
404+
},
405+
privacyFlags: []session.PrivacyFlag{
406+
session.ClearAmounts,
407+
},
408+
expectedReplacement: &lnrpc.WalletBalanceResponse{
409+
TotalBalance: 1_000_000,
410+
ConfirmedBalance: 1_000_000,
411+
UnconfirmedBalance: 1_000_000,
412+
LockedBalance: 1_000_000,
413+
ReservedBalanceAnchorChan: 1_000_000,
414+
AccountBalance: map[string]*lnrpc.WalletAccountBalance{
415+
"first": {
416+
ConfirmedBalance: 1_000_000,
417+
UnconfirmedBalance: 1_000_000,
418+
},
419+
},
420+
},
421+
},
356422
}
357423

358424
decodedID := &lnrpc.MacaroonId{

0 commit comments

Comments
 (0)