lnwire+htlcswitch: minor grammatical, formatting fixes after error PR
This commit is contained in:
parent
79b8d26b1a
commit
a04fa76a4c
@ -20,7 +20,7 @@ func (k *circuitKey) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// paymentCircuit is used by the htlc switch subsystem to determine the
|
// paymentCircuit is used by the htlc switch subsystem to determine the
|
||||||
// fowrards/backwards path for the settle/fail HTLC messages. A payment circuit
|
// forwards/backwards path for the settle/fail HTLC messages. A payment circuit
|
||||||
// will be created once a channel link forwards the htlc add request and
|
// will be created once a channel link forwards the htlc add request and
|
||||||
// removed when we receive settle/fail htlc message.
|
// removed when we receive settle/fail htlc message.
|
||||||
type paymentCircuit struct {
|
type paymentCircuit struct {
|
||||||
@ -38,7 +38,7 @@ type paymentCircuit struct {
|
|||||||
// request back.
|
// request back.
|
||||||
Dest lnwire.ShortChannelID
|
Dest lnwire.ShortChannelID
|
||||||
|
|
||||||
// Obfuscator is used to obfuscate the onion failure before sending it
|
// Obfuscator is used to re-encrypt the onion failure before sending it
|
||||||
// back to the originator of the payment.
|
// back to the originator of the payment.
|
||||||
Obfuscator Obfuscator
|
Obfuscator Obfuscator
|
||||||
|
|
||||||
|
@ -7,22 +7,31 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Deobfuscator entity which is used to de-obfuscate the onion opaque reason and
|
// Deobfuscator is an interface that is used to decrypt the onion encrypted
|
||||||
// extract failure.
|
// failure reason an extra out a well formed error.
|
||||||
type Deobfuscator interface {
|
type Deobfuscator interface {
|
||||||
// Deobfuscate function decodes the onion error failure.
|
// Deobfuscate peels off each layer of onion encryption from the first
|
||||||
|
// hop, to the source of the error. A fully populated
|
||||||
|
// lnwire.FailureMessage is returned.
|
||||||
Deobfuscate(lnwire.OpaqueReason) (lnwire.FailureMessage, error)
|
Deobfuscate(lnwire.OpaqueReason) (lnwire.FailureMessage, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obfuscator entity which is used to do the initial and backward onion
|
// Obfuscator is an interface that is used to encrypt HTLC related errors at
|
||||||
// failure obfuscation.
|
// the source of the error, and also at each intermediate hop all the way back
|
||||||
|
// to the source of the payment.
|
||||||
type Obfuscator interface {
|
type Obfuscator interface {
|
||||||
// InitialObfuscate is used to convert the failure into opaque
|
// InitialObfuscate is used to convert the failure into opaque
|
||||||
// reason.
|
// reason.
|
||||||
|
|
||||||
|
// InitialObfuscate transforms a concrete failure message into an
|
||||||
|
// encrypted opaque failure reason. This method will be used at the
|
||||||
|
// source that the error occurs. It differs from BackwardObfuscate
|
||||||
|
// slightly, in that it computes a proper MAC over the error.
|
||||||
InitialObfuscate(lnwire.FailureMessage) (lnwire.OpaqueReason, error)
|
InitialObfuscate(lnwire.FailureMessage) (lnwire.OpaqueReason, error)
|
||||||
|
|
||||||
// BackwardObfuscate is used to make the processing over onion error
|
// BackwardObfuscate wraps an already encrypted opaque reason error in
|
||||||
// when it moves backward to the htlc sender.
|
// an additional layer of onion encryption. This process repeats until
|
||||||
|
// the error arrives at the source of the payment.
|
||||||
BackwardObfuscate(lnwire.OpaqueReason) lnwire.OpaqueReason
|
BackwardObfuscate(lnwire.OpaqueReason) lnwire.OpaqueReason
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,35 +40,36 @@ type FailureObfuscator struct {
|
|||||||
*sphinx.OnionObfuscator
|
*sphinx.OnionObfuscator
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitialObfuscate is used by the failure sender to decode the failure and
|
// InitialObfuscate transforms a concrete failure message into an encrypted
|
||||||
// make the initial failure obfuscation with addition of the failure data hmac.
|
// opaque failure reason. This method will be used at the source that the error
|
||||||
|
// occurs. It differs from BackwardObfuscate slightly, in that it computes a
|
||||||
|
// proper MAC over the error.
|
||||||
//
|
//
|
||||||
// NOTE: Part of the Obfuscator interface.
|
// NOTE: Part of the Obfuscator interface.
|
||||||
func (o *FailureObfuscator) InitialObfuscate(failure lnwire.FailureMessage) (
|
func (o *FailureObfuscator) InitialObfuscate(failure lnwire.FailureMessage) (lnwire.OpaqueReason, error) {
|
||||||
lnwire.OpaqueReason, error) {
|
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
if err := lnwire.EncodeFailure(&b, failure, 0); err != nil {
|
if err := lnwire.EncodeFailure(&b, failure, 0); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make the initial obfuscation with appending hmac.
|
// We pass a true as the first parameter to indicate that a MAC should
|
||||||
|
// be added.
|
||||||
return o.OnionObfuscator.Obfuscate(true, b.Bytes()), nil
|
return o.OnionObfuscator.Obfuscate(true, b.Bytes()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// BackwardObfuscate is used by the forwarding nodes in order to obfuscate the
|
// BackwardObfuscate wraps an already encrypted opaque reason error in an
|
||||||
// already obfuscated onion failure blob with the stream which have been
|
// additional layer of onion encryption. This process repeats until the error
|
||||||
// generated with our shared secret. The reason we re-encrypt the message on the
|
// arrives at the source of the payment. We re-encrypt the message on the
|
||||||
// backwards path is to ensure that the error is computationally
|
// backwards path to ensure that the error is indistinguishable from any other
|
||||||
// indistinguishable from any other error seen.
|
// error seen.
|
||||||
//
|
//
|
||||||
// NOTE: Part of the Obfuscator interface.
|
// NOTE: Part of the Obfuscator interface.
|
||||||
func (o *FailureObfuscator) BackwardObfuscate(
|
func (o *FailureObfuscator) BackwardObfuscate(reason lnwire.OpaqueReason) lnwire.OpaqueReason {
|
||||||
reason lnwire.OpaqueReason) lnwire.OpaqueReason {
|
|
||||||
return o.OnionObfuscator.Obfuscate(false, reason)
|
return o.OnionObfuscator.Obfuscate(false, reason)
|
||||||
}
|
}
|
||||||
|
|
||||||
// A compile time check to ensure FailureObfuscator implements the
|
// A compile time check to ensure FailureObfuscator implements the Obfuscator
|
||||||
// Obfuscator interface.
|
// interface.
|
||||||
var _ Obfuscator = (*FailureObfuscator)(nil)
|
var _ Obfuscator = (*FailureObfuscator)(nil)
|
||||||
|
|
||||||
// FailureDeobfuscator wraps the sphinx data obfuscator and adds awareness of
|
// FailureDeobfuscator wraps the sphinx data obfuscator and adds awareness of
|
||||||
@ -68,11 +78,13 @@ type FailureDeobfuscator struct {
|
|||||||
*sphinx.OnionDeobfuscator
|
*sphinx.OnionDeobfuscator
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deobfuscate decodes the obfuscated onion failure.
|
// Deobfuscate peels off each layer of onion encryption from the first hop, to
|
||||||
|
// the source of the error. A fully populated lnwire.FailureMessage is
|
||||||
|
// returned.
|
||||||
//
|
//
|
||||||
// NOTE: Part of the Obfuscator interface.
|
// NOTE: Part of the Obfuscator interface.
|
||||||
func (o *FailureDeobfuscator) Deobfuscate(reason lnwire.OpaqueReason) (lnwire.FailureMessage,
|
func (o *FailureDeobfuscator) Deobfuscate(reason lnwire.OpaqueReason) (lnwire.FailureMessage, error) {
|
||||||
error) {
|
|
||||||
_, failureData, err := o.OnionDeobfuscator.Deobfuscate(reason)
|
_, failureData, err := o.OnionDeobfuscator.Deobfuscate(reason)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -191,10 +191,11 @@ func (p *OnionProcessor) DecodeHopIterator(r io.Reader, rHash []byte) (HopIterat
|
|||||||
}, lnwire.CodeNone
|
}, lnwire.CodeNone
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeOnionObfuscator takes the onion blob as input extract the shared secret
|
// DecodeOnionObfuscator takes an io.Reader which should contain the onion
|
||||||
// and return the entity which is able to obfuscate failure data.
|
// packet as original received by a forwarding node and creates an Obfuscator
|
||||||
func (p *OnionProcessor) DecodeOnionObfuscator(r io.Reader) (Obfuscator,
|
// instance using the derived shared secret. In the case that en error occurs,
|
||||||
lnwire.FailCode) {
|
// a lnwire failure code detailing the parsing failure will be returned.
|
||||||
|
func (p *OnionProcessor) DecodeOnionObfuscator(r io.Reader) (Obfuscator, lnwire.FailCode) {
|
||||||
onionPkt := &sphinx.OnionPacket{}
|
onionPkt := &sphinx.OnionPacket{}
|
||||||
if err := onionPkt.Decode(r); err != nil {
|
if err := onionPkt.Decode(r); err != nil {
|
||||||
return nil, lnwire.CodeTemporaryChannelFailure
|
return nil, lnwire.CodeTemporaryChannelFailure
|
||||||
|
@ -83,17 +83,18 @@ type ChannelLinkConfig struct {
|
|||||||
// contained in the forwarding blob within each HTLC.
|
// contained in the forwarding blob within each HTLC.
|
||||||
Switch *Switch
|
Switch *Switch
|
||||||
|
|
||||||
// DecodeHopIterator function is responsible for decoding htlc Sphinx onion
|
// DecodeHopIterator function is responsible for decoding htlc Sphinx
|
||||||
// blob, and creating hop iterator which will give us next destination
|
// onion blob, and creating hop iterator which will give us next
|
||||||
// of htlc.
|
// destination of htlc.
|
||||||
DecodeHopIterator func(r io.Reader, rHash []byte) (HopIterator, lnwire.FailCode)
|
DecodeHopIterator func(r io.Reader, rHash []byte) (HopIterator, lnwire.FailCode)
|
||||||
|
|
||||||
// DecodeOnionObfuscator function is responsible for decoding htlc Sphinx
|
// DecodeOnionObfuscator function is responsible for decoding htlc
|
||||||
// onion blob, and creating onion failure obfuscator.
|
// Sphinx onion blob, and creating onion failure obfuscator.
|
||||||
DecodeOnionObfuscator func(r io.Reader) (Obfuscator, lnwire.FailCode)
|
DecodeOnionObfuscator func(r io.Reader) (Obfuscator, lnwire.FailCode)
|
||||||
|
|
||||||
// GetLastChannelUpdate retrieve the topology info about the channel in
|
// GetLastChannelUpdate reterives the latest routing policy for this
|
||||||
// order to create the channel update.
|
// particualr channel. This will be used to provide payment senders our
|
||||||
|
// laest policy when sending encrypted error messages.
|
||||||
GetLastChannelUpdate func() (*lnwire.ChannelUpdate, error)
|
GetLastChannelUpdate func() (*lnwire.ChannelUpdate, error)
|
||||||
|
|
||||||
// Peer is a lightning network node with which we have the channel link
|
// Peer is a lightning network node with which we have the channel link
|
||||||
@ -419,6 +420,9 @@ func (l *channelLink) handleDownStreamPkt(pkt *htlcPacket) {
|
|||||||
index, err := l.channel.AddHTLC(htlc)
|
index, err := l.channel.AddHTLC(htlc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch err {
|
switch err {
|
||||||
|
|
||||||
|
// The channels spare bandwidth is fully allocated, so
|
||||||
|
// we'll put this HTLC into the overflow queue.
|
||||||
case lnwallet.ErrMaxHTLCNumber:
|
case lnwallet.ErrMaxHTLCNumber:
|
||||||
log.Infof("Downstream htlc add update with "+
|
log.Infof("Downstream htlc add update with "+
|
||||||
"payment hash(%x) have been added to "+
|
"payment hash(%x) have been added to "+
|
||||||
@ -428,19 +432,26 @@ func (l *channelLink) handleDownStreamPkt(pkt *htlcPacket) {
|
|||||||
l.overflowQueue.consume(pkt)
|
l.overflowQueue.consume(pkt)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
// The HTLC was unable to be added to the state
|
||||||
|
// machine, as a result, we'll signal the switch to
|
||||||
|
// cancel the pending payment.
|
||||||
default:
|
default:
|
||||||
// The HTLC was unable to be added to the state
|
|
||||||
// machine, as a result, we'll signal the switch to
|
|
||||||
// cancel the pending payment.
|
|
||||||
var (
|
var (
|
||||||
isObfuscated bool
|
isObfuscated bool
|
||||||
reason lnwire.OpaqueReason
|
reason lnwire.OpaqueReason
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// We'll parse the sphinx packet enclosed so we
|
||||||
|
// can obtain the shared secret required to
|
||||||
|
// encrypt the error back to the source.
|
||||||
failure := lnwire.NewTemporaryChannelFailure(nil)
|
failure := lnwire.NewTemporaryChannelFailure(nil)
|
||||||
onionReader := bytes.NewReader(htlc.OnionBlob[:])
|
onionReader := bytes.NewReader(htlc.OnionBlob[:])
|
||||||
obfuscator, failCode := l.cfg.DecodeOnionObfuscator(onionReader)
|
obfuscator, failCode := l.cfg.DecodeOnionObfuscator(onionReader)
|
||||||
if failCode != lnwire.CodeNone {
|
|
||||||
|
switch {
|
||||||
|
// If we were unable to parse the onion blob,
|
||||||
|
// then we'll send an error back to the source.
|
||||||
|
case failCode != lnwire.CodeNone:
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
err := lnwire.EncodeFailure(&b, failure, 0)
|
err := lnwire.EncodeFailure(&b, failure, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -449,7 +460,10 @@ func (l *channelLink) handleDownStreamPkt(pkt *htlcPacket) {
|
|||||||
}
|
}
|
||||||
reason = lnwire.OpaqueReason(b.Bytes())
|
reason = lnwire.OpaqueReason(b.Bytes())
|
||||||
isObfuscated = false
|
isObfuscated = false
|
||||||
} else {
|
|
||||||
|
// Otherwise, we'll send back a proper failure
|
||||||
|
// message.
|
||||||
|
default:
|
||||||
reason, err = obfuscator.InitialObfuscate(failure)
|
reason, err = obfuscator.InitialObfuscate(failure)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("unable to obfuscate error: %v", err)
|
log.Errorf("unable to obfuscate error: %v", err)
|
||||||
@ -458,13 +472,16 @@ func (l *channelLink) handleDownStreamPkt(pkt *htlcPacket) {
|
|||||||
isObfuscated = true
|
isObfuscated = true
|
||||||
}
|
}
|
||||||
|
|
||||||
go l.cfg.Switch.forward(newFailPacket(
|
upddateFail := &lnwire.UpdateFailHTLC{
|
||||||
l.ShortChanID(),
|
Reason: reason,
|
||||||
&lnwire.UpdateFailHTLC{
|
}
|
||||||
Reason: reason,
|
failPkt := newFailPacket(
|
||||||
}, htlc.PaymentHash, htlc.Amount, isObfuscated,
|
l.ShortChanID(), upddateFail,
|
||||||
))
|
htlc.PaymentHash, htlc.Amount,
|
||||||
|
isObfuscated,
|
||||||
|
)
|
||||||
|
|
||||||
|
go l.cfg.Switch.forward(failPkt)
|
||||||
log.Infof("Unable to handle downstream add HTLC: %v", err)
|
log.Infof("Unable to handle downstream add HTLC: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -568,16 +585,18 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) {
|
|||||||
// TODO(roasbeef): add preimage to DB in order to swipe
|
// TODO(roasbeef): add preimage to DB in order to swipe
|
||||||
// repeated r-values
|
// repeated r-values
|
||||||
|
|
||||||
// If remote side have been unable to parse the onion blob we have sent
|
|
||||||
// to it, than we should transform the malformed notification to the the
|
|
||||||
// usual htlc fail message.
|
|
||||||
case *lnwire.UpdateFailMalformedHTLC:
|
case *lnwire.UpdateFailMalformedHTLC:
|
||||||
|
// If remote side have been unable to parse the onion blob we
|
||||||
|
// have sent to it, than we should transform the malformed HTLC
|
||||||
|
// message to the usual HTLC fail message.
|
||||||
idx := msg.ID
|
idx := msg.ID
|
||||||
if err := l.channel.ReceiveFailHTLC(idx); err != nil {
|
if err := l.channel.ReceiveFailHTLC(idx); err != nil {
|
||||||
l.fail("unable to handle upstream fail HTLC: %v", err)
|
l.fail("unable to handle upstream fail HTLC: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert the failure type encoded within the HTLC fail
|
||||||
|
// message to the proper generic lnwire error code.
|
||||||
var failure lnwire.FailureMessage
|
var failure lnwire.FailureMessage
|
||||||
switch msg.FailureCode {
|
switch msg.FailureCode {
|
||||||
case lnwire.CodeInvalidOnionVersion:
|
case lnwire.CodeInvalidOnionVersion:
|
||||||
@ -594,11 +613,14 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) {
|
|||||||
OnionSHA256: msg.ShaOnionBlob,
|
OnionSHA256: msg.ShaOnionBlob,
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
// TODO(roasbeef): fail channel here?
|
||||||
log.Errorf("unable to understand code of received " +
|
log.Errorf("unable to understand code of received " +
|
||||||
"malformed error")
|
"malformed error")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// With the error parsed, we'll convert the into it's opaque
|
||||||
|
// form.
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
if err := lnwire.EncodeFailure(&b, failure, 0); err != nil {
|
if err := lnwire.EncodeFailure(&b, failure, 0); err != nil {
|
||||||
log.Errorf("unable to encode malformed error: %v", err)
|
log.Errorf("unable to encode malformed error: %v", err)
|
||||||
@ -943,7 +965,7 @@ func (l *channelLink) processLockedInHtlcs(
|
|||||||
|
|
||||||
// An incoming HTLC add has been full-locked in. As a result we
|
// An incoming HTLC add has been full-locked in. As a result we
|
||||||
// can no examine the forwarding details of the HTLC, and the
|
// can no examine the forwarding details of the HTLC, and the
|
||||||
// HTLC itself ti decide if: we should forward it, cancel it,
|
// HTLC itself to decide if: we should forward it, cancel it,
|
||||||
// or are able to settle it (and it adheres to our fee related
|
// or are able to settle it (and it adheres to our fee related
|
||||||
// constraints).
|
// constraints).
|
||||||
case lnwallet.Add:
|
case lnwallet.Add:
|
||||||
@ -952,23 +974,26 @@ func (l *channelLink) processLockedInHtlcs(
|
|||||||
onionBlob := l.clearedOnionBlobs[pd.Index]
|
onionBlob := l.clearedOnionBlobs[pd.Index]
|
||||||
delete(l.clearedOnionBlobs, pd.Index)
|
delete(l.clearedOnionBlobs, pd.Index)
|
||||||
|
|
||||||
// Retrieve onion obfuscator from onion blob in order to produce
|
// Retrieve onion obfuscator from onion blob in order
|
||||||
// initial obfuscation of the onion failureCode.
|
// to produce initial obfuscation of the onion
|
||||||
|
// failureCode.
|
||||||
onionReader := bytes.NewReader(onionBlob[:])
|
onionReader := bytes.NewReader(onionBlob[:])
|
||||||
obfuscator, failureCode := l.cfg.DecodeOnionObfuscator(onionReader)
|
obfuscator, failureCode := l.cfg.DecodeOnionObfuscator(onionReader)
|
||||||
if failureCode != lnwire.CodeNone {
|
if failureCode != lnwire.CodeNone {
|
||||||
log.Error("unable to decode onion obfuscator")
|
// If we unable to process the onion blob than
|
||||||
// If we unable to process the onion blob than we should send
|
// we should send the malformed htlc error to
|
||||||
// the malformed htlc error to payment sender.
|
// payment sender.
|
||||||
l.sendMalformedHTLCError(pd.RHash, failureCode, onionBlob[:])
|
l.sendMalformedHTLCError(pd.RHash, failureCode, onionBlob[:])
|
||||||
needUpdate = true
|
needUpdate = true
|
||||||
|
|
||||||
|
log.Error("unable to decode onion obfuscator")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Before adding the new htlc to the state machine,
|
// Before adding the new htlc to the state machine,
|
||||||
// parse the onion object in order to obtain the
|
// parse the onion object in order to obtain the
|
||||||
// routing information with DecodeHopIterator function which
|
// routing information with DecodeHopIterator function
|
||||||
// process the Sphinx packet.
|
// which process the Sphinx packet.
|
||||||
//
|
//
|
||||||
// We include the payment hash of the htlc as it's
|
// We include the payment hash of the htlc as it's
|
||||||
// authenticated within the Sphinx packet itself as
|
// authenticated within the Sphinx packet itself as
|
||||||
@ -979,11 +1004,13 @@ func (l *channelLink) processLockedInHtlcs(
|
|||||||
onionReader = bytes.NewReader(onionBlob[:])
|
onionReader = bytes.NewReader(onionBlob[:])
|
||||||
chanIterator, failureCode := l.cfg.DecodeHopIterator(onionReader, pd.RHash[:])
|
chanIterator, failureCode := l.cfg.DecodeHopIterator(onionReader, pd.RHash[:])
|
||||||
if failureCode != lnwire.CodeNone {
|
if failureCode != lnwire.CodeNone {
|
||||||
log.Error("unable to decode onion hop iterator")
|
// If we unable to process the onion blob than
|
||||||
// If we unable to process the onion blob than we should send
|
// we should send the malformed htlc error to
|
||||||
// the malformed htlc error to payment sender.
|
// payment sender.
|
||||||
l.sendMalformedHTLCError(pd.RHash, failureCode, onionBlob[:])
|
l.sendMalformedHTLCError(pd.RHash, failureCode, onionBlob[:])
|
||||||
needUpdate = true
|
needUpdate = true
|
||||||
|
|
||||||
|
log.Error("unable to decode onion hop iterator")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1009,9 +1036,7 @@ func (l *channelLink) processLockedInHtlcs(
|
|||||||
// the hop-payload included in the HTLC to
|
// the hop-payload included in the HTLC to
|
||||||
// ensure that it was crafted correctly by the
|
// ensure that it was crafted correctly by the
|
||||||
// sender and matches the HTLC we were
|
// sender and matches the HTLC we were
|
||||||
// extended. Additionally, we'll ensure that
|
// extended.
|
||||||
// our time-lock value has been computed
|
|
||||||
// correctly.
|
|
||||||
if !l.cfg.DebugHTLC &&
|
if !l.cfg.DebugHTLC &&
|
||||||
fwdInfo.AmountToForward != invoice.Terms.Value {
|
fwdInfo.AmountToForward != invoice.Terms.Value {
|
||||||
|
|
||||||
@ -1026,6 +1051,9 @@ func (l *channelLink) processLockedInHtlcs(
|
|||||||
needUpdate = true
|
needUpdate = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We'll also ensure that our time-lock value
|
||||||
|
// has been computed correctly.
|
||||||
if !l.cfg.DebugHTLC &&
|
if !l.cfg.DebugHTLC &&
|
||||||
fwdInfo.OutgoingCTLV != l.cfg.FwrdingPolicy.TimeLockDelta {
|
fwdInfo.OutgoingCTLV != l.cfg.FwrdingPolicy.TimeLockDelta {
|
||||||
|
|
||||||
@ -1096,6 +1124,10 @@ func (l *channelLink) processLockedInHtlcs(
|
|||||||
pd.RHash[:], l.cfg.FwrdingPolicy.MinHTLC,
|
pd.RHash[:], l.cfg.FwrdingPolicy.MinHTLC,
|
||||||
pd.Amount)
|
pd.Amount)
|
||||||
|
|
||||||
|
// As part of the returned error, we'll
|
||||||
|
// send our latest routing policy so
|
||||||
|
// the sending node obtains the most up
|
||||||
|
// to date data.
|
||||||
var failure lnwire.FailureMessage
|
var failure lnwire.FailureMessage
|
||||||
update, err := l.cfg.GetLastChannelUpdate()
|
update, err := l.cfg.GetLastChannelUpdate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1134,6 +1166,10 @@ func (l *channelLink) processLockedInHtlcs(
|
|||||||
btcutil.Amount(pd.Amount-fwdInfo.AmountToForward),
|
btcutil.Amount(pd.Amount-fwdInfo.AmountToForward),
|
||||||
btcutil.Amount(expectedFee))
|
btcutil.Amount(expectedFee))
|
||||||
|
|
||||||
|
// As part of the returned error, we'll
|
||||||
|
// send our latest routing policy so
|
||||||
|
// the sending node obtains the most up
|
||||||
|
// to date data.
|
||||||
var failure lnwire.FailureMessage
|
var failure lnwire.FailureMessage
|
||||||
update, err := l.cfg.GetLastChannelUpdate()
|
update, err := l.cfg.GetLastChannelUpdate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1163,6 +1199,9 @@ func (l *channelLink) processLockedInHtlcs(
|
|||||||
pd.RHash[:], pd.Timeout-timeDelta,
|
pd.RHash[:], pd.Timeout-timeDelta,
|
||||||
fwdInfo.OutgoingCTLV)
|
fwdInfo.OutgoingCTLV)
|
||||||
|
|
||||||
|
// Grab the latest routing policy so
|
||||||
|
// the sending node is up to date with
|
||||||
|
// our current policy.
|
||||||
update, err := l.cfg.GetLastChannelUpdate()
|
update, err := l.cfg.GetLastChannelUpdate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.fail("unable to create channel update "+
|
l.fail("unable to create channel update "+
|
||||||
@ -1211,7 +1250,7 @@ func (l *channelLink) processLockedInHtlcs(
|
|||||||
|
|
||||||
if needUpdate {
|
if needUpdate {
|
||||||
// With all the settle/cancel updates added to the local and
|
// With all the settle/cancel updates added to the local and
|
||||||
// remote htlc logs, initiate a state transition by updating
|
// remote HTLC logs, initiate a state transition by updating
|
||||||
// the remote commitment chain.
|
// the remote commitment chain.
|
||||||
if err := l.updateCommitTx(); err != nil {
|
if err := l.updateCommitTx(); err != nil {
|
||||||
l.fail("unable to update commitment: %v", err)
|
l.fail("unable to update commitment: %v", err)
|
||||||
@ -1222,8 +1261,8 @@ func (l *channelLink) processLockedInHtlcs(
|
|||||||
return packetsToForward
|
return packetsToForward
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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(rHash [32]byte, failure lnwire.FailureMessage,
|
||||||
obfuscator Obfuscator) {
|
obfuscator Obfuscator) {
|
||||||
reason, err := obfuscator.InitialObfuscate(failure)
|
reason, err := obfuscator.InitialObfuscate(failure)
|
||||||
@ -1245,7 +1284,7 @@ func (l *channelLink) sendHTLCError(rHash [32]byte, failure lnwire.FailureMessag
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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(rHash [32]byte, code lnwire.FailCode,
|
||||||
onionBlob []byte) {
|
onionBlob []byte) {
|
||||||
@ -1263,8 +1302,8 @@ func (l *channelLink) sendMalformedHTLCError(rHash [32]byte, code lnwire.FailCod
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// fail helper function which is used to encapsulate the action neccessary
|
// fail helper function which is used to encapsulate the action necessary for
|
||||||
// for proper disconnect.
|
// proper disconnect.
|
||||||
func (l *channelLink) fail(format string, a ...interface{}) {
|
func (l *channelLink) fail(format string, a ...interface{}) {
|
||||||
reason := errors.Errorf(format, a...)
|
reason := errors.Errorf(format, a...)
|
||||||
log.Error(reason)
|
log.Error(reason)
|
||||||
|
@ -35,20 +35,19 @@ type htlcPacket struct {
|
|||||||
// htlc lnwire message type of which depends on switch request type.
|
// htlc lnwire message type of which depends on switch request type.
|
||||||
htlc lnwire.Message
|
htlc lnwire.Message
|
||||||
|
|
||||||
// obfuscator is entity which is needed to make the obfuscation of the
|
// obfuscator contains the necessary state to allow the switch to wrap
|
||||||
// onion failure, it is carried inside the packet from channel
|
// any forwarded errors in an additional layer of encryption.
|
||||||
// link to the switch because we have to create onion error inside the
|
//
|
||||||
// switch to, but we unable to restore obfuscator from the onion, because
|
// TODO(andrew.shvv) revisit after refactoring the way of returning
|
||||||
// on stage of forwarding onion inside payment belongs to the remote node.
|
// errors inside the htlcswitch packet.
|
||||||
// TODO(andrew.shvv) revisit after refactoring the way of returning errors
|
|
||||||
// inside the htlcswitch packet.
|
|
||||||
obfuscator Obfuscator
|
obfuscator Obfuscator
|
||||||
|
|
||||||
// isObfuscated is used in case if switch sent the packet to the link,
|
// isObfuscated is set to true if an error occurs as soon as the switch
|
||||||
// but error have occurred locally, in this case we shouldn't obfuscate
|
// forwards a packet to the link. If so, and this is an error packet,
|
||||||
// it again.
|
// then this allows the switch to avoid doubly encrypting the error.
|
||||||
// TODO(andrew.shvv) revisit after refactoring the way of returning errors
|
//
|
||||||
// inside the htlcswitch packet.
|
// TODO(andrew.shvv) revisit after refactoring the way of returning
|
||||||
|
// errors inside the htlcswitch packet.
|
||||||
isObfuscated bool
|
isObfuscated bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,23 +304,27 @@ func (s *Switch) handleLocalDispatch(payment *pendingPayment, packet *htlcPacket
|
|||||||
payment.preimage <- htlc.PaymentPreimage
|
payment.preimage <- htlc.PaymentPreimage
|
||||||
s.removePendingPayment(payment.amount, payment.paymentHash)
|
s.removePendingPayment(payment.amount, payment.paymentHash)
|
||||||
|
|
||||||
// We've just received a fail update which means we can finalize
|
// We've just received a fail update which means we can finalize the
|
||||||
// the user payment and return fail response.
|
// user payment and return fail response.
|
||||||
case *lnwire.UpdateFailHTLC:
|
case *lnwire.UpdateFailHTLC:
|
||||||
// Retrieving the fail code from byte representation of error.
|
|
||||||
var userErr error
|
var userErr error
|
||||||
|
|
||||||
|
// We'll attempt to fully decrypt the onion encrypted error. If
|
||||||
|
// we're unable to then we'll bail early.
|
||||||
failure, err := payment.deobfuscator.Deobfuscate(htlc.Reason)
|
failure, err := payment.deobfuscator.Deobfuscate(htlc.Reason)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
userErr = errors.Errorf("unable to de-obfuscate "+
|
userErr = errors.Errorf("unable to de-obfuscate "+
|
||||||
"onion failure, htlc with hash(%v): %v", payment.paymentHash[:],
|
"onion failure, htlc with hash(%v): %v",
|
||||||
err)
|
payment.paymentHash[:], err)
|
||||||
log.Error(userErr)
|
log.Error(userErr)
|
||||||
} else {
|
} else {
|
||||||
// Process payment failure by updating the lightning network
|
// Process payment failure by updating the lightning
|
||||||
// topology by using router subsystem handler.
|
// network topology by using router subsystem handler.
|
||||||
var update *lnwire.ChannelUpdate
|
var update *lnwire.ChannelUpdate
|
||||||
|
|
||||||
|
// Only a few error message actually contain a channel
|
||||||
|
// update message, so we'll filter out for those that
|
||||||
|
// do.
|
||||||
switch failure := failure.(type) {
|
switch failure := failure.(type) {
|
||||||
case *lnwire.FailTemporaryChannelFailure:
|
case *lnwire.FailTemporaryChannelFailure:
|
||||||
update = failure.Update
|
update = failure.Update
|
||||||
@ -336,10 +340,21 @@ func (s *Switch) handleLocalDispatch(payment *pendingPayment, packet *htlcPacket
|
|||||||
update = &failure.Update
|
update = &failure.Update
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we've been sent an error that includes an update,
|
||||||
|
// then we'll apply it to the local graph.
|
||||||
|
//
|
||||||
|
// TODO(roasbeef): instead, make all onion errors the
|
||||||
|
// error interface, and handle this within the router.
|
||||||
|
// Will allow us more flexibility w.r.t how we handle
|
||||||
|
// the error.
|
||||||
if update != nil {
|
if update != nil {
|
||||||
log.Info("Received payment failure(%v), applying lightning "+
|
log.Info("Received payment failure(%v), "+
|
||||||
"network topology update", failure.Code())
|
"applying lightning network topology update",
|
||||||
s.cfg.UpdateTopology(update)
|
failure.Code())
|
||||||
|
|
||||||
|
if err := s.cfg.UpdateTopology(update); err != nil {
|
||||||
|
log.Errorf("unable to update topology: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
userErr = errors.New(failure.Code())
|
userErr = errors.New(failure.Code())
|
||||||
@ -611,15 +626,23 @@ func (s *Switch) htlcForwarder() {
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
// A local close request has arrived, we'll forward this to the
|
||||||
|
// relevant link (if it exists) so the channel can be
|
||||||
|
// cooperatively closed (if possible).
|
||||||
case req := <-s.chanCloseRequests:
|
case req := <-s.chanCloseRequests:
|
||||||
s.handleChanelClose(req)
|
s.handleChanelClose(req)
|
||||||
|
|
||||||
|
// A new packet has arrived for forwarding, we'll interpret the
|
||||||
|
// packet concretely, then either forward it along, or
|
||||||
|
// interpret a return packet to a locally initialized one.
|
||||||
case cmd := <-s.htlcPlex:
|
case cmd := <-s.htlcPlex:
|
||||||
var (
|
var (
|
||||||
paymentHash lnwallet.PaymentHash
|
paymentHash lnwallet.PaymentHash
|
||||||
amount btcutil.Amount
|
amount btcutil.Amount
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Only three types of message should be forwarded:
|
||||||
|
// add, fails, and settles. Anything else is an error.
|
||||||
switch m := cmd.pkt.htlc.(type) {
|
switch m := cmd.pkt.htlc.(type) {
|
||||||
case *lnwire.UpdateAddHTLC:
|
case *lnwire.UpdateAddHTLC:
|
||||||
paymentHash = m.PaymentHash
|
paymentHash = m.PaymentHash
|
||||||
@ -632,6 +655,12 @@ func (s *Switch) htlcForwarder() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we can locate this packet in our local records,
|
||||||
|
// then this means a local sub-system initiated it.
|
||||||
|
// Otherwise, this is just a packet to be forwarded, so
|
||||||
|
// we'll treat it as so.
|
||||||
|
//
|
||||||
|
// TODO(roasbeef): can fast path this
|
||||||
payment, err := s.findPayment(amount, paymentHash)
|
payment, err := s.findPayment(amount, paymentHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd.err <- s.handlePacketForward(cmd.pkt)
|
cmd.err <- s.handlePacketForward(cmd.pkt)
|
||||||
|
@ -10,34 +10,36 @@ import (
|
|||||||
"github.com/roasbeef/btcutil"
|
"github.com/roasbeef/btcutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FailureMessage represent the onion failure object which is able to identify itself
|
// FailureMessage represents the onion failure object identified by its unique
|
||||||
// by returning the unique failure code.
|
// failure code.
|
||||||
type FailureMessage interface {
|
type FailureMessage interface {
|
||||||
Code() FailCode
|
Code() FailCode
|
||||||
}
|
}
|
||||||
|
|
||||||
// failureMessageLength is the size of the failure message plus the size
|
// failureMessageLength is the size of the failure message plus the size of
|
||||||
// of padding. FailureMessage message always should be equals to this size.
|
// padding. The FailureMessage message should always be EXACLTY this size.
|
||||||
const failureMessageLength = 128
|
const failureMessageLength = 128
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// FlagBadOnion error flag denotes unparsable onion, encrypted by
|
// FlagBadOnion error flag describes an unparseable, encrypted by
|
||||||
// previous node.
|
// previous node.
|
||||||
FlagBadOnion FailCode = 0x8000
|
FlagBadOnion FailCode = 0x8000
|
||||||
|
|
||||||
// FlagPerm error flag denotes permanent failure.
|
// FlagPerm error flag indicates a permanent failure.
|
||||||
FlagPerm FailCode = 0x4000
|
FlagPerm FailCode = 0x4000
|
||||||
|
|
||||||
// FlagNode error flag denotes node failure.
|
// FlagNode error flag indicates anode failure.
|
||||||
FlagNode FailCode = 0x2000
|
FlagNode FailCode = 0x2000
|
||||||
|
|
||||||
// FlagUpdate error flag denotes new channel update enclosed.
|
// FlagUpdate error flag indicates a new channel update is enclosed
|
||||||
|
// within the error.
|
||||||
FlagUpdate FailCode = 0x1000
|
FlagUpdate FailCode = 0x1000
|
||||||
)
|
)
|
||||||
|
|
||||||
// FailCode specifies the precise reason that an upstream HTLC was cancelled.
|
// FailCode specifies the precise reason that an upstream HTLC was cancelled.
|
||||||
// Each UpdateFailHTLC message carries a FailCode which is to be passed back
|
// Each UpdateFailHTLC message carries a FailCode which is to be passed
|
||||||
// unaltered to the source of the HTLC within the route.
|
// backwards, encrypted at each step back to the source of the HTLC within the
|
||||||
|
// route.
|
||||||
type FailCode uint16
|
type FailCode uint16
|
||||||
|
|
||||||
// The currently defined onion failure types within this current version of the
|
// The currently defined onion failure types within this current version of the
|
||||||
@ -67,7 +69,7 @@ const (
|
|||||||
CodeFinalIncorrectHtlcAmount FailCode = 19
|
CodeFinalIncorrectHtlcAmount FailCode = 19
|
||||||
)
|
)
|
||||||
|
|
||||||
// String returns string representation of the failure code.
|
// String returns the string representation of the failure code.
|
||||||
func (c FailCode) String() string {
|
func (c FailCode) String() string {
|
||||||
switch c {
|
switch c {
|
||||||
case CodeInvalidRealm:
|
case CodeInvalidRealm:
|
||||||
@ -140,7 +142,7 @@ func (c FailCode) String() string {
|
|||||||
|
|
||||||
// FailInvalidRealm is returned if the realm byte is unknown.
|
// FailInvalidRealm is returned if the realm byte is unknown.
|
||||||
//
|
//
|
||||||
// NOTE: might be returned by any node.
|
// NOTE: May be returned by any node in the payment route.
|
||||||
type FailInvalidRealm struct{}
|
type FailInvalidRealm struct{}
|
||||||
|
|
||||||
// Code returns the failure unique code.
|
// Code returns the failure unique code.
|
||||||
@ -153,7 +155,7 @@ func (f FailInvalidRealm) Code() FailCode {
|
|||||||
// FailTemporaryNodeFailure is returned if an otherwise unspecified transient
|
// FailTemporaryNodeFailure is returned if an otherwise unspecified transient
|
||||||
// error occurs for the entire node.
|
// error occurs for the entire node.
|
||||||
//
|
//
|
||||||
// NOTE: might be returned by any node.
|
// NOTE: May be returned by any node in the payment route.
|
||||||
type FailTemporaryNodeFailure struct{}
|
type FailTemporaryNodeFailure struct{}
|
||||||
|
|
||||||
// Code returns the failure unique code.
|
// Code returns the failure unique code.
|
||||||
@ -165,7 +167,7 @@ func (f FailTemporaryNodeFailure) Code() FailCode {
|
|||||||
// FailPermanentNodeFailure is returned if an otherwise unspecified permanent
|
// FailPermanentNodeFailure is returned if an otherwise unspecified permanent
|
||||||
// error occurs for the entire node.
|
// error occurs for the entire node.
|
||||||
//
|
//
|
||||||
// NOTE: might be returned by any node.
|
// NOTE: May be returned by any node in the payment route.
|
||||||
type FailPermanentNodeFailure struct{}
|
type FailPermanentNodeFailure struct{}
|
||||||
|
|
||||||
// Code returns the failure unique code.
|
// Code returns the failure unique code.
|
||||||
@ -179,7 +181,7 @@ func (f FailPermanentNodeFailure) Code() FailCode {
|
|||||||
// advertised in its node_announcement features which were not present in the
|
// advertised in its node_announcement features which were not present in the
|
||||||
// onion.
|
// onion.
|
||||||
//
|
//
|
||||||
// NOTE: might be returned by any node.
|
// NOTE: May be returned by any node in the payment route.
|
||||||
type FailRequiredNodeFeatureMissing struct{}
|
type FailRequiredNodeFeatureMissing struct{}
|
||||||
|
|
||||||
// Code returns the failure unique code.
|
// Code returns the failure unique code.
|
||||||
@ -189,10 +191,10 @@ func (f FailRequiredNodeFeatureMissing) Code() FailCode {
|
|||||||
return CodeRequiredNodeFeatureMissing
|
return CodeRequiredNodeFeatureMissing
|
||||||
}
|
}
|
||||||
|
|
||||||
// FailPermanentChannelFailure is return if an otherwise unspecified
|
// FailPermanentChannelFailure is return if an otherwise unspecified permanent
|
||||||
// permanent error occurs for the outgoing channel (eg. channel (recently).
|
// error occurs for the outgoing channel (eg. channel (recently).
|
||||||
//
|
//
|
||||||
// NOTE: might be return by forwarding node only.
|
// NOTE: May be returned by any node in the payment route.
|
||||||
type FailPermanentChannelFailure struct{}
|
type FailPermanentChannelFailure struct{}
|
||||||
|
|
||||||
// Code returns the failure unique code.
|
// Code returns the failure unique code.
|
||||||
@ -202,11 +204,11 @@ func (f FailPermanentChannelFailure) Code() FailCode {
|
|||||||
return CodePermanentChannelFailure
|
return CodePermanentChannelFailure
|
||||||
}
|
}
|
||||||
|
|
||||||
// FailRequiredChannelFeatureMissing is return if the outgoing channel has
|
// FailRequiredChannelFeatureMissing is returned if the outgoing channel has a
|
||||||
// requirement advertised in its channel announcement features which were not
|
// requirement advertised in its channel announcement features which were not
|
||||||
// present in the onion.
|
// present in the onion.
|
||||||
//
|
//
|
||||||
// NOTE: might be return by forwarding node only.
|
// NOTE: May only be returned by intermediate nodes.
|
||||||
type FailRequiredChannelFeatureMissing struct{}
|
type FailRequiredChannelFeatureMissing struct{}
|
||||||
|
|
||||||
// Code returns the failure unique code.
|
// Code returns the failure unique code.
|
||||||
@ -219,7 +221,7 @@ func (f FailRequiredChannelFeatureMissing) Code() FailCode {
|
|||||||
// FailUnknownNextPeer is returned if the next peer specified by the onion is
|
// FailUnknownNextPeer is returned if the next peer specified by the onion is
|
||||||
// not known.
|
// not known.
|
||||||
//
|
//
|
||||||
// NOTE: might be return by forwarding node only.
|
// NOTE: May only be returned by intermediate nodes.
|
||||||
type FailUnknownNextPeer struct{}
|
type FailUnknownNextPeer struct{}
|
||||||
|
|
||||||
// Code returns the failure unique code.
|
// Code returns the failure unique code.
|
||||||
@ -229,12 +231,12 @@ func (f FailUnknownNextPeer) Code() FailCode {
|
|||||||
return CodeUnknownNextPeer
|
return CodeUnknownNextPeer
|
||||||
}
|
}
|
||||||
|
|
||||||
// FailUnknownPaymentHash is returned If the payment hash has already been paid,
|
// FailUnknownPaymentHash is returned If the payment hash has already been
|
||||||
// the final node MAY treat the payment hash as unknown, or may succeed in
|
// paid, the final node MAY treat the payment hash as unknown, or may succeed
|
||||||
// accepting the HTLC. If the payment hash is unknown, the final node MUST fail
|
// in accepting the HTLC. If the payment hash is unknown, the final node MUST
|
||||||
// the HTLC.
|
// fail the HTLC.
|
||||||
//
|
//
|
||||||
// NOTE: might be returned by final node only.
|
// NOTE: May only be returned by the final node in the path.
|
||||||
type FailUnknownPaymentHash struct{}
|
type FailUnknownPaymentHash struct{}
|
||||||
|
|
||||||
// Code returns the failure unique code.
|
// Code returns the failure unique code.
|
||||||
@ -250,7 +252,7 @@ func (f FailUnknownPaymentHash) Code() FailCode {
|
|||||||
// This allows the sender to reduce information leakage by altering the amount,
|
// This allows the sender to reduce information leakage by altering the amount,
|
||||||
// without allowing accidental gross overpayment.
|
// without allowing accidental gross overpayment.
|
||||||
//
|
//
|
||||||
// NOTE: might be returned by final node only.
|
// NOTE: May only be returned by the final node in the path.
|
||||||
type FailIncorrectPaymentAmount struct{}
|
type FailIncorrectPaymentAmount struct{}
|
||||||
|
|
||||||
// Code returns the failure unique code.
|
// Code returns the failure unique code.
|
||||||
@ -263,7 +265,7 @@ func (f FailIncorrectPaymentAmount) Code() FailCode {
|
|||||||
// FailFinalExpiryTooSoon is returned if the cltv_expiry is too low, the final
|
// FailFinalExpiryTooSoon is returned if the cltv_expiry is too low, the final
|
||||||
// node MUST fail the HTLC.
|
// node MUST fail the HTLC.
|
||||||
//
|
//
|
||||||
// NOTE: might be returned by final node only.
|
// NOTE: May only be returned by the final node in the path.
|
||||||
type FailFinalExpiryTooSoon struct{}
|
type FailFinalExpiryTooSoon struct{}
|
||||||
|
|
||||||
// Code returns the failure unique code.
|
// Code returns the failure unique code.
|
||||||
@ -275,7 +277,7 @@ func (f FailFinalExpiryTooSoon) Code() FailCode {
|
|||||||
|
|
||||||
// FailInvalidOnionVersion is returned if the onion version byte is unknown.
|
// FailInvalidOnionVersion is returned if the onion version byte is unknown.
|
||||||
//
|
//
|
||||||
// NOTE: should be return by forwarding node only.
|
// NOTE: May be returned only by intermediate nodes.
|
||||||
type FailInvalidOnionVersion struct {
|
type FailInvalidOnionVersion struct {
|
||||||
// OnionSHA256 hash of the onion blob which haven't been proceeded.
|
// OnionSHA256 hash of the onion blob which haven't been proceeded.
|
||||||
OnionSHA256 [sha256.Size]byte
|
OnionSHA256 [sha256.Size]byte
|
||||||
@ -309,7 +311,7 @@ func (f *FailInvalidOnionVersion) Encode(w io.Writer, pver uint32) error {
|
|||||||
|
|
||||||
// FailInvalidOnionHmac is return if the onion HMAC is incorrect.
|
// FailInvalidOnionHmac is return if the onion HMAC is incorrect.
|
||||||
//
|
//
|
||||||
// NOTE: might be return by forwarding node only.
|
// NOTE: May only be returned by intermediate nodes.
|
||||||
type FailInvalidOnionHmac struct {
|
type FailInvalidOnionHmac struct {
|
||||||
// OnionSHA256 hash of the onion blob which haven't been proceeded.
|
// OnionSHA256 hash of the onion blob which haven't been proceeded.
|
||||||
OnionSHA256 [sha256.Size]byte
|
OnionSHA256 [sha256.Size]byte
|
||||||
@ -344,7 +346,7 @@ func (f *FailInvalidOnionHmac) Encode(w io.Writer, pver uint32) error {
|
|||||||
// FailInvalidOnionKey is return if the ephemeral key in the onion is
|
// FailInvalidOnionKey is return if the ephemeral key in the onion is
|
||||||
// unparsable.
|
// unparsable.
|
||||||
//
|
//
|
||||||
// NOTE: might be return by forwarding node only.
|
// NOTE: May only be returned by intermediate nodes.
|
||||||
type FailInvalidOnionKey struct {
|
type FailInvalidOnionKey struct {
|
||||||
// OnionSHA256 hash of the onion blob which haven't been proceeded.
|
// OnionSHA256 hash of the onion blob which haven't been proceeded.
|
||||||
OnionSHA256 [sha256.Size]byte
|
OnionSHA256 [sha256.Size]byte
|
||||||
@ -376,16 +378,16 @@ func (f *FailInvalidOnionKey) Encode(w io.Writer, pver uint32) error {
|
|||||||
return writeElement(w, f.OnionSHA256[:])
|
return writeElement(w, f.OnionSHA256[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// FailTemporaryChannelFailure is if an otherwise unspecified transient
|
// FailTemporaryChannelFailure is if an otherwise unspecified transient error
|
||||||
// error occurs for the outgoing channel (eg. channel capacity reached,
|
// occurs for the outgoing channel (eg. channel capacity reached, too many
|
||||||
// too many in-flight htlc)
|
// in-flight htlcs)
|
||||||
//
|
//
|
||||||
// NOTE: might be return by forwarding node only.
|
// NOTE: May only be returned by intermediate nodes.
|
||||||
type FailTemporaryChannelFailure struct {
|
type FailTemporaryChannelFailure struct {
|
||||||
// Update is used to update information about state of the channel which
|
// Update is used to update information about state of the channel
|
||||||
// caused the failure.
|
// which caused the failure.
|
||||||
//
|
//
|
||||||
// NOTE: Field is optional.
|
// NOTE: This field is optional.
|
||||||
Update *ChannelUpdate
|
Update *ChannelUpdate
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,11 +441,11 @@ func (f *FailTemporaryChannelFailure) Encode(w io.Writer, pver uint32) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// FailAmountBelowMinimum is returned if the HTLC does not reach the
|
// FailAmountBelowMinimum is returned if the HTLC does not reach the current
|
||||||
// current minimum amount, we tell them the amount of the incoming HTLC
|
// minimum amount, we tell them the amount of the incoming HTLC and the current
|
||||||
// and the current channel setting for the outgoing channel.
|
// channel setting for the outgoing channel.
|
||||||
//
|
//
|
||||||
// NOTE: might be return by forwarding node only.
|
// NOTE: May only be returned by the intermediate nodes in the path.
|
||||||
type FailAmountBelowMinimum struct {
|
type FailAmountBelowMinimum struct {
|
||||||
// HtlcMsat is the wrong amount of the incoming HTLC.
|
// HtlcMsat is the wrong amount of the incoming HTLC.
|
||||||
HtlcMsat btcutil.Amount
|
HtlcMsat btcutil.Amount
|
||||||
@ -456,6 +458,7 @@ type FailAmountBelowMinimum struct {
|
|||||||
// NewAmountBelowMinimum creates new instance of the FailAmountBelowMinimum.
|
// NewAmountBelowMinimum creates new instance of the FailAmountBelowMinimum.
|
||||||
func NewAmountBelowMinimum(htlcMsat btcutil.Amount,
|
func NewAmountBelowMinimum(htlcMsat btcutil.Amount,
|
||||||
update ChannelUpdate) *FailAmountBelowMinimum {
|
update ChannelUpdate) *FailAmountBelowMinimum {
|
||||||
|
|
||||||
return &FailAmountBelowMinimum{
|
return &FailAmountBelowMinimum{
|
||||||
HtlcMsat: htlcMsat,
|
HtlcMsat: htlcMsat,
|
||||||
Update: update,
|
Update: update,
|
||||||
@ -477,8 +480,6 @@ func (f *FailAmountBelowMinimum) Decode(r io.Reader, pver uint32) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// At current moment length is not used but in future we may use it to
|
|
||||||
// differ versions of the update message.
|
|
||||||
var length uint16
|
var length uint16
|
||||||
if err := readElement(r, &length); err != nil {
|
if err := readElement(r, &length); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -496,9 +497,6 @@ func (f *FailAmountBelowMinimum) Encode(w io.Writer, pver uint32) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// We write the length here as the size of the channel updates may differ in
|
|
||||||
// the future and at times additional information is coupled (appended to or
|
|
||||||
// prepended to the channel update itself) along with the channel update.
|
|
||||||
err := writeElement(w, uint16(f.Update.MaxPayloadLength(pver)))
|
err := writeElement(w, uint16(f.Update.MaxPayloadLength(pver)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -507,17 +505,17 @@ func (f *FailAmountBelowMinimum) Encode(w io.Writer, pver uint32) error {
|
|||||||
return f.Update.Encode(w, pver)
|
return f.Update.Encode(w, pver)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FailFeeInsufficient is returned if the HTLC does not pay sufficient
|
// FailFeeInsufficient is returned if the HTLC does not pay sufficient fee, we
|
||||||
// fee, we tell them the amount of the incoming HTLC and the current
|
// tell them the amount of the incoming HTLC and the current channel setting
|
||||||
// channel setting for the outgoing channel.
|
// for the outgoing channel.
|
||||||
//
|
//
|
||||||
// NOTE: might be return by forwarding node only.
|
// NOTE: May only be returned by intermediate nodes.
|
||||||
type FailFeeInsufficient struct {
|
type FailFeeInsufficient struct {
|
||||||
// HtlcMsat is the wrong amount of the incoming HTLC.
|
// HtlcMsat is the wrong amount of the incoming HTLC.
|
||||||
HtlcMsat btcutil.Amount
|
HtlcMsat btcutil.Amount
|
||||||
|
|
||||||
// Update is used to update information about state of the channel which
|
// Update is used to update information about state of the channel
|
||||||
// caused the failure.
|
// which caused the failure.
|
||||||
Update ChannelUpdate
|
Update ChannelUpdate
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -545,8 +543,6 @@ func (f *FailFeeInsufficient) Decode(r io.Reader, pver uint32) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// At current moment length is not used but in future we may use it to
|
|
||||||
// differ versions of the update message.
|
|
||||||
var length uint16
|
var length uint16
|
||||||
if err := readElement(r, &length); err != nil {
|
if err := readElement(r, &length); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -564,9 +560,6 @@ func (f *FailFeeInsufficient) Encode(w io.Writer, pver uint32) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// We write the length here as the size of the channel updates may differ in
|
|
||||||
// the future and at times additional information is coupled (appended to or
|
|
||||||
// prepended to the channel update itself) along with the channel update.
|
|
||||||
err := writeElement(w, uint16(f.Update.MaxPayloadLength(pver)))
|
err := writeElement(w, uint16(f.Update.MaxPayloadLength(pver)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -575,24 +568,26 @@ func (f *FailFeeInsufficient) Encode(w io.Writer, pver uint32) error {
|
|||||||
return f.Update.Encode(w, pver)
|
return f.Update.Encode(w, pver)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FailIncorrectCltvExpiry is returned if outgoing cltv value does not
|
// FailIncorrectCltvExpiry is returned if outgoing cltv value does not match
|
||||||
// match the update add htlc's cltv expiry minus cltv expiry delta
|
// the update add htlc's cltv expiry minus cltv expiry delta for the outgoing
|
||||||
// for the outgoing channel, we tell them the cltv expiry and the
|
// channel, we tell them the cltv expiry and the current channel setting for
|
||||||
// current channel setting for the outgoing channel.
|
// the outgoing channel.
|
||||||
//
|
//
|
||||||
// NOTE: might be return by forwarding node only.
|
// NOTE: May only be returned by intermediate nodes.
|
||||||
type FailIncorrectCltvExpiry struct {
|
type FailIncorrectCltvExpiry struct {
|
||||||
// CltvExpiry is the wrong absolute timeout in blocks, after which outgoing
|
// CltvExpiry is the wrong absolute timeout in blocks, after which
|
||||||
// HTLC expires.
|
// outgoing HTLC expires.
|
||||||
CltvExpiry uint32
|
CltvExpiry uint32
|
||||||
|
|
||||||
// Update is used to update information about state of the channel which
|
// Update is used to update information about state of the channel
|
||||||
// caused the failure.
|
// which caused the failure.
|
||||||
Update ChannelUpdate
|
Update ChannelUpdate
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewIncorrectCltvExpiry creates new instance of the FailIncorrectCltvExpiry.
|
// NewIncorrectCltvExpiry creates new instance of the FailIncorrectCltvExpiry.
|
||||||
func NewIncorrectCltvExpiry(cltvExpiry uint32, update ChannelUpdate) *FailIncorrectCltvExpiry {
|
func NewIncorrectCltvExpiry(cltvExpiry uint32,
|
||||||
|
update ChannelUpdate) *FailIncorrectCltvExpiry {
|
||||||
|
|
||||||
return &FailIncorrectCltvExpiry{
|
return &FailIncorrectCltvExpiry{
|
||||||
CltvExpiry: cltvExpiry,
|
CltvExpiry: cltvExpiry,
|
||||||
Update: update,
|
Update: update,
|
||||||
@ -614,8 +609,6 @@ func (f *FailIncorrectCltvExpiry) Decode(r io.Reader, pver uint32) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// At current moment length is not used but in future we may use it to
|
|
||||||
// differ versions of the update message.
|
|
||||||
var length uint16
|
var length uint16
|
||||||
if err := readElement(r, &length); err != nil {
|
if err := readElement(r, &length); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -633,9 +626,6 @@ func (f *FailIncorrectCltvExpiry) Encode(w io.Writer, pver uint32) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// We write the length here as the size of the channel updates may differ in
|
|
||||||
// the future and at times additional information is coupled (appended to or
|
|
||||||
// prepended to the channel update itself) along with the channel update.
|
|
||||||
err := writeElement(w, uint16(f.Update.MaxPayloadLength(pver)))
|
err := writeElement(w, uint16(f.Update.MaxPayloadLength(pver)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -644,17 +634,17 @@ func (f *FailIncorrectCltvExpiry) Encode(w io.Writer, pver uint32) error {
|
|||||||
return f.Update.Encode(w, pver)
|
return f.Update.Encode(w, pver)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FailExpiryTooSoon is returned if the ctlv-expiry is too near, we tell
|
// FailExpiryTooSoon is returned if the ctlv-expiry is too near, we tell them
|
||||||
// them the the current channel setting for the outgoing channel.
|
// the current channel setting for the outgoing channel.
|
||||||
//
|
//
|
||||||
// NOTE: might be return by forwarding node only.
|
// NOTE: May only be returned by intermediate nodes.
|
||||||
type FailExpiryTooSoon struct {
|
type FailExpiryTooSoon struct {
|
||||||
// Update is used to update information about state of the channel which
|
// Update is used to update information about state of the channel
|
||||||
// caused the failure.
|
// which caused the failure.
|
||||||
Update ChannelUpdate
|
Update ChannelUpdate
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewExpiryTooSoon creates new instance of the FailExpiryTooSoon
|
// NewExpiryTooSoon creates new instance of the FailExpiryTooSoon.
|
||||||
func NewExpiryTooSoon(update ChannelUpdate) *FailExpiryTooSoon {
|
func NewExpiryTooSoon(update ChannelUpdate) *FailExpiryTooSoon {
|
||||||
return &FailExpiryTooSoon{
|
return &FailExpiryTooSoon{
|
||||||
Update: update,
|
Update: update,
|
||||||
@ -672,8 +662,6 @@ func (f *FailExpiryTooSoon) Code() FailCode {
|
|||||||
//
|
//
|
||||||
// NOTE: Part of the Serializable interface.
|
// NOTE: Part of the Serializable interface.
|
||||||
func (f *FailExpiryTooSoon) Decode(r io.Reader, pver uint32) error {
|
func (f *FailExpiryTooSoon) Decode(r io.Reader, pver uint32) error {
|
||||||
// At current moment length is not used but in future we may use it to
|
|
||||||
// differ versions of the update message.
|
|
||||||
var length uint16
|
var length uint16
|
||||||
if err := readElement(r, &length); err != nil {
|
if err := readElement(r, &length); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -687,9 +675,6 @@ func (f *FailExpiryTooSoon) Decode(r io.Reader, pver uint32) error {
|
|||||||
//
|
//
|
||||||
// NOTE: Part of the Serializable interface.
|
// NOTE: Part of the Serializable interface.
|
||||||
func (f *FailExpiryTooSoon) Encode(w io.Writer, pver uint32) error {
|
func (f *FailExpiryTooSoon) Encode(w io.Writer, pver uint32) error {
|
||||||
// We write the length here as the size of the channel updates may differ in
|
|
||||||
// the future and at times additional information is coupled (appended to or
|
|
||||||
// prepended to the channel update itself) along with the channel update.
|
|
||||||
err := writeElement(w, uint16(f.Update.MaxPayloadLength(pver)))
|
err := writeElement(w, uint16(f.Update.MaxPayloadLength(pver)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -698,18 +683,18 @@ func (f *FailExpiryTooSoon) Encode(w io.Writer, pver uint32) error {
|
|||||||
return f.Update.Encode(w, pver)
|
return f.Update.Encode(w, pver)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FailChannelDisabled is returned if the channel is disabled, we tell
|
// FailChannelDisabled is returned if the channel is disabled, we tell them the
|
||||||
// them the the current channel setting for the outgoing channel.
|
// current channel setting for the outgoing channel.
|
||||||
//
|
//
|
||||||
// NOTE: might be return by forwarding node only.
|
// NOTE: May only be returned by intermediate nodes.
|
||||||
type FailChannelDisabled struct {
|
type FailChannelDisabled struct {
|
||||||
// Flags least-significant bit must be set to 0 if the creating node
|
// Flags least-significant bit must be set to 0 if the creating node
|
||||||
// corresponds to the first node in the previously sent channel
|
// corresponds to the first node in the previously sent channel
|
||||||
// announcement and 1 otherwise.
|
// announcement and 1 otherwise.
|
||||||
Flags uint16
|
Flags uint16
|
||||||
|
|
||||||
// Update is used to update information about state of the channel which
|
// Update is used to update information about state of the channel
|
||||||
// caused the failure.
|
// which caused the failure.
|
||||||
Update ChannelUpdate
|
Update ChannelUpdate
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -736,8 +721,6 @@ func (f *FailChannelDisabled) Decode(r io.Reader, pver uint32) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// At current moment length is not used but in future we may use it to
|
|
||||||
// differ versions of the update message.
|
|
||||||
var length uint16
|
var length uint16
|
||||||
if err := readElement(r, &length); err != nil {
|
if err := readElement(r, &length); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -755,9 +738,6 @@ func (f *FailChannelDisabled) Encode(w io.Writer, pver uint32) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// We write the length here as the size of the channel updates may differ in
|
|
||||||
// the future and at times additional information is coupled (appended to or
|
|
||||||
// prepended to the channel update itself) along with the channel update.
|
|
||||||
err := writeElement(w, uint16(f.Update.MaxPayloadLength(pver)))
|
err := writeElement(w, uint16(f.Update.MaxPayloadLength(pver)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -771,8 +751,8 @@ func (f *FailChannelDisabled) Encode(w io.Writer, pver uint32) error {
|
|||||||
//
|
//
|
||||||
// NOTE: might be returned by final node only.
|
// NOTE: might be returned by final node only.
|
||||||
type FailFinalIncorrectCltvExpiry struct {
|
type FailFinalIncorrectCltvExpiry struct {
|
||||||
// CltvExpiry is the wrong absolute timeout in blocks, after which outgoing
|
// CltvExpiry is the wrong absolute timeout in blocks, after which
|
||||||
// HTLC expires.
|
// outgoing HTLC expires.
|
||||||
CltvExpiry uint32
|
CltvExpiry uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -805,10 +785,10 @@ func (f *FailFinalIncorrectCltvExpiry) Encode(w io.Writer, pver uint32) error {
|
|||||||
return writeElement(w, f.CltvExpiry)
|
return writeElement(w, f.CltvExpiry)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FailFinalIncorrectHtlcAmount is returned if the amt_to_forward is
|
// FailFinalIncorrectHtlcAmount is returned if the amt_to_forward is higher
|
||||||
// higher than incoming_htlc_amt of the HTLC at the final hop.
|
// than incoming_htlc_amt of the HTLC at the final hop.
|
||||||
//
|
//
|
||||||
// NOTE: might be returned by final node only.
|
// NOTE: May only be returned by the final node.
|
||||||
type FailFinalIncorrectHtlcAmount struct {
|
type FailFinalIncorrectHtlcAmount struct {
|
||||||
// IncomingHTLCAmount is the wrong forwarded htlc amount.
|
// IncomingHTLCAmount is the wrong forwarded htlc amount.
|
||||||
IncomingHTLCAmount btcutil.Amount
|
IncomingHTLCAmount btcutil.Amount
|
||||||
@ -843,8 +823,8 @@ func (f *FailFinalIncorrectHtlcAmount) Encode(w io.Writer, pver uint32) error {
|
|||||||
return writeElement(w, f.IncomingHTLCAmount)
|
return writeElement(w, f.IncomingHTLCAmount)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeFailure decodes, validates, and parses the lnwire onion failure, for the
|
// DecodeFailure decodes, validates, and parses the lnwire onion failure, for
|
||||||
// provided protocol version.
|
// the provided protocol version.
|
||||||
func DecodeFailure(r io.Reader, pver uint32) (FailureMessage, error) {
|
func DecodeFailure(r io.Reader, pver uint32) (FailureMessage, error) {
|
||||||
// Start processing the failure message by reading the code.
|
// Start processing the failure message by reading the code.
|
||||||
var code uint16
|
var code uint16
|
||||||
@ -852,14 +832,14 @@ func DecodeFailure(r io.Reader, pver uint32) (FailureMessage, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the empty failure by given code and populate the failure
|
// Create the empty failure by given code and populate the failure with
|
||||||
// with additional data if needed.
|
// additional data if needed.
|
||||||
failure, err := makeEmptyOnionError(FailCode(code))
|
failure, err := makeEmptyOnionError(FailCode(code))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read failure length, check its size and read the failure message
|
// Read the failure length, check its size and read the failure message
|
||||||
// in order to check padding afterwards.
|
// in order to check padding afterwards.
|
||||||
var failureLength uint16
|
var failureLength uint16
|
||||||
if err := readElement(r, &failureLength); err != nil {
|
if err := readElement(r, &failureLength); err != nil {
|
||||||
@ -885,7 +865,8 @@ func DecodeFailure(r io.Reader, pver uint32) (FailureMessage, error) {
|
|||||||
return failure, nil
|
return failure, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncodeFailure encodes, including the necessary onion failure header information.
|
// EncodeFailure encodes, including the necessary onion failure header
|
||||||
|
// information.
|
||||||
func EncodeFailure(w io.Writer, failure FailureMessage, pver uint32) error {
|
func EncodeFailure(w io.Writer, failure FailureMessage, pver uint32) error {
|
||||||
var failureMessageBuffer bytes.Buffer
|
var failureMessageBuffer bytes.Buffer
|
||||||
|
|
||||||
|
11
server.go
11
server.go
@ -244,16 +244,17 @@ func newServer(listenAddrs []string, chanDB *channeldb.DB, cc *chainControl,
|
|||||||
htlcAdd *lnwire.UpdateAddHTLC,
|
htlcAdd *lnwire.UpdateAddHTLC,
|
||||||
circuit *sphinx.Circuit) ([32]byte, error) {
|
circuit *sphinx.Circuit) ([32]byte, error) {
|
||||||
|
|
||||||
// Initialize the data obfuscator in order to be able to decode the
|
// Using the created circuit, initialize the error
|
||||||
// onion failure and wrap it so that we could process lnwire onion
|
// decryptor so we can parse+decode any failures
|
||||||
// failures.
|
// incurred by this payment within the switch.
|
||||||
failureDeobfuscator := &htlcswitch.FailureDeobfuscator{
|
errorDecryptor := &htlcswitch.FailureDeobfuscator{
|
||||||
OnionDeobfuscator: sphinx.NewOnionDeobfuscator(circuit),
|
OnionDeobfuscator: sphinx.NewOnionDeobfuscator(circuit),
|
||||||
}
|
}
|
||||||
|
|
||||||
var firstHopPub [33]byte
|
var firstHopPub [33]byte
|
||||||
copy(firstHopPub[:], firstHop.SerializeCompressed())
|
copy(firstHopPub[:], firstHop.SerializeCompressed())
|
||||||
return s.htlcSwitch.SendHTLC(firstHopPub, htlcAdd, failureDeobfuscator)
|
|
||||||
|
return s.htlcSwitch.SendHTLC(firstHopPub, htlcAdd, errorDecryptor)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user