@@ -13,6 +13,7 @@ import (
1313 "time"
1414
1515 "github.com/btcsuite/btcd/chaincfg/chainhash"
16+ "github.com/lightninglabs/faraday/frdrpc"
1617 "github.com/lightninglabs/lightning-terminal/firewalldb"
1718 mid "github.com/lightninglabs/lightning-terminal/rpcmiddleware"
1819 "github.com/lightninglabs/lightning-terminal/session"
@@ -535,6 +536,13 @@ func (p *PrivacyMapper) checkers(db firewalldb.PrivacyMapDB,
535536 flags session.PrivacyFlags ) map [string ]mid.RoundTripChecker {
536537
537538 return map [string ]mid.RoundTripChecker {
539+ //nolint:ll
540+ "/frdrpc.FaradayServer/ForwardingAbility" : mid .NewResponseRewriter (
541+ & frdrpc.ForwardingAbilityRequest {},
542+ & frdrpc.ForwardingAbilityResponse {},
543+ handleForwardingAbilityResponse (db , flags ),
544+ mid .PassThroughErrorHandler ,
545+ ),
538546 "/lnrpc.Lightning/GetInfo" : mid .NewResponseRewriter (
539547 & lnrpc.GetInfoRequest {}, & lnrpc.GetInfoResponse {},
540548 handleGetInfoResponse (db , flags ),
@@ -585,7 +593,6 @@ func (p *PrivacyMapper) checkers(db firewalldb.PrivacyMapDB,
585593 handlePendingChannelsResponse (db , flags , p .randIntn ),
586594 mid .PassThroughErrorHandler ,
587595 ),
588-
589596 "/lnrpc.Lightning/BatchOpenChannel" : mid .NewFullRewriter (
590597 & lnrpc.BatchOpenChannelRequest {},
591598 & lnrpc.BatchOpenChannelResponse {},
@@ -600,7 +607,6 @@ func (p *PrivacyMapper) checkers(db firewalldb.PrivacyMapDB,
600607 handleChannelOpenResponse (db , flags ),
601608 mid .PassThroughErrorHandler ,
602609 ),
603-
604610 "/lnrpc.Lightning/ConnectPeer" : mid .NewRequestRewriter (
605611 & lnrpc.ConnectPeerRequest {},
606612 & lnrpc.ConnectPeerResponse {},
@@ -609,6 +615,69 @@ func (p *PrivacyMapper) checkers(db firewalldb.PrivacyMapDB,
609615 }
610616}
611617
618+ func handleForwardingAbilityResponse (db firewalldb.PrivacyMapDB ,
619+ flags session.PrivacyFlags ) func (ctx context.Context ,
620+ r * frdrpc.ForwardingAbilityResponse ) (proto.Message , error ) {
621+
622+ return func (ctx context.Context , r * frdrpc.ForwardingAbilityResponse ) (
623+ proto.Message , error ) {
624+
625+ // When pubkey hiding is disabled or there are no peers to
626+ // obfuscate, pass the response through untouched and avoid
627+ // opening a write transaction.
628+ if flags .Contains (session .ClearPubkeys ) || len (r .Peers ) == 0 {
629+ return r , nil
630+ }
631+
632+ // The response addresses peers by index from a shared peer
633+ // list, so obfuscate each peer in place to keep the entries'
634+ // packed indices valid. The list need not stay sorted because
635+ // decoding resolves peers purely by index.
636+ peers := make ([][]byte , len (r .Peers ))
637+
638+ err := db .Update (ctx , func (ctx context.Context ,
639+ tx firewalldb.PrivacyMapTx ) error {
640+
641+ for i , p := range r .Peers {
642+ // Skip empty pubkeys to avoid storing a
643+ // degenerate empty-to-empty mapping.
644+ if len (p ) == 0 {
645+ peers [i ] = p
646+
647+ continue
648+ }
649+
650+ // Hide the pubkey so a peer maps to the same
651+ // pseudonym across RPCs.
652+ pseudoBytes , err := firewalldb .HideBytes (
653+ ctx , tx , p ,
654+ )
655+ if err != nil {
656+ return err
657+ }
658+
659+ peers [i ] = pseudoBytes
660+ }
661+
662+ return nil
663+ })
664+ if err != nil {
665+ return nil , err
666+ }
667+
668+ // Peers are obfuscated in place, so the index-keyed entries and
669+ // up-but-idle bitmask stay valid and pass through unchanged.
670+ return & frdrpc.ForwardingAbilityResponse {
671+ Peers : peers ,
672+ Entries : r .Entries ,
673+ StartTime : r .StartTime ,
674+ EndTime : r .EndTime ,
675+ UpButIdleBitmask : r .UpButIdleBitmask ,
676+ UptimeThreshold : r .UptimeThreshold ,
677+ }, nil
678+ }
679+ }
680+
612681func handleGetInfoResponse (db firewalldb.PrivacyMapDB ,
613682 flags session.PrivacyFlags ) func (ctx context.Context ,
614683 r * lnrpc.GetInfoResponse ) (proto.Message , error ) {
0 commit comments