lnwallet: Change channel update methods to accept HTLC ID.

Previously, some methods on a LightningChannel like SettleHTLC and
FailHTLC would identify HTLCs by payment hash. This would not always
work correctly if there are multiple HTLCs with the same payment hash,
so instead we change these methods to identify HTLCs by their unique
identifiers instead.
This commit is contained in:
Jim Posen 2017-10-24 00:48:52 -07:00 committed by Olaoluwa Osuntokun
parent 1328e61c00
commit 317b44e220
4 changed files with 181 additions and 140 deletions

View File

@ -743,8 +743,7 @@ func (l *channelLink) handleDownStreamPkt(pkt *htlcPacket, isReProcess bool) {
// An HTLC we forward to the switch has just settled somewhere // An HTLC we forward to the switch has just settled somewhere
// upstream. Therefore we settle the HTLC within the our local // upstream. Therefore we settle the HTLC within the our local
// state machine. // state machine.
pre := htlc.PaymentPreimage err := l.channel.SettleHTLC(htlc.PaymentPreimage, pkt.destID)
logIndex, _, err := l.channel.SettleHTLC(pre)
if err != nil { if err != nil {
// TODO(roasbeef): broadcast on-chain // TODO(roasbeef): broadcast on-chain
l.fail("unable to settle incoming HTLC: %v", err) l.fail("unable to settle incoming HTLC: %v", err)
@ -755,7 +754,7 @@ func (l *channelLink) handleDownStreamPkt(pkt *htlcPacket, isReProcess bool) {
// message to target the specific channel and HTLC to be // message to target the specific channel and HTLC to be
// cancelled. // cancelled.
htlc.ChanID = l.ChanID() htlc.ChanID = l.ChanID()
htlc.ID = logIndex htlc.ID = pkt.destID
// Then we send the HTLC settle message to the connected peer // Then we send the HTLC settle message to the connected peer
// so we can continue the propagation of the settle message. // so we can continue the propagation of the settle message.
@ -765,7 +764,7 @@ func (l *channelLink) handleDownStreamPkt(pkt *htlcPacket, isReProcess bool) {
case *lnwire.UpdateFailHTLC: case *lnwire.UpdateFailHTLC:
// An HTLC cancellation has been triggered somewhere upstream, // An HTLC cancellation has been triggered somewhere upstream,
// we'll remove then HTLC from our local state machine. // we'll remove then HTLC from our local state machine.
logIndex, err := l.channel.FailHTLC(pkt.payHash, htlc.Reason) err := l.channel.FailHTLC(pkt.destID, htlc.Reason)
if err != nil { if err != nil {
log.Errorf("unable to cancel HTLC: %v", err) log.Errorf("unable to cancel HTLC: %v", err)
return return
@ -776,7 +775,7 @@ func (l *channelLink) handleDownStreamPkt(pkt *htlcPacket, isReProcess bool) {
// cancelled. The "Reason" field will have already been set // cancelled. The "Reason" field will have already been set
// within the switch. // within the switch.
htlc.ChanID = l.ChanID() htlc.ChanID = l.ChanID()
htlc.ID = logIndex htlc.ID = pkt.destID
// Finally, we send the HTLC message to the peer which // Finally, we send the HTLC message to the peer which
// initially created the HTLC. // initially created the HTLC.
@ -891,7 +890,7 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) {
// If remote side have been unable to parse the onion blob we // If remote side have been unable to parse the onion blob we
// have sent to it, than we should transform the malformed HTLC // have sent to it, than we should transform the malformed HTLC
// message to the usual HTLC fail message. // message to the usual HTLC fail message.
_, err := l.channel.ReceiveFailHTLC(msg.ID, b.Bytes()) err := l.channel.ReceiveFailHTLC(msg.ID, b.Bytes())
if err != nil { if err != nil {
l.fail("unable to handle upstream fail HTLC: %v", err) l.fail("unable to handle upstream fail HTLC: %v", err)
return return
@ -899,7 +898,7 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) {
case *lnwire.UpdateFailHTLC: case *lnwire.UpdateFailHTLC:
idx := msg.ID idx := msg.ID
_, err := l.channel.ReceiveFailHTLC(idx, msg.Reason[:]) err := l.channel.ReceiveFailHTLC(idx, msg.Reason[:])
if err != nil { if err != nil {
l.fail("unable to handle upstream fail HTLC: %v", err) l.fail("unable to handle upstream fail HTLC: %v", err)
return return
@ -1219,7 +1218,7 @@ func (l *channelLink) processLockedInHtlcs(
// continue to propagate it. // continue to propagate it.
failPacket := &htlcPacket{ failPacket := &htlcPacket{
src: l.ShortChanID(), src: l.ShortChanID(),
srcID: pd.HtlcIndex, srcID: pd.ParentIndex,
payHash: pd.RHash, payHash: pd.RHash,
amount: pd.Amount, amount: pd.Amount,
isObfuscated: false, isObfuscated: false,
@ -1256,7 +1255,7 @@ func (l *channelLink) processLockedInHtlcs(
// If we're unable to process the onion blob // If we're unable to process the onion blob
// than we should send the malformed htlc error // than we should send the malformed htlc error
// to payment sender. // to payment sender.
l.sendMalformedHTLCError(pd.RHash, failureCode, l.sendMalformedHTLCError(pd.HtlcIndex, failureCode,
onionBlob[:]) onionBlob[:])
needUpdate = true needUpdate = true
@ -1284,7 +1283,7 @@ func (l *channelLink) processLockedInHtlcs(
// If we're unable to process the onion blob // If we're unable to process the onion blob
// than we should send the malformed htlc error // than we should send the malformed htlc error
// to payment sender. // to payment sender.
l.sendMalformedHTLCError(pd.RHash, failureCode, l.sendMalformedHTLCError(pd.HtlcIndex, failureCode,
onionBlob[:]) onionBlob[:])
needUpdate = true needUpdate = true
@ -1309,7 +1308,7 @@ func (l *channelLink) processLockedInHtlcs(
pd.Timeout, heightNow) pd.Timeout, heightNow)
failure := lnwire.FailFinalIncorrectCltvExpiry{} failure := lnwire.FailFinalIncorrectCltvExpiry{}
l.sendHTLCError(pd.RHash, &failure, obfuscator) l.sendHTLCError(pd.HtlcIndex, &failure, obfuscator)
needUpdate = true needUpdate = true
continue continue
} }
@ -1324,7 +1323,7 @@ func (l *channelLink) processLockedInHtlcs(
log.Errorf("unable to query invoice registry: "+ log.Errorf("unable to query invoice registry: "+
" %v", err) " %v", err)
failure := lnwire.FailUnknownPaymentHash{} failure := lnwire.FailUnknownPaymentHash{}
l.sendHTLCError(pd.RHash, failure, obfuscator) l.sendHTLCError(pd.HtlcIndex, failure, obfuscator)
needUpdate = true needUpdate = true
continue continue
} }
@ -1340,7 +1339,7 @@ func (l *channelLink) processLockedInHtlcs(
"amount: expected %v, received %v", "amount: expected %v, received %v",
invoice.Terms.Value, pd.Amount) invoice.Terms.Value, pd.Amount)
failure := lnwire.FailIncorrectPaymentAmount{} failure := lnwire.FailIncorrectPaymentAmount{}
l.sendHTLCError(pd.RHash, failure, obfuscator) l.sendHTLCError(pd.HtlcIndex, failure, obfuscator)
needUpdate = true needUpdate = true
continue continue
} }
@ -1360,7 +1359,7 @@ func (l *channelLink) processLockedInHtlcs(
fwdInfo.AmountToForward) fwdInfo.AmountToForward)
failure := lnwire.FailIncorrectPaymentAmount{} failure := lnwire.FailIncorrectPaymentAmount{}
l.sendHTLCError(pd.RHash, failure, obfuscator) l.sendHTLCError(pd.HtlcIndex, failure, obfuscator)
needUpdate = true needUpdate = true
continue continue
} }
@ -1382,7 +1381,7 @@ func (l *channelLink) processLockedInHtlcs(
failure := lnwire.NewFinalIncorrectCltvExpiry( failure := lnwire.NewFinalIncorrectCltvExpiry(
fwdInfo.OutgoingCTLV, fwdInfo.OutgoingCTLV,
) )
l.sendHTLCError(pd.RHash, failure, obfuscator) l.sendHTLCError(pd.HtlcIndex, failure, obfuscator)
needUpdate = true needUpdate = true
continue continue
case pd.Timeout != fwdInfo.OutgoingCTLV: case pd.Timeout != fwdInfo.OutgoingCTLV:
@ -1394,7 +1393,7 @@ func (l *channelLink) processLockedInHtlcs(
failure := lnwire.NewFinalIncorrectCltvExpiry( failure := lnwire.NewFinalIncorrectCltvExpiry(
fwdInfo.OutgoingCTLV, fwdInfo.OutgoingCTLV,
) )
l.sendHTLCError(pd.RHash, failure, obfuscator) l.sendHTLCError(pd.HtlcIndex, failure, obfuscator)
needUpdate = true needUpdate = true
continue continue
} }
@ -1408,7 +1407,7 @@ func (l *channelLink) processLockedInHtlcs(
} }
preimage := invoice.Terms.PaymentPreimage preimage := invoice.Terms.PaymentPreimage
logIndex, _, err := l.channel.SettleHTLC(preimage) err = l.channel.SettleHTLC(preimage, pd.HtlcIndex)
if err != nil { if err != nil {
l.fail("unable to settle htlc: %v", err) l.fail("unable to settle htlc: %v", err)
return nil return nil
@ -1427,7 +1426,7 @@ func (l *channelLink) processLockedInHtlcs(
// notification about it remote peer. // notification about it remote peer.
l.cfg.Peer.SendMessage(&lnwire.UpdateFufillHTLC{ l.cfg.Peer.SendMessage(&lnwire.UpdateFufillHTLC{
ChanID: l.ChanID(), ChanID: l.ChanID(),
ID: logIndex, ID: pd.HtlcIndex,
PaymentPreimage: preimage, PaymentPreimage: preimage,
}) })
needUpdate = true needUpdate = true
@ -1456,7 +1455,7 @@ func (l *channelLink) processLockedInHtlcs(
failure = lnwire.NewExpiryTooSoon(*update) failure = lnwire.NewExpiryTooSoon(*update)
} }
l.sendHTLCError(pd.RHash, failure, obfuscator) l.sendHTLCError(pd.HtlcIndex, failure, obfuscator)
needUpdate = true needUpdate = true
continue continue
} }
@ -1483,7 +1482,7 @@ func (l *channelLink) processLockedInHtlcs(
pd.Amount, *update) pd.Amount, *update)
} }
l.sendHTLCError(pd.RHash, failure, obfuscator) l.sendHTLCError(pd.HtlcIndex, failure, obfuscator)
needUpdate = true needUpdate = true
continue continue
} }
@ -1525,7 +1524,7 @@ func (l *channelLink) processLockedInHtlcs(
*update) *update)
} }
l.sendHTLCError(pd.RHash, failure, obfuscator) l.sendHTLCError(pd.HtlcIndex, failure, obfuscator)
needUpdate = true needUpdate = true
continue continue
} }
@ -1557,7 +1556,7 @@ func (l *channelLink) processLockedInHtlcs(
failure := lnwire.NewIncorrectCltvExpiry( failure := lnwire.NewIncorrectCltvExpiry(
pd.Timeout, *update) pd.Timeout, *update)
l.sendHTLCError(pd.RHash, failure, obfuscator) l.sendHTLCError(pd.HtlcIndex, failure, obfuscator)
needUpdate = true needUpdate = true
continue continue
} }
@ -1584,7 +1583,7 @@ func (l *channelLink) processLockedInHtlcs(
"remaining route %v", err) "remaining route %v", err)
failure := lnwire.NewTemporaryChannelFailure(nil) failure := lnwire.NewTemporaryChannelFailure(nil)
l.sendHTLCError(pd.RHash, failure, obfuscator) l.sendHTLCError(pd.HtlcIndex, failure, obfuscator)
needUpdate = true needUpdate = true
continue continue
} }
@ -1616,8 +1615,8 @@ func (l *channelLink) processLockedInHtlcs(
// 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(rHash [32]byte, failure lnwire.FailureMessage, func (l *channelLink) sendHTLCError(htlcIndex uint64,
e ErrorEncrypter) { failure lnwire.FailureMessage, e ErrorEncrypter) {
reason, err := e.EncryptFirstHop(failure) reason, err := e.EncryptFirstHop(failure)
if err != nil { if err != nil {
@ -1625,7 +1624,7 @@ func (l *channelLink) sendHTLCError(rHash [32]byte, failure lnwire.FailureMessag
return return
} }
index, err := l.channel.FailHTLC(rHash, reason) err = l.channel.FailHTLC(htlcIndex, reason)
if err != nil { if err != nil {
log.Errorf("unable cancel htlc: %v", err) log.Errorf("unable cancel htlc: %v", err)
return return
@ -1633,18 +1632,18 @@ func (l *channelLink) sendHTLCError(rHash [32]byte, failure lnwire.FailureMessag
l.cfg.Peer.SendMessage(&lnwire.UpdateFailHTLC{ l.cfg.Peer.SendMessage(&lnwire.UpdateFailHTLC{
ChanID: l.ChanID(), ChanID: l.ChanID(),
ID: index, ID: htlcIndex,
Reason: reason, Reason: reason,
}) })
} }
// 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(rHash [32]byte, code lnwire.FailCode, func (l *channelLink) sendMalformedHTLCError(htlcIndex uint64,
onionBlob []byte) { code lnwire.FailCode, onionBlob []byte) {
shaOnionBlob := sha256.Sum256(onionBlob) shaOnionBlob := sha256.Sum256(onionBlob)
index, err := l.channel.MalformedFailHTLC(rHash, code, shaOnionBlob) err := l.channel.MalformedFailHTLC(htlcIndex, code, shaOnionBlob)
if err != nil { if err != nil {
log.Errorf("unable cancel htlc: %v", err) log.Errorf("unable cancel htlc: %v", err)
return return
@ -1652,7 +1651,7 @@ func (l *channelLink) sendMalformedHTLCError(rHash [32]byte, code lnwire.FailCod
l.cfg.Peer.SendMessage(&lnwire.UpdateFailMalformedHTLC{ l.cfg.Peer.SendMessage(&lnwire.UpdateFailMalformedHTLC{
ChanID: l.ChanID(), ChanID: l.ChanID(),
ID: index, ID: htlcIndex,
ShaOnionBlob: shaOnionBlob, ShaOnionBlob: shaOnionBlob,
FailureCode: code, FailureCode: code,
}) })

View File

@ -1583,6 +1583,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) {
// remain unchanged (but Alice will need to pay the fee for the extra // remain unchanged (but Alice will need to pay the fee for the extra
// HTLC). // HTLC).
updateMsg := &lnwire.UpdateAddHTLC{ updateMsg := &lnwire.UpdateAddHTLC{
ID: 0,
Amount: htlcAmt, Amount: htlcAmt,
Expiry: 9, Expiry: 9,
PaymentHash: htlc.PaymentHash, // Re-using the same payment hash. PaymentHash: htlc.PaymentHash, // Re-using the same payment hash.
@ -1607,6 +1608,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) {
// Finally, we'll test the scenario of failing an HTLC received by the // Finally, we'll test the scenario of failing an HTLC received by the
// remote node. This should result in no perceived bandwidth changes. // remote node. This should result in no perceived bandwidth changes.
htlcAdd := &lnwire.UpdateAddHTLC{ htlcAdd := &lnwire.UpdateAddHTLC{
ID: 1,
Amount: htlcAmt, Amount: htlcAmt,
Expiry: 9, Expiry: 9,
PaymentHash: htlc.PaymentHash, PaymentHash: htlc.PaymentHash,

View File

@ -17,8 +17,6 @@ import (
"github.com/roasbeef/btcd/blockchain" "github.com/roasbeef/btcd/blockchain"
"github.com/roasbeef/btcd/chaincfg/chainhash" "github.com/roasbeef/btcd/chaincfg/chainhash"
"encoding/hex"
"github.com/roasbeef/btcd/btcec" "github.com/roasbeef/btcd/btcec"
"github.com/roasbeef/btcd/txscript" "github.com/roasbeef/btcd/txscript"
"github.com/roasbeef/btcd/wire" "github.com/roasbeef/btcd/wire"
@ -3895,6 +3893,11 @@ func (lc *LightningChannel) ReceiveHTLC(htlc *lnwire.UpdateAddHTLC) (uint64, err
lc.Lock() lc.Lock()
defer lc.Unlock() defer lc.Unlock()
if htlc.ID != lc.remoteUpdateLog.htlcCounter {
return 0, fmt.Errorf("ID %d on HTLC add does not match expected next "+
"ID %d", htlc.ID, lc.remoteUpdateLog.htlcCounter)
}
if err := lc.validateCommitmentSanity(lc.remoteUpdateLog.logIndex, if err := lc.validateCommitmentSanity(lc.remoteUpdateLog.logIndex,
lc.localUpdateLog.logIndex, true, false, true); err != nil { lc.localUpdateLog.logIndex, true, false, true); err != nil {
return 0, err return 0, err
@ -3922,36 +3925,41 @@ func (lc *LightningChannel) ReceiveHTLC(htlc *lnwire.UpdateAddHTLC) (uint64, err
// creating the corresponding wire message. In the case the supplied preimage // creating the corresponding wire message. In the case the supplied preimage
// is invalid, an error is returned. Additionally, the value of the settled // is invalid, an error is returned. Additionally, the value of the settled
// HTLC is also returned. // HTLC is also returned.
func (lc *LightningChannel) SettleHTLC(preimage [32]byte) (uint64, func (lc *LightningChannel) SettleHTLC(preimage [32]byte, htlcIndex uint64,
lnwire.MilliSatoshi, error) { ) error {
lc.Lock() lc.Lock()
defer lc.Unlock() defer lc.Unlock()
paymentHash := sha256.Sum256(preimage[:]) htlc := lc.remoteUpdateLog.lookupHtlc(htlcIndex)
targetHTLCs, ok := lc.rHashMap[paymentHash] if htlc == nil {
if !ok { return fmt.Errorf("No HTLC with ID %d in channel %v", htlcIndex,
return 0, 0, fmt.Errorf("invalid payment hash(%v)", lc.channelState.ShortChanID)
hex.EncodeToString(paymentHash[:])) }
if htlc.RHash != sha256.Sum256(preimage[:]) {
return fmt.Errorf("Invalid payment preimage %x for hash %x",
preimage[:], htlc.RHash[:])
} }
targetHTLC := targetHTLCs[0]
pd := &PaymentDescriptor{ pd := &PaymentDescriptor{
Amount: targetHTLC.Amount, Amount: htlc.Amount,
RPreimage: preimage, RPreimage: preimage,
LogIndex: lc.localUpdateLog.logIndex, LogIndex: lc.localUpdateLog.logIndex,
ParentIndex: targetHTLC.HtlcIndex, ParentIndex: htlcIndex,
EntryType: Settle, EntryType: Settle,
} }
lc.localUpdateLog.appendUpdate(pd) lc.localUpdateLog.appendUpdate(pd)
paymentHash := htlc.RHash
lc.rHashMap[paymentHash][0] = nil lc.rHashMap[paymentHash][0] = nil
lc.rHashMap[paymentHash] = lc.rHashMap[paymentHash][1:] lc.rHashMap[paymentHash] = lc.rHashMap[paymentHash][1:]
if len(lc.rHashMap[paymentHash]) == 0 { if len(lc.rHashMap[paymentHash]) == 0 {
delete(lc.rHashMap, paymentHash) delete(lc.rHashMap, paymentHash)
} }
return targetHTLC.HtlcIndex, targetHTLC.Amount, nil return nil
} }
// ReceiveHTLCSettle attempts to settle an existing outgoing HTLC indexed by an // ReceiveHTLCSettle attempts to settle an existing outgoing HTLC indexed by an
@ -3962,15 +3970,15 @@ func (lc *LightningChannel) ReceiveHTLCSettle(preimage [32]byte, htlcIndex uint6
lc.Lock() lc.Lock()
defer lc.Unlock() defer lc.Unlock()
paymentHash := sha256.Sum256(preimage[:])
htlc := lc.localUpdateLog.lookupHtlc(htlcIndex) htlc := lc.localUpdateLog.lookupHtlc(htlcIndex)
if htlc == nil { if htlc == nil {
return fmt.Errorf("non-existent log entry") return fmt.Errorf("No HTLC with ID %d in channel %v", htlcIndex,
lc.channelState.ShortChanID)
} }
if !bytes.Equal(htlc.RHash[:], paymentHash[:]) { if htlc.RHash != sha256.Sum256(preimage[:]) {
return fmt.Errorf("invalid payment hash(%v)", return fmt.Errorf("Invalid payment preimage %x for hash %x",
hex.EncodeToString(paymentHash[:])) preimage[:], htlc.RHash[:])
} }
pd := &PaymentDescriptor{ pd := &PaymentDescriptor{
@ -3990,22 +3998,20 @@ func (lc *LightningChannel) ReceiveHTLCSettle(preimage [32]byte, htlcIndex uint6
// entry which will remove the target log entry within the next commitment // entry which will remove the target log entry within the next commitment
// update. This method is intended to be called in order to cancel in // update. This method is intended to be called in order to cancel in
// _incoming_ HTLC. // _incoming_ HTLC.
// func (lc *LightningChannel) FailHTLC(htlcIndex uint64, reason []byte) error {
// TODO(roasbeef): add value as well?
func (lc *LightningChannel) FailHTLC(rHash [32]byte, reason []byte) (uint64, error) {
lc.Lock() lc.Lock()
defer lc.Unlock() defer lc.Unlock()
addEntries, ok := lc.rHashMap[rHash] htlc := lc.remoteUpdateLog.lookupHtlc(htlcIndex)
if !ok { if htlc == nil {
return 0, fmt.Errorf("unable to find HTLC to fail") return fmt.Errorf("No HTLC with ID %d in channel %v", htlcIndex,
lc.channelState.ShortChanID)
} }
addEntry := addEntries[0]
pd := &PaymentDescriptor{ pd := &PaymentDescriptor{
Amount: addEntry.Amount, Amount: htlc.Amount,
RHash: addEntry.RHash, RHash: htlc.RHash,
ParentIndex: addEntry.HtlcIndex, ParentIndex: htlcIndex,
LogIndex: lc.localUpdateLog.logIndex, LogIndex: lc.localUpdateLog.logIndex,
EntryType: Fail, EntryType: Fail,
FailReason: reason, FailReason: reason,
@ -4013,34 +4019,36 @@ func (lc *LightningChannel) FailHTLC(rHash [32]byte, reason []byte) (uint64, err
lc.localUpdateLog.appendUpdate(pd) lc.localUpdateLog.appendUpdate(pd)
rHash := htlc.RHash
lc.rHashMap[rHash][0] = nil lc.rHashMap[rHash][0] = nil
lc.rHashMap[rHash] = lc.rHashMap[rHash][1:] lc.rHashMap[rHash] = lc.rHashMap[rHash][1:]
if len(lc.rHashMap[rHash]) == 0 { if len(lc.rHashMap[rHash]) == 0 {
delete(lc.rHashMap, rHash) delete(lc.rHashMap, rHash)
} }
return addEntry.HtlcIndex, nil return nil
} }
// MalformedFailHTLC attempts to fail a targeted HTLC by its payment hash, // MalformedFailHTLC attempts to fail a targeted HTLC by its payment hash,
// inserting an entry which will remove the target log entry within the next // inserting an entry which will remove the target log entry within the next
// commitment update. This method is intended to be called in order to cancel // commitment update. This method is intended to be called in order to cancel
// in _incoming_ HTLC. // in _incoming_ HTLC.
func (lc *LightningChannel) MalformedFailHTLC(rHash [32]byte, func (lc *LightningChannel) MalformedFailHTLC(htlcIndex uint64,
failCode lnwire.FailCode, shaOnionBlob [sha256.Size]byte) (uint64, error) { failCode lnwire.FailCode, shaOnionBlob [sha256.Size]byte) error {
lc.Lock() lc.Lock()
defer lc.Unlock() defer lc.Unlock()
addEntries, ok := lc.rHashMap[rHash] htlc := lc.remoteUpdateLog.lookupHtlc(htlcIndex)
if !ok { if htlc == nil {
return 0, fmt.Errorf("unable to find HTLC to fail") return fmt.Errorf("No HTLC with ID %d in channel %v", htlcIndex,
lc.channelState.ShortChanID)
} }
addEntry := addEntries[0]
pd := &PaymentDescriptor{ pd := &PaymentDescriptor{
Amount: addEntry.Amount, Amount: htlc.Amount,
RHash: addEntry.RHash, RHash: htlc.RHash,
ParentIndex: addEntry.HtlcIndex, ParentIndex: htlcIndex,
LogIndex: lc.localUpdateLog.logIndex, LogIndex: lc.localUpdateLog.logIndex,
EntryType: MalformedFail, EntryType: MalformedFail,
FailCode: failCode, FailCode: failCode,
@ -4049,13 +4057,14 @@ func (lc *LightningChannel) MalformedFailHTLC(rHash [32]byte,
lc.localUpdateLog.appendUpdate(pd) lc.localUpdateLog.appendUpdate(pd)
rHash := htlc.RHash
lc.rHashMap[rHash][0] = nil lc.rHashMap[rHash][0] = nil
lc.rHashMap[rHash] = lc.rHashMap[rHash][1:] lc.rHashMap[rHash] = lc.rHashMap[rHash][1:]
if len(lc.rHashMap[rHash]) == 0 { if len(lc.rHashMap[rHash]) == 0 {
delete(lc.rHashMap, rHash) delete(lc.rHashMap, rHash)
} }
return addEntry.HtlcIndex, nil return nil
} }
// ReceiveFailHTLC attempts to cancel a targeted HTLC by its log index, // ReceiveFailHTLC attempts to cancel a targeted HTLC by its log index,
@ -4063,15 +4072,16 @@ func (lc *LightningChannel) MalformedFailHTLC(rHash [32]byte,
// commitment update. This method should be called in response to the upstream // commitment update. This method should be called in response to the upstream
// party cancelling an outgoing HTLC. The value of the failed HTLC is returned // party cancelling an outgoing HTLC. The value of the failed HTLC is returned
// along with an error indicating success. // along with an error indicating success.
func (lc *LightningChannel) ReceiveFailHTLC(htlcIndex uint64, func (lc *LightningChannel) ReceiveFailHTLC(htlcIndex uint64, reason []byte,
reason []byte) (lnwire.MilliSatoshi, error) { ) error {
lc.Lock() lc.Lock()
defer lc.Unlock() defer lc.Unlock()
htlc := lc.localUpdateLog.lookupHtlc(htlcIndex) htlc := lc.localUpdateLog.lookupHtlc(htlcIndex)
if htlc == nil { if htlc == nil {
return 0, fmt.Errorf("unable to find HTLC to fail") return fmt.Errorf("No HTLC with ID %d in channel %v", htlcIndex,
lc.channelState.ShortChanID)
} }
pd := &PaymentDescriptor{ pd := &PaymentDescriptor{
@ -4085,7 +4095,7 @@ func (lc *LightningChannel) ReceiveFailHTLC(htlcIndex uint64,
lc.remoteUpdateLog.appendUpdate(pd) lc.remoteUpdateLog.appendUpdate(pd)
return htlc.Amount, nil return nil
} }
// ChannelPoint returns the outpoint of the original funding transaction which // ChannelPoint returns the outpoint of the original funding transaction which

View File

@ -408,14 +408,15 @@ func calcStaticFee(numHTLCs int) btcutil.Amount {
// createHTLC is a utility function for generating an HTLC with a given // createHTLC is a utility function for generating an HTLC with a given
// preimage and a given amount. // preimage and a given amount.
func createHTLC(data int, amount lnwire.MilliSatoshi) (*lnwire.UpdateAddHTLC, [32]byte) { func createHTLC(id int, amount lnwire.MilliSatoshi) (*lnwire.UpdateAddHTLC, [32]byte) {
preimage := bytes.Repeat([]byte{byte(data)}, 32) preimage := bytes.Repeat([]byte{byte(id)}, 32)
paymentHash := sha256.Sum256(preimage) paymentHash := sha256.Sum256(preimage)
var returnPreimage [32]byte var returnPreimage [32]byte
copy(returnPreimage[:], preimage) copy(returnPreimage[:], preimage)
return &lnwire.UpdateAddHTLC{ return &lnwire.UpdateAddHTLC{
ID: uint64(id),
PaymentHash: paymentHash, PaymentHash: paymentHash,
Amount: amount, Amount: amount,
Expiry: uint32(5), Expiry: uint32(5),
@ -468,10 +469,13 @@ func TestSimpleAddSettleWorkflow(t *testing.T) {
// First Alice adds the outgoing HTLC to her local channel's state // First Alice adds the outgoing HTLC to her local channel's state
// update log. Then Alice sends this wire message over to Bob who adds // update log. Then Alice sends this wire message over to Bob who adds
// this htlc to his remote state update log. // this htlc to his remote state update log.
if _, err := aliceChannel.AddHTLC(htlc); err != nil { aliceHtlcIndex, err := aliceChannel.AddHTLC(htlc)
if err != nil {
t.Fatalf("unable to add htlc: %v", err) t.Fatalf("unable to add htlc: %v", err)
} }
if _, err := bobChannel.ReceiveHTLC(htlc); err != nil {
bobHtlcIndex, err := bobChannel.ReceiveHTLC(htlc)
if err != nil {
t.Fatalf("unable to recv htlc: %v", err) t.Fatalf("unable to recv htlc: %v", err)
} }
@ -596,11 +600,13 @@ func TestSimpleAddSettleWorkflow(t *testing.T) {
// HTLC once he learns of the preimage. // HTLC once he learns of the preimage.
var preimage [32]byte var preimage [32]byte
copy(preimage[:], paymentPreimage) copy(preimage[:], paymentPreimage)
settleIndex, _, err := bobChannel.SettleHTLC(preimage) err = bobChannel.SettleHTLC(preimage, bobHtlcIndex)
if err != nil { if err != nil {
t.Fatalf("bob unable to settle inbound htlc: %v", err) t.Fatalf("bob unable to settle inbound htlc: %v", err)
} }
if err := aliceChannel.ReceiveHTLCSettle(preimage, settleIndex); err != nil {
err = aliceChannel.ReceiveHTLCSettle(preimage, aliceHtlcIndex)
if err != nil {
t.Fatalf("alice unable to accept settle of outbound htlc: %v", err) t.Fatalf("alice unable to accept settle of outbound htlc: %v", err)
} }
@ -742,7 +748,7 @@ func TestCheckCommitTxSize(t *testing.T) {
// Adding HTLCs and check that size stays in allowable estimation // Adding HTLCs and check that size stays in allowable estimation
// error window. // error window.
for i := 1; i <= 10; i++ { for i := 0; i <= 10; i++ {
htlc, _ := createHTLC(i, lnwire.MilliSatoshi(1e7)) htlc, _ := createHTLC(i, lnwire.MilliSatoshi(1e7))
if _, err := aliceChannel.AddHTLC(htlc); err != nil { if _, err := aliceChannel.AddHTLC(htlc); err != nil {
@ -755,20 +761,21 @@ func TestCheckCommitTxSize(t *testing.T) {
if err := forceStateTransition(aliceChannel, bobChannel); err != nil { if err := forceStateTransition(aliceChannel, bobChannel); err != nil {
t.Fatalf("unable to complete state update: %v", err) t.Fatalf("unable to complete state update: %v", err)
} }
checkSize(aliceChannel, i) checkSize(aliceChannel, i+1)
checkSize(bobChannel, i) checkSize(bobChannel, i+1)
} }
// Settle HTLCs and check that estimation is counting cost of settle // Settle HTLCs and check that estimation is counting cost of settle
// HTLCs properly. // HTLCs properly.
for i := 10; i >= 1; i-- { for i := 10; i >= 0; i-- {
_, preimage := createHTLC(i, lnwire.MilliSatoshi(1e7)) _, preimage := createHTLC(i, lnwire.MilliSatoshi(1e7))
settleIndex, _, err := bobChannel.SettleHTLC(preimage) err := bobChannel.SettleHTLC(preimage, uint64(i))
if err != nil { if err != nil {
t.Fatalf("bob unable to settle inbound htlc: %v", err) t.Fatalf("bob unable to settle inbound htlc: %v", err)
} }
err = aliceChannel.ReceiveHTLCSettle(preimage, settleIndex)
err = aliceChannel.ReceiveHTLCSettle(preimage, uint64(i))
if err != nil { if err != nil {
t.Fatalf("alice unable to accept settle of outbound htlc: %v", err) t.Fatalf("alice unable to accept settle of outbound htlc: %v", err)
} }
@ -776,8 +783,8 @@ func TestCheckCommitTxSize(t *testing.T) {
if err := forceStateTransition(bobChannel, aliceChannel); err != nil { if err := forceStateTransition(bobChannel, aliceChannel); err != nil {
t.Fatalf("unable to complete state update: %v", err) t.Fatalf("unable to complete state update: %v", err)
} }
checkSize(aliceChannel, i-1) checkSize(aliceChannel, i)
checkSize(bobChannel, i-1) checkSize(bobChannel, i)
} }
} }
@ -1059,22 +1066,24 @@ func TestForceCloseDustOutput(t *testing.T) {
// Have Bobs' to-self output be below her dust limit and check // Have Bobs' to-self output be below her dust limit and check
// ForceCloseSummary again on both peers. // ForceCloseSummary again on both peers.
htlc, preimage := createHTLC(0, bobAmount-htlcAmount) htlc, preimage := createHTLC(0, bobAmount-htlcAmount)
if _, err := bobChannel.AddHTLC(htlc); err != nil { bobHtlcIndex, err := bobChannel.AddHTLC(htlc)
t.Fatalf("bob unable to add htlc: %v", err) if err != nil {
t.Fatalf("alice unable to add htlc: %v", err)
} }
if _, err := aliceChannel.ReceiveHTLC(htlc); err != nil { aliceHtlcIndex, err := aliceChannel.ReceiveHTLC(htlc)
t.Fatalf("alice unable to receive htlc: %v", err) if err != nil {
t.Fatalf("bob unable to receive htlc: %v", err)
} }
if err := forceStateTransition(bobChannel, aliceChannel); err != nil { if err := forceStateTransition(bobChannel, aliceChannel); err != nil {
t.Fatalf("Can't update the channel state: %v", err) t.Fatalf("Can't update the channel state: %v", err)
} }
// Settle HTLC and sign new commitment. // Settle HTLC and sign new commitment.
settleIndex, _, err := aliceChannel.SettleHTLC(preimage) err = aliceChannel.SettleHTLC(preimage, aliceHtlcIndex)
if err != nil { if err != nil {
t.Fatalf("bob unable to settle inbound htlc: %v", err) t.Fatalf("bob unable to settle inbound htlc: %v", err)
} }
err = bobChannel.ReceiveHTLCSettle(preimage, settleIndex) err = bobChannel.ReceiveHTLCSettle(preimage, bobHtlcIndex)
if err != nil { if err != nil {
t.Fatalf("alice unable to accept settle of outbound htlc: %v", err) t.Fatalf("alice unable to accept settle of outbound htlc: %v", err)
} }
@ -1241,10 +1250,12 @@ func TestHTLCDustLimit(t *testing.T) {
htlcAmount := lnwire.NewMSatFromSatoshis(htlcSat) htlcAmount := lnwire.NewMSatFromSatoshis(htlcSat)
htlc, preimage := createHTLC(0, htlcAmount) htlc, preimage := createHTLC(0, htlcAmount)
if _, err := aliceChannel.AddHTLC(htlc); err != nil { aliceHtlcIndex, err := aliceChannel.AddHTLC(htlc)
if err != nil {
t.Fatalf("alice unable to add htlc: %v", err) t.Fatalf("alice unable to add htlc: %v", err)
} }
if _, err := bobChannel.ReceiveHTLC(htlc); err != nil { bobHtlcIndex, err := bobChannel.ReceiveHTLC(htlc)
if err != nil {
t.Fatalf("bob unable to receive htlc: %v", err) t.Fatalf("bob unable to receive htlc: %v", err)
} }
if err := forceStateTransition(aliceChannel, bobChannel); err != nil { if err := forceStateTransition(aliceChannel, bobChannel); err != nil {
@ -1273,11 +1284,11 @@ func TestHTLCDustLimit(t *testing.T) {
} }
// Settle HTLC and create a new commitment state. // Settle HTLC and create a new commitment state.
settleIndex, _, err := bobChannel.SettleHTLC(preimage) err = bobChannel.SettleHTLC(preimage, bobHtlcIndex)
if err != nil { if err != nil {
t.Fatalf("bob unable to settle inbound htlc: %v", err) t.Fatalf("bob unable to settle inbound htlc: %v", err)
} }
err = aliceChannel.ReceiveHTLCSettle(preimage, settleIndex) err = aliceChannel.ReceiveHTLCSettle(preimage, aliceHtlcIndex)
if err != nil { if err != nil {
t.Fatalf("alice unable to accept settle of outbound htlc: %v", err) t.Fatalf("alice unable to accept settle of outbound htlc: %v", err)
} }
@ -1330,20 +1341,22 @@ func TestChannelBalanceDustLimit(t *testing.T) {
htlcAmount := lnwire.NewMSatFromSatoshis(htlcSat) htlcAmount := lnwire.NewMSatFromSatoshis(htlcSat)
htlc, preimage := createHTLC(0, htlcAmount) htlc, preimage := createHTLC(0, htlcAmount)
if _, err := aliceChannel.AddHTLC(htlc); err != nil { aliceHtlcIndex, err := aliceChannel.AddHTLC(htlc)
if err != nil {
t.Fatalf("alice unable to add htlc: %v", err) t.Fatalf("alice unable to add htlc: %v", err)
} }
if _, err := bobChannel.ReceiveHTLC(htlc); err != nil { bobHtlcIndex, err := bobChannel.ReceiveHTLC(htlc)
if err != nil {
t.Fatalf("bob unable to receive htlc: %v", err) t.Fatalf("bob unable to receive htlc: %v", err)
} }
if err := forceStateTransition(aliceChannel, bobChannel); err != nil { if err := forceStateTransition(aliceChannel, bobChannel); err != nil {
t.Fatalf("state transition error: %v", err) t.Fatalf("state transition error: %v", err)
} }
settleIndex, _, err := bobChannel.SettleHTLC(preimage) err = bobChannel.SettleHTLC(preimage, bobHtlcIndex)
if err != nil { if err != nil {
t.Fatalf("bob unable to settle inbound htlc: %v", err) t.Fatalf("bob unable to settle inbound htlc: %v", err)
} }
err = aliceChannel.ReceiveHTLCSettle(preimage, settleIndex) err = aliceChannel.ReceiveHTLCSettle(preimage, aliceHtlcIndex)
if err != nil { if err != nil {
t.Fatalf("alice unable to accept settle of outbound htlc: %v", err) t.Fatalf("alice unable to accept settle of outbound htlc: %v", err)
} }
@ -1392,6 +1405,7 @@ func TestStateUpdatePersistence(t *testing.T) {
for i := 0; i < 3; i++ { for i := 0; i < 3; i++ {
rHash := sha256.Sum256(alicePreimage[:]) rHash := sha256.Sum256(alicePreimage[:])
h := &lnwire.UpdateAddHTLC{ h := &lnwire.UpdateAddHTLC{
ID: uint64(i),
PaymentHash: rHash, PaymentHash: rHash,
Amount: htlcAmt, Amount: htlcAmt,
Expiry: uint32(10), Expiry: uint32(10),
@ -1587,20 +1601,20 @@ func TestStateUpdatePersistence(t *testing.T) {
// Now settle all the HTLCs, then force a state update. The state // Now settle all the HTLCs, then force a state update. The state
// update should succeed as both sides have identical. // update should succeed as both sides have identical.
for i := 0; i < 3; i++ { for i := 0; i < 3; i++ {
settleIndex, _, err := bobChannelNew.SettleHTLC(alicePreimage) err := bobChannelNew.SettleHTLC(alicePreimage, uint64(i))
if err != nil { if err != nil {
t.Fatalf("unable to settle htlc #%v: %v", i, err) t.Fatalf("unable to settle htlc #%v: %v", i, err)
} }
err = aliceChannelNew.ReceiveHTLCSettle(alicePreimage, settleIndex) err = aliceChannelNew.ReceiveHTLCSettle(alicePreimage, uint64(i))
if err != nil { if err != nil {
t.Fatalf("unable to settle htlc#%v: %v", i, err) t.Fatalf("unable to settle htlc#%v: %v", i, err)
} }
} }
settleIndex, _, err := aliceChannelNew.SettleHTLC(bobPreimage) err = aliceChannelNew.SettleHTLC(bobPreimage, 0)
if err != nil { if err != nil {
t.Fatalf("unable to settle htlc: %v", err) t.Fatalf("unable to settle htlc: %v", err)
} }
err = bobChannelNew.ReceiveHTLCSettle(bobPreimage, settleIndex) err = bobChannelNew.ReceiveHTLCSettle(bobPreimage, 0)
if err != nil { if err != nil {
t.Fatalf("unable to settle htlc: %v", err) t.Fatalf("unable to settle htlc: %v", err)
} }
@ -1678,12 +1692,13 @@ func TestCancelHTLC(t *testing.T) {
Amount: htlcAmt, Amount: htlcAmt,
Expiry: 10, Expiry: 10,
} }
paymentHash := htlc.PaymentHash
if _, err := aliceChannel.AddHTLC(htlc); err != nil { aliceHtlcIndex, err := aliceChannel.AddHTLC(htlc)
if err != nil {
t.Fatalf("unable to add alice htlc: %v", err) t.Fatalf("unable to add alice htlc: %v", err)
} }
if _, err := bobChannel.ReceiveHTLC(htlc); err != nil { bobHtlcIndex, err := bobChannel.ReceiveHTLC(htlc)
if err != nil {
t.Fatalf("unable to add bob htlc: %v", err) t.Fatalf("unable to add bob htlc: %v", err)
} }
if err := forceStateTransition(aliceChannel, bobChannel); err != nil { if err := forceStateTransition(aliceChannel, bobChannel); err != nil {
@ -1703,11 +1718,12 @@ func TestCancelHTLC(t *testing.T) {
// Now, with the HTLC committed on both sides, trigger a cancellation // Now, with the HTLC committed on both sides, trigger a cancellation
// from Bob to Alice, removing the HTLC. // from Bob to Alice, removing the HTLC.
htlcCancelIndex, err := bobChannel.FailHTLC(paymentHash, []byte("failreason")) err = bobChannel.FailHTLC(bobHtlcIndex, []byte("failreason"))
if err != nil { if err != nil {
t.Fatalf("unable to cancel HTLC: %v", err) t.Fatalf("unable to cancel HTLC: %v", err)
} }
if _, err := aliceChannel.ReceiveFailHTLC(htlcCancelIndex, []byte("bad")); err != nil { err = aliceChannel.ReceiveFailHTLC(aliceHtlcIndex, []byte("bad"))
if err != nil {
t.Fatalf("unable to recv htlc cancel: %v", err) t.Fatalf("unable to recv htlc cancel: %v", err)
} }
@ -2452,10 +2468,12 @@ func TestChanSyncFullySynced(t *testing.T) {
Amount: htlcAmt, Amount: htlcAmt,
Expiry: uint32(5), Expiry: uint32(5),
} }
if _, err := aliceChannel.AddHTLC(htlc); err != nil { aliceHtlcIndex, err := aliceChannel.AddHTLC(htlc)
if err != nil {
t.Fatalf("unable to add htlc: %v", err) t.Fatalf("unable to add htlc: %v", err)
} }
if _, err := bobChannel.ReceiveHTLC(htlc); err != nil { bobHtlcIndex, err := bobChannel.ReceiveHTLC(htlc)
if err != nil {
t.Fatalf("unable to recv htlc: %v", err) t.Fatalf("unable to recv htlc: %v", err)
} }
@ -2470,11 +2488,11 @@ func TestChanSyncFullySynced(t *testing.T) {
// If bob settles the HTLC, and then initiates a state transition, they // If bob settles the HTLC, and then initiates a state transition, they
// should both still think that they're in sync. // should both still think that they're in sync.
settleIndex, _, err := bobChannel.SettleHTLC(paymentPreimage) err = bobChannel.SettleHTLC(paymentPreimage, bobHtlcIndex)
if err != nil { if err != nil {
t.Fatalf("unable to settle htlc: %v", err) t.Fatalf("unable to settle htlc: %v", err)
} }
err = aliceChannel.ReceiveHTLCSettle(paymentPreimage, settleIndex) err = aliceChannel.ReceiveHTLCSettle(paymentPreimage, aliceHtlcIndex)
if err != nil { if err != nil {
t.Fatalf("unable to settle htlc: %v", err) t.Fatalf("unable to settle htlc: %v", err)
} }
@ -2573,9 +2591,12 @@ func TestChanSyncOweCommitment(t *testing.T) {
OnionBlob: fakeOnionBlob, OnionBlob: fakeOnionBlob,
} }
if _, err := bobChannel.AddHTLC(h); err != nil { htlcIndex, err := bobChannel.AddHTLC(h)
if err != nil {
t.Fatalf("unable to add bob's htlc: %v", err) t.Fatalf("unable to add bob's htlc: %v", err)
} }
h.ID = htlcIndex
if _, err := aliceChannel.ReceiveHTLC(h); err != nil { if _, err := aliceChannel.ReceiveHTLC(h); err != nil {
t.Fatalf("unable to recv bob's htlc: %v", err) t.Fatalf("unable to recv bob's htlc: %v", err)
} }
@ -2594,11 +2615,11 @@ func TestChanSyncOweCommitment(t *testing.T) {
// Next, Alice's settles all 3 HTLC's from Bob, and also adds a new // Next, Alice's settles all 3 HTLC's from Bob, and also adds a new
// HTLC of her own. // HTLC of her own.
for i := 0; i < 3; i++ { for i := 0; i < 3; i++ {
settleIndex, _, err := aliceChannel.SettleHTLC(bobPreimage) err := aliceChannel.SettleHTLC(bobPreimage, uint64(i))
if err != nil { if err != nil {
t.Fatalf("unable to settle htlc: %v", err) t.Fatalf("unable to settle htlc: %v", err)
} }
err = bobChannel.ReceiveHTLCSettle(bobPreimage, settleIndex) err = bobChannel.ReceiveHTLCSettle(bobPreimage, uint64(i))
if err != nil { if err != nil {
t.Fatalf("unable to settle htlc: %v", err) t.Fatalf("unable to settle htlc: %v", err)
} }
@ -2613,10 +2634,12 @@ func TestChanSyncOweCommitment(t *testing.T) {
Expiry: uint32(10), Expiry: uint32(10),
OnionBlob: fakeOnionBlob, OnionBlob: fakeOnionBlob,
} }
if _, err := aliceChannel.AddHTLC(aliceHtlc); err != nil { aliceHtlcIndex, err := aliceChannel.AddHTLC(aliceHtlc)
if err != nil {
t.Fatalf("unable to add alice's htlc: %v", err) t.Fatalf("unable to add alice's htlc: %v", err)
} }
if _, err := bobChannel.ReceiveHTLC(aliceHtlc); err != nil { bobHtlcIndex, err := bobChannel.ReceiveHTLC(aliceHtlc)
if err != nil {
t.Fatalf("unable to recv alice's htlc: %v", err) t.Fatalf("unable to recv alice's htlc: %v", err)
} }
@ -2815,11 +2838,11 @@ func TestChanSyncOweCommitment(t *testing.T) {
// We'll conclude the test by having Bob settle Alice's HTLC, then // We'll conclude the test by having Bob settle Alice's HTLC, then
// initiate a state transition. // initiate a state transition.
settleIndex, _, err := bobChannel.SettleHTLC(alicePreimage) err = bobChannel.SettleHTLC(alicePreimage, bobHtlcIndex)
if err != nil { if err != nil {
t.Fatalf("unable to settle htlc: %v", err) t.Fatalf("unable to settle htlc: %v", err)
} }
err = aliceChannel.ReceiveHTLCSettle(alicePreimage, settleIndex) err = aliceChannel.ReceiveHTLCSettle(alicePreimage, aliceHtlcIndex)
if err != nil { if err != nil {
t.Fatalf("unable to settle htlc: %v", err) t.Fatalf("unable to settle htlc: %v", err)
} }
@ -2880,10 +2903,12 @@ func TestChanSyncOweRevocation(t *testing.T) {
Amount: htlcAmt, Amount: htlcAmt,
Expiry: uint32(10), Expiry: uint32(10),
} }
if _, err := bobChannel.AddHTLC(bobHtlc); err != nil { bobHtlcIndex, err := bobChannel.AddHTLC(bobHtlc)
if err != nil {
t.Fatalf("unable to add bob's htlc: %v", err) t.Fatalf("unable to add bob's htlc: %v", err)
} }
if _, err := aliceChannel.ReceiveHTLC(bobHtlc); err != nil { aliceHtlcIndex, err := aliceChannel.ReceiveHTLC(bobHtlc)
if err != nil {
t.Fatalf("unable to recv bob's htlc: %v", err) t.Fatalf("unable to recv bob's htlc: %v", err)
} }
if err := forceStateTransition(bobChannel, aliceChannel); err != nil { if err := forceStateTransition(bobChannel, aliceChannel); err != nil {
@ -2892,11 +2917,11 @@ func TestChanSyncOweRevocation(t *testing.T) {
// Next, Alice will settle that single HTLC, the _begin_ the start of a // Next, Alice will settle that single HTLC, the _begin_ the start of a
// state transition. // state transition.
settleIndex, _, err := aliceChannel.SettleHTLC(bobPreimage) err = aliceChannel.SettleHTLC(bobPreimage, aliceHtlcIndex)
if err != nil { if err != nil {
t.Fatalf("unable to settle htlc: %v", err) t.Fatalf("unable to settle htlc: %v", err)
} }
err = bobChannel.ReceiveHTLCSettle(bobPreimage, settleIndex) err = bobChannel.ReceiveHTLCSettle(bobPreimage, bobHtlcIndex)
if err != nil { if err != nil {
t.Fatalf("unable to settle htlc: %v", err) t.Fatalf("unable to settle htlc: %v", err)
} }
@ -3064,10 +3089,12 @@ func TestChanSyncOweRevocationAndCommit(t *testing.T) {
Amount: htlcAmt, Amount: htlcAmt,
Expiry: uint32(10), Expiry: uint32(10),
} }
if _, err := bobChannel.AddHTLC(bobHtlc); err != nil { bobHtlcIndex, err := bobChannel.AddHTLC(bobHtlc)
if err != nil {
t.Fatalf("unable to add bob's htlc: %v", err) t.Fatalf("unable to add bob's htlc: %v", err)
} }
if _, err := aliceChannel.ReceiveHTLC(bobHtlc); err != nil { aliceHtlcIndex, err := aliceChannel.ReceiveHTLC(bobHtlc)
if err != nil {
t.Fatalf("unable to recv bob's htlc: %v", err) t.Fatalf("unable to recv bob's htlc: %v", err)
} }
if err := forceStateTransition(bobChannel, aliceChannel); err != nil { if err := forceStateTransition(bobChannel, aliceChannel); err != nil {
@ -3076,11 +3103,11 @@ func TestChanSyncOweRevocationAndCommit(t *testing.T) {
// Next, Alice will settle that incoming HTLC, then we'll start the // Next, Alice will settle that incoming HTLC, then we'll start the
// core of the test itself. // core of the test itself.
settleIndex, _, err := aliceChannel.SettleHTLC(bobPreimage) err = aliceChannel.SettleHTLC(bobPreimage, aliceHtlcIndex)
if err != nil { if err != nil {
t.Fatalf("unable to settle htlc: %v", err) t.Fatalf("unable to settle htlc: %v", err)
} }
err = bobChannel.ReceiveHTLCSettle(bobPreimage, settleIndex) err = bobChannel.ReceiveHTLCSettle(bobPreimage, bobHtlcIndex)
if err != nil { if err != nil {
t.Fatalf("unable to settle htlc: %v", err) t.Fatalf("unable to settle htlc: %v", err)
} }
@ -3232,10 +3259,12 @@ func TestChanSyncOweRevocationAndCommitForceTransition(t *testing.T) {
Amount: htlcAmt, Amount: htlcAmt,
Expiry: uint32(10), Expiry: uint32(10),
} }
if _, err := bobChannel.AddHTLC(bobHtlc); err != nil { bobHtlcIndex, err := bobChannel.AddHTLC(bobHtlc)
if err != nil {
t.Fatalf("unable to add bob's htlc: %v", err) t.Fatalf("unable to add bob's htlc: %v", err)
} }
if _, err := aliceChannel.ReceiveHTLC(bobHtlc); err != nil { aliceHtlcIndex, err := aliceChannel.ReceiveHTLC(bobHtlc)
if err != nil {
t.Fatalf("unable to recv bob's htlc: %v", err) t.Fatalf("unable to recv bob's htlc: %v", err)
} }
if err := forceStateTransition(bobChannel, aliceChannel); err != nil { if err := forceStateTransition(bobChannel, aliceChannel); err != nil {
@ -3244,11 +3273,11 @@ func TestChanSyncOweRevocationAndCommitForceTransition(t *testing.T) {
// Next, Alice will settle that incoming HTLC, then we'll start the // Next, Alice will settle that incoming HTLC, then we'll start the
// core of the test itself. // core of the test itself.
settleIndex, _, err := aliceChannel.SettleHTLC(bobPreimage) err = aliceChannel.SettleHTLC(bobPreimage, aliceHtlcIndex)
if err != nil { if err != nil {
t.Fatalf("unable to settle htlc: %v", err) t.Fatalf("unable to settle htlc: %v", err)
} }
err = bobChannel.ReceiveHTLCSettle(bobPreimage, settleIndex) err = bobChannel.ReceiveHTLCSettle(bobPreimage, bobHtlcIndex)
if err != nil { if err != nil {
t.Fatalf("unable to settle htlc: %v", err) t.Fatalf("unable to settle htlc: %v", err)
} }
@ -3799,7 +3828,7 @@ func TestChanAvailableBandwidth(t *testing.T) {
// transaction. // transaction.
htlcAmt = lnwire.NewMSatFromSatoshis(30000) htlcAmt = lnwire.NewMSatFromSatoshis(30000)
for i := 0; i < numHtlcs; i++ { for i := 0; i < numHtlcs; i++ {
htlc, preImage := createHTLC(i, htlcAmt) htlc, preImage := createHTLC(numHtlcs+i, htlcAmt)
if _, err := aliceChannel.AddHTLC(htlc); err != nil { if _, err := aliceChannel.AddHTLC(htlc); err != nil {
t.Fatalf("unable to add htlc: %v", err) t.Fatalf("unable to add htlc: %v", err)
} }
@ -3816,21 +3845,22 @@ func TestChanAvailableBandwidth(t *testing.T) {
// the update log). // the update log).
for i := 0; i < (numHtlcs*2)-1; i++ { for i := 0; i < (numHtlcs*2)-1; i++ {
preImage := alicePreimages[i] preImage := alicePreimages[i]
settleIndex, _, err := bobChannel.SettleHTLC(preImage) err := bobChannel.SettleHTLC(preImage, uint64(i))
if err != nil { if err != nil {
t.Fatalf("unable to settle htlc: %v", err) t.Fatalf("unable to settle htlc: %v", err)
} }
err = aliceChannel.ReceiveHTLCSettle(preImage, settleIndex) err = aliceChannel.ReceiveHTLCSettle(preImage, uint64(i))
if err != nil { if err != nil {
t.Fatalf("unable to settle htlc: %v", err) t.Fatalf("unable to settle htlc: %v", err)
} }
} }
failHash := sha256.Sum256(alicePreimages[5][:])
failIndex, err := bobChannel.FailHTLC(failHash, []byte("f")) htlcIndex := uint64((numHtlcs * 2) - 1)
err = bobChannel.FailHTLC(htlcIndex, []byte("f"))
if err != nil { if err != nil {
t.Fatalf("unable to cancel HTLC: %v", err) t.Fatalf("unable to cancel HTLC: %v", err)
} }
_, err = aliceChannel.ReceiveFailHTLC(failIndex, []byte("bad")) err = aliceChannel.ReceiveFailHTLC(htlcIndex, []byte("bad"))
if err != nil { if err != nil {
t.Fatalf("unable to recv htlc cancel: %v", err) t.Fatalf("unable to recv htlc cancel: %v", err)
} }