htlcswitch/switch+payment_result: define networkResult, extractResult
This commit is contained in:
parent
5a8b892bb6
commit
f99d0c4c68
@ -1,6 +1,10 @@
|
||||
package htlcswitch
|
||||
|
||||
import "errors"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrPaymentIDNotFound is an error returned if the given paymentID is
|
||||
@ -12,8 +16,9 @@ var (
|
||||
ErrPaymentIDAlreadyExists = errors.New("paymentID already exists")
|
||||
)
|
||||
|
||||
// PaymentResult wraps a result received from the network after a payment
|
||||
// attempt was made.
|
||||
// PaymentResult wraps a decoded result received from the network after a
|
||||
// payment attempt was made. This is what is eventually handed to the router
|
||||
// for processing.
|
||||
type PaymentResult struct {
|
||||
// Preimage is set by the switch in case a sent HTLC was settled.
|
||||
Preimage [32]byte
|
||||
@ -23,3 +28,21 @@ type PaymentResult struct {
|
||||
// error will be a *ForwardingError.
|
||||
Error error
|
||||
}
|
||||
|
||||
// networkResult is the raw result received from the network after a payment
|
||||
// attempt has been made. Since the switch doesn't always have the necessary
|
||||
// data to decode the raw message, we store it together with some meta data,
|
||||
// and decode it when the router query for the final result.
|
||||
type networkResult struct {
|
||||
// msg is the received result. This should be of type UpdateFulfillHTLC
|
||||
// or UpdateFailHTLC.
|
||||
msg lnwire.Message
|
||||
|
||||
// unencrypted indicates whether the failure encoded in the message is
|
||||
// unencrypted, and hence doesn't need to be decrypted.
|
||||
unencrypted bool
|
||||
|
||||
// isResolution indicates whether this is a resolution message, in
|
||||
// which the failure reason might not be included.
|
||||
isResolution bool
|
||||
}
|
||||
|
@ -880,53 +880,21 @@ func (s *Switch) handleLocalResponse(pkt *htlcPacket) {
|
||||
// has been restarted since sending the payment.
|
||||
payment := s.findPayment(pkt.incomingHTLCID)
|
||||
|
||||
var result *PaymentResult
|
||||
// The error reason will be unencypted in case this a local
|
||||
// failure or a converted error.
|
||||
unencrypted := pkt.localFailure || pkt.convertedError
|
||||
n := &networkResult{
|
||||
msg: pkt.htlc,
|
||||
unencrypted: unencrypted,
|
||||
isResolution: pkt.isResolution,
|
||||
}
|
||||
|
||||
switch htlc := pkt.htlc.(type) {
|
||||
|
||||
// We've received a settle update which means we can finalize the user
|
||||
// payment and return successful response.
|
||||
case *lnwire.UpdateFulfillHTLC:
|
||||
// Persistently mark that a payment to this payment hash
|
||||
// succeeded. This will prevent us from ever making another
|
||||
// payment to this hash.
|
||||
err := s.control.Success(pkt.circuit.PaymentHash)
|
||||
if err != nil && err != ErrPaymentAlreadyCompleted {
|
||||
log.Warnf("Unable to mark completed payment %x: %v",
|
||||
pkt.circuit.PaymentHash, err)
|
||||
return
|
||||
}
|
||||
|
||||
result = &PaymentResult{
|
||||
Preimage: htlc.PaymentPreimage,
|
||||
}
|
||||
|
||||
// We've received a fail update which means we can finalize the user
|
||||
// payment and return fail response.
|
||||
case *lnwire.UpdateFailHTLC:
|
||||
// Persistently mark that a payment to this payment hash failed.
|
||||
// This will permit us to make another attempt at a successful
|
||||
// payment.
|
||||
err := s.control.Fail(pkt.circuit.PaymentHash)
|
||||
if err != nil && err != ErrPaymentAlreadyCompleted {
|
||||
log.Warnf("Unable to ground payment %x: %v",
|
||||
pkt.circuit.PaymentHash, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 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,
|
||||
)
|
||||
result = &PaymentResult{
|
||||
Error: paymentErr,
|
||||
}
|
||||
|
||||
default:
|
||||
log.Warnf("Received unknown response type: %T", pkt.htlc)
|
||||
result, err := s.extractResult(
|
||||
payment, n, pkt.incomingHTLCID,
|
||||
pkt.circuit.PaymentHash,
|
||||
)
|
||||
if err != nil {
|
||||
log.Errorf("Unable to extract result: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -937,6 +905,55 @@ func (s *Switch) handleLocalResponse(pkt *htlcPacket) {
|
||||
}
|
||||
}
|
||||
|
||||
// extractResult uses the given deobfuscator to extract the payment result from
|
||||
// the given network message.
|
||||
func (s *Switch) extractResult(payment *pendingPayment, n *networkResult,
|
||||
paymentID uint64, paymentHash lntypes.Hash) (*PaymentResult, error) {
|
||||
|
||||
switch htlc := n.msg.(type) {
|
||||
|
||||
// We've received a settle update which means we can finalize the user
|
||||
// payment and return successful response.
|
||||
case *lnwire.UpdateFulfillHTLC:
|
||||
// Persistently mark that a payment to this payment hash
|
||||
// succeeded. This will prevent us from ever making another
|
||||
// payment to this hash.
|
||||
err := s.control.Success(paymentHash)
|
||||
if err != nil && err != ErrPaymentAlreadyCompleted {
|
||||
return nil, fmt.Errorf("Unable to mark completed "+
|
||||
"payment %x: %v", paymentHash, err)
|
||||
}
|
||||
|
||||
return &PaymentResult{
|
||||
Preimage: htlc.PaymentPreimage,
|
||||
}, nil
|
||||
|
||||
// We've received a fail update which means we can finalize the
|
||||
// user payment and return fail response.
|
||||
case *lnwire.UpdateFailHTLC:
|
||||
// Persistently mark that a payment to this payment hash
|
||||
// failed. This will permit us to make another attempt at a
|
||||
// successful payment.
|
||||
err := s.control.Fail(paymentHash)
|
||||
if err != nil && err != ErrPaymentAlreadyCompleted {
|
||||
return nil, fmt.Errorf("Unable to ground payment "+
|
||||
"%x: %v", paymentHash, err)
|
||||
}
|
||||
paymentErr := s.parseFailedPayment(
|
||||
payment, paymentID, payment.paymentHash, n.unencrypted,
|
||||
n.isResolution, htlc,
|
||||
)
|
||||
|
||||
return &PaymentResult{
|
||||
Error: paymentErr,
|
||||
}, nil
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("Received unknown response type: %T",
|
||||
htlc)
|
||||
}
|
||||
}
|
||||
|
||||
// parseFailedPayment determines the appropriate failure message to return to
|
||||
// a user initiated payment. The three cases handled are:
|
||||
// 1) An unencrypted failure, which should already plaintext.
|
||||
|
Loading…
Reference in New Issue
Block a user