Merge pull request #9097 from ProofOfKeags/refactor/evaluate-htlc-view
[KILO]: DynComms Prefactor: Refactor/evaluate htlc view
This commit is contained in:
9 files changed
+429
-974
No files matched your search
@@ -35,7 +35,7 @@ require (
|
|||||||
github.com/lightningnetwork/lightning-onion v1.2.1-0.20240712235311-98bd56499dfb
|
github.com/lightningnetwork/lightning-onion v1.2.1-0.20240712235311-98bd56499dfb
|
||||||
github.com/lightningnetwork/lnd/cert v1.2.2
|
github.com/lightningnetwork/lnd/cert v1.2.2
|
||||||
github.com/lightningnetwork/lnd/clock v1.1.1
|
github.com/lightningnetwork/lnd/clock v1.1.1
|
||||||
github.com/lightningnetwork/lnd/fn v1.2.1
|
github.com/lightningnetwork/lnd/fn v1.2.2
|
||||||
github.com/lightningnetwork/lnd/healthcheck v1.2.5
|
github.com/lightningnetwork/lnd/healthcheck v1.2.5
|
||||||
github.com/lightningnetwork/lnd/kvdb v1.4.10
|
github.com/lightningnetwork/lnd/kvdb v1.4.10
|
||||||
github.com/lightningnetwork/lnd/queue v1.1.1
|
github.com/lightningnetwork/lnd/queue v1.1.1
|
||||||
|
|||||||
@@ -453,8 +453,8 @@ github.com/lightningnetwork/lnd/cert v1.2.2 h1:71YK6hogeJtxSxw2teq3eGeuy4rHGKcFf
|
|||||||
github.com/lightningnetwork/lnd/cert v1.2.2/go.mod h1:jQmFn/Ez4zhDgq2hnYSw8r35bqGVxViXhX6Cd7HXM6U=
|
github.com/lightningnetwork/lnd/cert v1.2.2/go.mod h1:jQmFn/Ez4zhDgq2hnYSw8r35bqGVxViXhX6Cd7HXM6U=
|
||||||
github.com/lightningnetwork/lnd/clock v1.1.1 h1:OfR3/zcJd2RhH0RU+zX/77c0ZiOnIMsDIBjgjWdZgA0=
|
github.com/lightningnetwork/lnd/clock v1.1.1 h1:OfR3/zcJd2RhH0RU+zX/77c0ZiOnIMsDIBjgjWdZgA0=
|
||||||
github.com/lightningnetwork/lnd/clock v1.1.1/go.mod h1:mGnAhPyjYZQJmebS7aevElXKTFDuO+uNFFfMXK1W8xQ=
|
github.com/lightningnetwork/lnd/clock v1.1.1/go.mod h1:mGnAhPyjYZQJmebS7aevElXKTFDuO+uNFFfMXK1W8xQ=
|
||||||
github.com/lightningnetwork/lnd/fn v1.2.1 h1:pPsVGrwi9QBwdLJzaEGK33wmiVKOxs/zc8H7+MamFf0=
|
github.com/lightningnetwork/lnd/fn v1.2.2 h1:rVtmGW1cQTmYce2XdUbRcc5qLDxqu+aQ6IGRpyspakk=
|
||||||
github.com/lightningnetwork/lnd/fn v1.2.1/go.mod h1:SyFohpVrARPKH3XVAJZlXdVe+IwMYc4OMAvrDY32kw0=
|
github.com/lightningnetwork/lnd/fn v1.2.2/go.mod h1:SyFohpVrARPKH3XVAJZlXdVe+IwMYc4OMAvrDY32kw0=
|
||||||
github.com/lightningnetwork/lnd/healthcheck v1.2.5 h1:aTJy5xeBpcWgRtW/PGBDe+LMQEmNm/HQewlQx2jt7OA=
|
github.com/lightningnetwork/lnd/healthcheck v1.2.5 h1:aTJy5xeBpcWgRtW/PGBDe+LMQEmNm/HQewlQx2jt7OA=
|
||||||
github.com/lightningnetwork/lnd/healthcheck v1.2.5/go.mod h1:G7Tst2tVvWo7cx6mSBEToQC5L1XOGxzZTPB29g9Rv2I=
|
github.com/lightningnetwork/lnd/healthcheck v1.2.5/go.mod h1:G7Tst2tVvWo7cx6mSBEToQC5L1XOGxzZTPB29g9Rv2I=
|
||||||
github.com/lightningnetwork/lnd/kvdb v1.4.10 h1:vK89IVv1oVH9ubQWU+EmoCQFeVRaC8kfmOrqHbY5zoY=
|
github.com/lightningnetwork/lnd/kvdb v1.4.10 h1:vK89IVv1oVH9ubQWU+EmoCQFeVRaC8kfmOrqHbY5zoY=
|
||||||
|
|||||||
@@ -117,3 +117,5 @@ func MapDual[A, B any](d Dual[A], f func(A) B) Dual[B] {
|
|||||||
Remote: f(d.Remote),
|
Remote: f(d.Remote),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var BothParties []ChannelParty = []ChannelParty{Local, Remote}
|
||||||
@@ -109,10 +109,10 @@ func newAuxHtlcDescriptor(p *paymentDescriptor) AuxHtlcDescriptor {
|
|||||||
ParentIndex: p.ParentIndex,
|
ParentIndex: p.ParentIndex,
|
||||||
EntryType: p.EntryType,
|
EntryType: p.EntryType,
|
||||||
CustomRecords: p.CustomRecords.Copy(),
|
CustomRecords: p.CustomRecords.Copy(),
|
||||||
addCommitHeightRemote: p.addCommitHeightRemote,
|
addCommitHeightRemote: p.addCommitHeights.Remote,
|
||||||
addCommitHeightLocal: p.addCommitHeightLocal,
|
addCommitHeightLocal: p.addCommitHeights.Local,
|
||||||
removeCommitHeightRemote: p.removeCommitHeightRemote,
|
removeCommitHeightRemote: p.removeCommitHeights.Remote,
|
||||||
removeCommitHeightLocal: p.removeCommitHeightLocal,
|
removeCommitHeightLocal: p.removeCommitHeights.Local,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+272
-295
@@ -1087,10 +1087,12 @@ func (lc *LightningChannel) logUpdateToPayDesc(logUpdate *channeldb.LogUpdate,
|
|||||||
EntryType: Add,
|
EntryType: Add,
|
||||||
HtlcIndex: wireMsg.ID,
|
HtlcIndex: wireMsg.ID,
|
||||||
LogIndex: logUpdate.LogIndex,
|
LogIndex: logUpdate.LogIndex,
|
||||||
addCommitHeightRemote: commitHeight,
|
|
||||||
OnionBlob: wireMsg.OnionBlob,
|
OnionBlob: wireMsg.OnionBlob,
|
||||||
BlindingPoint: wireMsg.BlindingPoint,
|
BlindingPoint: wireMsg.BlindingPoint,
|
||||||
CustomRecords: wireMsg.CustomRecords.Copy(),
|
CustomRecords: wireMsg.CustomRecords.Copy(),
|
||||||
|
addCommitHeights: lntypes.Dual[uint64]{
|
||||||
|
Remote: commitHeight,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
isDustRemote := HtlcIsDust(
|
isDustRemote := HtlcIsDust(
|
||||||
@@ -1132,7 +1134,9 @@ func (lc *LightningChannel) logUpdateToPayDesc(logUpdate *channeldb.LogUpdate,
|
|||||||
LogIndex: logUpdate.LogIndex,
|
LogIndex: logUpdate.LogIndex,
|
||||||
ParentIndex: ogHTLC.HtlcIndex,
|
ParentIndex: ogHTLC.HtlcIndex,
|
||||||
EntryType: Settle,
|
EntryType: Settle,
|
||||||
removeCommitHeightRemote: commitHeight,
|
removeCommitHeights: lntypes.Dual[uint64]{
|
||||||
|
Remote: commitHeight,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we sent a failure for a prior incoming HTLC, then we'll consult
|
// If we sent a failure for a prior incoming HTLC, then we'll consult
|
||||||
@@ -1150,7 +1154,9 @@ func (lc *LightningChannel) logUpdateToPayDesc(logUpdate *channeldb.LogUpdate,
|
|||||||
LogIndex: logUpdate.LogIndex,
|
LogIndex: logUpdate.LogIndex,
|
||||||
EntryType: Fail,
|
EntryType: Fail,
|
||||||
FailReason: wireMsg.Reason[:],
|
FailReason: wireMsg.Reason[:],
|
||||||
removeCommitHeightRemote: commitHeight,
|
removeCommitHeights: lntypes.Dual[uint64]{
|
||||||
|
Remote: commitHeight,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTLC fails due to malformed onion blobs are treated the exact same
|
// HTLC fails due to malformed onion blobs are treated the exact same
|
||||||
@@ -1168,7 +1174,9 @@ func (lc *LightningChannel) logUpdateToPayDesc(logUpdate *channeldb.LogUpdate,
|
|||||||
EntryType: MalformedFail,
|
EntryType: MalformedFail,
|
||||||
FailCode: wireMsg.FailureCode,
|
FailCode: wireMsg.FailureCode,
|
||||||
ShaOnionBlob: wireMsg.ShaOnionBlob,
|
ShaOnionBlob: wireMsg.ShaOnionBlob,
|
||||||
removeCommitHeightRemote: commitHeight,
|
removeCommitHeights: lntypes.Dual[uint64]{
|
||||||
|
Remote: commitHeight,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// For fee updates we'll create a FeeUpdate type to add to the log. We
|
// For fee updates we'll create a FeeUpdate type to add to the log. We
|
||||||
@@ -1185,8 +1193,12 @@ func (lc *LightningChannel) logUpdateToPayDesc(logUpdate *channeldb.LogUpdate,
|
|||||||
btcutil.Amount(wireMsg.FeePerKw),
|
btcutil.Amount(wireMsg.FeePerKw),
|
||||||
),
|
),
|
||||||
EntryType: FeeUpdate,
|
EntryType: FeeUpdate,
|
||||||
addCommitHeightRemote: commitHeight,
|
addCommitHeights: lntypes.Dual[uint64]{
|
||||||
removeCommitHeightRemote: commitHeight,
|
Remote: commitHeight,
|
||||||
|
},
|
||||||
|
removeCommitHeights: lntypes.Dual[uint64]{
|
||||||
|
Remote: commitHeight,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1223,7 +1235,9 @@ func (lc *LightningChannel) localLogUpdateToPayDesc(logUpdate *channeldb.LogUpda
|
|||||||
LogIndex: logUpdate.LogIndex,
|
LogIndex: logUpdate.LogIndex,
|
||||||
ParentIndex: ogHTLC.HtlcIndex,
|
ParentIndex: ogHTLC.HtlcIndex,
|
||||||
EntryType: Settle,
|
EntryType: Settle,
|
||||||
removeCommitHeightRemote: commitHeight,
|
removeCommitHeights: lntypes.Dual[uint64]{
|
||||||
|
Remote: commitHeight,
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
// If we sent a failure for a prior incoming HTLC, then we'll consult the
|
// If we sent a failure for a prior incoming HTLC, then we'll consult the
|
||||||
@@ -1240,7 +1254,9 @@ func (lc *LightningChannel) localLogUpdateToPayDesc(logUpdate *channeldb.LogUpda
|
|||||||
LogIndex: logUpdate.LogIndex,
|
LogIndex: logUpdate.LogIndex,
|
||||||
EntryType: Fail,
|
EntryType: Fail,
|
||||||
FailReason: wireMsg.Reason[:],
|
FailReason: wireMsg.Reason[:],
|
||||||
removeCommitHeightRemote: commitHeight,
|
removeCommitHeights: lntypes.Dual[uint64]{
|
||||||
|
Remote: commitHeight,
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
// HTLC fails due to malformed onion blocks are treated the exact same
|
// HTLC fails due to malformed onion blocks are treated the exact same
|
||||||
@@ -1257,7 +1273,9 @@ func (lc *LightningChannel) localLogUpdateToPayDesc(logUpdate *channeldb.LogUpda
|
|||||||
EntryType: MalformedFail,
|
EntryType: MalformedFail,
|
||||||
FailCode: wireMsg.FailureCode,
|
FailCode: wireMsg.FailureCode,
|
||||||
ShaOnionBlob: wireMsg.ShaOnionBlob,
|
ShaOnionBlob: wireMsg.ShaOnionBlob,
|
||||||
removeCommitHeightRemote: commitHeight,
|
removeCommitHeights: lntypes.Dual[uint64]{
|
||||||
|
Remote: commitHeight,
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
case *lnwire.UpdateFee:
|
case *lnwire.UpdateFee:
|
||||||
@@ -1268,8 +1286,12 @@ func (lc *LightningChannel) localLogUpdateToPayDesc(logUpdate *channeldb.LogUpda
|
|||||||
btcutil.Amount(wireMsg.FeePerKw),
|
btcutil.Amount(wireMsg.FeePerKw),
|
||||||
),
|
),
|
||||||
EntryType: FeeUpdate,
|
EntryType: FeeUpdate,
|
||||||
addCommitHeightRemote: commitHeight,
|
addCommitHeights: lntypes.Dual[uint64]{
|
||||||
removeCommitHeightRemote: commitHeight,
|
Remote: commitHeight,
|
||||||
|
},
|
||||||
|
removeCommitHeights: lntypes.Dual[uint64]{
|
||||||
|
Remote: commitHeight,
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -1301,10 +1323,12 @@ func (lc *LightningChannel) remoteLogUpdateToPayDesc(logUpdate *channeldb.LogUpd
|
|||||||
EntryType: Add,
|
EntryType: Add,
|
||||||
HtlcIndex: wireMsg.ID,
|
HtlcIndex: wireMsg.ID,
|
||||||
LogIndex: logUpdate.LogIndex,
|
LogIndex: logUpdate.LogIndex,
|
||||||
addCommitHeightLocal: commitHeight,
|
|
||||||
OnionBlob: wireMsg.OnionBlob,
|
OnionBlob: wireMsg.OnionBlob,
|
||||||
BlindingPoint: wireMsg.BlindingPoint,
|
BlindingPoint: wireMsg.BlindingPoint,
|
||||||
CustomRecords: wireMsg.CustomRecords.Copy(),
|
CustomRecords: wireMsg.CustomRecords.Copy(),
|
||||||
|
addCommitHeights: lntypes.Dual[uint64]{
|
||||||
|
Local: commitHeight,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't need to generate an htlc script yet. This will be
|
// We don't need to generate an htlc script yet. This will be
|
||||||
@@ -1326,7 +1350,9 @@ func (lc *LightningChannel) remoteLogUpdateToPayDesc(logUpdate *channeldb.LogUpd
|
|||||||
LogIndex: logUpdate.LogIndex,
|
LogIndex: logUpdate.LogIndex,
|
||||||
ParentIndex: ogHTLC.HtlcIndex,
|
ParentIndex: ogHTLC.HtlcIndex,
|
||||||
EntryType: Settle,
|
EntryType: Settle,
|
||||||
removeCommitHeightLocal: commitHeight,
|
removeCommitHeights: lntypes.Dual[uint64]{
|
||||||
|
Local: commitHeight,
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
// If we received a failure for a prior outgoing HTLC, then we'll
|
// If we received a failure for a prior outgoing HTLC, then we'll
|
||||||
@@ -1343,7 +1369,9 @@ func (lc *LightningChannel) remoteLogUpdateToPayDesc(logUpdate *channeldb.LogUpd
|
|||||||
LogIndex: logUpdate.LogIndex,
|
LogIndex: logUpdate.LogIndex,
|
||||||
EntryType: Fail,
|
EntryType: Fail,
|
||||||
FailReason: wireMsg.Reason[:],
|
FailReason: wireMsg.Reason[:],
|
||||||
removeCommitHeightLocal: commitHeight,
|
removeCommitHeights: lntypes.Dual[uint64]{
|
||||||
|
Local: commitHeight,
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
// HTLC fails due to malformed onion blobs are treated the exact same
|
// HTLC fails due to malformed onion blobs are treated the exact same
|
||||||
@@ -1360,7 +1388,9 @@ func (lc *LightningChannel) remoteLogUpdateToPayDesc(logUpdate *channeldb.LogUpd
|
|||||||
EntryType: MalformedFail,
|
EntryType: MalformedFail,
|
||||||
FailCode: wireMsg.FailureCode,
|
FailCode: wireMsg.FailureCode,
|
||||||
ShaOnionBlob: wireMsg.ShaOnionBlob,
|
ShaOnionBlob: wireMsg.ShaOnionBlob,
|
||||||
removeCommitHeightLocal: commitHeight,
|
removeCommitHeights: lntypes.Dual[uint64]{
|
||||||
|
Local: commitHeight,
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
// For fee updates we'll create a FeeUpdate type to add to the log. We
|
// For fee updates we'll create a FeeUpdate type to add to the log. We
|
||||||
@@ -1377,8 +1407,12 @@ func (lc *LightningChannel) remoteLogUpdateToPayDesc(logUpdate *channeldb.LogUpd
|
|||||||
btcutil.Amount(wireMsg.FeePerKw),
|
btcutil.Amount(wireMsg.FeePerKw),
|
||||||
),
|
),
|
||||||
EntryType: FeeUpdate,
|
EntryType: FeeUpdate,
|
||||||
addCommitHeightLocal: commitHeight,
|
addCommitHeights: lntypes.Dual[uint64]{
|
||||||
removeCommitHeightLocal: commitHeight,
|
Local: commitHeight,
|
||||||
|
},
|
||||||
|
removeCommitHeights: lntypes.Dual[uint64]{
|
||||||
|
Local: commitHeight,
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -1611,8 +1645,9 @@ func (lc *LightningChannel) restoreStateLogs(
|
|||||||
// map we created earlier. Note that if this HTLC is not in
|
// map we created earlier. Note that if this HTLC is not in
|
||||||
// incomingRemoteAddHeights, the remote add height will be set
|
// incomingRemoteAddHeights, the remote add height will be set
|
||||||
// to zero, which indicates that it is not added yet.
|
// to zero, which indicates that it is not added yet.
|
||||||
htlc.addCommitHeightLocal = localCommitment.height
|
htlc.addCommitHeights.Local = localCommitment.height
|
||||||
htlc.addCommitHeightRemote = incomingRemoteAddHeights[htlc.HtlcIndex]
|
htlc.addCommitHeights.Remote =
|
||||||
|
incomingRemoteAddHeights[htlc.HtlcIndex]
|
||||||
|
|
||||||
// Restore the htlc back to the remote log.
|
// Restore the htlc back to the remote log.
|
||||||
lc.updateLogs.Remote.restoreHtlc(&htlc)
|
lc.updateLogs.Remote.restoreHtlc(&htlc)
|
||||||
@@ -1626,8 +1661,9 @@ func (lc *LightningChannel) restoreStateLogs(
|
|||||||
// As for the incoming HTLCs, we'll use the current remote
|
// As for the incoming HTLCs, we'll use the current remote
|
||||||
// commit height as remote add height, and consult the map
|
// commit height as remote add height, and consult the map
|
||||||
// created above for the local add height.
|
// created above for the local add height.
|
||||||
htlc.addCommitHeightRemote = remoteCommitment.height
|
htlc.addCommitHeights.Remote = remoteCommitment.height
|
||||||
htlc.addCommitHeightLocal = outgoingLocalAddHeights[htlc.HtlcIndex]
|
htlc.addCommitHeights.Local =
|
||||||
|
outgoingLocalAddHeights[htlc.HtlcIndex]
|
||||||
|
|
||||||
// Restore the htlc back to the local log.
|
// Restore the htlc back to the local log.
|
||||||
lc.updateLogs.Local.restoreHtlc(&htlc)
|
lc.updateLogs.Local.restoreHtlc(&htlc)
|
||||||
@@ -1722,15 +1758,15 @@ func (lc *LightningChannel) restorePendingRemoteUpdates(
|
|||||||
switch payDesc.EntryType {
|
switch payDesc.EntryType {
|
||||||
case FeeUpdate:
|
case FeeUpdate:
|
||||||
if heightSet {
|
if heightSet {
|
||||||
payDesc.addCommitHeightRemote = height
|
payDesc.addCommitHeights.Remote = height
|
||||||
payDesc.removeCommitHeightRemote = height
|
payDesc.removeCommitHeights.Remote = height
|
||||||
}
|
}
|
||||||
|
|
||||||
lc.updateLogs.Remote.restoreUpdate(payDesc)
|
lc.updateLogs.Remote.restoreUpdate(payDesc)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if heightSet {
|
if heightSet {
|
||||||
payDesc.removeCommitHeightRemote = height
|
payDesc.removeCommitHeights.Remote = height
|
||||||
}
|
}
|
||||||
|
|
||||||
lc.updateLogs.Remote.restoreUpdate(payDesc)
|
lc.updateLogs.Remote.restoreUpdate(payDesc)
|
||||||
@@ -2639,11 +2675,8 @@ type HtlcView struct {
|
|||||||
// created using this view.
|
// created using this view.
|
||||||
NextHeight uint64
|
NextHeight uint64
|
||||||
|
|
||||||
// OurUpdates are our outgoing HTLCs.
|
// Updates is a Dual of the Local and Remote HTLCs.
|
||||||
OurUpdates []*paymentDescriptor
|
Updates lntypes.Dual[[]*paymentDescriptor]
|
||||||
|
|
||||||
// TheirUpdates are their incoming HTLCs.
|
|
||||||
TheirUpdates []*paymentDescriptor
|
|
||||||
|
|
||||||
// FeePerKw is the fee rate in sat/kw of the commitment transaction.
|
// FeePerKw is the fee rate in sat/kw of the commitment transaction.
|
||||||
FeePerKw chainfee.SatPerKWeight
|
FeePerKw chainfee.SatPerKWeight
|
||||||
@@ -2652,13 +2685,13 @@ type HtlcView struct {
|
|||||||
// AuxOurUpdates returns the outgoing HTLCs as a read-only copy of
|
// AuxOurUpdates returns the outgoing HTLCs as a read-only copy of
|
||||||
// AuxHtlcDescriptors.
|
// AuxHtlcDescriptors.
|
||||||
func (v *HtlcView) AuxOurUpdates() []AuxHtlcDescriptor {
|
func (v *HtlcView) AuxOurUpdates() []AuxHtlcDescriptor {
|
||||||
return fn.Map(newAuxHtlcDescriptor, v.OurUpdates)
|
return fn.Map(newAuxHtlcDescriptor, v.Updates.Local)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AuxTheirUpdates returns the incoming HTLCs as a read-only copy of
|
// AuxTheirUpdates returns the incoming HTLCs as a read-only copy of
|
||||||
// AuxHtlcDescriptors.
|
// AuxHtlcDescriptors.
|
||||||
func (v *HtlcView) AuxTheirUpdates() []AuxHtlcDescriptor {
|
func (v *HtlcView) AuxTheirUpdates() []AuxHtlcDescriptor {
|
||||||
return fn.Map(newAuxHtlcDescriptor, v.TheirUpdates)
|
return fn.Map(newAuxHtlcDescriptor, v.Updates.Remote)
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetchHTLCView returns all the candidate HTLC updates which should be
|
// fetchHTLCView returns all the candidate HTLC updates which should be
|
||||||
@@ -2692,8 +2725,10 @@ func (lc *LightningChannel) fetchHTLCView(theirLogIndex,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &HtlcView{
|
return &HtlcView{
|
||||||
OurUpdates: ourHTLCs,
|
Updates: lntypes.Dual[[]*paymentDescriptor]{
|
||||||
TheirUpdates: theirHTLCs,
|
Local: ourHTLCs,
|
||||||
|
Remote: theirHTLCs,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2817,15 +2852,15 @@ func (lc *LightningChannel) fetchCommitmentView(
|
|||||||
// commitment are mutated, we'll manually copy over each HTLC to its
|
// commitment are mutated, we'll manually copy over each HTLC to its
|
||||||
// respective slice.
|
// respective slice.
|
||||||
c.outgoingHTLCs = make(
|
c.outgoingHTLCs = make(
|
||||||
[]paymentDescriptor, len(filteredHTLCView.OurUpdates),
|
[]paymentDescriptor, len(filteredHTLCView.Updates.Local),
|
||||||
)
|
)
|
||||||
for i, htlc := range filteredHTLCView.OurUpdates {
|
for i, htlc := range filteredHTLCView.Updates.Local {
|
||||||
c.outgoingHTLCs[i] = *htlc
|
c.outgoingHTLCs[i] = *htlc
|
||||||
}
|
}
|
||||||
c.incomingHTLCs = make(
|
c.incomingHTLCs = make(
|
||||||
[]paymentDescriptor, len(filteredHTLCView.TheirUpdates),
|
[]paymentDescriptor, len(filteredHTLCView.Updates.Remote),
|
||||||
)
|
)
|
||||||
for i, htlc := range filteredHTLCView.TheirUpdates {
|
for i, htlc := range filteredHTLCView.Updates.Remote {
|
||||||
c.incomingHTLCs[i] = *htlc
|
c.incomingHTLCs[i] = *htlc
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2854,16 +2889,13 @@ func fundingTxIn(chanState *channeldb.OpenChannel) wire.TxIn {
|
|||||||
// returned reflects the current state of HTLCs within the remote or local
|
// returned reflects the current state of HTLCs within the remote or local
|
||||||
// commitment chain, and the current commitment fee rate.
|
// commitment chain, and the current commitment fee rate.
|
||||||
//
|
//
|
||||||
// If mutateState is set to true, then the add height of all added HTLCs
|
// The return values of this function are as follows:
|
||||||
// will be set to nextHeight, and the remove height of all removed HTLCs
|
// 1. The new htlcView reflecting the current channel state.
|
||||||
// will be set to nextHeight. This should therefore only be set to true
|
// 2. A Dual of the updates which have not yet been committed in
|
||||||
// once for each height, and only in concert with signing a new commitment.
|
// 'whoseCommitChain's commitment chain.
|
||||||
// TODO(halseth): return htlcs to mutate instead of mutating inside
|
func (lc *LightningChannel) evaluateHTLCView(view *HtlcView,
|
||||||
// method.
|
whoseCommitChain lntypes.ChannelParty, nextHeight uint64) (*HtlcView,
|
||||||
func (lc *LightningChannel) evaluateHTLCView(view *HtlcView, ourBalance,
|
lntypes.Dual[[]*paymentDescriptor], lntypes.Dual[int64], error) {
|
||||||
theirBalance *lnwire.MilliSatoshi, nextHeight uint64,
|
|
||||||
whoseCommitChain lntypes.ChannelParty, mutateState bool) (*HtlcView,
|
|
||||||
error) {
|
|
||||||
|
|
||||||
// We initialize the view's fee rate to the fee rate of the unfiltered
|
// We initialize the view's fee rate to the fee rate of the unfiltered
|
||||||
// view. If any fee updates are found when evaluating the view, it will
|
// view. If any fee updates are found when evaluating the view, it will
|
||||||
@@ -2872,128 +2904,162 @@ func (lc *LightningChannel) evaluateHTLCView(view *HtlcView, ourBalance,
|
|||||||
FeePerKw: view.FeePerKw,
|
FeePerKw: view.FeePerKw,
|
||||||
NextHeight: nextHeight,
|
NextHeight: nextHeight,
|
||||||
}
|
}
|
||||||
|
noUncommitted := lntypes.Dual[[]*paymentDescriptor]{}
|
||||||
|
|
||||||
|
// The fee rate of our view is always the last UpdateFee message from
|
||||||
|
// the channel's OpeningParty.
|
||||||
|
openerUpdates := view.Updates.GetForParty(lc.channelState.Initiator())
|
||||||
|
feeUpdates := fn.Filter(func(u *paymentDescriptor) bool {
|
||||||
|
return u.EntryType == FeeUpdate
|
||||||
|
}, openerUpdates)
|
||||||
|
lastFeeUpdate := fn.Last(feeUpdates)
|
||||||
|
lastFeeUpdate.WhenSome(func(pd *paymentDescriptor) {
|
||||||
|
newView.FeePerKw = chainfee.SatPerKWeight(
|
||||||
|
pd.Amount.ToSatoshis(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
// We use two maps, one for the local log and one for the remote log to
|
// We use two maps, one for the local log and one for the remote log to
|
||||||
// keep track of which entries we need to skip when creating the final
|
// keep track of which entries we need to skip when creating the final
|
||||||
// htlc view. We skip an entry whenever we find a settle or a timeout
|
// htlc view. We skip an entry whenever we find a settle or a timeout
|
||||||
// modifying an entry.
|
// modifying an entry.
|
||||||
skipUs := make(map[uint64]struct{})
|
skip := lntypes.Dual[fn.Set[uint64]]{
|
||||||
skipThem := make(map[uint64]struct{})
|
Local: fn.NewSet[uint64](),
|
||||||
|
Remote: fn.NewSet[uint64](),
|
||||||
// First we run through non-add entries in both logs, populating the
|
|
||||||
// skip sets and mutating the current chain state (crediting balances,
|
|
||||||
// etc) to reflect the settle/timeout entry encountered.
|
|
||||||
for _, entry := range view.OurUpdates {
|
|
||||||
switch entry.EntryType {
|
|
||||||
// Skip adds for now. They will be processed below.
|
|
||||||
case Add:
|
|
||||||
continue
|
|
||||||
|
|
||||||
// Process fee updates, updating the current feePerKw.
|
|
||||||
case FeeUpdate:
|
|
||||||
processFeeUpdate(
|
|
||||||
entry, nextHeight, whoseCommitChain,
|
|
||||||
mutateState, newView,
|
|
||||||
)
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're settling an inbound HTLC, and it hasn't been
|
balanceDeltas := lntypes.Dual[int64]{}
|
||||||
// processed yet, then increment our state tracking the total
|
|
||||||
// number of satoshis we've received within the channel.
|
|
||||||
if mutateState && entry.EntryType == Settle &&
|
|
||||||
whoseCommitChain.IsLocal() &&
|
|
||||||
entry.removeCommitHeightLocal == 0 {
|
|
||||||
|
|
||||||
lc.channelState.TotalMSatReceived += entry.Amount
|
parties := [2]lntypes.ChannelParty{lntypes.Local, lntypes.Remote}
|
||||||
|
for _, party := range parties {
|
||||||
|
// First we run through non-add entries in both logs,
|
||||||
|
// populating the skip sets.
|
||||||
|
resolutions := fn.Filter(func(pd *paymentDescriptor) bool {
|
||||||
|
switch pd.EntryType {
|
||||||
|
case Settle, Fail, MalformedFail:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
}, view.Updates.GetForParty(party))
|
||||||
|
|
||||||
|
for _, entry := range resolutions {
|
||||||
addEntry, err := lc.fetchParent(
|
addEntry, err := lc.fetchParent(
|
||||||
entry, whoseCommitChain, lntypes.Remote,
|
entry, whoseCommitChain, party.CounterParty(),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
noDeltas := lntypes.Dual[int64]{}
|
||||||
|
return nil, noUncommitted, noDeltas, err
|
||||||
}
|
}
|
||||||
|
|
||||||
skipThem[addEntry.HtlcIndex] = struct{}{}
|
skipSet := skip.GetForParty(party.CounterParty())
|
||||||
|
skipSet.Add(addEntry.HtlcIndex)
|
||||||
|
|
||||||
processRemoveEntry(
|
rmvHeight := entry.removeCommitHeights.GetForParty(
|
||||||
entry, ourBalance, theirBalance, nextHeight,
|
whoseCommitChain,
|
||||||
whoseCommitChain, true, mutateState,
|
)
|
||||||
|
if rmvHeight == 0 {
|
||||||
|
switch {
|
||||||
|
// If an incoming HTLC is being settled, then
|
||||||
|
// this means that the preimage has been
|
||||||
|
// received by the settling party Therefore, we
|
||||||
|
// increase the settling party's balance by the
|
||||||
|
// HTLC amount.
|
||||||
|
case entry.EntryType == Settle:
|
||||||
|
delta := int64(entry.Amount)
|
||||||
|
balanceDeltas.ModifyForParty(
|
||||||
|
party,
|
||||||
|
func(acc int64) int64 {
|
||||||
|
return acc + delta
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
// Otherwise, this HTLC is being failed out,
|
||||||
|
// therefore the value of the HTLC should
|
||||||
|
// return to the failing party's counterparty.
|
||||||
|
case entry.EntryType != Settle:
|
||||||
|
delta := int64(entry.Amount)
|
||||||
|
balanceDeltas.ModifyForParty(
|
||||||
|
party.CounterParty(),
|
||||||
|
func(acc int64) int64 {
|
||||||
|
return acc + delta
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
for _, entry := range view.TheirUpdates {
|
|
||||||
switch entry.EntryType {
|
|
||||||
// Skip adds for now. They will be processed below.
|
|
||||||
case Add:
|
|
||||||
continue
|
|
||||||
|
|
||||||
// Process fee updates, updating the current feePerKw.
|
|
||||||
case FeeUpdate:
|
|
||||||
processFeeUpdate(
|
|
||||||
entry, nextHeight, whoseCommitChain,
|
|
||||||
mutateState, newView,
|
|
||||||
)
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the remote party is settling one of our outbound HTLC's,
|
|
||||||
// and it hasn't been processed, yet, the increment our state
|
|
||||||
// tracking the total number of satoshis we've sent within the
|
|
||||||
// channel.
|
|
||||||
if mutateState && entry.EntryType == Settle &&
|
|
||||||
whoseCommitChain.IsLocal() &&
|
|
||||||
entry.removeCommitHeightLocal == 0 {
|
|
||||||
|
|
||||||
lc.channelState.TotalMSatSent += entry.Amount
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addEntry, err := lc.fetchParent(
|
|
||||||
entry, whoseCommitChain, lntypes.Local,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
skipUs[addEntry.HtlcIndex] = struct{}{}
|
|
||||||
|
|
||||||
processRemoveEntry(
|
|
||||||
entry, ourBalance, theirBalance, nextHeight,
|
|
||||||
whoseCommitChain, false, mutateState,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next we take a second pass through all the log entries, skipping any
|
// Next we take a second pass through all the log entries, skipping any
|
||||||
// settled HTLCs, and debiting the chain state balance due to any newly
|
// settled HTLCs, and debiting the chain state balance due to any newly
|
||||||
// added HTLCs.
|
// added HTLCs.
|
||||||
for _, entry := range view.OurUpdates {
|
for _, party := range parties {
|
||||||
isAdd := entry.EntryType == Add
|
liveAdds := fn.Filter(func(pd *paymentDescriptor) bool {
|
||||||
if _, ok := skipUs[entry.HtlcIndex]; !isAdd || ok {
|
return pd.EntryType == Add &&
|
||||||
continue
|
!skip.GetForParty(party).Contains(pd.HtlcIndex)
|
||||||
|
}, view.Updates.GetForParty(party))
|
||||||
|
|
||||||
|
for _, entry := range liveAdds {
|
||||||
|
// Skip the entries that have already had their add
|
||||||
|
// commit height set for this commit chain.
|
||||||
|
addHeight := entry.addCommitHeights.GetForParty(
|
||||||
|
whoseCommitChain,
|
||||||
|
)
|
||||||
|
if addHeight == 0 {
|
||||||
|
// If this is a new incoming (un-committed)
|
||||||
|
// HTLC, then we need to update their balance
|
||||||
|
// accordingly by subtracting the amount of
|
||||||
|
// the HTLC that are funds pending.
|
||||||
|
// Similarly, we need to debit our balance if
|
||||||
|
// this is an out going HTLC to reflect the
|
||||||
|
// pending balance.
|
||||||
|
balanceDeltas.ModifyForParty(
|
||||||
|
party,
|
||||||
|
func(acc int64) int64 {
|
||||||
|
return acc - int64(entry.Amount)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
processAddEntry(
|
newView.Updates.SetForParty(party, liveAdds)
|
||||||
entry, ourBalance, theirBalance, nextHeight,
|
}
|
||||||
whoseCommitChain, false, mutateState,
|
|
||||||
|
// Create a function that is capable of identifying whether or not the
|
||||||
|
// paymentDescriptor has been committed in the commitment chain
|
||||||
|
// corresponding to whoseCommitmentChain.
|
||||||
|
isUncommitted := func(update *paymentDescriptor) bool {
|
||||||
|
switch update.EntryType {
|
||||||
|
case Add:
|
||||||
|
return update.addCommitHeights.GetForParty(
|
||||||
|
whoseCommitChain,
|
||||||
|
) == 0
|
||||||
|
|
||||||
|
case FeeUpdate:
|
||||||
|
return update.addCommitHeights.GetForParty(
|
||||||
|
whoseCommitChain,
|
||||||
|
) == 0
|
||||||
|
|
||||||
|
case Settle, Fail, MalformedFail:
|
||||||
|
return update.removeCommitHeights.GetForParty(
|
||||||
|
whoseCommitChain,
|
||||||
|
) == 0
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic("invalid paymentDescriptor EntryType")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect all of the updates that haven't had their commit heights set
|
||||||
|
// for the commitment chain corresponding to whoseCommitmentChain.
|
||||||
|
uncommittedUpdates := lntypes.MapDual(
|
||||||
|
view.Updates,
|
||||||
|
func(us []*paymentDescriptor) []*paymentDescriptor {
|
||||||
|
return fn.Filter(isUncommitted, us)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
newView.OurUpdates = append(newView.OurUpdates, entry)
|
return newView, uncommittedUpdates, balanceDeltas, nil
|
||||||
}
|
|
||||||
for _, entry := range view.TheirUpdates {
|
|
||||||
isAdd := entry.EntryType == Add
|
|
||||||
if _, ok := skipThem[entry.HtlcIndex]; !isAdd || ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
processAddEntry(
|
|
||||||
entry, ourBalance, theirBalance, nextHeight,
|
|
||||||
whoseCommitChain, true, mutateState,
|
|
||||||
)
|
|
||||||
|
|
||||||
newView.TheirUpdates = append(newView.TheirUpdates, entry)
|
|
||||||
}
|
|
||||||
|
|
||||||
return newView, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetchParent is a helper that looks up update log parent entries in the
|
// fetchParent is a helper that looks up update log parent entries in the
|
||||||
@@ -3031,146 +3097,15 @@ func (lc *LightningChannel) fetchParent(entry *paymentDescriptor,
|
|||||||
|
|
||||||
// The parent add height should never be zero at this point. If
|
// The parent add height should never be zero at this point. If
|
||||||
// that's the case we probably forgot to send a new commitment.
|
// that's the case we probably forgot to send a new commitment.
|
||||||
case whoseCommitChain.IsRemote() &&
|
case addEntry.addCommitHeights.GetForParty(whoseCommitChain) == 0:
|
||||||
addEntry.addCommitHeightRemote == 0:
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("parent entry %d for update %d "+
|
return nil, fmt.Errorf("parent entry %d for update %d "+
|
||||||
"had zero remote add height", entry.ParentIndex,
|
"had zero %v add height", entry.ParentIndex,
|
||||||
entry.LogIndex)
|
entry.LogIndex, whoseCommitChain)
|
||||||
|
|
||||||
case whoseCommitChain.IsLocal() &&
|
|
||||||
addEntry.addCommitHeightLocal == 0:
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("parent entry %d for update %d "+
|
|
||||||
"had zero local add height", entry.ParentIndex,
|
|
||||||
entry.LogIndex)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return addEntry, nil
|
return addEntry, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// processAddEntry evaluates the effect of an add entry within the HTLC log.
|
|
||||||
// If the HTLC hasn't yet been committed in either chain, then the height it
|
|
||||||
// was committed is updated. Keeping track of this inclusion height allows us to
|
|
||||||
// later compact the log once the change is fully committed in both chains.
|
|
||||||
func processAddEntry(htlc *paymentDescriptor, ourBalance,
|
|
||||||
theirBalance *lnwire.MilliSatoshi, nextHeight uint64,
|
|
||||||
whoseCommitChain lntypes.ChannelParty, isIncoming, mutateState bool) {
|
|
||||||
|
|
||||||
// If we're evaluating this entry for the remote chain (to create/view
|
|
||||||
// a new commitment), then we'll may be updating the height this entry
|
|
||||||
// was added to the chain. Otherwise, we may be updating the entry's
|
|
||||||
// height w.r.t the local chain.
|
|
||||||
var addHeight *uint64
|
|
||||||
if whoseCommitChain.IsRemote() {
|
|
||||||
addHeight = &htlc.addCommitHeightRemote
|
|
||||||
} else {
|
|
||||||
addHeight = &htlc.addCommitHeightLocal
|
|
||||||
}
|
|
||||||
|
|
||||||
if *addHeight != 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if isIncoming {
|
|
||||||
// If this is a new incoming (un-committed) HTLC, then we need
|
|
||||||
// to update their balance accordingly by subtracting the
|
|
||||||
// amount of the HTLC that are funds pending.
|
|
||||||
*theirBalance -= htlc.Amount
|
|
||||||
} else {
|
|
||||||
// Similarly, we need to debit our balance if this is an out
|
|
||||||
// going HTLC to reflect the pending balance.
|
|
||||||
*ourBalance -= htlc.Amount
|
|
||||||
}
|
|
||||||
|
|
||||||
if mutateState {
|
|
||||||
*addHeight = nextHeight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// processRemoveEntry processes a log entry which settles or times out a
|
|
||||||
// previously added HTLC. If the removal entry has already been processed, it
|
|
||||||
// is skipped.
|
|
||||||
func processRemoveEntry(htlc *paymentDescriptor, ourBalance,
|
|
||||||
theirBalance *lnwire.MilliSatoshi, nextHeight uint64,
|
|
||||||
whoseCommitChain lntypes.ChannelParty, isIncoming, mutateState bool) {
|
|
||||||
|
|
||||||
var removeHeight *uint64
|
|
||||||
if whoseCommitChain.IsRemote() {
|
|
||||||
removeHeight = &htlc.removeCommitHeightRemote
|
|
||||||
} else {
|
|
||||||
removeHeight = &htlc.removeCommitHeightLocal
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignore any removal entries which have already been processed.
|
|
||||||
if *removeHeight != 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
// If an incoming HTLC is being settled, then this means that we've
|
|
||||||
// received the preimage either from another subsystem, or the
|
|
||||||
// upstream peer in the route. Therefore, we increase our balance by
|
|
||||||
// the HTLC amount.
|
|
||||||
case isIncoming && htlc.EntryType == Settle:
|
|
||||||
*ourBalance += htlc.Amount
|
|
||||||
|
|
||||||
// Otherwise, this HTLC is being failed out, therefore the value of the
|
|
||||||
// HTLC should return to the remote party.
|
|
||||||
case isIncoming && (htlc.EntryType == Fail || htlc.EntryType == MalformedFail):
|
|
||||||
*theirBalance += htlc.Amount
|
|
||||||
|
|
||||||
// If an outgoing HTLC is being settled, then this means that the
|
|
||||||
// downstream party resented the preimage or learned of it via a
|
|
||||||
// downstream peer. In either case, we credit their settled value with
|
|
||||||
// the value of the HTLC.
|
|
||||||
case !isIncoming && htlc.EntryType == Settle:
|
|
||||||
*theirBalance += htlc.Amount
|
|
||||||
|
|
||||||
// Otherwise, one of our outgoing HTLC's has timed out, so the value of
|
|
||||||
// the HTLC should be returned to our settled balance.
|
|
||||||
case !isIncoming && (htlc.EntryType == Fail || htlc.EntryType == MalformedFail):
|
|
||||||
*ourBalance += htlc.Amount
|
|
||||||
}
|
|
||||||
|
|
||||||
if mutateState {
|
|
||||||
*removeHeight = nextHeight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// processFeeUpdate processes a log update that updates the current commitment
|
|
||||||
// fee.
|
|
||||||
func processFeeUpdate(feeUpdate *paymentDescriptor, nextHeight uint64,
|
|
||||||
whoseCommitChain lntypes.ChannelParty, mutateState bool,
|
|
||||||
view *HtlcView) {
|
|
||||||
|
|
||||||
// Fee updates are applied for all commitments after they are
|
|
||||||
// sent/received, so we consider them being added and removed at the
|
|
||||||
// same height.
|
|
||||||
var addHeight *uint64
|
|
||||||
var removeHeight *uint64
|
|
||||||
if whoseCommitChain.IsRemote() {
|
|
||||||
addHeight = &feeUpdate.addCommitHeightRemote
|
|
||||||
removeHeight = &feeUpdate.removeCommitHeightRemote
|
|
||||||
} else {
|
|
||||||
addHeight = &feeUpdate.addCommitHeightLocal
|
|
||||||
removeHeight = &feeUpdate.removeCommitHeightLocal
|
|
||||||
}
|
|
||||||
|
|
||||||
if *addHeight != 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the update wasn't already locked in, update the current fee rate
|
|
||||||
// to reflect this update.
|
|
||||||
view.FeePerKw = chainfee.SatPerKWeight(feeUpdate.Amount.ToSatoshis())
|
|
||||||
|
|
||||||
if mutateState {
|
|
||||||
*addHeight = nextHeight
|
|
||||||
*removeHeight = nextHeight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// generateRemoteHtlcSigJobs generates a series of HTLC signature jobs for the
|
// generateRemoteHtlcSigJobs generates a series of HTLC signature jobs for the
|
||||||
// sig pool, along with a channel that if closed, will cancel any jobs after
|
// sig pool, along with a channel that if closed, will cancel any jobs after
|
||||||
// they have been submitted to the sigPool. This method is to be used when
|
// they have been submitted to the sigPool. This method is to be used when
|
||||||
@@ -3419,8 +3354,8 @@ func (lc *LightningChannel) createCommitDiff(newCommit *commitment,
|
|||||||
// If this entry wasn't committed at the exact height of this
|
// If this entry wasn't committed at the exact height of this
|
||||||
// remote commitment, then we'll skip it as it was already
|
// remote commitment, then we'll skip it as it was already
|
||||||
// lingering in the log.
|
// lingering in the log.
|
||||||
if pd.addCommitHeightRemote != newCommit.height &&
|
if pd.addCommitHeights.Remote != newCommit.height &&
|
||||||
pd.removeCommitHeightRemote != newCommit.height {
|
pd.removeCommitHeights.Remote != newCommit.height {
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -3734,10 +3669,12 @@ func (lc *LightningChannel) validateCommitmentSanity(theirLogCounter,
|
|||||||
// appropriate update log, in order to validate the sanity of the
|
// appropriate update log, in order to validate the sanity of the
|
||||||
// commitment resulting from _actually adding_ this HTLC to the state.
|
// commitment resulting from _actually adding_ this HTLC to the state.
|
||||||
if predictOurAdd != nil {
|
if predictOurAdd != nil {
|
||||||
view.OurUpdates = append(view.OurUpdates, predictOurAdd)
|
view.Updates.Local = append(view.Updates.Local, predictOurAdd)
|
||||||
}
|
}
|
||||||
if predictTheirAdd != nil {
|
if predictTheirAdd != nil {
|
||||||
view.TheirUpdates = append(view.TheirUpdates, predictTheirAdd)
|
view.Updates.Remote = append(
|
||||||
|
view.Updates.Remote, predictTheirAdd,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
ourBalance, theirBalance, commitWeight, filteredView, err := lc.computeView(
|
ourBalance, theirBalance, commitWeight, filteredView, err := lc.computeView(
|
||||||
@@ -3892,7 +3829,7 @@ func (lc *LightningChannel) validateCommitmentSanity(theirLogCounter,
|
|||||||
// First check that the remote updates won't violate it's channel
|
// First check that the remote updates won't violate it's channel
|
||||||
// constraints.
|
// constraints.
|
||||||
err = validateUpdates(
|
err = validateUpdates(
|
||||||
filteredView.TheirUpdates, &lc.channelState.RemoteChanCfg,
|
filteredView.Updates.Remote, &lc.channelState.RemoteChanCfg,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -3901,7 +3838,7 @@ func (lc *LightningChannel) validateCommitmentSanity(theirLogCounter,
|
|||||||
// Secondly check that our updates won't violate our channel
|
// Secondly check that our updates won't violate our channel
|
||||||
// constraints.
|
// constraints.
|
||||||
err = validateUpdates(
|
err = validateUpdates(
|
||||||
filteredView.OurUpdates, &lc.channelState.LocalChanCfg,
|
filteredView.Updates.Local, &lc.channelState.LocalChanCfg,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -4643,13 +4580,40 @@ func (lc *LightningChannel) computeView(view *HtlcView,
|
|||||||
// channel constraints to the final commitment state. If any fee
|
// channel constraints to the final commitment state. If any fee
|
||||||
// updates are found in the logs, the commitment fee rate should be
|
// updates are found in the logs, the commitment fee rate should be
|
||||||
// changed, so we'll also set the feePerKw to this new value.
|
// changed, so we'll also set the feePerKw to this new value.
|
||||||
filteredHTLCView, err := lc.evaluateHTLCView(
|
filteredHTLCView, uncommitted, deltas, err := lc.evaluateHTLCView(
|
||||||
view, &ourBalance, &theirBalance, nextHeight, whoseCommitChain,
|
view, whoseCommitChain, nextHeight,
|
||||||
updateState,
|
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, 0, nil, err
|
return 0, 0, 0, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add the balance deltas to the balances we got from the commitment
|
||||||
|
// state.
|
||||||
|
if deltas.Local >= 0 {
|
||||||
|
ourBalance += lnwire.MilliSatoshi(deltas.Local)
|
||||||
|
} else {
|
||||||
|
ourBalance -= lnwire.MilliSatoshi(-1 * deltas.Local)
|
||||||
|
}
|
||||||
|
if deltas.Remote >= 0 {
|
||||||
|
theirBalance += lnwire.MilliSatoshi(deltas.Remote)
|
||||||
|
} else {
|
||||||
|
theirBalance -= lnwire.MilliSatoshi(-1 * deltas.Remote)
|
||||||
|
}
|
||||||
|
|
||||||
|
if updateState {
|
||||||
|
for _, party := range lntypes.BothParties {
|
||||||
|
for _, u := range uncommitted.GetForParty(party) {
|
||||||
|
u.setCommitHeight(whoseCommitChain, nextHeight)
|
||||||
|
|
||||||
|
if whoseCommitChain == lntypes.Local &&
|
||||||
|
u.EntryType == Settle {
|
||||||
|
|
||||||
|
lc.recordSettlement(party, u.Amount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
feePerKw := filteredHTLCView.FeePerKw
|
feePerKw := filteredHTLCView.FeePerKw
|
||||||
|
|
||||||
// Here we override the view's fee-rate if a dry-run fee-rate was
|
// Here we override the view's fee-rate if a dry-run fee-rate was
|
||||||
@@ -4659,8 +4623,8 @@ func (lc *LightningChannel) computeView(view *HtlcView,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We need to first check ourBalance and theirBalance to be negative
|
// We need to first check ourBalance and theirBalance to be negative
|
||||||
// because MilliSathoshi is a unsigned type and can underflow in
|
// because MilliSathoshi is a unsigned type and can underflow in the
|
||||||
// `evaluateHTLCView`. This should never happen for views which do not
|
// code above. This should never happen for views which do not
|
||||||
// include new updates (remote or local).
|
// include new updates (remote or local).
|
||||||
if int64(ourBalance) < 0 {
|
if int64(ourBalance) < 0 {
|
||||||
err := fmt.Errorf("%w: our balance", ErrBelowChanReserve)
|
err := fmt.Errorf("%w: our balance", ErrBelowChanReserve)
|
||||||
@@ -4674,7 +4638,7 @@ func (lc *LightningChannel) computeView(view *HtlcView,
|
|||||||
// Now go through all HTLCs at this stage, to calculate the total
|
// Now go through all HTLCs at this stage, to calculate the total
|
||||||
// weight, needed to calculate the transaction fee.
|
// weight, needed to calculate the transaction fee.
|
||||||
var totalHtlcWeight lntypes.WeightUnit
|
var totalHtlcWeight lntypes.WeightUnit
|
||||||
for _, htlc := range filteredHTLCView.OurUpdates {
|
for _, htlc := range filteredHTLCView.Updates.Local {
|
||||||
if HtlcIsDust(
|
if HtlcIsDust(
|
||||||
lc.channelState.ChanType, false, whoseCommitChain,
|
lc.channelState.ChanType, false, whoseCommitChain,
|
||||||
feePerKw, htlc.Amount.ToSatoshis(), dustLimit,
|
feePerKw, htlc.Amount.ToSatoshis(), dustLimit,
|
||||||
@@ -4685,7 +4649,7 @@ func (lc *LightningChannel) computeView(view *HtlcView,
|
|||||||
|
|
||||||
totalHtlcWeight += input.HTLCWeight
|
totalHtlcWeight += input.HTLCWeight
|
||||||
}
|
}
|
||||||
for _, htlc := range filteredHTLCView.TheirUpdates {
|
for _, htlc := range filteredHTLCView.Updates.Remote {
|
||||||
if HtlcIsDust(
|
if HtlcIsDust(
|
||||||
lc.channelState.ChanType, true, whoseCommitChain,
|
lc.channelState.ChanType, true, whoseCommitChain,
|
||||||
feePerKw, htlc.Amount.ToSatoshis(), dustLimit,
|
feePerKw, htlc.Amount.ToSatoshis(), dustLimit,
|
||||||
@@ -4702,6 +4666,18 @@ func (lc *LightningChannel) computeView(view *HtlcView,
|
|||||||
return ourBalance, theirBalance, totalCommitWeight, filteredHTLCView, nil
|
return ourBalance, theirBalance, totalCommitWeight, filteredHTLCView, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// recordSettlement updates the lifetime payment flow values in persistent state
|
||||||
|
// of the LightningChannel, adding amt to the total received by the redeemer.
|
||||||
|
func (lc *LightningChannel) recordSettlement(
|
||||||
|
redeemer lntypes.ChannelParty, amt lnwire.MilliSatoshi) {
|
||||||
|
|
||||||
|
if redeemer == lntypes.Local {
|
||||||
|
lc.channelState.TotalMSatReceived += amt
|
||||||
|
} else {
|
||||||
|
lc.channelState.TotalMSatSent += amt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// genHtlcSigValidationJobs generates a series of signatures verification jobs
|
// genHtlcSigValidationJobs generates a series of signatures verification jobs
|
||||||
// meant to verify all the signatures for HTLC's attached to a newly created
|
// meant to verify all the signatures for HTLC's attached to a newly created
|
||||||
// commitment state. The jobs generated are fully populated, and can be sent
|
// commitment state. The jobs generated are fully populated, and can be sent
|
||||||
@@ -5655,19 +5631,20 @@ func (lc *LightningChannel) ReceiveRevocation(revMsg *lnwire.RevokeAndAck) (
|
|||||||
// both of the remote and local heights are non-zero. If either
|
// both of the remote and local heights are non-zero. If either
|
||||||
// of these values is zero, it has yet to be committed in both
|
// of these values is zero, it has yet to be committed in both
|
||||||
// the local and remote chains.
|
// the local and remote chains.
|
||||||
committedAdd := pd.addCommitHeightRemote > 0 &&
|
committedAdd := pd.addCommitHeights.Remote > 0 &&
|
||||||
pd.addCommitHeightLocal > 0
|
pd.addCommitHeights.Local > 0
|
||||||
committedRmv := pd.removeCommitHeightRemote > 0 &&
|
committedRmv := pd.removeCommitHeights.Remote > 0 &&
|
||||||
pd.removeCommitHeightLocal > 0
|
pd.removeCommitHeights.Local > 0
|
||||||
|
|
||||||
// Using the height of the remote and local commitments,
|
// Using the height of the remote and local commitments,
|
||||||
// preemptively compute whether or not to forward this HTLC for
|
// preemptively compute whether or not to forward this HTLC for
|
||||||
// the case in which this in an Add HTLC, or if this is a
|
// the case in which this in an Add HTLC, or if this is a
|
||||||
// Settle, Fail, or MalformedFail.
|
// Settle, Fail, or MalformedFail.
|
||||||
shouldFwdAdd := remoteChainTail == pd.addCommitHeightRemote &&
|
shouldFwdAdd := remoteChainTail == pd.addCommitHeights.Remote &&
|
||||||
localChainTail >= pd.addCommitHeightLocal
|
localChainTail >= pd.addCommitHeights.Local
|
||||||
shouldFwdRmv := remoteChainTail == pd.removeCommitHeightRemote &&
|
shouldFwdRmv := remoteChainTail ==
|
||||||
localChainTail >= pd.removeCommitHeightLocal
|
pd.removeCommitHeights.Remote &&
|
||||||
|
localChainTail >= pd.removeCommitHeights.Local
|
||||||
|
|
||||||
// We'll only forward any new HTLC additions iff, it's "freshly
|
// We'll only forward any new HTLC additions iff, it's "freshly
|
||||||
// locked in". Meaning that the HTLC was only *just* considered
|
// locked in". Meaning that the HTLC was only *just* considered
|
||||||
|
|||||||
+109
-659
@@ -7614,13 +7614,13 @@ func TestChannelRestoreCommitHeight(t *testing.T) {
|
|||||||
t.Fatalf("htlc not found in log")
|
t.Fatalf("htlc not found in log")
|
||||||
}
|
}
|
||||||
|
|
||||||
if pd.addCommitHeightLocal != expLocal {
|
if pd.addCommitHeights.Local != expLocal {
|
||||||
t.Fatalf("expected local add height to be %d, was %d",
|
t.Fatalf("expected local add height to be %d, was %d",
|
||||||
expLocal, pd.addCommitHeightLocal)
|
expLocal, pd.addCommitHeights.Local)
|
||||||
}
|
}
|
||||||
if pd.addCommitHeightRemote != expRemote {
|
if pd.addCommitHeights.Remote != expRemote {
|
||||||
t.Fatalf("expected remote add height to be %d, was %d",
|
t.Fatalf("expected remote add height to be %d, was %d",
|
||||||
expRemote, pd.addCommitHeightRemote)
|
expRemote, pd.addCommitHeights.Remote)
|
||||||
}
|
}
|
||||||
return newChannel
|
return newChannel
|
||||||
}
|
}
|
||||||
@@ -8403,15 +8403,19 @@ func TestFetchParent(t *testing.T) {
|
|||||||
// This entry will be added at log index =0.
|
// This entry will be added at log index =0.
|
||||||
{
|
{
|
||||||
HtlcIndex: 1,
|
HtlcIndex: 1,
|
||||||
addCommitHeightLocal: 100,
|
addCommitHeights: lntypes.Dual[uint64]{
|
||||||
addCommitHeightRemote: 100,
|
Local: 100,
|
||||||
|
Remote: 100,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
// This entry will be added at log index =1, it
|
// This entry will be added at log index =1, it
|
||||||
// is the parent entry we are looking for.
|
// is the parent entry we are looking for.
|
||||||
{
|
{
|
||||||
HtlcIndex: 2,
|
HtlcIndex: 2,
|
||||||
addCommitHeightLocal: 100,
|
addCommitHeights: lntypes.Dual[uint64]{
|
||||||
addCommitHeightRemote: 0,
|
Local: 100,
|
||||||
|
Remote: 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
whoseCommitChain: lntypes.Remote,
|
whoseCommitChain: lntypes.Remote,
|
||||||
@@ -8425,15 +8429,19 @@ func TestFetchParent(t *testing.T) {
|
|||||||
// This entry will be added at log index =0.
|
// This entry will be added at log index =0.
|
||||||
{
|
{
|
||||||
HtlcIndex: 1,
|
HtlcIndex: 1,
|
||||||
addCommitHeightLocal: 100,
|
addCommitHeights: lntypes.Dual[uint64]{
|
||||||
addCommitHeightRemote: 100,
|
Local: 100,
|
||||||
|
Remote: 100,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
// This entry will be added at log index =1, it
|
// This entry will be added at log index =1, it
|
||||||
// is the parent entry we are looking for.
|
// is the parent entry we are looking for.
|
||||||
{
|
{
|
||||||
HtlcIndex: 2,
|
HtlcIndex: 2,
|
||||||
addCommitHeightLocal: 0,
|
addCommitHeights: lntypes.Dual[uint64]{
|
||||||
addCommitHeightRemote: 100,
|
Local: 0,
|
||||||
|
Remote: 100,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
localEntries: nil,
|
localEntries: nil,
|
||||||
@@ -8448,15 +8456,19 @@ func TestFetchParent(t *testing.T) {
|
|||||||
// This entry will be added at log index =0.
|
// This entry will be added at log index =0.
|
||||||
{
|
{
|
||||||
HtlcIndex: 1,
|
HtlcIndex: 1,
|
||||||
addCommitHeightLocal: 100,
|
addCommitHeights: lntypes.Dual[uint64]{
|
||||||
addCommitHeightRemote: 100,
|
Local: 100,
|
||||||
|
Remote: 100,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
// This entry will be added at log index =1, it
|
// This entry will be added at log index =1, it
|
||||||
// is the parent entry we are looking for.
|
// is the parent entry we are looking for.
|
||||||
{
|
{
|
||||||
HtlcIndex: 2,
|
HtlcIndex: 2,
|
||||||
addCommitHeightLocal: 0,
|
addCommitHeights: lntypes.Dual[uint64]{
|
||||||
addCommitHeightRemote: 100,
|
Local: 0,
|
||||||
|
Remote: 100,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
remoteEntries: nil,
|
remoteEntries: nil,
|
||||||
@@ -8472,15 +8484,19 @@ func TestFetchParent(t *testing.T) {
|
|||||||
// This entry will be added at log index =0.
|
// This entry will be added at log index =0.
|
||||||
{
|
{
|
||||||
HtlcIndex: 1,
|
HtlcIndex: 1,
|
||||||
addCommitHeightLocal: 100,
|
addCommitHeights: lntypes.Dual[uint64]{
|
||||||
addCommitHeightRemote: 100,
|
Local: 100,
|
||||||
|
Remote: 100,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
// This entry will be added at log index =1, it
|
// This entry will be added at log index =1, it
|
||||||
// is the parent entry we are looking for.
|
// is the parent entry we are looking for.
|
||||||
{
|
{
|
||||||
HtlcIndex: 2,
|
HtlcIndex: 2,
|
||||||
addCommitHeightLocal: 100,
|
addCommitHeights: lntypes.Dual[uint64]{
|
||||||
addCommitHeightRemote: 0,
|
Local: 100,
|
||||||
|
Remote: 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
remoteEntries: nil,
|
remoteEntries: nil,
|
||||||
@@ -8496,15 +8512,19 @@ func TestFetchParent(t *testing.T) {
|
|||||||
// This entry will be added at log index =0.
|
// This entry will be added at log index =0.
|
||||||
{
|
{
|
||||||
HtlcIndex: 1,
|
HtlcIndex: 1,
|
||||||
addCommitHeightLocal: 100,
|
addCommitHeights: lntypes.Dual[uint64]{
|
||||||
addCommitHeightRemote: 0,
|
Local: 100,
|
||||||
|
Remote: 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
// This entry will be added at log index =1, it
|
// This entry will be added at log index =1, it
|
||||||
// is the parent entry we are looking for.
|
// is the parent entry we are looking for.
|
||||||
{
|
{
|
||||||
HtlcIndex: 2,
|
HtlcIndex: 2,
|
||||||
addCommitHeightLocal: 100,
|
addCommitHeights: lntypes.Dual[uint64]{
|
||||||
addCommitHeightRemote: 100,
|
Local: 100,
|
||||||
|
Remote: 100,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
whoseCommitChain: lntypes.Remote,
|
whoseCommitChain: lntypes.Remote,
|
||||||
@@ -8519,15 +8539,19 @@ func TestFetchParent(t *testing.T) {
|
|||||||
// This entry will be added at log index =0.
|
// This entry will be added at log index =0.
|
||||||
{
|
{
|
||||||
HtlcIndex: 1,
|
HtlcIndex: 1,
|
||||||
addCommitHeightLocal: 0,
|
addCommitHeights: lntypes.Dual[uint64]{
|
||||||
addCommitHeightRemote: 100,
|
Local: 0,
|
||||||
|
Remote: 100,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
// This entry will be added at log index =1, it
|
// This entry will be added at log index =1, it
|
||||||
// is the parent entry we are looking for.
|
// is the parent entry we are looking for.
|
||||||
{
|
{
|
||||||
HtlcIndex: 2,
|
HtlcIndex: 2,
|
||||||
addCommitHeightLocal: 100,
|
addCommitHeights: lntypes.Dual[uint64]{
|
||||||
addCommitHeightRemote: 100,
|
Local: 100,
|
||||||
|
Remote: 100,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
remoteEntries: nil,
|
remoteEntries: nil,
|
||||||
@@ -8626,6 +8650,7 @@ func TestEvaluateView(t *testing.T) {
|
|||||||
name string
|
name string
|
||||||
ourHtlcs []*paymentDescriptor
|
ourHtlcs []*paymentDescriptor
|
||||||
theirHtlcs []*paymentDescriptor
|
theirHtlcs []*paymentDescriptor
|
||||||
|
channelInitiator lntypes.ChannelParty
|
||||||
whoseCommitChain lntypes.ChannelParty
|
whoseCommitChain lntypes.ChannelParty
|
||||||
mutateState bool
|
mutateState bool
|
||||||
|
|
||||||
@@ -8655,6 +8680,7 @@ func TestEvaluateView(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "our fee update is applied",
|
name: "our fee update is applied",
|
||||||
|
channelInitiator: lntypes.Local,
|
||||||
whoseCommitChain: lntypes.Local,
|
whoseCommitChain: lntypes.Local,
|
||||||
mutateState: false,
|
mutateState: false,
|
||||||
ourHtlcs: []*paymentDescriptor{
|
ourHtlcs: []*paymentDescriptor{
|
||||||
@@ -8672,6 +8698,7 @@ func TestEvaluateView(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "their fee update is applied",
|
name: "their fee update is applied",
|
||||||
|
channelInitiator: lntypes.Remote,
|
||||||
whoseCommitChain: lntypes.Local,
|
whoseCommitChain: lntypes.Local,
|
||||||
mutateState: false,
|
mutateState: false,
|
||||||
ourHtlcs: []*paymentDescriptor{},
|
ourHtlcs: []*paymentDescriptor{},
|
||||||
@@ -8731,7 +8758,9 @@ func TestEvaluateView(t *testing.T) {
|
|||||||
HtlcIndex: 0,
|
HtlcIndex: 0,
|
||||||
Amount: htlcAddAmount,
|
Amount: htlcAddAmount,
|
||||||
EntryType: Add,
|
EntryType: Add,
|
||||||
addCommitHeightLocal: addHeight,
|
addCommitHeights: lntypes.Dual[uint64]{
|
||||||
|
Local: addHeight,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
theirHtlcs: []*paymentDescriptor{
|
theirHtlcs: []*paymentDescriptor{
|
||||||
@@ -8766,7 +8795,9 @@ func TestEvaluateView(t *testing.T) {
|
|||||||
HtlcIndex: 0,
|
HtlcIndex: 0,
|
||||||
Amount: htlcAddAmount,
|
Amount: htlcAddAmount,
|
||||||
EntryType: Add,
|
EntryType: Add,
|
||||||
addCommitHeightLocal: addHeight,
|
addCommitHeights: lntypes.Dual[uint64]{
|
||||||
|
Local: addHeight,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
theirHtlcs: []*paymentDescriptor{
|
theirHtlcs: []*paymentDescriptor{
|
||||||
@@ -8816,13 +8847,17 @@ func TestEvaluateView(t *testing.T) {
|
|||||||
HtlcIndex: 0,
|
HtlcIndex: 0,
|
||||||
Amount: htlcAddAmount,
|
Amount: htlcAddAmount,
|
||||||
EntryType: Add,
|
EntryType: Add,
|
||||||
addCommitHeightLocal: addHeight,
|
addCommitHeights: lntypes.Dual[uint64]{
|
||||||
|
Local: addHeight,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
HtlcIndex: 1,
|
HtlcIndex: 1,
|
||||||
Amount: htlcAddAmount,
|
Amount: htlcAddAmount,
|
||||||
EntryType: Add,
|
EntryType: Add,
|
||||||
addCommitHeightLocal: addHeight,
|
addCommitHeights: lntypes.Dual[uint64]{
|
||||||
|
Local: addHeight,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedFee: feePerKw,
|
expectedFee: feePerKw,
|
||||||
@@ -8860,7 +8895,9 @@ func TestEvaluateView(t *testing.T) {
|
|||||||
HtlcIndex: 0,
|
HtlcIndex: 0,
|
||||||
Amount: htlcAddAmount,
|
Amount: htlcAddAmount,
|
||||||
EntryType: Add,
|
EntryType: Add,
|
||||||
addCommitHeightLocal: addHeight,
|
addCommitHeights: lntypes.Dual[uint64]{
|
||||||
|
Local: addHeight,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedFee: feePerKw,
|
expectedFee: feePerKw,
|
||||||
@@ -8877,8 +8914,10 @@ func TestEvaluateView(t *testing.T) {
|
|||||||
test := test
|
test := test
|
||||||
|
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
isInitiator := test.channelInitiator == lntypes.Local
|
||||||
lc := LightningChannel{
|
lc := LightningChannel{
|
||||||
channelState: &channeldb.OpenChannel{
|
channelState: &channeldb.OpenChannel{
|
||||||
|
IsInitiator: isInitiator,
|
||||||
TotalMSatSent: 0,
|
TotalMSatSent: 0,
|
||||||
TotalMSatReceived: 0,
|
TotalMSatReceived: 0,
|
||||||
},
|
},
|
||||||
@@ -8907,40 +8946,62 @@ func TestEvaluateView(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
view := &HtlcView{
|
view := &HtlcView{
|
||||||
OurUpdates: test.ourHtlcs,
|
Updates: lntypes.Dual[[]*paymentDescriptor]{
|
||||||
TheirUpdates: test.theirHtlcs,
|
Local: test.ourHtlcs,
|
||||||
|
Remote: test.theirHtlcs,
|
||||||
|
},
|
||||||
FeePerKw: feePerKw,
|
FeePerKw: feePerKw,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
// Evaluate the htlc view, mutate as test expects.
|
||||||
// Create vars to store balance changes. We do
|
// We do not check the balance deltas in this test
|
||||||
// not check these values in this test because
|
// because balance modification happens on the htlc
|
||||||
// balance modification happens on the htlc
|
|
||||||
// processing level.
|
// processing level.
|
||||||
ourBalance lnwire.MilliSatoshi
|
result, uncommitted, _, err := lc.evaluateHTLCView(
|
||||||
theirBalance lnwire.MilliSatoshi
|
view, test.whoseCommitChain, nextHeight,
|
||||||
)
|
)
|
||||||
|
|
||||||
// Evaluate the htlc view, mutate as test expects.
|
|
||||||
result, err := lc.evaluateHTLCView(
|
|
||||||
view, &ourBalance, &theirBalance, nextHeight,
|
|
||||||
test.whoseCommitChain, test.mutateState,
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(proofofkeags): This block is here because we
|
||||||
|
// extracted this code from a previous implementation
|
||||||
|
// of evaluateHTLCView, due to a reduced scope of
|
||||||
|
// responsibility of that function. Consider removing
|
||||||
|
// it from the test altogether.
|
||||||
|
if test.mutateState {
|
||||||
|
for _, party := range lntypes.BothParties {
|
||||||
|
us := uncommitted.GetForParty(party)
|
||||||
|
for _, u := range us {
|
||||||
|
u.setCommitHeight(
|
||||||
|
test.whoseCommitChain,
|
||||||
|
nextHeight,
|
||||||
|
)
|
||||||
|
if test.whoseCommitChain ==
|
||||||
|
lntypes.Local &&
|
||||||
|
u.EntryType == Settle {
|
||||||
|
|
||||||
|
lc.recordSettlement(
|
||||||
|
party, u.Amount,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if result.FeePerKw != test.expectedFee {
|
if result.FeePerKw != test.expectedFee {
|
||||||
t.Fatalf("expected fee: %v, got: %v",
|
t.Fatalf("expected fee: %v, got: %v",
|
||||||
test.expectedFee, result.FeePerKw)
|
test.expectedFee, result.FeePerKw)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkExpectedHtlcs(
|
checkExpectedHtlcs(
|
||||||
t, result.OurUpdates, test.ourExpectedHtlcs,
|
t, result.Updates.Local, test.ourExpectedHtlcs,
|
||||||
)
|
)
|
||||||
|
|
||||||
checkExpectedHtlcs(
|
checkExpectedHtlcs(
|
||||||
t, result.TheirUpdates, test.theirExpectedHtlcs,
|
t, result.Updates.Remote,
|
||||||
|
test.theirExpectedHtlcs,
|
||||||
)
|
)
|
||||||
|
|
||||||
if lc.channelState.TotalMSatSent != test.expectSent {
|
if lc.channelState.TotalMSatSent != test.expectSent {
|
||||||
@@ -8987,617 +9048,6 @@ type heights struct {
|
|||||||
remoteRemove uint64
|
remoteRemove uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestProcessFeeUpdate tests the applying of fee updates and mutation of
|
|
||||||
// local and remote add and remove heights on update messages.
|
|
||||||
func TestProcessFeeUpdate(t *testing.T) {
|
|
||||||
const (
|
|
||||||
// height is a non-zero height that can be used for htlcs
|
|
||||||
// heights.
|
|
||||||
height = 200
|
|
||||||
|
|
||||||
// nextHeight is a constant that we use for the next height in
|
|
||||||
// all unit tests.
|
|
||||||
nextHeight = 400
|
|
||||||
|
|
||||||
// feePerKw is the fee we start all of our unit tests with.
|
|
||||||
feePerKw = 1
|
|
||||||
|
|
||||||
// ourFeeUpdateAmt is an amount that we update fees to expressed
|
|
||||||
// in msat.
|
|
||||||
ourFeeUpdateAmt = 20000
|
|
||||||
|
|
||||||
// ourFeeUpdatePerSat is the fee rate *in satoshis* that we
|
|
||||||
// expect if we update to ourFeeUpdateAmt.
|
|
||||||
ourFeeUpdatePerSat = chainfee.SatPerKWeight(20)
|
|
||||||
)
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
startHeights heights
|
|
||||||
expectedHeights heights
|
|
||||||
whoseCommitChain lntypes.ChannelParty
|
|
||||||
mutate bool
|
|
||||||
expectedFee chainfee.SatPerKWeight
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
// Looking at local chain, local add is non-zero so
|
|
||||||
// the update has been applied already; no fee change.
|
|
||||||
name: "non-zero local height, fee unchanged",
|
|
||||||
startHeights: heights{
|
|
||||||
localAdd: height,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteAdd: 0,
|
|
||||||
remoteRemove: height,
|
|
||||||
},
|
|
||||||
expectedHeights: heights{
|
|
||||||
localAdd: height,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteAdd: 0,
|
|
||||||
remoteRemove: height,
|
|
||||||
},
|
|
||||||
whoseCommitChain: lntypes.Local,
|
|
||||||
mutate: false,
|
|
||||||
expectedFee: feePerKw,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Looking at local chain, local add is zero so the
|
|
||||||
// update has not been applied yet; we expect a fee
|
|
||||||
// update.
|
|
||||||
name: "zero local height, fee changed",
|
|
||||||
startHeights: heights{
|
|
||||||
localAdd: 0,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteAdd: height,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
expectedHeights: heights{
|
|
||||||
localAdd: 0,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteAdd: height,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
whoseCommitChain: lntypes.Local,
|
|
||||||
mutate: false,
|
|
||||||
expectedFee: ourFeeUpdatePerSat,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Looking at remote chain, the remote add height is
|
|
||||||
// zero, so the update has not been applied so we expect
|
|
||||||
// a fee change.
|
|
||||||
name: "zero remote height, fee changed",
|
|
||||||
startHeights: heights{
|
|
||||||
localAdd: height,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteAdd: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
expectedHeights: heights{
|
|
||||||
localAdd: height,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteAdd: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
whoseCommitChain: lntypes.Remote,
|
|
||||||
mutate: false,
|
|
||||||
expectedFee: ourFeeUpdatePerSat,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Looking at remote chain, the remote add height is
|
|
||||||
// non-zero, so the update has been applied so we expect
|
|
||||||
// no fee change.
|
|
||||||
name: "non-zero remote height, no fee change",
|
|
||||||
startHeights: heights{
|
|
||||||
localAdd: height,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteAdd: height,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
expectedHeights: heights{
|
|
||||||
localAdd: height,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteAdd: height,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
whoseCommitChain: lntypes.Remote,
|
|
||||||
mutate: false,
|
|
||||||
expectedFee: feePerKw,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Local add height is non-zero, so the update has
|
|
||||||
// already been applied; we do not expect fee to
|
|
||||||
// change or any mutations to be applied.
|
|
||||||
name: "non-zero local height, mutation not applied",
|
|
||||||
startHeights: heights{
|
|
||||||
localAdd: height,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteAdd: 0,
|
|
||||||
remoteRemove: height,
|
|
||||||
},
|
|
||||||
expectedHeights: heights{
|
|
||||||
localAdd: height,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteAdd: 0,
|
|
||||||
remoteRemove: height,
|
|
||||||
},
|
|
||||||
whoseCommitChain: lntypes.Local,
|
|
||||||
mutate: true,
|
|
||||||
expectedFee: feePerKw,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Local add is zero and we are looking at our local
|
|
||||||
// chain, so the update has not been applied yet. We
|
|
||||||
// expect the local add and remote heights to be
|
|
||||||
// mutated.
|
|
||||||
name: "zero height, fee changed, mutation applied",
|
|
||||||
startHeights: heights{
|
|
||||||
localAdd: 0,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteAdd: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
expectedHeights: heights{
|
|
||||||
localAdd: nextHeight,
|
|
||||||
localRemove: nextHeight,
|
|
||||||
remoteAdd: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
whoseCommitChain: lntypes.Local,
|
|
||||||
mutate: true,
|
|
||||||
expectedFee: ourFeeUpdatePerSat,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
test := test
|
|
||||||
|
|
||||||
t.Run(test.name, func(t *testing.T) {
|
|
||||||
// Create a fee update with add and remove heights as
|
|
||||||
// set in the test.
|
|
||||||
heights := test.startHeights
|
|
||||||
update := &paymentDescriptor{
|
|
||||||
Amount: ourFeeUpdateAmt,
|
|
||||||
addCommitHeightRemote: heights.remoteAdd,
|
|
||||||
addCommitHeightLocal: heights.localAdd,
|
|
||||||
removeCommitHeightRemote: heights.remoteRemove,
|
|
||||||
removeCommitHeightLocal: heights.localRemove,
|
|
||||||
EntryType: FeeUpdate,
|
|
||||||
}
|
|
||||||
|
|
||||||
view := &HtlcView{
|
|
||||||
FeePerKw: chainfee.SatPerKWeight(feePerKw),
|
|
||||||
}
|
|
||||||
processFeeUpdate(
|
|
||||||
update, nextHeight, test.whoseCommitChain,
|
|
||||||
test.mutate, view,
|
|
||||||
)
|
|
||||||
|
|
||||||
if view.FeePerKw != test.expectedFee {
|
|
||||||
t.Fatalf("expected fee: %v, got: %v",
|
|
||||||
test.expectedFee, feePerKw)
|
|
||||||
}
|
|
||||||
|
|
||||||
checkHeights(t, update, test.expectedHeights)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkHeights(t *testing.T, update *paymentDescriptor, expected heights) {
|
|
||||||
updateHeights := heights{
|
|
||||||
localAdd: update.addCommitHeightLocal,
|
|
||||||
localRemove: update.removeCommitHeightLocal,
|
|
||||||
remoteAdd: update.addCommitHeightRemote,
|
|
||||||
remoteRemove: update.removeCommitHeightRemote,
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(updateHeights, expected) {
|
|
||||||
t.Fatalf("expected: %v, got: %v", expected, updateHeights)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestProcessAddRemoveEntry tests the updating of our and their balances when
|
|
||||||
// we process adds, settles and fails. It also tests the mutating of add and
|
|
||||||
// remove heights.
|
|
||||||
func TestProcessAddRemoveEntry(t *testing.T) {
|
|
||||||
const (
|
|
||||||
// addHeight is a non-zero addHeight that is used for htlc
|
|
||||||
// add heights.
|
|
||||||
addHeight = 100
|
|
||||||
|
|
||||||
// removeHeight is a non-zero removeHeight that is used for
|
|
||||||
// htlc remove heights.
|
|
||||||
removeHeight = 200
|
|
||||||
|
|
||||||
// nextHeight is a constant that we use for the nextHeight in
|
|
||||||
// all unit tests.
|
|
||||||
nextHeight = 400
|
|
||||||
|
|
||||||
// updateAmount is the amount that the update is set to.
|
|
||||||
updateAmount = lnwire.MilliSatoshi(10)
|
|
||||||
|
|
||||||
// startBalance is a balance we start both sides out with
|
|
||||||
// so that balances can be incremented.
|
|
||||||
startBalance = lnwire.MilliSatoshi(100)
|
|
||||||
)
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
startHeights heights
|
|
||||||
whoseCommitChain lntypes.ChannelParty
|
|
||||||
isIncoming bool
|
|
||||||
mutateState bool
|
|
||||||
ourExpectedBalance lnwire.MilliSatoshi
|
|
||||||
theirExpectedBalance lnwire.MilliSatoshi
|
|
||||||
expectedHeights heights
|
|
||||||
updateType updateType
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "add, remote chain, already processed",
|
|
||||||
startHeights: heights{
|
|
||||||
localAdd: 0,
|
|
||||||
remoteAdd: addHeight,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
whoseCommitChain: lntypes.Remote,
|
|
||||||
isIncoming: false,
|
|
||||||
mutateState: false,
|
|
||||||
ourExpectedBalance: startBalance,
|
|
||||||
theirExpectedBalance: startBalance,
|
|
||||||
expectedHeights: heights{
|
|
||||||
localAdd: 0,
|
|
||||||
remoteAdd: addHeight,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
updateType: Add,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "add, local chain, already processed",
|
|
||||||
startHeights: heights{
|
|
||||||
localAdd: addHeight,
|
|
||||||
remoteAdd: 0,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
whoseCommitChain: lntypes.Local,
|
|
||||||
isIncoming: false,
|
|
||||||
mutateState: false,
|
|
||||||
ourExpectedBalance: startBalance,
|
|
||||||
theirExpectedBalance: startBalance,
|
|
||||||
expectedHeights: heights{
|
|
||||||
localAdd: addHeight,
|
|
||||||
remoteAdd: 0,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
updateType: Add,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "incoming add, local chain, not mutated",
|
|
||||||
startHeights: heights{
|
|
||||||
localAdd: 0,
|
|
||||||
remoteAdd: 0,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
whoseCommitChain: lntypes.Local,
|
|
||||||
isIncoming: true,
|
|
||||||
mutateState: false,
|
|
||||||
ourExpectedBalance: startBalance,
|
|
||||||
theirExpectedBalance: startBalance - updateAmount,
|
|
||||||
expectedHeights: heights{
|
|
||||||
localAdd: 0,
|
|
||||||
remoteAdd: 0,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
updateType: Add,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "incoming add, local chain, mutated",
|
|
||||||
startHeights: heights{
|
|
||||||
localAdd: 0,
|
|
||||||
remoteAdd: 0,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
whoseCommitChain: lntypes.Local,
|
|
||||||
isIncoming: true,
|
|
||||||
mutateState: true,
|
|
||||||
ourExpectedBalance: startBalance,
|
|
||||||
theirExpectedBalance: startBalance - updateAmount,
|
|
||||||
expectedHeights: heights{
|
|
||||||
localAdd: nextHeight,
|
|
||||||
remoteAdd: 0,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
updateType: Add,
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: "outgoing add, remote chain, not mutated",
|
|
||||||
startHeights: heights{
|
|
||||||
localAdd: 0,
|
|
||||||
remoteAdd: 0,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
whoseCommitChain: lntypes.Remote,
|
|
||||||
isIncoming: false,
|
|
||||||
mutateState: false,
|
|
||||||
ourExpectedBalance: startBalance - updateAmount,
|
|
||||||
theirExpectedBalance: startBalance,
|
|
||||||
expectedHeights: heights{
|
|
||||||
localAdd: 0,
|
|
||||||
remoteAdd: 0,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
updateType: Add,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "outgoing add, remote chain, mutated",
|
|
||||||
startHeights: heights{
|
|
||||||
localAdd: 0,
|
|
||||||
remoteAdd: 0,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
whoseCommitChain: lntypes.Remote,
|
|
||||||
isIncoming: false,
|
|
||||||
mutateState: true,
|
|
||||||
ourExpectedBalance: startBalance - updateAmount,
|
|
||||||
theirExpectedBalance: startBalance,
|
|
||||||
expectedHeights: heights{
|
|
||||||
localAdd: 0,
|
|
||||||
remoteAdd: nextHeight,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
updateType: Add,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "settle, remote chain, already processed",
|
|
||||||
startHeights: heights{
|
|
||||||
localAdd: addHeight,
|
|
||||||
remoteAdd: addHeight,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: removeHeight,
|
|
||||||
},
|
|
||||||
whoseCommitChain: lntypes.Remote,
|
|
||||||
isIncoming: false,
|
|
||||||
mutateState: false,
|
|
||||||
ourExpectedBalance: startBalance,
|
|
||||||
theirExpectedBalance: startBalance,
|
|
||||||
expectedHeights: heights{
|
|
||||||
localAdd: addHeight,
|
|
||||||
remoteAdd: addHeight,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: removeHeight,
|
|
||||||
},
|
|
||||||
updateType: Settle,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "settle, local chain, already processed",
|
|
||||||
startHeights: heights{
|
|
||||||
localAdd: addHeight,
|
|
||||||
remoteAdd: addHeight,
|
|
||||||
localRemove: removeHeight,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
whoseCommitChain: lntypes.Local,
|
|
||||||
isIncoming: false,
|
|
||||||
mutateState: false,
|
|
||||||
ourExpectedBalance: startBalance,
|
|
||||||
theirExpectedBalance: startBalance,
|
|
||||||
expectedHeights: heights{
|
|
||||||
localAdd: addHeight,
|
|
||||||
remoteAdd: addHeight,
|
|
||||||
localRemove: removeHeight,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
updateType: Settle,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Remote chain, and not processed yet. Incoming settle,
|
|
||||||
// so we expect our balance to increase.
|
|
||||||
name: "incoming settle",
|
|
||||||
startHeights: heights{
|
|
||||||
localAdd: addHeight,
|
|
||||||
remoteAdd: addHeight,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
whoseCommitChain: lntypes.Remote,
|
|
||||||
isIncoming: true,
|
|
||||||
mutateState: false,
|
|
||||||
ourExpectedBalance: startBalance + updateAmount,
|
|
||||||
theirExpectedBalance: startBalance,
|
|
||||||
expectedHeights: heights{
|
|
||||||
localAdd: addHeight,
|
|
||||||
remoteAdd: addHeight,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
updateType: Settle,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Remote chain, and not processed yet. Incoming settle,
|
|
||||||
// so we expect our balance to increase.
|
|
||||||
name: "outgoing settle",
|
|
||||||
startHeights: heights{
|
|
||||||
localAdd: addHeight,
|
|
||||||
remoteAdd: addHeight,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
whoseCommitChain: lntypes.Remote,
|
|
||||||
isIncoming: false,
|
|
||||||
mutateState: false,
|
|
||||||
ourExpectedBalance: startBalance,
|
|
||||||
theirExpectedBalance: startBalance + updateAmount,
|
|
||||||
expectedHeights: heights{
|
|
||||||
localAdd: addHeight,
|
|
||||||
remoteAdd: addHeight,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
updateType: Settle,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Remote chain, and not processed yet. Incoming fail,
|
|
||||||
// so we expect their balance to increase.
|
|
||||||
name: "incoming fail",
|
|
||||||
startHeights: heights{
|
|
||||||
localAdd: addHeight,
|
|
||||||
remoteAdd: addHeight,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
whoseCommitChain: lntypes.Remote,
|
|
||||||
isIncoming: true,
|
|
||||||
mutateState: false,
|
|
||||||
ourExpectedBalance: startBalance,
|
|
||||||
theirExpectedBalance: startBalance + updateAmount,
|
|
||||||
expectedHeights: heights{
|
|
||||||
localAdd: addHeight,
|
|
||||||
remoteAdd: addHeight,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
updateType: Fail,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Remote chain, and not processed yet. Outgoing fail,
|
|
||||||
// so we expect our balance to increase.
|
|
||||||
name: "outgoing fail",
|
|
||||||
startHeights: heights{
|
|
||||||
localAdd: addHeight,
|
|
||||||
remoteAdd: addHeight,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
whoseCommitChain: lntypes.Remote,
|
|
||||||
isIncoming: false,
|
|
||||||
mutateState: false,
|
|
||||||
ourExpectedBalance: startBalance + updateAmount,
|
|
||||||
theirExpectedBalance: startBalance,
|
|
||||||
expectedHeights: heights{
|
|
||||||
localAdd: addHeight,
|
|
||||||
remoteAdd: addHeight,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
updateType: Fail,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Local chain, and not processed yet. Incoming settle,
|
|
||||||
// so we expect our balance to increase. Mutate is
|
|
||||||
// true, so we expect our remove removeHeight to have
|
|
||||||
// changed.
|
|
||||||
name: "fail, our remove height mutated",
|
|
||||||
startHeights: heights{
|
|
||||||
localAdd: addHeight,
|
|
||||||
remoteAdd: addHeight,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
whoseCommitChain: lntypes.Local,
|
|
||||||
isIncoming: true,
|
|
||||||
mutateState: true,
|
|
||||||
ourExpectedBalance: startBalance + updateAmount,
|
|
||||||
theirExpectedBalance: startBalance,
|
|
||||||
expectedHeights: heights{
|
|
||||||
localAdd: addHeight,
|
|
||||||
remoteAdd: addHeight,
|
|
||||||
localRemove: nextHeight,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
updateType: Settle,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Remote chain, and not processed yet. Incoming settle,
|
|
||||||
// so we expect our balance to increase. Mutate is
|
|
||||||
// true, so we expect their remove removeHeight to have
|
|
||||||
// changed.
|
|
||||||
name: "fail, their remove height mutated",
|
|
||||||
startHeights: heights{
|
|
||||||
localAdd: addHeight,
|
|
||||||
remoteAdd: addHeight,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: 0,
|
|
||||||
},
|
|
||||||
whoseCommitChain: lntypes.Remote,
|
|
||||||
isIncoming: true,
|
|
||||||
mutateState: true,
|
|
||||||
ourExpectedBalance: startBalance + updateAmount,
|
|
||||||
theirExpectedBalance: startBalance,
|
|
||||||
expectedHeights: heights{
|
|
||||||
localAdd: addHeight,
|
|
||||||
remoteAdd: addHeight,
|
|
||||||
localRemove: 0,
|
|
||||||
remoteRemove: nextHeight,
|
|
||||||
},
|
|
||||||
updateType: Settle,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
test := test
|
|
||||||
|
|
||||||
t.Run(test.name, func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
heights := test.startHeights
|
|
||||||
update := &paymentDescriptor{
|
|
||||||
Amount: updateAmount,
|
|
||||||
addCommitHeightLocal: heights.localAdd,
|
|
||||||
addCommitHeightRemote: heights.remoteAdd,
|
|
||||||
removeCommitHeightLocal: heights.localRemove,
|
|
||||||
removeCommitHeightRemote: heights.remoteRemove,
|
|
||||||
EntryType: test.updateType,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
// Start both parties off with an initial
|
|
||||||
// balance. Copy by value here so that we do
|
|
||||||
// not mutate the startBalance constant.
|
|
||||||
ourBalance, theirBalance = startBalance,
|
|
||||||
startBalance
|
|
||||||
)
|
|
||||||
|
|
||||||
// Choose the processing function we need based on the
|
|
||||||
// update type. Process remove is used for settles,
|
|
||||||
// fails and malformed htlcs.
|
|
||||||
process := processRemoveEntry
|
|
||||||
if test.updateType == Add {
|
|
||||||
process = processAddEntry
|
|
||||||
}
|
|
||||||
|
|
||||||
process(
|
|
||||||
update, &ourBalance, &theirBalance, nextHeight,
|
|
||||||
test.whoseCommitChain, test.isIncoming,
|
|
||||||
test.mutateState,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Check that balances were updated as expected.
|
|
||||||
if ourBalance != test.ourExpectedBalance {
|
|
||||||
t.Fatalf("expected our balance: %v, got: %v",
|
|
||||||
test.ourExpectedBalance, ourBalance)
|
|
||||||
}
|
|
||||||
|
|
||||||
if theirBalance != test.theirExpectedBalance {
|
|
||||||
t.Fatalf("expected their balance: %v, got: %v",
|
|
||||||
test.theirExpectedBalance, theirBalance)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that heights on the update are as expected.
|
|
||||||
checkHeights(t, update, test.expectedHeights)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestChannelUnsignedAckedFailure tests that unsigned acked updates are
|
// TestChannelUnsignedAckedFailure tests that unsigned acked updates are
|
||||||
// properly restored after signing for them and disconnecting.
|
// properly restored after signing for them and disconnecting.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -702,7 +702,7 @@ func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance,
|
|||||||
}
|
}
|
||||||
|
|
||||||
numHTLCs := int64(0)
|
numHTLCs := int64(0)
|
||||||
for _, htlc := range filteredHTLCView.OurUpdates {
|
for _, htlc := range filteredHTLCView.Updates.Local {
|
||||||
if HtlcIsDust(
|
if HtlcIsDust(
|
||||||
cb.chanState.ChanType, false, whoseCommit, feePerKw,
|
cb.chanState.ChanType, false, whoseCommit, feePerKw,
|
||||||
htlc.Amount.ToSatoshis(), dustLimit,
|
htlc.Amount.ToSatoshis(), dustLimit,
|
||||||
@@ -713,7 +713,7 @@ func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance,
|
|||||||
|
|
||||||
numHTLCs++
|
numHTLCs++
|
||||||
}
|
}
|
||||||
for _, htlc := range filteredHTLCView.TheirUpdates {
|
for _, htlc := range filteredHTLCView.Updates.Remote {
|
||||||
if HtlcIsDust(
|
if HtlcIsDust(
|
||||||
cb.chanState.ChanType, true, whoseCommit, feePerKw,
|
cb.chanState.ChanType, true, whoseCommit, feePerKw,
|
||||||
htlc.Amount.ToSatoshis(), dustLimit,
|
htlc.Amount.ToSatoshis(), dustLimit,
|
||||||
@@ -827,7 +827,7 @@ func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance,
|
|||||||
// purposes of sorting.
|
// purposes of sorting.
|
||||||
cltvs := make([]uint32, len(commitTx.TxOut))
|
cltvs := make([]uint32, len(commitTx.TxOut))
|
||||||
htlcIndexes := make([]input.HtlcIndex, len(commitTx.TxOut))
|
htlcIndexes := make([]input.HtlcIndex, len(commitTx.TxOut))
|
||||||
for _, htlc := range filteredHTLCView.OurUpdates {
|
for _, htlc := range filteredHTLCView.Updates.Local {
|
||||||
if HtlcIsDust(
|
if HtlcIsDust(
|
||||||
cb.chanState.ChanType, false, whoseCommit, feePerKw,
|
cb.chanState.ChanType, false, whoseCommit, feePerKw,
|
||||||
htlc.Amount.ToSatoshis(), dustLimit,
|
htlc.Amount.ToSatoshis(), dustLimit,
|
||||||
@@ -855,7 +855,7 @@ func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance,
|
|||||||
cltvs = append(cltvs, htlc.Timeout) //nolint
|
cltvs = append(cltvs, htlc.Timeout) //nolint
|
||||||
htlcIndexes = append(htlcIndexes, htlc.HtlcIndex) //nolint
|
htlcIndexes = append(htlcIndexes, htlc.HtlcIndex) //nolint
|
||||||
}
|
}
|
||||||
for _, htlc := range filteredHTLCView.TheirUpdates {
|
for _, htlc := range filteredHTLCView.Updates.Remote {
|
||||||
if HtlcIsDust(
|
if HtlcIsDust(
|
||||||
cb.chanState.ChanType, true, whoseCommit, feePerKw,
|
cb.chanState.ChanType, true, whoseCommit, feePerKw,
|
||||||
htlc.Amount.ToSatoshis(), dustLimit,
|
htlc.Amount.ToSatoshis(), dustLimit,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||||
"github.com/lightningnetwork/lnd/input"
|
"github.com/lightningnetwork/lnd/input"
|
||||||
|
"github.com/lightningnetwork/lnd/lntypes"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -165,16 +166,14 @@ type paymentDescriptor struct {
|
|||||||
// which included this HTLC on either the remote or local commitment
|
// which included this HTLC on either the remote or local commitment
|
||||||
// chain. This value is used to determine when an HTLC is fully
|
// chain. This value is used to determine when an HTLC is fully
|
||||||
// "locked-in".
|
// "locked-in".
|
||||||
addCommitHeightRemote uint64
|
addCommitHeights lntypes.Dual[uint64]
|
||||||
addCommitHeightLocal uint64
|
|
||||||
|
|
||||||
// removeCommitHeight[Remote|Local] encodes the height of the
|
// removeCommitHeight[Remote|Local] encodes the height of the
|
||||||
// commitment which removed the parent pointer of this
|
// commitment which removed the parent pointer of this
|
||||||
// paymentDescriptor either due to a timeout or a settle. Once both
|
// paymentDescriptor either due to a timeout or a settle. Once both
|
||||||
// these heights are below the tail of both chains, the log entries can
|
// these heights are below the tail of both chains, the log entries can
|
||||||
// safely be removed.
|
// safely be removed.
|
||||||
removeCommitHeightRemote uint64
|
removeCommitHeights lntypes.Dual[uint64]
|
||||||
removeCommitHeightLocal uint64
|
|
||||||
|
|
||||||
// OnionBlob is an opaque blob which is used to complete multi-hop
|
// OnionBlob is an opaque blob which is used to complete multi-hop
|
||||||
// routing.
|
// routing.
|
||||||
@@ -284,3 +283,31 @@ func (pd *paymentDescriptor) toLogUpdate() channeldb.LogUpdate {
|
|||||||
UpdateMsg: msg,
|
UpdateMsg: msg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setCommitHeight updates the appropriate addCommitHeight and/or
|
||||||
|
// removeCommitHeight for whoseCommitChain and locks it in at nextHeight.
|
||||||
|
func (pd *paymentDescriptor) setCommitHeight(
|
||||||
|
whoseCommitChain lntypes.ChannelParty, nextHeight uint64) {
|
||||||
|
|
||||||
|
switch pd.EntryType {
|
||||||
|
case Add:
|
||||||
|
pd.addCommitHeights.SetForParty(
|
||||||
|
whoseCommitChain, nextHeight,
|
||||||
|
)
|
||||||
|
case Settle, Fail, MalformedFail:
|
||||||
|
pd.removeCommitHeights.SetForParty(
|
||||||
|
whoseCommitChain, nextHeight,
|
||||||
|
)
|
||||||
|
case FeeUpdate:
|
||||||
|
// Fee updates are applied for all commitments
|
||||||
|
// after they are sent/received, so we consider
|
||||||
|
// them being added and removed at the same
|
||||||
|
// height.
|
||||||
|
pd.addCommitHeights.SetForParty(
|
||||||
|
whoseCommitChain, nextHeight,
|
||||||
|
)
|
||||||
|
pd.removeCommitHeights.SetForParty(
|
||||||
|
whoseCommitChain, nextHeight,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -153,6 +153,7 @@ func compactLogs(ourLog, theirLog *updateLog,
|
|||||||
nextA = e.Next()
|
nextA = e.Next()
|
||||||
|
|
||||||
htlc := e.Value
|
htlc := e.Value
|
||||||
|
rmvHeights := htlc.removeCommitHeights
|
||||||
|
|
||||||
// We skip Adds, as they will be removed along with the
|
// We skip Adds, as they will be removed along with the
|
||||||
// fail/settles below.
|
// fail/settles below.
|
||||||
@@ -162,9 +163,7 @@ func compactLogs(ourLog, theirLog *updateLog,
|
|||||||
|
|
||||||
// If the HTLC hasn't yet been removed from either
|
// If the HTLC hasn't yet been removed from either
|
||||||
// chain, the skip it.
|
// chain, the skip it.
|
||||||
if htlc.removeCommitHeightRemote == 0 ||
|
if rmvHeights.Remote == 0 || rmvHeights.Local == 0 {
|
||||||
htlc.removeCommitHeightLocal == 0 {
|
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,8 +171,8 @@ func compactLogs(ourLog, theirLog *updateLog,
|
|||||||
// is at least the height in which the HTLC was
|
// is at least the height in which the HTLC was
|
||||||
// removed, then evict the settle/timeout entry along
|
// removed, then evict the settle/timeout entry along
|
||||||
// with the original add entry.
|
// with the original add entry.
|
||||||
if remoteChainTail >= htlc.removeCommitHeightRemote &&
|
if remoteChainTail >= rmvHeights.Remote &&
|
||||||
localChainTail >= htlc.removeCommitHeightLocal {
|
localChainTail >= rmvHeights.Local {
|
||||||
|
|
||||||
// Fee updates have no parent htlcs, so we only
|
// Fee updates have no parent htlcs, so we only
|
||||||
// remove the update itself.
|
// remove the update itself.
|
||||||
|
|||||||
Reference in new issue
Block a user