Skip to content

Commit 7e3cfe2

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 8b6f69a commit 7e3cfe2

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,
@@ -2947,7 +2948,8 @@ func (lc *LightningChannel) evaluateHTLCView(view *HtlcView, ourBalance,
29472948
entry, whoseCommitChain, party.CounterParty(),
29482949
)
29492950
if err != nil {
2950-
return nil, noUncommitted, err
2951+
noDeltas := lntypes.Dual[int64]{}
2952+
return nil, noUncommitted, noDeltas, err
29512953
}
29522954

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

29712977
// Otherwise, this HTLC is being failed out,
29722978
// therefore the value of the HTLC should
2973-
// return to the remote party.
2974-
case party.CounterParty() == lntypes.Remote &&
2975-
entry.EntryType != Settle:
2976-
2977-
*theirBalance += entry.Amount
2978-
2979-
// If an outgoing HTLC is being settled, then
2980-
// this means that the downstream party
2981-
// resented the preimage or learned of it via a
2982-
// downstream peer. In either case, we credit
2983-
// their settled value with the value of the
2984-
// HTLC.
2985-
case party.CounterParty() == lntypes.Local &&
2986-
entry.EntryType == Settle:
2987-
2988-
*theirBalance += entry.Amount
2989-
2990-
// Otherwise, one of our outgoing HTLC's has
2991-
// timed out, so the value of the HTLC should
2992-
// be returned to our settled balance.
2993-
case party.CounterParty() == lntypes.Local &&
2994-
entry.EntryType != Settle:
2995-
2996-
*ourBalance += entry.Amount
2979+
// return to the failing party's counterparty.
2980+
case entry.EntryType != Settle:
2981+
delta := int64(entry.Amount)
2982+
balanceDeltas.ModifyForParty(
2983+
party.CounterParty(),
2984+
func(acc int64) int64 {
2985+
return acc + delta
2986+
},
2987+
)
29972988
}
29982989
}
29992990
}
@@ -3015,19 +3006,19 @@ func (lc *LightningChannel) evaluateHTLCView(view *HtlcView, ourBalance,
30153006
whoseCommitChain,
30163007
)
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)