htlcswitch/switch+payment_result: define networkResult, extractResult
This commit is contained in:
parent
5a8b892bb6
commit
f99d0c4c68
@ -1,6 +1,10 @@
|
|||||||
package htlcswitch
|
package htlcswitch
|
||||||
|
|
||||||
import "errors"
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrPaymentIDNotFound is an error returned if the given paymentID is
|
// ErrPaymentIDNotFound is an error returned if the given paymentID is
|
||||||
@ -12,8 +16,9 @@ var (
|
|||||||
ErrPaymentIDAlreadyExists = errors.New("paymentID already exists")
|
ErrPaymentIDAlreadyExists = errors.New("paymentID already exists")
|
||||||
)
|
)
|
||||||
|
|
||||||
// PaymentResult wraps a result received from the network after a payment
|
// PaymentResult wraps a decoded result received from the network after a
|
||||||
// attempt was made.
|
// payment attempt was made. This is what is eventually handed to the router
|
||||||
|
// for processing.
|
||||||
type PaymentResult struct {
|
type PaymentResult struct {
|
||||||
// Preimage is set by the switch in case a sent HTLC was settled.
|
// Preimage is set by the switch in case a sent HTLC was settled.
|
||||||
Preimage [32]byte
|
Preimage [32]byte
|
||||||
@ -23,3 +28,21 @@ type PaymentResult struct {
|
|||||||
// error will be a *ForwardingError.
|
// error will be a *ForwardingError.
|
||||||
Error error
|
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.
|
// has been restarted since sending the payment.
|
||||||
payment := s.findPayment(pkt.incomingHTLCID)
|
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) {
|
result, err := s.extractResult(
|
||||||
|
payment, n, pkt.incomingHTLCID,
|
||||||
// We've received a settle update which means we can finalize the user
|
pkt.circuit.PaymentHash,
|
||||||
// payment and return successful response.
|
)
|
||||||
case *lnwire.UpdateFulfillHTLC:
|
if err != nil {
|
||||||
// Persistently mark that a payment to this payment hash
|
log.Errorf("Unable to extract result: %v", err)
|
||||||
// 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)
|
|
||||||
return
|
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
|
// 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) An unencrypted failure, which should already plaintext.
|
// 1) An unencrypted failure, which should already plaintext.
|
||||||
|
Loading…
Reference in New Issue
Block a user