Skip to content

Commit 238720a

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 ea70103 commit 238720a

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
@@ -2928,6 +2927,8 @@ func (lc *LightningChannel) evaluateHTLCView(view *HtlcView, ourBalance,
29282927
Remote: fn.NewSet[uint64](),
29292928
}
29302929

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

29542956
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
}
@@ -3014,19 +3005,19 @@ func (lc *LightningChannel) evaluateHTLCView(view *HtlcView, ourBalance,
30143005
addHeights := &entry.addCommitHeights
30153006
addHeight := addHeights.GetForParty(whoseCommitChain)
30163007
if addHeight == 0 {
3017-
if party == lntypes.Remote {
3018-
// If this is a new incoming
3019-
// (un-committed) HTLC, then we need
3020-
// to update their balance accordingly
3021-
// by subtracting the amount of the
3022-
// HTLC that are funds pending.
3023-
*theirBalance -= entry.Amount
3024-
} else {
3025-
// Similarly, we need to debit our
3026-
// balance if this is an out going HTLC
3027-
// to reflect the pending balance.
3028-
*ourBalance -= entry.Amount
3029-
}
3008+
// If this is a new incoming (un-committed)
3009+
// HTLC, then we need to update their balance
3010+
// accordingly by subtracting the amount of
3011+
// the HTLC that are funds pending.
3012+
// Similarly, we need to debit our balance if
3013+
// this is an out going HTLC to reflect the
3014+
// pending balance.
3015+
balanceDeltas.ModifyForParty(
3016+
party,
3017+
func(acc int64) int64 {
3018+
return acc - int64(entry.Amount)
3019+
},
3020+
)
30303021
}
30313022
}
30323023

@@ -3067,7 +3058,7 @@ func (lc *LightningChannel) evaluateHTLCView(view *HtlcView, ourBalance,
30673058
},
30683059
)
30693060

3070-
return newView, uncommittedUpdates, nil
3061+
return newView, uncommittedUpdates, balanceDeltas, nil
30713062
}
30723063

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