htlcswitch+lnwallet: add malformed payment descriptor

This commit is contained in:
Andrey Samokhvalov
2017-08-14 14:21:57 +03:00
committed by Olaoluwa Osuntokun
parent e29193d550
commit a10ed36e8f
2 changed files with 69 additions and 5 deletions

View File

@@ -1513,7 +1513,9 @@ func (l *channelLink) sendHTLCError(rHash [32]byte, failure lnwire.FailureMessag
// to the payment sender. // to the payment sender.
func (l *channelLink) sendMalformedHTLCError(rHash [32]byte, code lnwire.FailCode, func (l *channelLink) sendMalformedHTLCError(rHash [32]byte, code lnwire.FailCode,
onionBlob []byte) { onionBlob []byte) {
index, err := l.channel.FailHTLC(rHash)
shaOnionBlob := sha256.Sum256(onionBlob)
index, err := l.channel.MalformedFailHTLC(rHash, code, shaOnionBlob)
if err != nil { if err != nil {
log.Errorf("unable cancel htlc: %v", err) log.Errorf("unable cancel htlc: %v", err)
return return
@@ -1522,7 +1524,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: index,
ShaOnionBlob: sha256.Sum256(onionBlob), ShaOnionBlob: shaOnionBlob,
FailureCode: code, FailureCode: code,
}) })
} }

View File

@@ -107,6 +107,13 @@ const (
// which contains the Fail entry. // which contains the Fail entry.
Fail Fail
// MalformedFail is an update type which removes a prior HTLC entry from the
// log. Adding a MalformedFail entry to ones log will modify the _remote_
// parties update log once a new commitment view has been evaluated which
// contains the MalformedFail entry. The difference from Fail type lie in
// the different data we have to store.
MalformedFail
// Settle is an update type which settles a prior HTLC crediting the // Settle is an update type which settles a prior HTLC crediting the
// balance of the receiving node. Adding a Settle entry to a log will // balance of the receiving node. Adding a Settle entry to a log will
// result in the settle entry being removed on the log as well as the // result in the settle entry being removed on the log as well as the
@@ -123,6 +130,8 @@ func (u updateType) String() string {
return "Add" return "Add"
case Fail: case Fail:
return "Fail" return "Fail"
case MalformedFail:
return "MalformedFail"
case Settle: case Settle:
return "Settle" return "Settle"
default: default:
@@ -214,11 +223,21 @@ type PaymentDescriptor struct {
// NOTE: Populated only on add payment descriptor entry types. // NOTE: Populated only on add payment descriptor entry types.
OnionBlob []byte OnionBlob []byte
// ShaOnionBlob is a sha of the onion blob.
//
// NOTE: Populated only in payment descriptor with MalfromedFail type.
ShaOnionBlob [sha256.Size]byte
// FailReason stores the reason why a particular payment was cancelled. // FailReason stores the reason why a particular payment was cancelled.
// //
// NOTE: Populate only in fail payment descriptor entry types. // NOTE: Populate only in fail payment descriptor entry types.
FailReason []byte FailReason []byte
// FailCode stores the code why a particular payment was cancelled.
//
// NOTE: Populated only in payment descriptor with MalfromedFail type.
FailCode lnwire.FailCode
// [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.
@@ -2153,7 +2172,7 @@ func processRemoveEntry(htlc *PaymentDescriptor, ourBalance,
// Otherwise, this HTLC is being failed out, therefore the value of the // Otherwise, this HTLC is being failed out, therefore the value of the
// HTLC should return to the remote party. // HTLC should return to the remote party.
case isIncoming && htlc.EntryType == Fail: case isIncoming && (htlc.EntryType == Fail || htlc.EntryType == MalformedFail):
*theirBalance += htlc.Amount *theirBalance += htlc.Amount
// If an outgoing HTLC is being settled, then this means that the // If an outgoing HTLC is being settled, then this means that the
@@ -2165,7 +2184,7 @@ func processRemoveEntry(htlc *PaymentDescriptor, ourBalance,
// Otherwise, one of our outgoing HTLC's has timed out, so the value of // Otherwise, one of our outgoing HTLC's has timed out, so the value of
// the HTLC should be returned to our settled balance. // the HTLC should be returned to our settled balance.
case !isIncoming && htlc.EntryType == Fail: case !isIncoming && (htlc.EntryType == Fail || htlc.EntryType == MalformedFail):
*ourBalance += htlc.Amount *ourBalance += htlc.Amount
} }
@@ -2510,6 +2529,13 @@ func (lc *LightningChannel) ReceiveReestablish(msg *lnwire.ChannelReestablish) (
ID: htlc.Index, ID: htlc.Index,
Reason: lnwire.OpaqueReason([]byte{}), Reason: lnwire.OpaqueReason([]byte{}),
}) })
case MalformedFail:
updates = append(updates, &lnwire.UpdateFailMalformedHTLC{
ChanID: chanID,
ID: htlc.Index,
ShaOnionBlob: htlc.ShaOnionBlob,
FailureCode: htlc.FailCode,
})
case Settle: case Settle:
updates = append(updates, &lnwire.UpdateFufillHTLC{ updates = append(updates, &lnwire.UpdateFufillHTLC{
ChanID: chanID, ChanID: chanID,
@@ -3253,7 +3279,43 @@ func (lc *LightningChannel) FailHTLC(rHash [32]byte, reason []byte) (uint64, err
return addEntry.HtlcIndex, nil return addEntry.HtlcIndex, nil
} }
// ReceiveFailHTLC attempts to cancel a targeted HTLC by its log htlc, // MalformedFailHTLC attempts to fail a targeted HTLC by its payment hash,
// 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
// in _incoming_ HTLC.
func (lc *LightningChannel) MalformedFailHTLC(rHash [32]byte,
failCode lnwire.FailCode, shaOnionBlob [sha256.Size]byte) (uint64, error) {
lc.Lock()
defer lc.Unlock()
addEntries, ok := lc.rHashMap[rHash]
if !ok {
return 0, fmt.Errorf("unable to find HTLC to fail")
}
addEntry := addEntries[0]
pd := &PaymentDescriptor{
Amount: addEntry.Amount,
RHash: addEntry.RHash,
ParentIndex: addEntry.HtlcIndex,
LogIndex: lc.localUpdateLog.logIndex,
EntryType: MalformedFail,
FailCode: failCode,
ShaOnionBlob: shaOnionBlob,
}
lc.localUpdateLog.appendUpdate(pd)
lc.rHashMap[rHash][0] = nil
lc.rHashMap[rHash] = lc.rHashMap[rHash][1:]
if len(lc.rHashMap[rHash]) == 0 {
delete(lc.rHashMap, rHash)
}
return addEntry.HtlcIndex, nil
}
// ReceiveFailHTLC attempts to cancel a targeted HTLC by its log index,
// 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 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