htlcswitch/switch: make parseFailedPayment not dependent on pkt

We will later persist the fields necessary to decrypt a received error.
This commit is contained in:
Johan T. Halseth 2019-05-16 15:27:28 +02:00
parent ed81cec0fa
commit bbbe3a37f5
No known key found for this signature in database
GPG Key ID: 15BAADA29DA20D26

@ -17,6 +17,7 @@ import (
"github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/chainntnfs"
"github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/contractcourt" "github.com/lightningnetwork/lnd/contractcourt"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/ticker" "github.com/lightningnetwork/lnd/ticker"
@ -67,7 +68,7 @@ var (
// updates to be received whether the payment has been rejected or proceed // updates to be received whether the payment has been rejected or proceed
// successfully. // successfully.
type pendingPayment struct { type pendingPayment struct {
paymentHash lnwallet.PaymentHash paymentHash lntypes.Hash
amount lnwire.MilliSatoshi amount lnwire.MilliSatoshi
preimage chan [sha256.Size]byte preimage chan [sha256.Size]byte
@ -913,7 +914,13 @@ func (s *Switch) handleLocalResponse(pkt *htlcPacket) {
return return
} }
paymentErr = s.parseFailedPayment(payment, pkt, htlc) // The error reason will be unencypted in case this a local
// failure or a converted error.
unencrypted := pkt.localFailure || pkt.convertedError
paymentErr = s.parseFailedPayment(
payment, pkt.incomingHTLCID, payment.paymentHash,
unencrypted, pkt.isResolution, htlc,
)
default: default:
log.Warnf("Received unknown response type: %T", pkt.htlc) log.Warnf("Received unknown response type: %T", pkt.htlc)
@ -931,11 +938,13 @@ func (s *Switch) handleLocalResponse(pkt *htlcPacket) {
// parseFailedPayment determines the appropriate failure message to return to // parseFailedPayment determines the appropriate failure message to return to
// a user initiated payment. The three cases handled are: // a user initiated payment. The three cases handled are:
// 1) A local failure, which should already plaintext. // 1) An unencrypted failure, which should already plaintext.
// 2) A resolution from the chain arbitrator, // 2) A resolution from the chain arbitrator, which possibly has no failure
// 3) A failure from the remote party, which will need to be decrypted using the // reason attached.
// payment deobfuscator. // 3) A failure from the remote party, which will need to be decrypted using
func (s *Switch) parseFailedPayment(payment *pendingPayment, pkt *htlcPacket, // the payment deobfuscator.
func (s *Switch) parseFailedPayment(payment *pendingPayment, paymentID uint64,
paymentHash lntypes.Hash, unencrypted, isResolution bool,
htlc *lnwire.UpdateFailHTLC) *ForwardingError { htlc *lnwire.UpdateFailHTLC) *ForwardingError {
var failure *ForwardingError var failure *ForwardingError
@ -945,14 +954,14 @@ func (s *Switch) parseFailedPayment(payment *pendingPayment, pkt *htlcPacket,
// The payment never cleared the link, so we don't need to // The payment never cleared the link, so we don't need to
// decrypt the error, simply decode it them report back to the // decrypt the error, simply decode it them report back to the
// user. // user.
case pkt.localFailure || pkt.convertedError: case unencrypted:
var userErr string var userErr string
r := bytes.NewReader(htlc.Reason) r := bytes.NewReader(htlc.Reason)
failureMsg, err := lnwire.DecodeFailure(r, 0) failureMsg, err := lnwire.DecodeFailure(r, 0)
if err != nil { if err != nil {
userErr = fmt.Sprintf("unable to decode onion failure, "+ userErr = fmt.Sprintf("unable to decode onion "+
"htlc with hash(%x): %v", "failure (hash=%v, pid=%d): %v",
pkt.circuit.PaymentHash[:], err) paymentHash, paymentID, err)
log.Error(userErr) log.Error(userErr)
// As this didn't even clear the link, we don't need to // As this didn't even clear the link, we don't need to
@ -970,9 +979,10 @@ func (s *Switch) parseFailedPayment(payment *pendingPayment, pkt *htlcPacket,
// the first hop. In this case, we'll report a permanent // the first hop. In this case, we'll report a permanent
// channel failure as this means us, or the remote party had to // channel failure as this means us, or the remote party had to
// go on chain. // go on chain.
case pkt.isResolution && htlc.Reason == nil: case isResolution && htlc.Reason == nil:
userErr := fmt.Sprintf("payment was resolved " + userErr := fmt.Sprintf("payment was resolved "+
"on-chain, then cancelled back") "on-chain, then cancelled back (hash=%v, pid=%d)",
paymentHash, paymentID)
failure = &ForwardingError{ failure = &ForwardingError{
ErrorSource: s.cfg.SelfKey, ErrorSource: s.cfg.SelfKey,
ExtraMsg: userErr, ExtraMsg: userErr,
@ -999,9 +1009,9 @@ func (s *Switch) parseFailedPayment(payment *pendingPayment, pkt *htlcPacket,
// error. If we're unable to then we'll bail early. // error. If we're unable to then we'll bail early.
failure, err = payment.deobfuscator.DecryptError(htlc.Reason) failure, err = payment.deobfuscator.DecryptError(htlc.Reason)
if err != nil { if err != nil {
userErr := fmt.Sprintf("unable to de-obfuscate onion "+ userErr := fmt.Sprintf("unable to de-obfuscate "+
"failure, htlc with hash(%x): %v", "onion failure (hash=%v, pid=%d): %v",
pkt.circuit.PaymentHash[:], err) paymentHash, paymentID, err)
log.Error(userErr) log.Error(userErr)
failure = &ForwardingError{ failure = &ForwardingError{
ErrorSource: s.cfg.SelfKey, ErrorSource: s.cfg.SelfKey,