Skip to content

Commit d2e2ef6

Browse files
committed
lnwallet: return balance changes rather than modifying references
Here we return the balance deltas from evaluateHTLCView rather than passing in references to variables that will be modified. It is a far cleaner and compositional approach which allows readers of this code to more effectively reason about the code without having to keep the whole codebase in their head.
1 parent 851cf55 commit d2e2ef6

File tree

2 files changed

+63
-65
lines changed

2 files changed

+63
-65
lines changed

lnwallet/channel.go

+58-53
Original file line numberDiff line numberDiff line change
@@ -2893,10 +2893,9 @@ func fundingTxIn(chanState *channeldb.OpenChannel) wire.TxIn {
28932893
// 1. The new htlcView reflecting the current channel state.
28942894
// 2. A Dual of the updates which have not yet been committed in
28952895
// 'whoseCommitChain's commitment chain.
2896-
func (lc *LightningChannel) evaluateHTLCView(view *HtlcView, ourBalance,
2897-
theirBalance *lnwire.MilliSatoshi, nextHeight uint64,
2898-
whoseCommitChain lntypes.ChannelParty) (*HtlcView,
2899-
lntypes.Dual[[]*paymentDescriptor], error) {
2896+
func (lc *LightningChannel) evaluateHTLCView(view *HtlcView,
2897+
whoseCommitChain lntypes.ChannelParty, nextHeight uint64) (*HtlcView,
2898+
lntypes.Dual[[]*paymentDescriptor], lntypes.Dual[int64], error) {
29002899

29012900
// We initialize the view's fee rate to the fee rate of the unfiltered
29022901
// view. If any fee updates are found when evaluating the view, it will
@@ -2929,6 +2928,8 @@ func (lc *LightningChannel) evaluateHTLCView(view *HtlcView, ourBalance,
29292928
Remote: fn.NewSet[uint64](),
29302929
}
29312930

2931+
balanceDeltas := lntypes.Dual[int64]{}
2932+
29322933
parties := [2]lntypes.ChannelParty{lntypes.Local, lntypes.Remote}
29332934
for _, party := range parties {
29342935
// First we run through non-add entries in both logs,
@@ -2949,7 +2950,8 @@ func (lc *LightningChannel) evaluateHTLCView(view *HtlcView, ourBalance,
29492950
entry, whoseCommitChain, party.CounterParty(),
29502951
)
29512952
if err != nil {
2952-
return nil, noUncommitted, err
2953+
noDeltas := lntypes.Dual[int64]{}
2954+
return nil, noUncommitted, noDeltas, err
29532955
}
29542956

29552957
skipSet := skip.GetForParty(party.CounterParty())
@@ -2960,41 +2962,30 @@ func (lc *LightningChannel) evaluateHTLCView(view *HtlcView, ourBalance,
29602962
if rmvHeight == 0 {
29612963
switch {
29622964
// If an incoming HTLC is being settled, then
2963-
// this means that we've received the preimage
2964-
// either from another subsystem, or the
2965-
// upstream peer in the route. Therefore, we
2966-
// increase our balance by the HTLC amount.
2967-
case party.CounterParty() == lntypes.Remote &&
2968-
entry.EntryType == Settle:
2969-
2970-
*ourBalance += entry.Amount
2965+
// this means that the preimage has been
2966+
// received by the settling party Therefore, we
2967+
// increase the settling party's balance by the
2968+
// HTLC amount.
2969+
case entry.EntryType == Settle:
2970+
delta := int64(entry.Amount)
2971+
balanceDeltas.ModifyForParty(
2972+
party,
2973+
func(acc int64) int64 {
2974+
return acc + delta
2975+
},
2976+
)
29712977

29722978
// Otherwise, this HTLC is being failed out,
29732979
// therefore the value of the HTLC should
2974-
// return to the remote party.
2975-
case party.CounterParty() == lntypes.Remote &&
2976-
entry.EntryType != Settle:
2977-
2978-
*theirBalance += entry.Amount
2979-
2980-
// If an outgoing HTLC is being settled, then
2981-
// this means that the downstream party
2982-
// resented the preimage or learned of it via a
2983-
// downstream peer. In either case, we credit
2984-
// their settled value with the value of the
2985-
// HTLC.
2986-
case party.CounterParty() == lntypes.Local &&
2987-
entry.EntryType == Settle:
2988-
2989-
*theirBalance += entry.Amount
2990-
2991-
// Otherwise, one of our outgoing HTLC's has
2992-
// timed out, so the value of the HTLC should
2993-
// be returned to our settled balance.
2994-
case party.CounterParty() == lntypes.Local &&
2995-
entry.EntryType != Settle:
2996-
2997-
*ourBalance += entry.Amount
2980+
// return to the failing party's counterparty.
2981+
case entry.EntryType != Settle:
2982+
delta := int64(entry.Amount)
2983+
balanceDeltas.ModifyForParty(
2984+
party.CounterParty(),
2985+
func(acc int64) int64 {
2986+
return acc + delta
2987+
},
2988+
)
29982989
}
29992990
}
30002991
}
@@ -3015,19 +3006,19 @@ func (lc *LightningChannel) evaluateHTLCView(view *HtlcView, ourBalance,
30153006
addHeights := &entry.addCommitHeights
30163007
addHeight := addHeights.GetForParty(whoseCommitChain)
30173008
if addHeight == 0 {
3018-
if party == lntypes.Remote {
3019-
// If this is a new incoming
3020-
// (un-committed) HTLC, then we need
3021-
// to update their balance accordingly
3022-
// by subtracting the amount of the
3023-
// HTLC that are funds pending.
3024-
*theirBalance -= entry.Amount
3025-
} else {
3026-
// Similarly, we need to debit our
3027-
// balance if this is an out going HTLC
3028-
// to reflect the pending balance.
3029-
*ourBalance -= entry.Amount
3030-
}
3009+
// If this is a new incoming (un-committed)
3010+
// HTLC, then we need to update their balance
3011+
// accordingly by subtracting the amount of
3012+
// the HTLC that are funds pending.
3013+
// Similarly, we need to debit our balance if
3014+
// this is an out going HTLC to reflect the
3015+
// pending balance.
3016+
balanceDeltas.ModifyForParty(
3017+
party,
3018+
func(acc int64) int64 {
3019+
return acc - int64(entry.Amount)
3020+
},
3021+
)
30313022
}
30323023
}
30333024

@@ -3068,7 +3059,7 @@ func (lc *LightningChannel) evaluateHTLCView(view *HtlcView, ourBalance,
30683059
},
30693060
)
30703061

3071-
return newView, uncommittedUpdates, nil
3062+
return newView, uncommittedUpdates, balanceDeltas, nil
30723063
}
30733064

30743065
// fetchParent is a helper that looks up update log parent entries in the
@@ -4589,12 +4580,26 @@ func (lc *LightningChannel) computeView(view *HtlcView,
45894580
// channel constraints to the final commitment state. If any fee
45904581
// updates are found in the logs, the commitment fee rate should be
45914582
// changed, so we'll also set the feePerKw to this new value.
4592-
filteredHTLCView, uncommitted, err := lc.evaluateHTLCView(
4593-
view, &ourBalance, &theirBalance, nextHeight, whoseCommitChain,
4583+
filteredHTLCView, uncommitted, deltas, err := lc.evaluateHTLCView(
4584+
view, whoseCommitChain, nextHeight,
45944585
)
45954586
if err != nil {
45964587
return 0, 0, 0, nil, err
45974588
}
4589+
4590+
// Add the balance deltas to the balances we got from the commitment
4591+
// state.
4592+
if deltas.Local >= 0 {
4593+
ourBalance += lnwire.MilliSatoshi(deltas.Local)
4594+
} else {
4595+
ourBalance -= lnwire.MilliSatoshi(-1 * deltas.Local)
4596+
}
4597+
if deltas.Remote >= 0 {
4598+
theirBalance += lnwire.MilliSatoshi(deltas.Remote)
4599+
} else {
4600+
theirBalance -= lnwire.MilliSatoshi(-1 * deltas.Remote)
4601+
}
4602+
45984603
if updateState {
45994604
state := lc.channelState
46004605
received := &state.TotalMSatReceived

lnwallet/channel_test.go

+5-12
Original file line numberDiff line numberDiff line change
@@ -8953,19 +8953,12 @@ func TestEvaluateView(t *testing.T) {
89538953
FeePerKw: feePerKw,
89548954
}
89558955

8956-
var (
8957-
// Create vars to store balance changes. We do
8958-
// not check these values in this test because
8959-
// balance modification happens on the htlc
8960-
// processing level.
8961-
ourBalance lnwire.MilliSatoshi
8962-
theirBalance lnwire.MilliSatoshi
8963-
)
8964-
89658956
// Evaluate the htlc view, mutate as test expects.
8966-
result, uncommitted, err := lc.evaluateHTLCView(
8967-
view, &ourBalance, &theirBalance, nextHeight,
8968-
test.whoseCommitChain,
8957+
// We do not check the balance deltas in this test
8958+
// because balance modification happens on the htlc
8959+
// processing level.
8960+
result, uncommitted, _, err := lc.evaluateHTLCView(
8961+
view, test.whoseCommitChain, nextHeight,
89698962
)
89708963

89718964
if err != nil {

0 commit comments

Comments
 (0)