Merge pull request #8981 from ProofOfKeags/refactor/payment-descriptor-quarantine

[KILO]: Quarantine paymentDescriptor to the lnwallet package
This commit is contained in:
Oliver Gugger authored and GitHub committed 2024-09-12 09:09:02 -06:00
commit 750770e190
14 files changed
+552 -718

No files matched your search

+21
View File
@@ -286,6 +286,27 @@ func NewFwdPkg(source lnwire.ShortChannelID, height uint64,
} }
} }
// SourceRef is a convenience method that returns an AddRef to this forwarding
// package for the index in the argument. It is the caller's responsibility
// to ensure that the index is in bounds.
func (f *FwdPkg) SourceRef(i uint16) AddRef {
return AddRef{
Height: f.Height,
Index: i,
}
}
// DestRef is a convenience method that returns a SettleFailRef to this
// forwarding package for the index in the argument. It is the caller's
// responsibility to ensure that the index is in bounds.
func (f *FwdPkg) DestRef(i uint16) SettleFailRef {
return SettleFailRef{
Source: f.Source,
Height: f.Height,
Index: i,
}
}
// ID returns an unique identifier for this package, used to ensure that sphinx // ID returns an unique identifier for this package, used to ensure that sphinx
// replay processing of this batch is idempotent. // replay processing of this batch is idempotent.
func (f *FwdPkg) ID() []byte { func (f *FwdPkg) ID() []byte {
+120 -128
View File
@@ -442,7 +442,8 @@ func (m *hookMap) invoke() {
// hodlHtlc contains htlc data that is required for resolution. // hodlHtlc contains htlc data that is required for resolution.
type hodlHtlc struct { type hodlHtlc struct {
pd *lnwallet.PaymentDescriptor add lnwire.UpdateAddHTLC
sourceRef channeldb.AddRef
obfuscator hop.ErrorEncrypter obfuscator hop.ErrorEncrypter
} }
@@ -992,15 +993,7 @@ func (l *channelLink) resolveFwdPkg(fwdPkg *channeldb.FwdPkg) error {
// If the package is fully acked but not completed, it must still have // If the package is fully acked but not completed, it must still have
// settles and fails to propagate. // settles and fails to propagate.
if !fwdPkg.SettleFailFilter.IsFull() { if !fwdPkg.SettleFailFilter.IsFull() {
settleFails, err := lnwallet.PayDescsFromRemoteLogUpdates( l.processRemoteSettleFails(fwdPkg)
fwdPkg.Source, fwdPkg.Height, fwdPkg.SettleFails,
)
if err != nil {
l.log.Errorf("unable to process remote log updates: %v",
err)
return err
}
l.processRemoteSettleFails(fwdPkg, settleFails)
} }
// Finally, replay *ALL ADDS* in this forwarding package. The // Finally, replay *ALL ADDS* in this forwarding package. The
@@ -1008,15 +1001,7 @@ func (l *channelLink) resolveFwdPkg(fwdPkg *channeldb.FwdPkg) error {
// shove the entire, original set of adds down the pipeline so that the // shove the entire, original set of adds down the pipeline so that the
// batch of adds presented to the sphinx router does not ever change. // batch of adds presented to the sphinx router does not ever change.
if !fwdPkg.AckFilter.IsFull() { if !fwdPkg.AckFilter.IsFull() {
adds, err := lnwallet.PayDescsFromRemoteLogUpdates( l.processRemoteAdds(fwdPkg)
fwdPkg.Source, fwdPkg.Height, fwdPkg.Adds,
)
if err != nil {
l.log.Errorf("unable to process remote log updates: %v",
err)
return err
}
l.processRemoteAdds(fwdPkg, adds)
// If the link failed during processing the adds, we must // If the link failed during processing the adds, we must
// return to ensure we won't attempted to update the state // return to ensure we won't attempted to update the state
@@ -1520,7 +1505,9 @@ func (l *channelLink) processHtlcResolution(resolution invoices.HtlcResolution,
l.log.Debugf("received settle resolution for %v "+ l.log.Debugf("received settle resolution for %v "+
"with outcome: %v", circuitKey, res.Outcome) "with outcome: %v", circuitKey, res.Outcome)
return l.settleHTLC(res.Preimage, htlc.pd) return l.settleHTLC(
res.Preimage, htlc.add.ID, htlc.sourceRef,
)
// For htlc failures, we get the relevant failure message based // For htlc failures, we get the relevant failure message based
// on the failure resolution and then fail the htlc. // on the failure resolution and then fail the htlc.
@@ -1530,10 +1517,11 @@ func (l *channelLink) processHtlcResolution(resolution invoices.HtlcResolution,
// Get the lnwire failure message based on the resolution // Get the lnwire failure message based on the resolution
// result. // result.
failure := getResolutionFailure(res, htlc.pd.Amount) failure := getResolutionFailure(res, htlc.add.Amount)
l.sendHTLCError( l.sendHTLCError(
htlc.pd, failure, htlc.obfuscator, true, htlc.add, htlc.sourceRef, failure, htlc.obfuscator,
true,
) )
return nil return nil
@@ -2333,8 +2321,7 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) {
// We now process the message and advance our remote commit // We now process the message and advance our remote commit
// chain. // chain.
fwdPkg, adds, settleFails, remoteHTLCs, err := l.channel. fwdPkg, remoteHTLCs, err := l.channel.ReceiveRevocation(msg)
ReceiveRevocation(msg)
if err != nil { if err != nil {
// TODO(halseth): force close? // TODO(halseth): force close?
l.failf( l.failf(
@@ -2384,8 +2371,8 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) {
} }
} }
l.processRemoteSettleFails(fwdPkg, settleFails) l.processRemoteSettleFails(fwdPkg)
l.processRemoteAdds(fwdPkg, adds) l.processRemoteAdds(fwdPkg)
// If the link failed during processing the adds, we must // If the link failed during processing the adds, we must
// return to ensure we won't attempted to update the state // return to ensure we won't attempted to update the state
@@ -3291,17 +3278,17 @@ func (l *channelLink) updateChannelFee(feePerKw chainfee.SatPerKWeight) error {
// the context of the provided forwarding package. Any settles or fails that // the context of the provided forwarding package. Any settles or fails that
// have already been acknowledged in the forwarding package will not be sent to // have already been acknowledged in the forwarding package will not be sent to
// the switch. // the switch.
func (l *channelLink) processRemoteSettleFails(fwdPkg *channeldb.FwdPkg, func (l *channelLink) processRemoteSettleFails(fwdPkg *channeldb.FwdPkg) {
settleFails []*lnwallet.PaymentDescriptor) { if len(fwdPkg.SettleFails) == 0 {
if len(settleFails) == 0 {
return return
} }
l.log.Debugf("settle-fail-filter: %v", fwdPkg.SettleFailFilter) l.log.Debugf("settle-fail-filter: %v", fwdPkg.SettleFailFilter)
var switchPackets []*htlcPacket var switchPackets []*htlcPacket
for i, pd := range settleFails { for i, update := range fwdPkg.SettleFails {
destRef := fwdPkg.DestRef(uint16(i))
// Skip any settles or fails that have already been // Skip any settles or fails that have already been
// acknowledged by the incoming link that originated the // acknowledged by the incoming link that originated the
// forwarded Add. // forwarded Add.
@@ -3312,12 +3299,11 @@ func (l *channelLink) processRemoteSettleFails(fwdPkg *channeldb.FwdPkg,
// TODO(roasbeef): rework log entries to a shared // TODO(roasbeef): rework log entries to a shared
// interface. // interface.
switch pd.EntryType { switch msg := update.UpdateMsg.(type) {
// A settle for an HTLC we previously forwarded HTLC has been // A settle for an HTLC we previously forwarded HTLC has been
// received. So we'll forward the HTLC to the switch which will // received. So we'll forward the HTLC to the switch which will
// handle propagating the settle to the prior hop. // handle propagating the settle to the prior hop.
case lnwallet.Settle: case *lnwire.UpdateFulfillHTLC:
// If hodl.SettleIncoming is requested, we will not // If hodl.SettleIncoming is requested, we will not
// forward the SETTLE to the switch and will not signal // forward the SETTLE to the switch and will not signal
// a free slot on the commitment transaction. // a free slot on the commitment transaction.
@@ -3328,11 +3314,9 @@ func (l *channelLink) processRemoteSettleFails(fwdPkg *channeldb.FwdPkg,
settlePacket := &htlcPacket{ settlePacket := &htlcPacket{
outgoingChanID: l.ShortChanID(), outgoingChanID: l.ShortChanID(),
outgoingHTLCID: pd.ParentIndex, outgoingHTLCID: msg.ID,
destRef: pd.DestRef, destRef: &destRef,
htlc: &lnwire.UpdateFulfillHTLC{ htlc: msg,
PaymentPreimage: pd.RPreimage,
},
} }
// Add the packet to the batch to be forwarded, and // Add the packet to the batch to be forwarded, and
@@ -3344,7 +3328,7 @@ func (l *channelLink) processRemoteSettleFails(fwdPkg *channeldb.FwdPkg,
// been received. As a result a new slot will be freed up in // been received. As a result a new slot will be freed up in
// our commitment state, so we'll forward this to the switch so // our commitment state, so we'll forward this to the switch so
// the backwards undo can continue. // the backwards undo can continue.
case lnwallet.Fail: case *lnwire.UpdateFailHTLC:
// If hodl.SettleIncoming is requested, we will not // If hodl.SettleIncoming is requested, we will not
// forward the FAIL to the switch and will not signal a // forward the FAIL to the switch and will not signal a
// free slot on the commitment transaction. // free slot on the commitment transaction.
@@ -3359,16 +3343,12 @@ func (l *channelLink) processRemoteSettleFails(fwdPkg *channeldb.FwdPkg,
// set on the packet. // set on the packet.
failPacket := &htlcPacket{ failPacket := &htlcPacket{
outgoingChanID: l.ShortChanID(), outgoingChanID: l.ShortChanID(),
outgoingHTLCID: pd.ParentIndex, outgoingHTLCID: msg.ID,
destRef: pd.DestRef, destRef: &destRef,
htlc: &lnwire.UpdateFailHTLC{ htlc: msg,
Reason: lnwire.OpaqueReason(
pd.FailReason,
),
},
} }
l.log.Debugf("Failed to send %s", pd.Amount) l.log.Debugf("Failed to send HTLC with ID=%d", msg.ID)
// If the failure message lacks an HMAC (but includes // If the failure message lacks an HMAC (but includes
// the 4 bytes for encoding the message and padding // the 4 bytes for encoding the message and padding
@@ -3378,7 +3358,7 @@ func (l *channelLink) processRemoteSettleFails(fwdPkg *channeldb.FwdPkg,
// to an actual error, by encrypting it as if we were // to an actual error, by encrypting it as if we were
// the originating hop. // the originating hop.
convertedErrorSize := lnwire.FailureMessageLength + 4 convertedErrorSize := lnwire.FailureMessageLength + 4
if len(pd.FailReason) == convertedErrorSize { if len(msg.Reason) == convertedErrorSize {
failPacket.convertedError = true failPacket.convertedError = true
} }
@@ -3401,32 +3381,29 @@ func (l *channelLink) processRemoteSettleFails(fwdPkg *channeldb.FwdPkg,
// indicating whether this is the first time these Adds are being processed, or // indicating whether this is the first time these Adds are being processed, or
// whether we are reprocessing as a result of a failure or restart. Adds that // whether we are reprocessing as a result of a failure or restart. Adds that
// have already been acknowledged in the forwarding package will be ignored. // have already been acknowledged in the forwarding package will be ignored.
func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg, //
lockedInHtlcs []*lnwallet.PaymentDescriptor) { //nolint:funlen
func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg) {
l.log.Tracef("processing %d remote adds for height %d", l.log.Tracef("processing %d remote adds for height %d",
len(lockedInHtlcs), fwdPkg.Height) len(fwdPkg.Adds), fwdPkg.Height)
decodeReqs := make( decodeReqs := make(
[]hop.DecodeHopIteratorRequest, 0, len(lockedInHtlcs), []hop.DecodeHopIteratorRequest, 0, len(fwdPkg.Adds),
) )
for _, pd := range lockedInHtlcs { for _, update := range fwdPkg.Adds {
switch pd.EntryType { if msg, ok := update.UpdateMsg.(*lnwire.UpdateAddHTLC); ok {
// TODO(conner): remove type switch?
case lnwallet.Add:
// Before adding the new htlc to the state machine, // Before adding the new htlc to the state machine,
// parse the onion object in order to obtain the // parse the onion object in order to obtain the
// routing information with DecodeHopIterator function // routing information with DecodeHopIterator function
// which process the Sphinx packet. // which process the Sphinx packet.
onionReader := bytes.NewReader(pd.OnionBlob) onionReader := bytes.NewReader(msg.OnionBlob[:])
req := hop.DecodeHopIteratorRequest{ req := hop.DecodeHopIteratorRequest{
OnionReader: onionReader, OnionReader: onionReader,
RHash: pd.RHash[:], RHash: msg.PaymentHash[:],
IncomingCltv: pd.Timeout, IncomingCltv: msg.Expiry,
IncomingAmount: pd.Amount, IncomingAmount: msg.Amount,
BlindingPoint: pd.BlindingPoint, BlindingPoint: msg.BlindingPoint,
} }
decodeReqs = append(decodeReqs, req) decodeReqs = append(decodeReqs, req)
@@ -3448,9 +3425,13 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg,
var switchPackets []*htlcPacket var switchPackets []*htlcPacket
for i, pd := range lockedInHtlcs { for i, update := range fwdPkg.Adds {
idx := uint16(i) idx := uint16(i)
//nolint:forcetypeassert
add := *update.UpdateMsg.(*lnwire.UpdateAddHTLC)
sourceRef := fwdPkg.SourceRef(idx)
if fwdPkg.State == channeldb.FwdStateProcessed && if fwdPkg.State == channeldb.FwdStateProcessed &&
fwdPkg.AckFilter.Contains(idx) { fwdPkg.AckFilter.Contains(idx) {
@@ -3468,11 +3449,6 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg,
// or are able to settle it (and it adheres to our fee related // or are able to settle it (and it adheres to our fee related
// constraints). // constraints).
// Fetch the onion blob that was included within this processed
// payment descriptor.
var onionBlob [lnwire.OnionPacketSize]byte
copy(onionBlob[:], pd.OnionBlob)
// Before adding the new htlc to the state machine, parse the // Before adding the new htlc to the state machine, parse the
// onion object in order to obtain the routing information with // onion object in order to obtain the routing information with
// DecodeHopIterator function which process the Sphinx packet. // DecodeHopIterator function which process the Sphinx packet.
@@ -3481,8 +3457,9 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg,
// If we're unable to process the onion blob then we // If we're unable to process the onion blob then we
// should send the malformed htlc error to payment // should send the malformed htlc error to payment
// sender. // sender.
l.sendMalformedHTLCError(pd.HtlcIndex, failureCode, l.sendMalformedHTLCError(
onionBlob[:], pd.SourceRef) add.ID, failureCode, add.OnionBlob, &sourceRef,
)
l.log.Errorf("unable to decode onion hop "+ l.log.Errorf("unable to decode onion hop "+
"iterator: %v", failureCode) "iterator: %v", failureCode)
@@ -3526,8 +3503,8 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg,
// We can't process this htlc, send back // We can't process this htlc, send back
// malformed. // malformed.
l.sendMalformedHTLCError( l.sendMalformedHTLCError(
pd.HtlcIndex, failureCode, add.ID, failureCode, add.OnionBlob,
onionBlob[:], pd.SourceRef, &sourceRef,
) )
continue continue
@@ -3540,8 +3517,10 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg,
// payloads. Deferring this non-trival effort till a // payloads. Deferring this non-trival effort till a
// later date // later date
failure := lnwire.NewInvalidOnionPayload(failedType, 0) failure := lnwire.NewInvalidOnionPayload(failedType, 0)
l.sendHTLCError( l.sendHTLCError(
pd, NewLinkError(failure), obfuscator, false, add, sourceRef, NewLinkError(failure),
obfuscator, false,
) )
l.log.Errorf("unable to decode forwarding "+ l.log.Errorf("unable to decode forwarding "+
@@ -3561,8 +3540,8 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg,
// should send the malformed htlc error to payment // should send the malformed htlc error to payment
// sender. // sender.
l.sendMalformedHTLCError( l.sendMalformedHTLCError(
pd.HtlcIndex, failureCode, onionBlob[:], add.ID, failureCode, add.OnionBlob,
pd.SourceRef, &sourceRef,
) )
l.log.Errorf("unable to decode onion "+ l.log.Errorf("unable to decode onion "+
@@ -3581,10 +3560,12 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg,
l.cfg.DisallowRouteBlinding { l.cfg.DisallowRouteBlinding {
failure := lnwire.NewInvalidBlinding( failure := lnwire.NewInvalidBlinding(
onionBlob[:], fn.Some(add.OnionBlob),
) )
l.sendHTLCError( l.sendHTLCError(
pd, NewLinkError(failure), obfuscator, false, add, sourceRef, NewLinkError(failure),
obfuscator, false,
) )
l.log.Error("rejected htlc that uses use as an " + l.log.Error("rejected htlc that uses use as an " +
@@ -3597,7 +3578,8 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg,
switch fwdInfo.NextHop { switch fwdInfo.NextHop {
case hop.Exit: case hop.Exit:
err := l.processExitHop( err := l.processExitHop(
pd, obfuscator, fwdInfo, heightNow, pld, add, sourceRef, obfuscator, fwdInfo,
heightNow, pld,
) )
if err != nil { if err != nil {
l.failf(LinkFailureError{ l.failf(LinkFailureError{
@@ -3631,18 +3613,20 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg,
} }
// Otherwise, it was already processed, we can // Otherwise, it was already processed, we can
// collect it and continue. // can collect it and continue.
addMsg := &lnwire.UpdateAddHTLC{ outgoingAdd := &lnwire.UpdateAddHTLC{
Expiry: fwdInfo.OutgoingCTLV, Expiry: fwdInfo.OutgoingCTLV,
Amount: fwdInfo.AmountToForward, Amount: fwdInfo.AmountToForward,
PaymentHash: pd.RHash, PaymentHash: add.PaymentHash,
BlindingPoint: fwdInfo.NextBlinding, BlindingPoint: fwdInfo.NextBlinding,
} }
// Finally, we'll encode the onion packet for // Finally, we'll encode the onion packet for
// the _next_ hop using the hop iterator // the _next_ hop using the hop iterator
// decoded for the current hop. // decoded for the current hop.
buf := bytes.NewBuffer(addMsg.OnionBlob[0:0]) buf := bytes.NewBuffer(
outgoingAdd.OnionBlob[0:0],
)
// We know this cannot fail, as this ADD // We know this cannot fail, as this ADD
// was marked forwarded in a previous // was marked forwarded in a previous
@@ -3654,18 +3638,18 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg,
//nolint:lll //nolint:lll
updatePacket := &htlcPacket{ updatePacket := &htlcPacket{
incomingChanID: l.ShortChanID(), incomingChanID: l.ShortChanID(),
incomingHTLCID: pd.HtlcIndex, incomingHTLCID: add.ID,
outgoingChanID: fwdInfo.NextHop, outgoingChanID: fwdInfo.NextHop,
sourceRef: pd.SourceRef, sourceRef: &sourceRef,
incomingAmount: pd.Amount, incomingAmount: add.Amount,
amount: addMsg.Amount, amount: outgoingAdd.Amount,
htlc: addMsg, htlc: outgoingAdd,
obfuscator: obfuscator, obfuscator: obfuscator,
incomingTimeout: pd.Timeout, incomingTimeout: add.Expiry,
outgoingTimeout: fwdInfo.OutgoingCTLV, outgoingTimeout: fwdInfo.OutgoingCTLV,
inOnionCustomRecords: pld.CustomRecords(), inOnionCustomRecords: pld.CustomRecords(),
inboundFee: inboundFee, inboundFee: inboundFee,
inWireCustomRecords: pd.CustomRecords.Copy(), inWireCustomRecords: add.CustomRecords.Copy(),
} }
switchPackets = append( switchPackets = append(
switchPackets, updatePacket, switchPackets, updatePacket,
@@ -3683,7 +3667,7 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg,
addMsg := &lnwire.UpdateAddHTLC{ addMsg := &lnwire.UpdateAddHTLC{
Expiry: fwdInfo.OutgoingCTLV, Expiry: fwdInfo.OutgoingCTLV,
Amount: fwdInfo.AmountToForward, Amount: fwdInfo.AmountToForward,
PaymentHash: pd.RHash, PaymentHash: add.PaymentHash,
BlindingPoint: fwdInfo.NextBlinding, BlindingPoint: fwdInfo.NextBlinding,
} }
@@ -3705,7 +3689,8 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg,
) )
l.sendHTLCError( l.sendHTLCError(
pd, NewLinkError(failure), obfuscator, false, add, sourceRef, NewLinkError(failure),
obfuscator, false,
) )
continue continue
} }
@@ -3724,18 +3709,18 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg,
//nolint:lll //nolint:lll
updatePacket := &htlcPacket{ updatePacket := &htlcPacket{
incomingChanID: l.ShortChanID(), incomingChanID: l.ShortChanID(),
incomingHTLCID: pd.HtlcIndex, incomingHTLCID: add.ID,
outgoingChanID: fwdInfo.NextHop, outgoingChanID: fwdInfo.NextHop,
sourceRef: pd.SourceRef, sourceRef: &sourceRef,
incomingAmount: pd.Amount, incomingAmount: add.Amount,
amount: addMsg.Amount, amount: addMsg.Amount,
htlc: addMsg, htlc: addMsg,
obfuscator: obfuscator, obfuscator: obfuscator,
incomingTimeout: pd.Timeout, incomingTimeout: add.Expiry,
outgoingTimeout: fwdInfo.OutgoingCTLV, outgoingTimeout: fwdInfo.OutgoingCTLV,
inOnionCustomRecords: pld.CustomRecords(), inOnionCustomRecords: pld.CustomRecords(),
inboundFee: inboundFee, inboundFee: inboundFee,
inWireCustomRecords: pd.CustomRecords.Copy(), inWireCustomRecords: add.CustomRecords.Copy(),
} }
fwdPkg.FwdFilter.Set(idx) fwdPkg.FwdFilter.Set(idx)
@@ -3775,9 +3760,10 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg,
// processExitHop handles an htlc for which this link is the exit hop. It // processExitHop handles an htlc for which this link is the exit hop. It
// returns a boolean indicating whether the commitment tx needs an update. // returns a boolean indicating whether the commitment tx needs an update.
func (l *channelLink) processExitHop(pd *lnwallet.PaymentDescriptor, func (l *channelLink) processExitHop(add lnwire.UpdateAddHTLC,
obfuscator hop.ErrorEncrypter, fwdInfo hop.ForwardingInfo, sourceRef channeldb.AddRef, obfuscator hop.ErrorEncrypter,
heightNow uint32, payload invoices.Payload) error { fwdInfo hop.ForwardingInfo, heightNow uint32,
payload invoices.Payload) error {
// If hodl.ExitSettle is requested, we will not validate the final hop's // If hodl.ExitSettle is requested, we will not validate the final hop's
// ADD, nor will we settle the corresponding invoice or respond with the // ADD, nor will we settle the corresponding invoice or respond with the
@@ -3791,30 +3777,31 @@ func (l *channelLink) processExitHop(pd *lnwallet.PaymentDescriptor,
// As we're the exit hop, we'll double check the hop-payload included in // As we're the exit hop, we'll double check the hop-payload included in
// the HTLC to ensure that it was crafted correctly by the sender and // the HTLC to ensure that it was crafted correctly by the sender and
// is compatible with the HTLC we were extended. // is compatible with the HTLC we were extended.
if pd.Amount < fwdInfo.AmountToForward { if add.Amount < fwdInfo.AmountToForward {
l.log.Errorf("onion payload of incoming htlc(%x) has "+ l.log.Errorf("onion payload of incoming htlc(%x) has "+
"incompatible value: expected <=%v, got %v", pd.RHash, "incompatible value: expected <=%v, got %v",
pd.Amount, fwdInfo.AmountToForward) add.PaymentHash, add.Amount, fwdInfo.AmountToForward)
failure := NewLinkError( failure := NewLinkError(
lnwire.NewFinalIncorrectHtlcAmount(pd.Amount), lnwire.NewFinalIncorrectHtlcAmount(add.Amount),
) )
l.sendHTLCError(pd, failure, obfuscator, true) l.sendHTLCError(add, sourceRef, failure, obfuscator, true)
return nil return nil
} }
// We'll also ensure that our time-lock value has been computed // We'll also ensure that our time-lock value has been computed
// correctly. // correctly.
if pd.Timeout < fwdInfo.OutgoingCTLV { if add.Expiry < fwdInfo.OutgoingCTLV {
l.log.Errorf("onion payload of incoming htlc(%x) has "+ l.log.Errorf("onion payload of incoming htlc(%x) has "+
"incompatible time-lock: expected <=%v, got %v", "incompatible time-lock: expected <=%v, got %v",
pd.RHash[:], pd.Timeout, fwdInfo.OutgoingCTLV) add.PaymentHash, add.Expiry, fwdInfo.OutgoingCTLV)
failure := NewLinkError( failure := NewLinkError(
lnwire.NewFinalIncorrectCltvExpiry(pd.Timeout), lnwire.NewFinalIncorrectCltvExpiry(add.Expiry),
) )
l.sendHTLCError(pd, failure, obfuscator, true)
l.sendHTLCError(add, sourceRef, failure, obfuscator, true)
return nil return nil
} }
@@ -3822,15 +3809,15 @@ func (l *channelLink) processExitHop(pd *lnwallet.PaymentDescriptor,
// Notify the invoiceRegistry of the exit hop htlc. If we crash right // Notify the invoiceRegistry of the exit hop htlc. If we crash right
// after this, this code will be re-executed after restart. We will // after this, this code will be re-executed after restart. We will
// receive back a resolution event. // receive back a resolution event.
invoiceHash := lntypes.Hash(pd.RHash) invoiceHash := lntypes.Hash(add.PaymentHash)
circuitKey := models.CircuitKey{ circuitKey := models.CircuitKey{
ChanID: l.ShortChanID(), ChanID: l.ShortChanID(),
HtlcID: pd.HtlcIndex, HtlcID: add.ID,
} }
event, err := l.cfg.Registry.NotifyExitHopHtlc( event, err := l.cfg.Registry.NotifyExitHopHtlc(
invoiceHash, pd.Amount, pd.Timeout, int32(heightNow), invoiceHash, add.Amount, add.Expiry, int32(heightNow),
circuitKey, l.hodlQueue.ChanIn(), payload, circuitKey, l.hodlQueue.ChanIn(), payload,
) )
if err != nil { if err != nil {
@@ -3839,7 +3826,8 @@ func (l *channelLink) processExitHop(pd *lnwallet.PaymentDescriptor,
// Create a hodlHtlc struct and decide either resolved now or later. // Create a hodlHtlc struct and decide either resolved now or later.
htlc := hodlHtlc{ htlc := hodlHtlc{
pd: pd, add: add,
sourceRef: sourceRef,
obfuscator: obfuscator, obfuscator: obfuscator,
} }
@@ -3856,14 +3844,14 @@ func (l *channelLink) processExitHop(pd *lnwallet.PaymentDescriptor,
// settleHTLC settles the HTLC on the channel. // settleHTLC settles the HTLC on the channel.
func (l *channelLink) settleHTLC(preimage lntypes.Preimage, func (l *channelLink) settleHTLC(preimage lntypes.Preimage,
pd *lnwallet.PaymentDescriptor) error { htlcIndex uint64, sourceRef channeldb.AddRef) error {
hash := preimage.Hash() hash := preimage.Hash()
l.log.Infof("settling htlc %v as exit hop", hash) l.log.Infof("settling htlc %v as exit hop", hash)
err := l.channel.SettleHTLC( err := l.channel.SettleHTLC(
preimage, pd.HtlcIndex, pd.SourceRef, nil, nil, preimage, htlcIndex, &sourceRef, nil, nil,
) )
if err != nil { if err != nil {
return fmt.Errorf("unable to settle htlc: %w", err) return fmt.Errorf("unable to settle htlc: %w", err)
@@ -3881,7 +3869,7 @@ func (l *channelLink) settleHTLC(preimage lntypes.Preimage,
// remote peer. // remote peer.
l.cfg.Peer.SendMessage(false, &lnwire.UpdateFulfillHTLC{ l.cfg.Peer.SendMessage(false, &lnwire.UpdateFulfillHTLC{
ChanID: l.ChanID(), ChanID: l.ChanID(),
ID: pd.HtlcIndex, ID: htlcIndex,
PaymentPreimage: preimage, PaymentPreimage: preimage,
}) })
@@ -3890,7 +3878,7 @@ func (l *channelLink) settleHTLC(preimage lntypes.Preimage,
HtlcKey{ HtlcKey{
IncomingCircuit: models.CircuitKey{ IncomingCircuit: models.CircuitKey{
ChanID: l.ShortChanID(), ChanID: l.ShortChanID(),
HtlcID: pd.HtlcIndex, HtlcID: htlcIndex,
}, },
}, },
preimage, preimage,
@@ -3925,8 +3913,9 @@ func (l *channelLink) forwardBatch(replay bool, packets ...*htlcPacket) {
// sendHTLCError functions cancels HTLC and send cancel message back to the // sendHTLCError functions cancels HTLC and send cancel message back to the
// peer from which HTLC was received. // peer from which HTLC was received.
func (l *channelLink) sendHTLCError(pd *lnwallet.PaymentDescriptor, func (l *channelLink) sendHTLCError(add lnwire.UpdateAddHTLC,
failure *LinkError, e hop.ErrorEncrypter, isReceive bool) { sourceRef channeldb.AddRef, failure *LinkError,
e hop.ErrorEncrypter, isReceive bool) {
reason, err := e.EncryptFirstHop(failure.WireMessage()) reason, err := e.EncryptFirstHop(failure.WireMessage())
if err != nil { if err != nil {
@@ -3934,7 +3923,7 @@ func (l *channelLink) sendHTLCError(pd *lnwallet.PaymentDescriptor,
return return
} }
err = l.channel.FailHTLC(pd.HtlcIndex, reason, pd.SourceRef, nil, nil) err = l.channel.FailHTLC(add.ID, reason, &sourceRef, nil, nil)
if err != nil { if err != nil {
l.log.Errorf("unable cancel htlc: %v", err) l.log.Errorf("unable cancel htlc: %v", err)
return return
@@ -3943,7 +3932,7 @@ func (l *channelLink) sendHTLCError(pd *lnwallet.PaymentDescriptor,
// Send the appropriate failure message depending on whether we're // Send the appropriate failure message depending on whether we're
// in a blinded route or not. // in a blinded route or not.
if err := l.sendIncomingHTLCFailureMsg( if err := l.sendIncomingHTLCFailureMsg(
pd.HtlcIndex, e, reason, add.ID, e, reason,
); err != nil { ); err != nil {
l.log.Errorf("unable to send HTLC failure: %v", err) l.log.Errorf("unable to send HTLC failure: %v", err)
return return
@@ -3963,12 +3952,12 @@ func (l *channelLink) sendHTLCError(pd *lnwallet.PaymentDescriptor,
HtlcKey{ HtlcKey{
IncomingCircuit: models.CircuitKey{ IncomingCircuit: models.CircuitKey{
ChanID: l.ShortChanID(), ChanID: l.ShortChanID(),
HtlcID: pd.HtlcIndex, HtlcID: add.ID,
}, },
}, },
HtlcInfo{ HtlcInfo{
IncomingTimeLock: pd.Timeout, IncomingTimeLock: add.Expiry,
IncomingAmt: pd.Amount, IncomingAmt: add.Amount,
}, },
eventType, eventType,
failure, failure,
@@ -4027,7 +4016,9 @@ func (l *channelLink) sendIncomingHTLCFailureMsg(htlcIndex uint64,
// The specification does not require that we set the onion // The specification does not require that we set the onion
// blob. // blob.
failureMsg := lnwire.NewInvalidBlinding(nil) failureMsg := lnwire.NewInvalidBlinding(
fn.None[[lnwire.OnionPacketSize]byte](),
)
reason, err := e.EncryptFirstHop(failureMsg) reason, err := e.EncryptFirstHop(failureMsg)
if err != nil { if err != nil {
return err return err
@@ -4065,9 +4056,10 @@ func (l *channelLink) sendIncomingHTLCFailureMsg(htlcIndex uint64,
// sendMalformedHTLCError helper function which sends the malformed HTLC update // sendMalformedHTLCError helper function which sends the malformed HTLC update
// to the payment sender. // to the payment sender.
func (l *channelLink) sendMalformedHTLCError(htlcIndex uint64, func (l *channelLink) sendMalformedHTLCError(htlcIndex uint64,
code lnwire.FailCode, onionBlob []byte, sourceRef *channeldb.AddRef) { code lnwire.FailCode, onionBlob [lnwire.OnionPacketSize]byte,
sourceRef *channeldb.AddRef) {
shaOnionBlob := sha256.Sum256(onionBlob) shaOnionBlob := sha256.Sum256(onionBlob[:])
err := l.channel.MalformedFailHTLC(htlcIndex, code, shaOnionBlob, sourceRef) err := l.channel.MalformedFailHTLC(htlcIndex, code, shaOnionBlob, sourceRef)
if err != nil { if err != nil {
l.log.Errorf("unable cancel htlc: %v", err) l.log.Errorf("unable cancel htlc: %v", err)
+1 -1
View File
@@ -129,7 +129,7 @@ func (l *linkTestContext) receiveRevAndAckAliceToBob() {
l.t.Fatalf("expected RevokeAndAck, got %T", msg) l.t.Fatalf("expected RevokeAndAck, got %T", msg)
} }
_, _, _, _, err := l.bobChannel.ReceiveRevocation(rev) _, _, err := l.bobChannel.ReceiveRevocation(rev)
if err != nil { if err != nil {
l.t.Fatalf("bob failed receiving revocation: %v", err) l.t.Fatalf("bob failed receiving revocation: %v", err)
} }
+3 -3
View File
@@ -2335,7 +2335,7 @@ func handleStateUpdate(link *channelLink,
if !ok { if !ok {
return fmt.Errorf("expected RevokeAndAck got %T", msg) return fmt.Errorf("expected RevokeAndAck got %T", msg)
} }
_, _, _, _, err = remoteChannel.ReceiveRevocation(revoke) _, _, err = remoteChannel.ReceiveRevocation(revoke)
if err != nil { if err != nil {
return fmt.Errorf("unable to receive "+ return fmt.Errorf("unable to receive "+
"revocation: %v", err) "revocation: %v", err)
@@ -2389,7 +2389,7 @@ func updateState(batchTick chan time.Time, link *channelLink,
return fmt.Errorf("expected RevokeAndAck got %T", return fmt.Errorf("expected RevokeAndAck got %T",
msg) msg)
} }
_, _, _, _, err = remoteChannel.ReceiveRevocation(revoke) _, _, err = remoteChannel.ReceiveRevocation(revoke)
if err != nil { if err != nil {
return fmt.Errorf("unable to receive "+ return fmt.Errorf("unable to receive "+
"revocation: %v", err) "revocation: %v", err)
@@ -3643,7 +3643,7 @@ func TestChannelLinkTrimCircuitsRemoteCommit(t *testing.T) {
rev, _, _, err := harness.bobChannel.RevokeCurrentCommitment() rev, _, _, err := harness.bobChannel.RevokeCurrentCommitment()
require.NoError(t, err, "unable to revoke current commitment") require.NoError(t, err, "unable to revoke current commitment")
_, _, _, _, err = alice.channel.ReceiveRevocation(rev) _, _, err = alice.channel.ReceiveRevocation(rev)
require.NoError(t, err, "unable to receive revocation") require.NoError(t, err, "unable to receive revocation")
// Restart Alice's link, which simulates a disconnection with the remote // Restart Alice's link, which simulates a disconnection with the remote
+15 -25
View File
@@ -1911,18 +1911,8 @@ func (s *Switch) loadChannelFwdPkgs(source lnwire.ShortChannelID) ([]*channeldb.
// NOTE: This should mimic the behavior processRemoteSettleFails. // NOTE: This should mimic the behavior processRemoteSettleFails.
func (s *Switch) reforwardSettleFails(fwdPkgs []*channeldb.FwdPkg) { func (s *Switch) reforwardSettleFails(fwdPkgs []*channeldb.FwdPkg) {
for _, fwdPkg := range fwdPkgs { for _, fwdPkg := range fwdPkgs {
settleFails, err := lnwallet.PayDescsFromRemoteLogUpdates( switchPackets := make([]*htlcPacket, 0, len(fwdPkg.SettleFails))
fwdPkg.Source, fwdPkg.Height, fwdPkg.SettleFails, for i, update := range fwdPkg.SettleFails {
)
if err != nil {
log.Errorf("Unable to process remote log updates: %v",
err)
continue
}
switchPackets := make([]*htlcPacket, 0, len(settleFails))
for i, pd := range settleFails {
// Skip any settles or fails that have already been // Skip any settles or fails that have already been
// acknowledged by the incoming link that originated the // acknowledged by the incoming link that originated the
// forwarded Add. // forwarded Add.
@@ -1930,20 +1920,18 @@ func (s *Switch) reforwardSettleFails(fwdPkgs []*channeldb.FwdPkg) {
continue continue
} }
switch pd.EntryType { switch msg := update.UpdateMsg.(type) {
// A settle for an HTLC we previously forwarded HTLC has // A settle for an HTLC we previously forwarded HTLC has
// been received. So we'll forward the HTLC to the // been received. So we'll forward the HTLC to the
// switch which will handle propagating the settle to // switch which will handle propagating the settle to
// the prior hop. // the prior hop.
case lnwallet.Settle: case *lnwire.UpdateFulfillHTLC:
destRef := fwdPkg.DestRef(uint16(i))
settlePacket := &htlcPacket{ settlePacket := &htlcPacket{
outgoingChanID: fwdPkg.Source, outgoingChanID: fwdPkg.Source,
outgoingHTLCID: pd.ParentIndex, outgoingHTLCID: msg.ID,
destRef: pd.DestRef, destRef: &destRef,
htlc: &lnwire.UpdateFulfillHTLC{ htlc: msg,
PaymentPreimage: pd.RPreimage,
},
} }
// Add the packet to the batch to be forwarded, and // Add the packet to the batch to be forwarded, and
@@ -1955,7 +1943,7 @@ func (s *Switch) reforwardSettleFails(fwdPkgs []*channeldb.FwdPkg) {
// received. As a result a new slot will be freed up in our // received. As a result a new slot will be freed up in our
// commitment state, so we'll forward this to the switch so the // commitment state, so we'll forward this to the switch so the
// backwards undo can continue. // backwards undo can continue.
case lnwallet.Fail: case *lnwire.UpdateFailHTLC:
// Fetch the reason the HTLC was canceled so // Fetch the reason the HTLC was canceled so
// we can continue to propagate it. This // we can continue to propagate it. This
// failure originated from another node, so // failure originated from another node, so
@@ -1964,11 +1952,13 @@ func (s *Switch) reforwardSettleFails(fwdPkgs []*channeldb.FwdPkg) {
// additional circuit information for us. // additional circuit information for us.
failPacket := &htlcPacket{ failPacket := &htlcPacket{
outgoingChanID: fwdPkg.Source, outgoingChanID: fwdPkg.Source,
outgoingHTLCID: pd.ParentIndex, outgoingHTLCID: msg.ID,
destRef: pd.DestRef, destRef: &channeldb.SettleFailRef{
htlc: &lnwire.UpdateFailHTLC{ Source: fwdPkg.Source,
Reason: lnwire.OpaqueReason(pd.FailReason), Height: fwdPkg.Height,
Index: uint16(i),
}, },
htlc: msg,
} }
// Add the packet to the batch to be forwarded, and // Add the packet to the batch to be forwarded, and
+173 -425
View File
File diff suppressed because it is too large. Load diff
+121 -103
View File
@@ -132,7 +132,7 @@ func testAddSettleWorkflow(t *testing.T, tweakless bool,
// Alice then processes this revocation, sending her own revocation for // Alice then processes this revocation, sending her own revocation for
// her prior commitment transaction. Alice shouldn't have any HTLCs to // her prior commitment transaction. Alice shouldn't have any HTLCs to
// forward since she's sending an outgoing HTLC. // forward since she's sending an outgoing HTLC.
fwdPkg, _, _, _, err := aliceChannel.ReceiveRevocation(bobRevocation) fwdPkg, _, err := aliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err, "alice unable to process bob's revocation") require.NoError(t, err, "alice unable to process bob's revocation")
if len(fwdPkg.Adds) != 0 { if len(fwdPkg.Adds) != 0 {
t.Fatalf("alice forwards %v add htlcs, should forward none", t.Fatalf("alice forwards %v add htlcs, should forward none",
@@ -157,7 +157,7 @@ func testAddSettleWorkflow(t *testing.T, tweakless bool,
// is fully locked in within both commitment transactions. Bob should // is fully locked in within both commitment transactions. Bob should
// also be able to forward an HTLC now that the HTLC has been locked // also be able to forward an HTLC now that the HTLC has been locked
// into both commitment transactions. // into both commitment transactions.
fwdPkg, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) fwdPkg, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
require.NoError(t, err, "bob unable to process alice's revocation") require.NoError(t, err, "bob unable to process alice's revocation")
if len(fwdPkg.Adds) != 1 { if len(fwdPkg.Adds) != 1 {
t.Fatalf("bob forwards %v add htlcs, should only forward one", t.Fatalf("bob forwards %v add htlcs, should only forward one",
@@ -249,7 +249,7 @@ func testAddSettleWorkflow(t *testing.T, tweakless bool,
aliceNewCommit, err = aliceChannel.SignNextCommitment() aliceNewCommit, err = aliceChannel.SignNextCommitment()
require.NoError(t, err, "alice unable to sign new commitment") require.NoError(t, err, "alice unable to sign new commitment")
fwdPkg, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation2) fwdPkg, _, err = bobChannel.ReceiveRevocation(aliceRevocation2)
require.NoError(t, err, "bob unable to process alice's revocation") require.NoError(t, err, "bob unable to process alice's revocation")
if len(fwdPkg.Adds) != 0 { if len(fwdPkg.Adds) != 0 {
t.Fatalf("bob forwards %v add htlcs, should forward none", t.Fatalf("bob forwards %v add htlcs, should forward none",
@@ -286,7 +286,7 @@ func testAddSettleWorkflow(t *testing.T, tweakless bool,
} }
} }
fwdPkg, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation2) fwdPkg, _, err = aliceChannel.ReceiveRevocation(bobRevocation2)
require.NoError(t, err, "alice unable to process bob's revocation") require.NoError(t, err, "alice unable to process bob's revocation")
if len(fwdPkg.Adds) != 0 { if len(fwdPkg.Adds) != 0 {
// Alice should now be able to forward the settlement HTLC to // Alice should now be able to forward the settlement HTLC to
@@ -468,7 +468,7 @@ func TestChannelZeroAddLocalHeight(t *testing.T) {
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment() aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
require.NoError(t, err) require.NoError(t, err)
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
require.NoError(t, err) require.NoError(t, err)
// We now restore Alice's channel as this was the point at which // We now restore Alice's channel as this was the point at which
@@ -644,7 +644,7 @@ func testCommitHTLCSigTieBreak(t *testing.T, restart bool) {
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment() bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
require.NoError(t, err, "unable to revoke bob's commitment") require.NoError(t, err, "unable to revoke bob's commitment")
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err, "unable to receive bob's revocation") require.NoError(t, err, "unable to receive bob's revocation")
// Now have Bob initiate the second half of the commitment dance. Here // Now have Bob initiate the second half of the commitment dance. Here
@@ -2556,7 +2556,7 @@ func TestUpdateFeeSenderCommits(t *testing.T) {
// Alice receives the revocation of the old one, and can now assume // Alice receives the revocation of the old one, and can now assume
// that Bob's received everything up to the signature she sent, // that Bob's received everything up to the signature she sent,
// including the HTLC and fee update. // including the HTLC and fee update.
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err, "alice unable to process bob's revocation") require.NoError(t, err, "alice unable to process bob's revocation")
// Alice receives new signature from Bob, and assumes this covers the // Alice receives new signature from Bob, and assumes this covers the
@@ -2584,7 +2584,7 @@ func TestUpdateFeeSenderCommits(t *testing.T) {
} }
// Bob receives revocation from Alice. // Bob receives revocation from Alice.
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
require.NoError(t, err, "bob unable to process alice's revocation") require.NoError(t, err, "bob unable to process alice's revocation")
} }
@@ -2644,7 +2644,7 @@ func TestUpdateFeeReceiverCommits(t *testing.T) {
require.NoError(t, err, "unable to generate bob revocation") require.NoError(t, err, "unable to generate bob revocation")
// Bob receives the revocation of the old commitment // Bob receives the revocation of the old commitment
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
require.NoError(t, err, "alice unable to process bob's revocation") require.NoError(t, err, "alice unable to process bob's revocation")
// Alice will sign next commitment. Since she sent the revocation, she // Alice will sign next commitment. Since she sent the revocation, she
@@ -2685,7 +2685,7 @@ func TestUpdateFeeReceiverCommits(t *testing.T) {
// Alice receives revocation from Bob, and can now be sure that Bob // Alice receives revocation from Bob, and can now be sure that Bob
// received the two updates, and they are considered locked in. // received the two updates, and they are considered locked in.
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err, "bob unable to process alice's revocation") require.NoError(t, err, "bob unable to process alice's revocation")
// Alice will receive the signature from Bob, which will cover what was // Alice will receive the signature from Bob, which will cover what was
@@ -2713,7 +2713,7 @@ func TestUpdateFeeReceiverCommits(t *testing.T) {
} }
// Bob receives revocation from Alice. // Bob receives revocation from Alice.
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
require.NoError(t, err, "bob unable to process alice's revocation") require.NoError(t, err, "bob unable to process alice's revocation")
} }
@@ -2822,7 +2822,7 @@ func TestUpdateFeeMultipleUpdates(t *testing.T) {
// Alice receives the revocation of the old one, and can now assume that // Alice receives the revocation of the old one, and can now assume that
// Bob's received everything up to the signature she sent, including the // Bob's received everything up to the signature she sent, including the
// HTLC and fee update. // HTLC and fee update.
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err, "alice unable to process bob's revocation") require.NoError(t, err, "alice unable to process bob's revocation")
// Alice receives new signature from Bob, and assumes this covers the // Alice receives new signature from Bob, and assumes this covers the
@@ -2852,7 +2852,7 @@ func TestUpdateFeeMultipleUpdates(t *testing.T) {
} }
// Bob receives revocation from Alice. // Bob receives revocation from Alice.
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
require.NoError(t, err, "bob unable to process alice's revocation") require.NoError(t, err, "bob unable to process alice's revocation")
} }
@@ -3267,13 +3267,13 @@ func testChanSyncOweCommitment(t *testing.T, chanType channeldb.ChannelType) {
require.NoError(t, err, "unable to revoke bob commitment") require.NoError(t, err, "unable to revoke bob commitment")
bobNewCommit, err := bobChannel.SignNextCommitment() bobNewCommit, err := bobChannel.SignNextCommitment()
require.NoError(t, err, "bob unable to sign commitment") require.NoError(t, err, "bob unable to sign commitment")
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err, "alice unable to recv revocation") require.NoError(t, err, "alice unable to recv revocation")
err = aliceChannel.ReceiveNewCommitment(bobNewCommit.CommitSigs) err = aliceChannel.ReceiveNewCommitment(bobNewCommit.CommitSigs)
require.NoError(t, err, "alice unable to rev bob's commitment") require.NoError(t, err, "alice unable to rev bob's commitment")
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment() aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
require.NoError(t, err, "alice unable to revoke commitment") require.NoError(t, err, "alice unable to revoke commitment")
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
require.NoError(t, err, "bob unable to recv revocation") require.NoError(t, err, "bob unable to recv revocation")
// At this point, we'll now assert that their log states are what we // At this point, we'll now assert that their log states are what we
@@ -3466,7 +3466,7 @@ func testChanSyncOweCommitmentPendingRemote(t *testing.T,
t.Fatalf("unable to revoke commitment: %v", err) t.Fatalf("unable to revoke commitment: %v", err)
} }
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevoke) _, _, err = aliceChannel.ReceiveRevocation(bobRevoke)
if err != nil { if err != nil {
t.Fatalf("unable to revoke commitment: %v", err) t.Fatalf("unable to revoke commitment: %v", err)
} }
@@ -3502,7 +3502,7 @@ func testChanSyncOweCommitmentPendingRemote(t *testing.T,
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevoke) _, _, err = bobChannel.ReceiveRevocation(aliceRevoke)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -3603,7 +3603,7 @@ func testChanSyncOweRevocation(t *testing.T, chanType channeldb.ChannelType) {
bobNewCommit, err := bobChannel.SignNextCommitment() bobNewCommit, err := bobChannel.SignNextCommitment()
require.NoError(t, err, "bob unable to sign commitment") require.NoError(t, err, "bob unable to sign commitment")
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err, "alice unable to recv revocation") require.NoError(t, err, "alice unable to recv revocation")
err = aliceChannel.ReceiveNewCommitment(bobNewCommit.CommitSigs) err = aliceChannel.ReceiveNewCommitment(bobNewCommit.CommitSigs)
require.NoError(t, err, "alice unable to rev bob's commitment") require.NoError(t, err, "alice unable to rev bob's commitment")
@@ -3698,7 +3698,7 @@ func testChanSyncOweRevocation(t *testing.T, chanType channeldb.ChannelType) {
// We'll continue by then allowing bob to process Alice's revocation // We'll continue by then allowing bob to process Alice's revocation
// message. // message.
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
require.NoError(t, err, "bob unable to recv revocation") require.NoError(t, err, "bob unable to recv revocation")
// Finally, Alice will add an HTLC over her own such that we assert the // Finally, Alice will add an HTLC over her own such that we assert the
@@ -3916,13 +3916,13 @@ func testChanSyncOweRevocationAndCommit(t *testing.T,
// We'll now finish the state transition by having Alice process both // We'll now finish the state transition by having Alice process both
// messages, and send her final revocation. // messages, and send her final revocation.
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err, "alice unable to recv revocation") require.NoError(t, err, "alice unable to recv revocation")
err = aliceChannel.ReceiveNewCommitment(bobNewCommit.CommitSigs) err = aliceChannel.ReceiveNewCommitment(bobNewCommit.CommitSigs)
require.NoError(t, err, "alice unable to recv bob's commitment") require.NoError(t, err, "alice unable to recv bob's commitment")
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment() aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
require.NoError(t, err, "alice unable to revoke commitment") require.NoError(t, err, "alice unable to revoke commitment")
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
require.NoError(t, err, "bob unable to recv revocation") require.NoError(t, err, "bob unable to recv revocation")
} }
@@ -4016,7 +4016,7 @@ func testChanSyncOweRevocationAndCommitForceTransition(t *testing.T,
// local commit chain getting height > remote commit chain. // local commit chain getting height > remote commit chain.
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment() aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
require.NoError(t, err, "alice unable to revoke commitment") require.NoError(t, err, "alice unable to revoke commitment")
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
require.NoError(t, err, "bob unable to recv revocation") require.NoError(t, err, "bob unable to recv revocation")
// Next, Alice will settle that incoming HTLC, then we'll start the // Next, Alice will settle that incoming HTLC, then we'll start the
@@ -4148,7 +4148,7 @@ func testChanSyncOweRevocationAndCommitForceTransition(t *testing.T,
// Now, we'll continue the exchange, sending Bob's revocation and // Now, we'll continue the exchange, sending Bob's revocation and
// signature message to Alice, ending with Alice sending her revocation // signature message to Alice, ending with Alice sending her revocation
// message to Bob. // message to Bob.
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err, "alice unable to recv revocation") require.NoError(t, err, "alice unable to recv revocation")
err = aliceChannel.ReceiveNewCommitment(&CommitSigs{ err = aliceChannel.ReceiveNewCommitment(&CommitSigs{
CommitSig: bobSigMsg.CommitSig, CommitSig: bobSigMsg.CommitSig,
@@ -4158,7 +4158,7 @@ func testChanSyncOweRevocationAndCommitForceTransition(t *testing.T,
require.NoError(t, err, "alice unable to rev bob's commitment") require.NoError(t, err, "alice unable to rev bob's commitment")
aliceRevocation, _, _, err = aliceChannel.RevokeCurrentCommitment() aliceRevocation, _, _, err = aliceChannel.RevokeCurrentCommitment()
require.NoError(t, err, "alice unable to revoke commitment") require.NoError(t, err, "alice unable to revoke commitment")
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
require.NoError(t, err, "bob unable to recv revocation") require.NoError(t, err, "bob unable to recv revocation")
} }
@@ -4584,13 +4584,13 @@ func TestChannelRetransmissionFeeUpdate(t *testing.T) {
require.NoError(t, err, "unable to revoke bob commitment") require.NoError(t, err, "unable to revoke bob commitment")
bobNewCommit, err := bobChannel.SignNextCommitment() bobNewCommit, err := bobChannel.SignNextCommitment()
require.NoError(t, err, "bob unable to sign commitment") require.NoError(t, err, "bob unable to sign commitment")
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err, "alice unable to recv revocation") require.NoError(t, err, "alice unable to recv revocation")
err = aliceChannel.ReceiveNewCommitment(bobNewCommit.CommitSigs) err = aliceChannel.ReceiveNewCommitment(bobNewCommit.CommitSigs)
require.NoError(t, err, "alice unable to rev bob's commitment") require.NoError(t, err, "alice unable to rev bob's commitment")
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment() aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
require.NoError(t, err, "alice unable to revoke commitment") require.NoError(t, err, "alice unable to revoke commitment")
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
require.NoError(t, err, "bob unable to recv revocation") require.NoError(t, err, "bob unable to recv revocation")
// Both parties should now have the latest fee rate locked-in. // Both parties should now have the latest fee rate locked-in.
@@ -4782,13 +4782,13 @@ func TestFeeUpdateOldDiskFormat(t *testing.T) {
require.NoError(t, err, "unable to revoke bob commitment") require.NoError(t, err, "unable to revoke bob commitment")
bobNewCommitSigs, err := bobChannel.SignNextCommitment() bobNewCommitSigs, err := bobChannel.SignNextCommitment()
require.NoError(t, err, "bob unable to sign commitment") require.NoError(t, err, "bob unable to sign commitment")
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err, "alice unable to recv revocation") require.NoError(t, err, "alice unable to recv revocation")
err = aliceChannel.ReceiveNewCommitment(bobNewCommitSigs.CommitSigs) err = aliceChannel.ReceiveNewCommitment(bobNewCommitSigs.CommitSigs)
require.NoError(t, err, "alice unable to rev bob's commitment") require.NoError(t, err, "alice unable to rev bob's commitment")
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment() aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
require.NoError(t, err, "alice unable to revoke commitment") require.NoError(t, err, "alice unable to revoke commitment")
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
require.NoError(t, err, "bob unable to recv revocation") require.NoError(t, err, "bob unable to recv revocation")
// Both parties should now have the latest fee rate locked-in. // Both parties should now have the latest fee rate locked-in.
@@ -5497,7 +5497,7 @@ func TestLockedInHtlcForwardingSkipAfterRestart(t *testing.T) {
} }
// Alice should detect that she doesn't need to forward any HTLC's. // Alice should detect that she doesn't need to forward any HTLC's.
fwdPkg, _, _, _, err := aliceChannel.ReceiveRevocation(bobRevocation) fwdPkg, _, err := aliceChannel.ReceiveRevocation(bobRevocation)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -5528,7 +5528,7 @@ func TestLockedInHtlcForwardingSkipAfterRestart(t *testing.T) {
// Bob should now detect that he now has 2 incoming HTLC's that he can // Bob should now detect that he now has 2 incoming HTLC's that he can
// forward along. // forward along.
fwdPkg, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) fwdPkg, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -5573,7 +5573,7 @@ func TestLockedInHtlcForwardingSkipAfterRestart(t *testing.T) {
// At this point, Bob receives the revocation from Alice, which is now // At this point, Bob receives the revocation from Alice, which is now
// his signal to examine all the HTLC's that have been locked in to // his signal to examine all the HTLC's that have been locked in to
// process. // process.
fwdPkg, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) fwdPkg, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -5622,22 +5622,31 @@ func TestLockedInHtlcForwardingSkipAfterRestart(t *testing.T) {
// Alice should detect that she doesn't need to forward any Adds's, but // Alice should detect that she doesn't need to forward any Adds's, but
// that the Fail has been locked in an can be forwarded. // that the Fail has been locked in an can be forwarded.
_, adds, settleFails, _, err := aliceChannel.ReceiveRevocation(bobRevocation) fwdPkg, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
adds := fwdPkg.Adds
settleFails := fwdPkg.SettleFails
if len(adds) != 0 { if len(adds) != 0 {
t.Fatalf("alice shouldn't forward any HTLC's, instead wants to "+ t.Fatalf("alice shouldn't forward any HTLC's, instead wants to "+
"forward %v htlcs", len(adds)) "forward %v htlcs", len(fwdPkg.Adds))
} }
if len(settleFails) != 1 { if len(settleFails) != 1 {
t.Fatalf("alice should only forward %d HTLC's, instead wants to "+ t.Fatalf("alice should only forward %d HTLC's, instead wants to "+
"forward %v htlcs", 1, len(settleFails)) "forward %v htlcs", 1, len(fwdPkg.SettleFails))
} }
if settleFails[0].ParentIndex != htlc.ID {
fail, ok := settleFails[0].UpdateMsg.(*lnwire.UpdateFailHTLC)
if !ok {
t.Fatalf("expected UpdateFailHTLC, got %T",
settleFails[0].UpdateMsg)
}
if fail.ID != htlc.ID {
t.Fatalf("alice should forward fail for htlcid=%d, instead "+ t.Fatalf("alice should forward fail for htlcid=%d, instead "+
"forwarding id=%d", htlc.ID, "forwarding id=%d", htlc.ID,
settleFails[0].ParentIndex) fail.ID)
} }
// We'll now restart both Alice and Bob. This emulates a reconnection // We'll now restart both Alice and Bob. This emulates a reconnection
@@ -5671,7 +5680,7 @@ func TestLockedInHtlcForwardingSkipAfterRestart(t *testing.T) {
// Alice should detect that she doesn't need to forward any HTLC's, as // Alice should detect that she doesn't need to forward any HTLC's, as
// the updates haven't been committed by Bob yet. // the updates haven't been committed by Bob yet.
fwdPkg, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) fwdPkg, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -5702,7 +5711,7 @@ func TestLockedInHtlcForwardingSkipAfterRestart(t *testing.T) {
// Bob should detect that he has nothing to forward, as he hasn't // Bob should detect that he has nothing to forward, as he hasn't
// received any HTLCs. // received any HTLCs.
fwdPkg, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) fwdPkg, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -5732,10 +5741,13 @@ func TestLockedInHtlcForwardingSkipAfterRestart(t *testing.T) {
// When Alice receives the revocation, she should detect that she // When Alice receives the revocation, she should detect that she
// can now forward the freshly locked-in Fail. // can now forward the freshly locked-in Fail.
_, adds, settleFails, _, err = aliceChannel.ReceiveRevocation(bobRevocation) fwdPkg, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
adds = fwdPkg.Adds
settleFails = fwdPkg.SettleFails
if len(adds) != 0 { if len(adds) != 0 {
t.Fatalf("alice shouldn't forward any HTLC's, instead wants to "+ t.Fatalf("alice shouldn't forward any HTLC's, instead wants to "+
"forward %v htlcs", len(adds)) "forward %v htlcs", len(adds))
@@ -5744,10 +5756,16 @@ func TestLockedInHtlcForwardingSkipAfterRestart(t *testing.T) {
t.Fatalf("alice should only forward one HTLC, instead wants to "+ t.Fatalf("alice should only forward one HTLC, instead wants to "+
"forward %v htlcs", len(settleFails)) "forward %v htlcs", len(settleFails))
} }
if settleFails[0].ParentIndex != htlc2.ID {
fail, ok = settleFails[0].UpdateMsg.(*lnwire.UpdateFailHTLC)
if !ok {
t.Fatalf("expected UpdateFailHTLC, got %T",
settleFails[0].UpdateMsg)
}
if fail.ID != htlc2.ID {
t.Fatalf("alice should forward fail for htlcid=%d, instead "+ t.Fatalf("alice should forward fail for htlcid=%d, instead "+
"forwarding id=%d", htlc2.ID, "forwarding id=%d", htlc2.ID,
settleFails[0].ParentIndex) fail.ID)
} }
} }
@@ -6347,13 +6365,13 @@ func TestMaxAsynchronousHtlcs(t *testing.T) {
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment() bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
require.NoError(t, err, "unable to revoke revocation") require.NoError(t, err, "unable to revoke revocation")
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err, "unable to receive revocation") require.NoError(t, err, "unable to receive revocation")
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment() aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
require.NoError(t, err, "unable to revoke revocation") require.NoError(t, err, "unable to revoke revocation")
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
require.NoError(t, err, "unable to receive revocation") require.NoError(t, err, "unable to receive revocation")
// Send the final Add which should succeed as in step 6. // Send the final Add which should succeed as in step 6.
@@ -6916,8 +6934,8 @@ func TestNewBreachRetributionSkipsDustHtlcs(t *testing.T) {
} }
} }
// compareHtlcs compares two PaymentDescriptors. // compareHtlcs compares two paymentDescriptors.
func compareHtlcs(htlc1, htlc2 *PaymentDescriptor) error { func compareHtlcs(htlc1, htlc2 *paymentDescriptor) error {
if htlc1.LogIndex != htlc2.LogIndex { if htlc1.LogIndex != htlc2.LogIndex {
return fmt.Errorf("htlc log index did not match") return fmt.Errorf("htlc log index did not match")
} }
@@ -6935,7 +6953,7 @@ func compareHtlcs(htlc1, htlc2 *PaymentDescriptor) error {
} }
// compareIndexes is a helper method to compare two index maps. // compareIndexes is a helper method to compare two index maps.
func compareIndexes(a, b map[uint64]*fn.Node[*PaymentDescriptor]) error { func compareIndexes(a, b map[uint64]*fn.Node[*paymentDescriptor]) error {
for k1, e1 := range a { for k1, e1 := range a {
e2, ok := b[k1] e2, ok := b[k1]
if !ok { if !ok {
@@ -7035,7 +7053,7 @@ func TestChannelRestoreUpdateLogs(t *testing.T) {
// sent. However her local commitment chain still won't include the // sent. However her local commitment chain still won't include the
// state with the HTLC, since she hasn't received a new commitment // state with the HTLC, since she hasn't received a new commitment
// signature from Bob yet. // signature from Bob yet.
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err, "unable to receive revocation") require.NoError(t, err, "unable to receive revocation")
// Now make Alice send and sign an additional HTLC. We don't let Bob // Now make Alice send and sign an additional HTLC. We don't let Bob
@@ -7211,7 +7229,7 @@ func TestChannelRestoreUpdateLogsFailedHTLC(t *testing.T) {
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment() aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
require.NoError(t, err, "unable to revoke commitment") require.NoError(t, err, "unable to revoke commitment")
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
require.NoError(t, err, "bob unable to process alice's revocation") require.NoError(t, err, "bob unable to process alice's revocation")
// At this point Alice has advanced her local commitment chain to a // At this point Alice has advanced her local commitment chain to a
@@ -7241,7 +7259,7 @@ func TestChannelRestoreUpdateLogsFailedHTLC(t *testing.T) {
// the corresponding Fail from the local update log. // the corresponding Fail from the local update log.
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment() bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
require.NoError(t, err, "unable to revoke commitment") require.NoError(t, err, "unable to revoke commitment")
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err, "unable to receive revocation") require.NoError(t, err, "unable to receive revocation")
assertInLogs(t, aliceChannel, 0, 0, 0, 0) assertInLogs(t, aliceChannel, 0, 0, 0, 0)
@@ -7404,7 +7422,7 @@ func TestChannelRestoreCommitHeight(t *testing.T) {
t.Fatalf("unable to create new channel: %v", err) t.Fatalf("unable to create new channel: %v", err)
} }
var pd *PaymentDescriptor var pd *paymentDescriptor
if remoteLog { if remoteLog {
h := newChannel.updateLogs.Local.lookupHtlc(htlcIndex) h := newChannel.updateLogs.Local.lookupHtlc(htlcIndex)
if h != nil { if h != nil {
@@ -7466,7 +7484,7 @@ func TestChannelRestoreCommitHeight(t *testing.T) {
bobChannel = restoreAndAssertCommitHeights(t, bobChannel, true, 0, 1, 0) bobChannel = restoreAndAssertCommitHeights(t, bobChannel, true, 0, 1, 0)
// Alice receives the revocation, ACKing her pending commitment. // Alice receives the revocation, ACKing her pending commitment.
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err, "unable to receive revocation") require.NoError(t, err, "unable to receive revocation")
// However, the HTLC is still not locked into her local commitment, so // However, the HTLC is still not locked into her local commitment, so
@@ -7495,7 +7513,7 @@ func TestChannelRestoreCommitHeight(t *testing.T) {
t, aliceChannel, false, 0, 1, 1, t, aliceChannel, false, 0, 1, 1,
) )
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
require.NoError(t, err, "unable to receive revocation") require.NoError(t, err, "unable to receive revocation")
// Alice ACKing Bob's pending commitment shouldn't change the heights // Alice ACKing Bob's pending commitment shouldn't change the heights
@@ -7540,7 +7558,7 @@ func TestChannelRestoreCommitHeight(t *testing.T) {
bobChannel = restoreAndAssertCommitHeights(t, bobChannel, true, 1, 2, 0) bobChannel = restoreAndAssertCommitHeights(t, bobChannel, true, 1, 2, 0)
// Alice receives the revocation, ACKing her pending commitment for Bob. // Alice receives the revocation, ACKing her pending commitment for Bob.
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err, "unable to receive revocation") require.NoError(t, err, "unable to receive revocation")
// Alice receiving Bob's revocation should bump both addCommitHeightRemote // Alice receiving Bob's revocation should bump both addCommitHeightRemote
@@ -7578,7 +7596,7 @@ func TestChannelRestoreCommitHeight(t *testing.T) {
// Bob receives the revocation, which should set both addCommitHeightRemote // Bob receives the revocation, which should set both addCommitHeightRemote
// fields to 2. // fields to 2.
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
require.NoError(t, err, "unable to receive revocation") require.NoError(t, err, "unable to receive revocation")
bobChannel = restoreAndAssertCommitHeights(t, bobChannel, true, 0, 2, 2) bobChannel = restoreAndAssertCommitHeights(t, bobChannel, true, 0, 2, 2)
@@ -7681,7 +7699,7 @@ func TestForceCloseBorkedState(t *testing.T) {
// At this point, all channel mutating methods should now fail as they // At this point, all channel mutating methods should now fail as they
// shouldn't be able to proceed if the channel is borked. // shouldn't be able to proceed if the channel is borked.
_, _, _, _, err = aliceChannel.ReceiveRevocation(revokeMsg) _, _, err = aliceChannel.ReceiveRevocation(revokeMsg)
if err != channeldb.ErrChanBorked { if err != channeldb.ErrChanBorked {
t.Fatalf("advance commitment tail should have failed") t.Fatalf("advance commitment tail should have failed")
} }
@@ -8173,8 +8191,8 @@ func TestFetchParent(t *testing.T) {
name string name string
whoseCommitChain lntypes.ChannelParty whoseCommitChain lntypes.ChannelParty
whoseUpdateLog lntypes.ChannelParty whoseUpdateLog lntypes.ChannelParty
localEntries []*PaymentDescriptor localEntries []*paymentDescriptor
remoteEntries []*PaymentDescriptor remoteEntries []*paymentDescriptor
// parentIndex is the parent index of the entry that we will // parentIndex is the parent index of the entry that we will
// lookup with fetch parent. // lookup with fetch parent.
@@ -8208,7 +8226,7 @@ func TestFetchParent(t *testing.T) {
{ {
name: "remote log + chain, remote add height 0", name: "remote log + chain, remote add height 0",
localEntries: nil, localEntries: nil,
remoteEntries: []*PaymentDescriptor{ remoteEntries: []*paymentDescriptor{
// This entry will be added at log index =0. // This entry will be added at log index =0.
{ {
HtlcIndex: 1, HtlcIndex: 1,
@@ -8230,7 +8248,7 @@ func TestFetchParent(t *testing.T) {
}, },
{ {
name: "remote log, local chain, local add height 0", name: "remote log, local chain, local add height 0",
remoteEntries: []*PaymentDescriptor{ remoteEntries: []*paymentDescriptor{
// This entry will be added at log index =0. // This entry will be added at log index =0.
{ {
HtlcIndex: 1, HtlcIndex: 1,
@@ -8253,7 +8271,7 @@ func TestFetchParent(t *testing.T) {
}, },
{ {
name: "local log + chain, local add height 0", name: "local log + chain, local add height 0",
localEntries: []*PaymentDescriptor{ localEntries: []*paymentDescriptor{
// This entry will be added at log index =0. // This entry will be added at log index =0.
{ {
HtlcIndex: 1, HtlcIndex: 1,
@@ -8277,7 +8295,7 @@ func TestFetchParent(t *testing.T) {
{ {
name: "local log + remote chain, remote add height 0", name: "local log + remote chain, remote add height 0",
localEntries: []*PaymentDescriptor{ localEntries: []*paymentDescriptor{
// This entry will be added at log index =0. // This entry will be added at log index =0.
{ {
HtlcIndex: 1, HtlcIndex: 1,
@@ -8301,7 +8319,7 @@ func TestFetchParent(t *testing.T) {
{ {
name: "remote log found", name: "remote log found",
localEntries: nil, localEntries: nil,
remoteEntries: []*PaymentDescriptor{ remoteEntries: []*paymentDescriptor{
// This entry will be added at log index =0. // This entry will be added at log index =0.
{ {
HtlcIndex: 1, HtlcIndex: 1,
@@ -8324,7 +8342,7 @@ func TestFetchParent(t *testing.T) {
}, },
{ {
name: "local log found", name: "local log found",
localEntries: []*PaymentDescriptor{ localEntries: []*paymentDescriptor{
// This entry will be added at log index =0. // This entry will be added at log index =0.
{ {
HtlcIndex: 1, HtlcIndex: 1,
@@ -8370,7 +8388,7 @@ func TestFetchParent(t *testing.T) {
} }
parent, err := lc.fetchParent( parent, err := lc.fetchParent(
&PaymentDescriptor{ &paymentDescriptor{
ParentIndex: test.parentIndex, ParentIndex: test.parentIndex,
}, },
test.whoseCommitChain, test.whoseCommitChain,
@@ -8433,8 +8451,8 @@ func TestEvaluateView(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
ourHtlcs []*PaymentDescriptor ourHtlcs []*paymentDescriptor
theirHtlcs []*PaymentDescriptor theirHtlcs []*paymentDescriptor
whoseCommitChain lntypes.ChannelParty whoseCommitChain lntypes.ChannelParty
mutateState bool mutateState bool
@@ -8466,7 +8484,7 @@ func TestEvaluateView(t *testing.T) {
name: "our fee update is applied", name: "our fee update is applied",
whoseCommitChain: lntypes.Local, whoseCommitChain: lntypes.Local,
mutateState: false, mutateState: false,
ourHtlcs: []*PaymentDescriptor{ ourHtlcs: []*paymentDescriptor{
{ {
Amount: ourFeeUpdateAmt, Amount: ourFeeUpdateAmt,
EntryType: FeeUpdate, EntryType: FeeUpdate,
@@ -8483,8 +8501,8 @@ func TestEvaluateView(t *testing.T) {
name: "their fee update is applied", name: "their fee update is applied",
whoseCommitChain: lntypes.Local, whoseCommitChain: lntypes.Local,
mutateState: false, mutateState: false,
ourHtlcs: []*PaymentDescriptor{}, ourHtlcs: []*paymentDescriptor{},
theirHtlcs: []*PaymentDescriptor{ theirHtlcs: []*paymentDescriptor{
{ {
Amount: theirFeeUpdateAmt, Amount: theirFeeUpdateAmt,
EntryType: FeeUpdate, EntryType: FeeUpdate,
@@ -8501,14 +8519,14 @@ func TestEvaluateView(t *testing.T) {
name: "htlcs adds without settles", name: "htlcs adds without settles",
whoseCommitChain: lntypes.Local, whoseCommitChain: lntypes.Local,
mutateState: false, mutateState: false,
ourHtlcs: []*PaymentDescriptor{ ourHtlcs: []*paymentDescriptor{
{ {
HtlcIndex: 0, HtlcIndex: 0,
Amount: htlcAddAmount, Amount: htlcAddAmount,
EntryType: Add, EntryType: Add,
}, },
}, },
theirHtlcs: []*PaymentDescriptor{ theirHtlcs: []*paymentDescriptor{
{ {
HtlcIndex: 0, HtlcIndex: 0,
Amount: htlcAddAmount, Amount: htlcAddAmount,
@@ -8535,7 +8553,7 @@ func TestEvaluateView(t *testing.T) {
name: "our htlc settled, state mutated", name: "our htlc settled, state mutated",
whoseCommitChain: lntypes.Local, whoseCommitChain: lntypes.Local,
mutateState: true, mutateState: true,
ourHtlcs: []*PaymentDescriptor{ ourHtlcs: []*paymentDescriptor{
{ {
HtlcIndex: 0, HtlcIndex: 0,
Amount: htlcAddAmount, Amount: htlcAddAmount,
@@ -8543,7 +8561,7 @@ func TestEvaluateView(t *testing.T) {
addCommitHeightLocal: addHeight, addCommitHeightLocal: addHeight,
}, },
}, },
theirHtlcs: []*PaymentDescriptor{ theirHtlcs: []*paymentDescriptor{
{ {
HtlcIndex: 0, HtlcIndex: 0,
Amount: htlcAddAmount, Amount: htlcAddAmount,
@@ -8570,7 +8588,7 @@ func TestEvaluateView(t *testing.T) {
name: "our htlc settled, state not mutated", name: "our htlc settled, state not mutated",
whoseCommitChain: lntypes.Local, whoseCommitChain: lntypes.Local,
mutateState: false, mutateState: false,
ourHtlcs: []*PaymentDescriptor{ ourHtlcs: []*paymentDescriptor{
{ {
HtlcIndex: 0, HtlcIndex: 0,
Amount: htlcAddAmount, Amount: htlcAddAmount,
@@ -8578,7 +8596,7 @@ func TestEvaluateView(t *testing.T) {
addCommitHeightLocal: addHeight, addCommitHeightLocal: addHeight,
}, },
}, },
theirHtlcs: []*PaymentDescriptor{ theirHtlcs: []*paymentDescriptor{
{ {
HtlcIndex: 0, HtlcIndex: 0,
Amount: htlcAddAmount, Amount: htlcAddAmount,
@@ -8605,7 +8623,7 @@ func TestEvaluateView(t *testing.T) {
name: "their htlc settled, state mutated", name: "their htlc settled, state mutated",
whoseCommitChain: lntypes.Local, whoseCommitChain: lntypes.Local,
mutateState: true, mutateState: true,
ourHtlcs: []*PaymentDescriptor{ ourHtlcs: []*paymentDescriptor{
{ {
HtlcIndex: 0, HtlcIndex: 0,
Amount: htlcAddAmount, Amount: htlcAddAmount,
@@ -8620,7 +8638,7 @@ func TestEvaluateView(t *testing.T) {
ParentIndex: 1, ParentIndex: 1,
}, },
}, },
theirHtlcs: []*PaymentDescriptor{ theirHtlcs: []*paymentDescriptor{
{ {
HtlcIndex: 0, HtlcIndex: 0,
Amount: htlcAddAmount, Amount: htlcAddAmount,
@@ -8649,7 +8667,7 @@ func TestEvaluateView(t *testing.T) {
whoseCommitChain: lntypes.Local, whoseCommitChain: lntypes.Local,
mutateState: false, mutateState: false,
ourHtlcs: []*PaymentDescriptor{ ourHtlcs: []*paymentDescriptor{
{ {
HtlcIndex: 0, HtlcIndex: 0,
Amount: htlcAddAmount, Amount: htlcAddAmount,
@@ -8664,7 +8682,7 @@ func TestEvaluateView(t *testing.T) {
ParentIndex: 0, ParentIndex: 0,
}, },
}, },
theirHtlcs: []*PaymentDescriptor{ theirHtlcs: []*paymentDescriptor{
{ {
HtlcIndex: 0, HtlcIndex: 0,
Amount: htlcAddAmount, Amount: htlcAddAmount,
@@ -8771,7 +8789,7 @@ func TestEvaluateView(t *testing.T) {
// checkExpectedHtlcs checks that a set of htlcs that we have contains all the // checkExpectedHtlcs checks that a set of htlcs that we have contains all the
// htlcs we expect. // htlcs we expect.
func checkExpectedHtlcs(t *testing.T, actual []*PaymentDescriptor, func checkExpectedHtlcs(t *testing.T, actual []*paymentDescriptor,
expected map[uint64]bool) { expected map[uint64]bool) {
if len(expected) != len(actual) { if len(expected) != len(actual) {
@@ -8963,7 +8981,7 @@ func TestProcessFeeUpdate(t *testing.T) {
// Create a fee update with add and remove heights as // Create a fee update with add and remove heights as
// set in the test. // set in the test.
heights := test.startHeights heights := test.startHeights
update := &PaymentDescriptor{ update := &paymentDescriptor{
Amount: ourFeeUpdateAmt, Amount: ourFeeUpdateAmt,
addCommitHeightRemote: heights.remoteAdd, addCommitHeightRemote: heights.remoteAdd,
addCommitHeightLocal: heights.localAdd, addCommitHeightLocal: heights.localAdd,
@@ -8990,7 +9008,7 @@ func TestProcessFeeUpdate(t *testing.T) {
} }
} }
func checkHeights(t *testing.T, update *PaymentDescriptor, expected heights) { func checkHeights(t *testing.T, update *paymentDescriptor, expected heights) {
updateHeights := heights{ updateHeights := heights{
localAdd: update.addCommitHeightLocal, localAdd: update.addCommitHeightLocal,
localRemove: update.removeCommitHeightLocal, localRemove: update.removeCommitHeightLocal,
@@ -9359,7 +9377,7 @@ func TestProcessAddRemoveEntry(t *testing.T) {
t.Parallel() t.Parallel()
heights := test.startHeights heights := test.startHeights
update := &PaymentDescriptor{ update := &paymentDescriptor{
Amount: updateAmount, Amount: updateAmount,
addCommitHeightLocal: heights.localAdd, addCommitHeightLocal: heights.localAdd,
addCommitHeightRemote: heights.remoteAdd, addCommitHeightRemote: heights.remoteAdd,
@@ -9477,7 +9495,7 @@ func TestChannelUnsignedAckedFailure(t *testing.T) {
// -----rev-----> // -----rev----->
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment() aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
require.NoError(t, err) require.NoError(t, err)
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
require.NoError(t, err) require.NoError(t, err)
// Alice should sign the next commitment and go down before // Alice should sign the next commitment and go down before
@@ -9502,7 +9520,7 @@ func TestChannelUnsignedAckedFailure(t *testing.T) {
// <----rev------ // <----rev------
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment() bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
require.NoError(t, err) require.NoError(t, err)
_, _, _, _, err = newAliceChannel.ReceiveRevocation(bobRevocation) _, _, err = newAliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err) require.NoError(t, err)
// Now Bob sends an HTLC to Alice. // Now Bob sends an HTLC to Alice.
@@ -9588,7 +9606,7 @@ func TestChannelLocalUnsignedUpdatesFailure(t *testing.T) {
// <----rev----- // <----rev-----
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment() bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
require.NoError(t, err) require.NoError(t, err)
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err) require.NoError(t, err)
// Restart Alice and assert that she can receive Bob's next commitment // Restart Alice and assert that she can receive Bob's next commitment
@@ -9672,7 +9690,7 @@ func TestChannelSignedAckRegression(t *testing.T) {
// <----rev----- // <----rev-----
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment() bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
require.NoError(t, err) require.NoError(t, err)
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err) require.NoError(t, err)
// <----sig----- // <----sig-----
@@ -9699,7 +9717,7 @@ func TestChannelSignedAckRegression(t *testing.T) {
// <----rev----- // <----rev-----
bobRevocation, _, _, err = bobChannel.RevokeCurrentCommitment() bobRevocation, _, _, err = bobChannel.RevokeCurrentCommitment()
require.NoError(t, err) require.NoError(t, err)
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err) require.NoError(t, err)
// Restart Bob's channel state here. // Restart Bob's channel state here.
@@ -9712,7 +9730,7 @@ func TestChannelSignedAckRegression(t *testing.T) {
// -----rev----> // -----rev---->
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment() aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
require.NoError(t, err) require.NoError(t, err)
fwdPkg, _, _, _, err := newBobChannel.ReceiveRevocation(aliceRevocation) fwdPkg, _, err := newBobChannel.ReceiveRevocation(aliceRevocation)
require.NoError(t, err) require.NoError(t, err)
// Assert that the fwdpkg is not empty. // Assert that the fwdpkg is not empty.
@@ -9804,7 +9822,7 @@ func TestIsChannelClean(t *testing.T) {
// <---rev--- // <---rev---
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment() bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
require.NoError(t, err) require.NoError(t, err)
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err) require.NoError(t, err)
assertCleanOrDirty(false, aliceChannel, bobChannel, t) assertCleanOrDirty(false, aliceChannel, bobChannel, t)
@@ -9818,7 +9836,7 @@ func TestIsChannelClean(t *testing.T) {
// ---rev---> // ---rev--->
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment() aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
require.NoError(t, err) require.NoError(t, err)
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
require.NoError(t, err) require.NoError(t, err)
assertCleanOrDirty(false, aliceChannel, bobChannel, t) assertCleanOrDirty(false, aliceChannel, bobChannel, t)
@@ -9839,7 +9857,7 @@ func TestIsChannelClean(t *testing.T) {
// ---rev---> // ---rev--->
aliceRevocation, _, _, err = aliceChannel.RevokeCurrentCommitment() aliceRevocation, _, _, err = aliceChannel.RevokeCurrentCommitment()
require.NoError(t, err) require.NoError(t, err)
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
require.NoError(t, err) require.NoError(t, err)
assertCleanOrDirty(false, aliceChannel, bobChannel, t) assertCleanOrDirty(false, aliceChannel, bobChannel, t)
@@ -9853,7 +9871,7 @@ func TestIsChannelClean(t *testing.T) {
// <---rev--- // <---rev---
bobRevocation, _, _, err = bobChannel.RevokeCurrentCommitment() bobRevocation, _, _, err = bobChannel.RevokeCurrentCommitment()
require.NoError(t, err) require.NoError(t, err)
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err) require.NoError(t, err)
assertCleanOrDirty(true, aliceChannel, bobChannel, t) assertCleanOrDirty(true, aliceChannel, bobChannel, t)
@@ -9877,7 +9895,7 @@ func TestIsChannelClean(t *testing.T) {
// <---rev--- // <---rev---
bobRevocation, _, _, err = bobChannel.RevokeCurrentCommitment() bobRevocation, _, _, err = bobChannel.RevokeCurrentCommitment()
require.NoError(t, err) require.NoError(t, err)
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err) require.NoError(t, err)
assertCleanOrDirty(false, aliceChannel, bobChannel, t) assertCleanOrDirty(false, aliceChannel, bobChannel, t)
@@ -9892,7 +9910,7 @@ func TestIsChannelClean(t *testing.T) {
// ---rev---> // ---rev--->
aliceRevocation, _, _, err = aliceChannel.RevokeCurrentCommitment() aliceRevocation, _, _, err = aliceChannel.RevokeCurrentCommitment()
require.NoError(t, err) require.NoError(t, err)
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
require.NoError(t, err) require.NoError(t, err)
assertCleanOrDirty(true, aliceChannel, bobChannel, t) assertCleanOrDirty(true, aliceChannel, bobChannel, t)
} }
@@ -10035,7 +10053,7 @@ func testGetDustSum(t *testing.T, chantype channeldb.ChannelType) {
// dust. // dust.
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment() bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
require.NoError(t, err) require.NoError(t, err)
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err) require.NoError(t, err)
checkDust(aliceChannel, htlc2Amt, htlc2Amt) checkDust(aliceChannel, htlc2Amt, htlc2Amt)
checkDust(bobChannel, htlc2Amt, htlc2Amt) checkDust(bobChannel, htlc2Amt, htlc2Amt)
@@ -10048,7 +10066,7 @@ func testGetDustSum(t *testing.T, chantype channeldb.ChannelType) {
require.NoError(t, err) require.NoError(t, err)
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment() aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
require.NoError(t, err) require.NoError(t, err)
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
require.NoError(t, err) require.NoError(t, err)
checkDust(aliceChannel, htlc2Amt, htlc2Amt) checkDust(aliceChannel, htlc2Amt, htlc2Amt)
checkDust(bobChannel, htlc2Amt, htlc2Amt) checkDust(bobChannel, htlc2Amt, htlc2Amt)
@@ -10554,7 +10572,7 @@ func testNewBreachRetribution(t *testing.T, chanType channeldb.ChannelType) {
} }
// TestExtractPayDescs asserts that `extractPayDescs` can correctly turn a // TestExtractPayDescs asserts that `extractPayDescs` can correctly turn a
// slice of htlcs into two slices of PaymentDescriptors. // slice of htlcs into two slices of paymentDescriptors.
func TestExtractPayDescs(t *testing.T) { func TestExtractPayDescs(t *testing.T) {
t.Parallel() t.Parallel()
@@ -10591,22 +10609,22 @@ func TestExtractPayDescs(t *testing.T) {
) )
require.NoError(t, err) require.NoError(t, err)
// Assert the incoming PaymentDescriptors are matched. // Assert the incoming paymentDescriptors are matched.
for i, pd := range incomingPDs { for i, pd := range incomingPDs {
htlc := incomings[i] htlc := incomings[i]
assertPayDescMatchHTLC(t, pd, htlc) assertPayDescMatchHTLC(t, pd, htlc)
} }
// Assert the outgoing PaymentDescriptors are matched. // Assert the outgoing paymentDescriptors are matched.
for i, pd := range outgoingPDs { for i, pd := range outgoingPDs {
htlc := outgoings[i] htlc := outgoings[i]
assertPayDescMatchHTLC(t, pd, htlc) assertPayDescMatchHTLC(t, pd, htlc)
} }
} }
// assertPayDescMatchHTLC compares a PaymentDescriptor to a channeldb.HTLC and // assertPayDescMatchHTLC compares a paymentDescriptor to a channeldb.HTLC and
// asserts that the fields are matched. // asserts that the fields are matched.
func assertPayDescMatchHTLC(t *testing.T, pd PaymentDescriptor, func assertPayDescMatchHTLC(t *testing.T, pd paymentDescriptor,
htlc channeldb.HTLC) { htlc channeldb.HTLC) {
require := require.New(t) require := require.New(t)
@@ -11008,7 +11026,7 @@ func TestAsynchronousSendingWithFeeBuffer(t *testing.T) {
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment() bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
require.NoError(t, err) require.NoError(t, err)
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
require.NoError(t, err) require.NoError(t, err)
// Before testing the behavior of the fee buffer, we are going to fail // Before testing the behavior of the fee buffer, we are going to fail
+3 -3
View File
@@ -1229,10 +1229,10 @@ func genHtlcScript(chanType channeldb.ChannelType, isIncoming bool,
// is incoming and if it's being applied to our commitment transaction or that // is incoming and if it's being applied to our commitment transaction or that
// of the remote node's. Additionally, in order to be able to efficiently // of the remote node's. Additionally, in order to be able to efficiently
// locate the added HTLC on the commitment transaction from the // locate the added HTLC on the commitment transaction from the
// PaymentDescriptor that generated it, the generated script is stored within // paymentDescriptor that generated it, the generated script is stored within
// the descriptor itself. // the descriptor itself.
func addHTLC(commitTx *wire.MsgTx, whoseCommit lntypes.ChannelParty, func addHTLC(commitTx *wire.MsgTx, whoseCommit lntypes.ChannelParty,
isIncoming bool, paymentDesc *PaymentDescriptor, isIncoming bool, paymentDesc *paymentDescriptor,
keyRing *CommitmentKeyRing, chanType channeldb.ChannelType, keyRing *CommitmentKeyRing, chanType channeldb.ChannelType,
auxLeaf input.AuxTapLeaf) error { auxLeaf input.AuxTapLeaf) error {
@@ -1253,7 +1253,7 @@ func addHTLC(commitTx *wire.MsgTx, whoseCommit lntypes.ChannelParty,
amountPending := int64(paymentDesc.Amount.ToSatoshis()) amountPending := int64(paymentDesc.Amount.ToSatoshis())
commitTx.AddTxOut(wire.NewTxOut(amountPending, pkScript)) commitTx.AddTxOut(wire.NewTxOut(amountPending, pkScript))
// Store the pkScript of this particular PaymentDescriptor so we can // Store the pkScript of this particular paymentDescriptor so we can
// quickly locate it within the commitment transaction later. // quickly locate it within the commitment transaction later.
if whoseCommit.IsLocal() { if whoseCommit.IsLocal() {
paymentDesc.ourPkScript = pkScript paymentDesc.ourPkScript = pkScript
+65 -7
View File
@@ -62,14 +62,19 @@ func (u updateType) String() string {
} }
} }
// PaymentDescriptor represents a commitment state update which either adds, // paymentDescriptor represents a commitment state update which either adds,
// settles, or removes an HTLC. PaymentDescriptors encapsulate all necessary // settles, or removes an HTLC. paymentDescriptors encapsulate all necessary
// metadata w.r.t to an HTLC, and additional data pairing a settle message to // metadata w.r.t to an HTLC, and additional data pairing a settle message to
// the original added HTLC. // the original added HTLC.
// //
// TODO(roasbeef): LogEntry interface?? // TODO(roasbeef): LogEntry interface??
// - need to separate attrs for cancel/add/settle/feeupdate // - need to separate attrs for cancel/add/settle/feeupdate
type PaymentDescriptor struct { type paymentDescriptor struct {
// ChanID is the ChannelID of the LightningChannel that this
// paymentDescriptor belongs to. We track this here so we can
// reconstruct the Messages that this paymentDescriptor is built from.
ChanID lnwire.ChannelID
// RHash is the payment hash for this HTLC. The HTLC can be settled iff // RHash is the payment hash for this HTLC. The HTLC can be settled iff
// the preimage to this hash is presented. // the preimage to this hash is presented.
RHash PaymentHash RHash PaymentHash
@@ -165,7 +170,7 @@ type PaymentDescriptor struct {
// 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 removeCommitHeightRemote uint64
@@ -175,7 +180,7 @@ type PaymentDescriptor struct {
// routing. // routing.
// //
// NOTE: Populated only on add payment descriptor entry types. // NOTE: Populated only on add payment descriptor entry types.
OnionBlob []byte OnionBlob [lnwire.OnionPacketSize]byte
// ShaOnionBlob is a sha of the onion blob. // ShaOnionBlob is a sha of the onion blob.
// //
@@ -194,7 +199,7 @@ type PaymentDescriptor struct {
// [our|their|]PkScript are the raw public key scripts that encodes the // [our|their|]PkScript are the raw public key scripts that encodes the
// redemption rules for this particular HTLC. These fields will only be // redemption rules for this particular HTLC. These fields will only be
// populated iff the EntryType of this PaymentDescriptor is Add. // populated iff the EntryType of this paymentDescriptor is Add.
// ourPkScript is the ourPkScript from the context of our local // ourPkScript is the ourPkScript from the context of our local
// commitment chain. theirPkScript is the latest pkScript from the // commitment chain. theirPkScript is the latest pkScript from the
// context of the remote commitment chain. // context of the remote commitment chain.
@@ -207,7 +212,7 @@ type PaymentDescriptor struct {
theirPkScript []byte theirPkScript []byte
theirWitnessScript []byte theirWitnessScript []byte
// EntryType denotes the exact type of the PaymentDescriptor. In the // EntryType denotes the exact type of the paymentDescriptor. In the
// case of a Timeout, or Settle type, then the Parent field will point // case of a Timeout, or Settle type, then the Parent field will point
// into the log to the HTLC being modified. // into the log to the HTLC being modified.
EntryType updateType EntryType updateType
@@ -226,3 +231,56 @@ type PaymentDescriptor struct {
// may have been attached to a sent HTLC. // may have been attached to a sent HTLC.
CustomRecords lnwire.CustomRecords CustomRecords lnwire.CustomRecords
} }
// toLogUpdate recovers the underlying LogUpdate from the paymentDescriptor.
// This operation is lossy and will forget some extra information tracked by the
// paymentDescriptor but the function is total in that all paymentDescriptors
// can be converted back to LogUpdates.
func (pd *paymentDescriptor) toLogUpdate() channeldb.LogUpdate {
var msg lnwire.Message
switch pd.EntryType {
case Add:
msg = &lnwire.UpdateAddHTLC{
ChanID: pd.ChanID,
ID: pd.HtlcIndex,
Amount: pd.Amount,
PaymentHash: pd.RHash,
Expiry: pd.Timeout,
OnionBlob: pd.OnionBlob,
BlindingPoint: pd.BlindingPoint,
CustomRecords: pd.CustomRecords.Copy(),
}
case Settle:
msg = &lnwire.UpdateFulfillHTLC{
ChanID: pd.ChanID,
ID: pd.ParentIndex,
PaymentPreimage: pd.RPreimage,
}
case Fail:
msg = &lnwire.UpdateFailHTLC{
ChanID: pd.ChanID,
ID: pd.ParentIndex,
Reason: pd.FailReason,
}
case MalformedFail:
msg = &lnwire.UpdateFailMalformedHTLC{
ChanID: pd.ChanID,
ID: pd.ParentIndex,
ShaOnionBlob: pd.ShaOnionBlob,
FailureCode: pd.FailCode,
}
case FeeUpdate:
// The Amount field holds the feerate denominated in
// msat. Since feerates are only denominated in sat/kw,
// we can convert it without loss of precision.
msg = &lnwire.UpdateFee{
ChanID: pd.ChanID,
FeePerKw: uint32(pd.Amount.ToSatoshis()),
}
}
return channeldb.LogUpdate{
LogIndex: pd.LogIndex,
UpdateMsg: msg,
}
}
+2 -2
View File
@@ -566,7 +566,7 @@ func ForceStateTransition(chanA, chanB *LightningChannel) error {
return err return err
} }
_, _, _, _, err = chanA.ReceiveRevocation(bobRevocation) _, _, err = chanA.ReceiveRevocation(bobRevocation)
if err != nil { if err != nil {
return err return err
} }
@@ -579,7 +579,7 @@ func ForceStateTransition(chanA, chanB *LightningChannel) error {
if err != nil { if err != nil {
return err return err
} }
_, _, _, _, err = chanB.ReceiveRevocation(aliceRevocation) _, _, err = chanB.ReceiveRevocation(aliceRevocation)
if err != nil { if err != nil {
return err return err
} }
+1 -1
View File
@@ -366,7 +366,7 @@ func testVectors(t *testing.T, chanType channeldb.ChannelType, test testCase) {
revMsg, _, _, err := remoteChannel.RevokeCurrentCommitment() revMsg, _, _, err := remoteChannel.RevokeCurrentCommitment()
require.NoError(t, err) require.NoError(t, err)
_, _, _, _, err = localChannel.ReceiveRevocation(revMsg) _, _, err = localChannel.ReceiveRevocation(revMsg)
require.NoError(t, err) require.NoError(t, err)
remoteNewCommit, err := remoteChannel.SignNextCommitment() remoteNewCommit, err := remoteChannel.SignNextCommitment()
+12 -12
View File
@@ -29,16 +29,16 @@ type updateLog struct {
// List is the updatelog itself, we embed this value so updateLog has // List is the updatelog itself, we embed this value so updateLog has
// access to all the method of a list.List. // access to all the method of a list.List.
*fn.List[*PaymentDescriptor] *fn.List[*paymentDescriptor]
// updateIndex maps a `logIndex` to a particular update entry. It // updateIndex maps a `logIndex` to a particular update entry. It
// deals with the four update types: // deals with the four update types:
// `Fail|MalformedFail|Settle|FeeUpdate` // `Fail|MalformedFail|Settle|FeeUpdate`
updateIndex map[uint64]*fn.Node[*PaymentDescriptor] updateIndex map[uint64]*fn.Node[*paymentDescriptor]
// htlcIndex maps a `htlcCounter` to an offered HTLC entry, hence the // htlcIndex maps a `htlcCounter` to an offered HTLC entry, hence the
// `Add` update. // `Add` update.
htlcIndex map[uint64]*fn.Node[*PaymentDescriptor] htlcIndex map[uint64]*fn.Node[*paymentDescriptor]
// modifiedHtlcs is a set that keeps track of all the current modified // modifiedHtlcs is a set that keeps track of all the current modified
// htlcs, hence update types `Fail|MalformedFail|Settle`. A modified // htlcs, hence update types `Fail|MalformedFail|Settle`. A modified
@@ -50,9 +50,9 @@ type updateLog struct {
// newUpdateLog creates a new updateLog instance. // newUpdateLog creates a new updateLog instance.
func newUpdateLog(logIndex, htlcCounter uint64) *updateLog { func newUpdateLog(logIndex, htlcCounter uint64) *updateLog {
return &updateLog{ return &updateLog{
List: fn.NewList[*PaymentDescriptor](), List: fn.NewList[*paymentDescriptor](),
updateIndex: make(map[uint64]*fn.Node[*PaymentDescriptor]), updateIndex: make(map[uint64]*fn.Node[*paymentDescriptor]),
htlcIndex: make(map[uint64]*fn.Node[*PaymentDescriptor]), htlcIndex: make(map[uint64]*fn.Node[*paymentDescriptor]),
logIndex: logIndex, logIndex: logIndex,
htlcCounter: htlcCounter, htlcCounter: htlcCounter,
modifiedHtlcs: fn.NewSet[uint64](), modifiedHtlcs: fn.NewSet[uint64](),
@@ -64,7 +64,7 @@ func newUpdateLog(logIndex, htlcCounter uint64) *updateLog {
// state. This function differs from appendHtlc in that it won't increment // state. This function differs from appendHtlc in that it won't increment
// either of log's counters. If the HTLC is already present, then it is // either of log's counters. If the HTLC is already present, then it is
// ignored. // ignored.
func (u *updateLog) restoreHtlc(pd *PaymentDescriptor) { func (u *updateLog) restoreHtlc(pd *paymentDescriptor) {
if _, ok := u.htlcIndex[pd.HtlcIndex]; ok { if _, ok := u.htlcIndex[pd.HtlcIndex]; ok {
return return
} }
@@ -74,7 +74,7 @@ func (u *updateLog) restoreHtlc(pd *PaymentDescriptor) {
// appendUpdate appends a new update to the tip of the updateLog. The entry is // appendUpdate appends a new update to the tip of the updateLog. The entry is
// also added to index accordingly. // also added to index accordingly.
func (u *updateLog) appendUpdate(pd *PaymentDescriptor) { func (u *updateLog) appendUpdate(pd *paymentDescriptor) {
u.updateIndex[u.logIndex] = u.PushBack(pd) u.updateIndex[u.logIndex] = u.PushBack(pd)
u.logIndex++ u.logIndex++
} }
@@ -82,13 +82,13 @@ func (u *updateLog) appendUpdate(pd *PaymentDescriptor) {
// restoreUpdate appends a new update to the tip of the updateLog. The entry is // restoreUpdate appends a new update to the tip of the updateLog. The entry is
// also added to index accordingly. This function differs from appendUpdate in // also added to index accordingly. This function differs from appendUpdate in
// that it won't increment the log index counter. // that it won't increment the log index counter.
func (u *updateLog) restoreUpdate(pd *PaymentDescriptor) { func (u *updateLog) restoreUpdate(pd *paymentDescriptor) {
u.updateIndex[pd.LogIndex] = u.PushBack(pd) u.updateIndex[pd.LogIndex] = u.PushBack(pd)
} }
// appendHtlc appends a new HTLC offer to the tip of the update log. The entry // appendHtlc appends a new HTLC offer to the tip of the update log. The entry
// is also added to the offer index accordingly. // is also added to the offer index accordingly.
func (u *updateLog) appendHtlc(pd *PaymentDescriptor) { func (u *updateLog) appendHtlc(pd *paymentDescriptor) {
u.htlcIndex[u.htlcCounter] = u.PushBack(pd) u.htlcIndex[u.htlcCounter] = u.PushBack(pd)
u.htlcCounter++ u.htlcCounter++
@@ -97,7 +97,7 @@ func (u *updateLog) appendHtlc(pd *PaymentDescriptor) {
// lookupHtlc attempts to look up an offered HTLC according to its offer // lookupHtlc attempts to look up an offered HTLC according to its offer
// index. If the entry isn't found, then a nil pointer is returned. // index. If the entry isn't found, then a nil pointer is returned.
func (u *updateLog) lookupHtlc(i uint64) *PaymentDescriptor { func (u *updateLog) lookupHtlc(i uint64) *paymentDescriptor {
htlc, ok := u.htlcIndex[i] htlc, ok := u.htlcIndex[i]
if !ok { if !ok {
return nil return nil
@@ -145,7 +145,7 @@ func compactLogs(ourLog, theirLog *updateLog,
localChainTail, remoteChainTail uint64) { localChainTail, remoteChainTail uint64) {
compactLog := func(logA, logB *updateLog) { compactLog := func(logA, logB *updateLog) {
var nextA *fn.Node[*PaymentDescriptor] var nextA *fn.Node[*paymentDescriptor]
for e := logA.Front(); e != nil; e = nextA { for e := logA.Front(); e != nil; e = nextA {
// Assign next iteration element at top of loop because // Assign next iteration element at top of loop because
// we may remove the current element from the list, // we may remove the current element from the list,
+9 -3
View File
@@ -10,6 +10,7 @@ import (
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/go-errors/errors" "github.com/go-errors/errors"
"github.com/lightningnetwork/lnd/fn"
"github.com/lightningnetwork/lnd/tlv" "github.com/lightningnetwork/lnd/tlv"
) )
@@ -1271,14 +1272,19 @@ func (f *FailInvalidBlinding) Encode(w *bytes.Buffer, _ uint32) error {
} }
// NewInvalidBlinding creates new instance of FailInvalidBlinding. // NewInvalidBlinding creates new instance of FailInvalidBlinding.
func NewInvalidBlinding(onion []byte) *FailInvalidBlinding { func NewInvalidBlinding(
onion fn.Option[[OnionPacketSize]byte]) *FailInvalidBlinding {
// The spec allows empty onion hashes for invalid blinding, so we only // The spec allows empty onion hashes for invalid blinding, so we only
// include our onion hash if it's provided. // include our onion hash if it's provided.
if onion == nil { if onion.IsNone() {
return &FailInvalidBlinding{} return &FailInvalidBlinding{}
} }
return &FailInvalidBlinding{OnionSHA256: sha256.Sum256(onion)} shaSum := fn.MapOptionZ(onion, func(o [OnionPacketSize]byte) [32]byte {
return sha256.Sum256(o[:])
})
return &FailInvalidBlinding{OnionSHA256: shaSum}
} }
// DecodeFailure decodes, validates, and parses the lnwire onion failure, for // DecodeFailure decodes, validates, and parses the lnwire onion failure, for
+6 -5
View File
@@ -9,11 +9,12 @@ import (
"testing" "testing"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/fn"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
var ( var (
testOnionHash = []byte{} testOnionHash = [OnionPacketSize]byte{}
testAmount = MilliSatoshi(1) testAmount = MilliSatoshi(1)
testCtlvExpiry = uint32(2) testCtlvExpiry = uint32(2)
testFlags = uint16(2) testFlags = uint16(2)
@@ -43,9 +44,9 @@ var onionFailures = []FailureMessage{
&FailMPPTimeout{}, &FailMPPTimeout{},
NewFailIncorrectDetails(99, 100), NewFailIncorrectDetails(99, 100),
NewInvalidOnionVersion(testOnionHash), NewInvalidOnionVersion(testOnionHash[:]),
NewInvalidOnionHmac(testOnionHash), NewInvalidOnionHmac(testOnionHash[:]),
NewInvalidOnionKey(testOnionHash), NewInvalidOnionKey(testOnionHash[:]),
NewTemporaryChannelFailure(&testChannelUpdate), NewTemporaryChannelFailure(&testChannelUpdate),
NewTemporaryChannelFailure(nil), NewTemporaryChannelFailure(nil),
NewAmountBelowMinimum(testAmount, testChannelUpdate), NewAmountBelowMinimum(testAmount, testChannelUpdate),
@@ -56,7 +57,7 @@ var onionFailures = []FailureMessage{
NewFinalIncorrectCltvExpiry(testCtlvExpiry), NewFinalIncorrectCltvExpiry(testCtlvExpiry),
NewFinalIncorrectHtlcAmount(testAmount), NewFinalIncorrectHtlcAmount(testAmount),
NewInvalidOnionPayload(testType, testOffset), NewInvalidOnionPayload(testType, testOffset),
NewInvalidBlinding(testOnionHash), NewInvalidBlinding(fn.Some(testOnionHash)),
} }
// TestEncodeDecodeCode tests the ability of onion errors to be properly encoded // TestEncodeDecodeCode tests the ability of onion errors to be properly encoded