Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/release-notes/release-notes-0.17.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@
-V`](https://github.com/lightninglabs/lightning-terminal/pull/1337): The `-V`
flag now prints litd's version instead of the integrated lnd version.

* [Refactor privacy mapper to prevent 32-bit truncation and optimize
allocations](https://github.com/lightninglabs/lightning-terminal/pull/1358):
Refactored the privacy mapper's random number generation to use `int64`
instead of `int` to prevent architecture-dependent truncation on 32-bit
runtimes, and introduced a `sync.Pool` for `*big.Int` to optimize allocations.

## RPC Updates

## Integrated Binary Updates
Expand Down
69 changes: 48 additions & 21 deletions firewall/privacy_mapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import (
"encoding/json"
"errors"
"fmt"
"math"
"math/big"
"strconv"
"strings"
"sync"
"time"

"github.com/btcsuite/btcd/chaincfg/chainhash"
Expand Down Expand Up @@ -61,14 +63,14 @@ var _ mid.RequestInterceptor = (*PrivacyMapper)(nil)
// requests to their real values and vice versa for responses.
type PrivacyMapper struct {
db firewalldb.PrivacyMapper
randIntn func(int) (int, error)
randIntn func(int64) (int64, error)
sessionDB firewalldb.SessionDB
}

// NewPrivacyMapper returns a new instance of PrivacyMapper. The randIntn
// function is used to draw randomness for request field obfuscation.
func NewPrivacyMapper(newDB firewalldb.PrivacyMapper,
randIntn func(int) (int, error),
randIntn func(int64) (int64, error),
sessionDB firewalldb.SessionDB) *PrivacyMapper {

return &PrivacyMapper{
Expand Down Expand Up @@ -379,7 +381,7 @@ func handleGetInfoResponse(db firewalldb.PrivacyMapDB,

func handleFwdHistoryResponse(db firewalldb.PrivacyMapDB,
flags session.PrivacyFlags,
randIntn func(int) (int, error)) func(ctx context.Context,
randIntn func(int64) (int64, error)) func(ctx context.Context,
r *lnrpc.ForwardingHistoryResponse) (proto.Message, error) {

return func(ctx context.Context, r *lnrpc.ForwardingHistoryResponse) (
Expand Down Expand Up @@ -582,7 +584,7 @@ func handleListChannelsRequest(db firewalldb.PrivacyMapDB,

func handleListChannelsResponse(db firewalldb.PrivacyMapDB,
flags session.PrivacyFlags,
randIntn func(int) (int, error)) func(ctx context.Context,
randIntn func(int64) (int64, error)) func(ctx context.Context,
r *lnrpc.ListChannelsResponse) (proto.Message, error) {

return func(ctx context.Context, r *lnrpc.ListChannelsResponse) (
Expand Down Expand Up @@ -866,7 +868,7 @@ func handleUpdatePolicyResponse(db firewalldb.PrivacyMapDB,

func handleWalletBalanceResponse(_ firewalldb.PrivacyMapDB,
flags session.PrivacyFlags,
randIntn func(int) (int, error)) func(ctx context.Context,
randIntn func(int64) (int64, error)) func(ctx context.Context,
r *lnrpc.WalletBalanceResponse) (proto.Message, error) {

return func(_ context.Context, r *lnrpc.WalletBalanceResponse) (
Expand Down Expand Up @@ -945,7 +947,7 @@ func handleWalletBalanceResponse(_ firewalldb.PrivacyMapDB,

func handleClosedChannelsResponse(db firewalldb.PrivacyMapDB,
flags session.PrivacyFlags,
randIntn func(int) (int, error)) func(ctx context.Context,
randIntn func(int64) (int64, error)) func(ctx context.Context,
r *lnrpc.ClosedChannelsResponse) (proto.Message, error) {

return func(ctx context.Context, r *lnrpc.ClosedChannelsResponse) (
Expand Down Expand Up @@ -1065,7 +1067,7 @@ func handleClosedChannelsResponse(db firewalldb.PrivacyMapDB,
// channel.
func obfuscatePendingChannel(ctx context.Context,
c *lnrpc.PendingChannelsResponse_PendingChannel,
tx firewalldb.PrivacyMapTx, randIntn func(int) (int, error),
tx firewalldb.PrivacyMapTx, randIntn func(int64) (int64, error),
flags session.PrivacyFlags) (
*lnrpc.PendingChannelsResponse_PendingChannel, error) {

Expand Down Expand Up @@ -1142,7 +1144,7 @@ func obfuscatePendingChannel(ctx context.Context,

func handlePendingChannelsResponse(db firewalldb.PrivacyMapDB,
flags session.PrivacyFlags,
randIntn func(int) (int, error)) func(ctx context.Context,
randIntn func(int64) (int64, error)) func(ctx context.Context,
r *lnrpc.PendingChannelsResponse) (proto.Message, error) {

return func(ctx context.Context, r *lnrpc.PendingChannelsResponse) (
Expand Down Expand Up @@ -1729,7 +1731,7 @@ func handleConnectPeerRequest(db firewalldb.PrivacyMapDB,
}

// maybeHideAmount hides an amount if the privacy flag is not set.
func maybeHideAmount(flags session.PrivacyFlags, randIntn func(int) (int,
func maybeHideAmount(flags session.PrivacyFlags, randIntn func(int64) (int64,
error), a int64) (int64, error) {

if !flags.Contains(session.ClearAmounts) {
Expand All @@ -1748,15 +1750,20 @@ func maybeHideAmount(flags session.PrivacyFlags, randIntn func(int) (int,

// hideAmount symmetrically randomizes an amount around a given relative
// variation interval. relativeVariation should be between 0 and 1.
func hideAmount(randIntn func(n int) (int, error), relativeVariation float64,
amount uint64) (uint64, error) {
func hideAmount(randIntn func(n int64) (int64, error),
relativeVariation float64, amount uint64) (uint64, error) {

if relativeVariation < 0 || relativeVariation > 1 {
return 0, fmt.Errorf("hide amount: relative variation is not "+
"between allowed bounds of [0, 1], is %v",
relativeVariation)
}

if amount > math.MaxInt64 {
return 0, fmt.Errorf("hide amount: amount %d overflows "+
"int64", amount)
}
Comment thread
bitromortac marked this conversation as resolved.

if amount == 0 {
return 0, nil
}
Expand All @@ -1765,8 +1772,13 @@ func hideAmount(randIntn func(n int) (int, error), relativeVariation float64,
// between 0 and 1.
fuzzInterval := uint64(float64(amount) * relativeVariation)

amountMin := int(amount - fuzzInterval)
amountMax := int(amount + fuzzInterval)
if amount+fuzzInterval > math.MaxInt64 {
return 0, fmt.Errorf("hide amount: amount %d with variation "+
"overflows int64", amount)
}

amountMin := int64(amount - fuzzInterval)
amountMax := int64(amount + fuzzInterval)

randAmount, err := randBetween(randIntn, amountMin, amountMax)
if err != nil {
Expand All @@ -1778,7 +1790,7 @@ func hideAmount(randIntn func(n int) (int, error), relativeVariation float64,

// hideTimestamp symmetrically randomizes a unix timestamp given an absolute
// variation interval. The random input is expected to be rand.Intn.
func hideTimestamp(randIntn func(n int) (int, error),
func hideTimestamp(randIntn func(n int64) (int64, error),
absoluteVariation time.Duration,
timestamp time.Time) (time.Time, error) {

Expand All @@ -1802,18 +1814,20 @@ func hideTimestamp(randIntn func(n int) (int, error),
timeMax := timestamp.Add(absoluteVariation)

timeNs, err := randBetween(
randIntn, int(timeMin.UnixNano()), int(timeMax.UnixNano()),
randIntn, timeMin.UnixNano(), timeMax.UnixNano(),
)
if err != nil {
return time.Time{}, err
}

return time.Unix(0, int64(timeNs)), nil
return time.Unix(0, timeNs), nil
}

// randBetween generates a random number between [min, max) given a source of
// randomness.
func randBetween(randIntn func(int) (int, error), min, max int) (int, error) {
func randBetween(randIntn func(int64) (int64, error),
min, max int64) (int64, error) {

if max < min {
return 0, fmt.Errorf("min is not allowed to be greater than "+
"max, (min: %v, max: %v)", min, max)
Expand All @@ -1833,7 +1847,7 @@ func randBetween(randIntn func(int) (int, error), min, max int) (int, error) {
}

// hideBool generates a random bool given a random input.
func hideBool(randIntn func(n int) (int, error)) (bool, error) {
func hideBool(randIntn func(n int64) (int64, error)) (bool, error) {
random, err := randIntn(2)
if err != nil {
return false, err
Expand All @@ -1844,18 +1858,31 @@ func hideBool(randIntn func(n int) (int, error)) (bool, error) {
return random >= 1, nil
}

// bigIntPool is a pool of *big.Int values to avoid frequent heap allocations in
// CryptoRandIntn.
var bigIntPool = sync.Pool{
New: func() any {
return new(big.Int)
},
}

// CryptoRandIntn generates a random number between [0, n).
func CryptoRandIntn(n int) (int, error) {
func CryptoRandIntn(n int64) (int64, error) {
if n == 0 {
return 0, nil
}

nBig, err := rand.Int(rand.Reader, big.NewInt(int64(n)))
nBig := bigIntPool.Get().(*big.Int)
defer bigIntPool.Put(nBig)

nBig.SetInt64(n)

randBig, err := rand.Int(rand.Reader, nBig)
if err != nil {
return 0, err
}

return int(nBig.Int64()), nil
return randBig.Int64(), nil
}

// ObfuscateConfig alters the config string by replacing sensitive data with
Expand Down
Loading
Loading