2017-06-08 20:55:41 +03:00
|
|
|
package lnwire
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/sha256"
|
2017-08-22 08:38:48 +03:00
|
|
|
"encoding/binary"
|
|
|
|
"fmt"
|
2017-06-08 20:55:41 +03:00
|
|
|
"io"
|
|
|
|
|
|
|
|
"bytes"
|
|
|
|
|
|
|
|
"github.com/go-errors/errors"
|
|
|
|
)
|
|
|
|
|
2017-07-15 06:08:29 +03:00
|
|
|
// FailureMessage represents the onion failure object identified by its unique
|
|
|
|
// failure code.
|
2017-06-08 20:55:41 +03:00
|
|
|
type FailureMessage interface {
|
|
|
|
Code() FailCode
|
|
|
|
}
|
|
|
|
|
2017-07-15 06:08:29 +03:00
|
|
|
// failureMessageLength is the size of the failure message plus the size of
|
|
|
|
// padding. The FailureMessage message should always be EXACLTY this size.
|
2017-08-22 08:38:48 +03:00
|
|
|
const failureMessageLength = 256
|
2017-06-08 20:55:41 +03:00
|
|
|
|
|
|
|
const (
|
2017-07-15 06:08:29 +03:00
|
|
|
// FlagBadOnion error flag describes an unparseable, encrypted by
|
2017-06-08 20:55:41 +03:00
|
|
|
// previous node.
|
|
|
|
FlagBadOnion FailCode = 0x8000
|
|
|
|
|
2017-07-15 06:08:29 +03:00
|
|
|
// FlagPerm error flag indicates a permanent failure.
|
2017-06-08 20:55:41 +03:00
|
|
|
FlagPerm FailCode = 0x4000
|
|
|
|
|
2017-07-15 06:08:29 +03:00
|
|
|
// FlagNode error flag indicates anode failure.
|
2017-06-08 20:55:41 +03:00
|
|
|
FlagNode FailCode = 0x2000
|
|
|
|
|
2017-07-15 06:08:29 +03:00
|
|
|
// FlagUpdate error flag indicates a new channel update is enclosed
|
|
|
|
// within the error.
|
2017-06-08 20:55:41 +03:00
|
|
|
FlagUpdate FailCode = 0x1000
|
|
|
|
)
|
|
|
|
|
|
|
|
// FailCode specifies the precise reason that an upstream HTLC was cancelled.
|
2017-07-15 06:08:29 +03:00
|
|
|
// Each UpdateFailHTLC message carries a FailCode which is to be passed
|
|
|
|
// backwards, encrypted at each step back to the source of the HTLC within the
|
|
|
|
// route.
|
2017-06-08 20:55:41 +03:00
|
|
|
type FailCode uint16
|
|
|
|
|
|
|
|
// The currently defined onion failure types within this current version of the
|
|
|
|
// Lightning protocol.
|
|
|
|
const (
|
|
|
|
CodeNone FailCode = 0
|
|
|
|
CodeInvalidRealm = FlagBadOnion | 1
|
|
|
|
CodeTemporaryNodeFailure = FlagNode | 2
|
|
|
|
CodePermanentNodeFailure = FlagPerm | FlagNode | 2
|
|
|
|
CodeRequiredNodeFeatureMissing = FlagPerm | FlagNode | 3
|
|
|
|
CodeInvalidOnionVersion = FlagBadOnion | FlagPerm | 4
|
|
|
|
CodeInvalidOnionHmac = FlagBadOnion | FlagPerm | 5
|
|
|
|
CodeInvalidOnionKey = FlagBadOnion | FlagPerm | 6
|
|
|
|
CodeTemporaryChannelFailure = FlagUpdate | 7
|
|
|
|
CodePermanentChannelFailure = FlagPerm | 8
|
|
|
|
CodeRequiredChannelFeatureMissing = FlagPerm | 9
|
|
|
|
CodeUnknownNextPeer = FlagPerm | 10
|
|
|
|
CodeAmountBelowMinimum = FlagUpdate | 11
|
|
|
|
CodeFeeInsufficient = FlagUpdate | 12
|
|
|
|
CodeIncorrectCltvExpiry = FlagUpdate | 13
|
|
|
|
CodeExpiryTooSoon = FlagUpdate | 14
|
|
|
|
CodeChannelDisabled = FlagUpdate | 20
|
|
|
|
CodeUnknownPaymentHash = FlagPerm | 15
|
|
|
|
CodeIncorrectPaymentAmount = FlagPerm | 16
|
|
|
|
CodeFinalExpiryTooSoon FailCode = 17
|
|
|
|
CodeFinalIncorrectCltvExpiry FailCode = 18
|
|
|
|
CodeFinalIncorrectHtlcAmount FailCode = 19
|
|
|
|
)
|
|
|
|
|
2017-07-15 06:08:29 +03:00
|
|
|
// String returns the string representation of the failure code.
|
2017-06-08 20:55:41 +03:00
|
|
|
func (c FailCode) String() string {
|
|
|
|
switch c {
|
|
|
|
case CodeInvalidRealm:
|
|
|
|
return "InvalidRealm"
|
|
|
|
|
|
|
|
case CodeTemporaryNodeFailure:
|
|
|
|
return "TemporaryNodeFailure"
|
|
|
|
|
|
|
|
case CodePermanentNodeFailure:
|
|
|
|
return "PermanentNodeFailure"
|
|
|
|
|
|
|
|
case CodeRequiredNodeFeatureMissing:
|
|
|
|
return "RequiredNodeFeatureMissing"
|
|
|
|
|
|
|
|
case CodeInvalidOnionVersion:
|
|
|
|
return "InvalidOnionVersion"
|
|
|
|
|
|
|
|
case CodeInvalidOnionHmac:
|
|
|
|
return "InvalidOnionHmac"
|
|
|
|
|
|
|
|
case CodeInvalidOnionKey:
|
|
|
|
return "InvalidOnionKey"
|
|
|
|
|
|
|
|
case CodeTemporaryChannelFailure:
|
|
|
|
return "TemporaryChannelFailure"
|
|
|
|
|
|
|
|
case CodePermanentChannelFailure:
|
|
|
|
return "PermanentChannelFailure"
|
|
|
|
|
|
|
|
case CodeRequiredChannelFeatureMissing:
|
|
|
|
return "RequiredChannelFeatureMissing"
|
|
|
|
|
|
|
|
case CodeUnknownNextPeer:
|
|
|
|
return "UnknownNextPeer"
|
|
|
|
|
|
|
|
case CodeAmountBelowMinimum:
|
|
|
|
return "AmountBelowMinimum"
|
|
|
|
|
|
|
|
case CodeFeeInsufficient:
|
|
|
|
return "FeeInsufficient"
|
|
|
|
|
|
|
|
case CodeIncorrectCltvExpiry:
|
|
|
|
return "IncorrectCltvExpiry"
|
|
|
|
|
|
|
|
case CodeExpiryTooSoon:
|
|
|
|
return "ExpiryTooSoon"
|
|
|
|
|
|
|
|
case CodeChannelDisabled:
|
|
|
|
return "ChannelDisabled"
|
|
|
|
|
|
|
|
case CodeUnknownPaymentHash:
|
|
|
|
return "UnknownPaymentHash"
|
|
|
|
|
|
|
|
case CodeIncorrectPaymentAmount:
|
|
|
|
return "IncorrectPaymentAmount"
|
|
|
|
|
|
|
|
case CodeFinalExpiryTooSoon:
|
|
|
|
return "FinalExpiryTooSoon"
|
|
|
|
|
|
|
|
case CodeFinalIncorrectCltvExpiry:
|
|
|
|
return "FinalIncorrectCltvExpiry"
|
|
|
|
|
|
|
|
case CodeFinalIncorrectHtlcAmount:
|
|
|
|
return "FinalIncorrectHtlcAmount"
|
|
|
|
|
|
|
|
default:
|
|
|
|
return "<unknown>"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// FailInvalidRealm is returned if the realm byte is unknown.
|
|
|
|
//
|
2017-07-15 06:08:29 +03:00
|
|
|
// NOTE: May be returned by any node in the payment route.
|
2017-06-08 20:55:41 +03:00
|
|
|
type FailInvalidRealm struct{}
|
|
|
|
|
|
|
|
// Code returns the failure unique code.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the FailureMessage interface.
|
|
|
|
func (f FailInvalidRealm) Code() FailCode {
|
|
|
|
return CodeInvalidRealm
|
|
|
|
}
|
|
|
|
|
|
|
|
// FailTemporaryNodeFailure is returned if an otherwise unspecified transient
|
|
|
|
// error occurs for the entire node.
|
|
|
|
//
|
2017-07-15 06:08:29 +03:00
|
|
|
// NOTE: May be returned by any node in the payment route.
|
2017-06-08 20:55:41 +03:00
|
|
|
type FailTemporaryNodeFailure struct{}
|
|
|
|
|
|
|
|
// Code returns the failure unique code.
|
|
|
|
// NOTE: Part of the FailureMessage interface.
|
|
|
|
func (f FailTemporaryNodeFailure) Code() FailCode {
|
|
|
|
return CodeTemporaryNodeFailure
|
|
|
|
}
|
|
|
|
|
|
|
|
// FailPermanentNodeFailure is returned if an otherwise unspecified permanent
|
|
|
|
// error occurs for the entire node.
|
|
|
|
//
|
2017-07-15 06:08:29 +03:00
|
|
|
// NOTE: May be returned by any node in the payment route.
|
2017-06-08 20:55:41 +03:00
|
|
|
type FailPermanentNodeFailure struct{}
|
|
|
|
|
|
|
|
// Code returns the failure unique code.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the FailureMessage interface.
|
|
|
|
func (f FailPermanentNodeFailure) Code() FailCode {
|
|
|
|
return CodePermanentNodeFailure
|
|
|
|
}
|
|
|
|
|
|
|
|
// FailRequiredNodeFeatureMissing is returned if a node has requirement
|
|
|
|
// advertised in its node_announcement features which were not present in the
|
|
|
|
// onion.
|
|
|
|
//
|
2017-07-15 06:08:29 +03:00
|
|
|
// NOTE: May be returned by any node in the payment route.
|
2017-06-08 20:55:41 +03:00
|
|
|
type FailRequiredNodeFeatureMissing struct{}
|
|
|
|
|
|
|
|
// Code returns the failure unique code.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the FailureMessage interface.
|
|
|
|
func (f FailRequiredNodeFeatureMissing) Code() FailCode {
|
|
|
|
return CodeRequiredNodeFeatureMissing
|
|
|
|
}
|
|
|
|
|
2017-07-15 06:08:29 +03:00
|
|
|
// FailPermanentChannelFailure is return if an otherwise unspecified permanent
|
|
|
|
// error occurs for the outgoing channel (eg. channel (recently).
|
2017-06-08 20:55:41 +03:00
|
|
|
//
|
2017-07-15 06:08:29 +03:00
|
|
|
// NOTE: May be returned by any node in the payment route.
|
2017-06-08 20:55:41 +03:00
|
|
|
type FailPermanentChannelFailure struct{}
|
|
|
|
|
|
|
|
// Code returns the failure unique code.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the FailureMessage interface.
|
|
|
|
func (f FailPermanentChannelFailure) Code() FailCode {
|
|
|
|
return CodePermanentChannelFailure
|
|
|
|
}
|
|
|
|
|
2017-07-15 06:08:29 +03:00
|
|
|
// FailRequiredChannelFeatureMissing is returned if the outgoing channel has a
|
2017-06-08 20:55:41 +03:00
|
|
|
// requirement advertised in its channel announcement features which were not
|
|
|
|
// present in the onion.
|
|
|
|
//
|
2017-07-15 06:08:29 +03:00
|
|
|
// NOTE: May only be returned by intermediate nodes.
|
2017-06-08 20:55:41 +03:00
|
|
|
type FailRequiredChannelFeatureMissing struct{}
|
|
|
|
|
|
|
|
// Code returns the failure unique code.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the FailureMessage interface.
|
|
|
|
func (f FailRequiredChannelFeatureMissing) Code() FailCode {
|
|
|
|
return CodeRequiredChannelFeatureMissing
|
|
|
|
}
|
|
|
|
|
|
|
|
// FailUnknownNextPeer is returned if the next peer specified by the onion is
|
|
|
|
// not known.
|
|
|
|
//
|
2017-07-15 06:08:29 +03:00
|
|
|
// NOTE: May only be returned by intermediate nodes.
|
2017-06-08 20:55:41 +03:00
|
|
|
type FailUnknownNextPeer struct{}
|
|
|
|
|
|
|
|
// Code returns the failure unique code.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the FailureMessage interface.
|
|
|
|
func (f FailUnknownNextPeer) Code() FailCode {
|
|
|
|
return CodeUnknownNextPeer
|
|
|
|
}
|
|
|
|
|
2017-07-15 06:08:29 +03:00
|
|
|
// FailUnknownPaymentHash is returned If the payment hash has already been
|
|
|
|
// paid, the final node MAY treat the payment hash as unknown, or may succeed
|
|
|
|
// in accepting the HTLC. If the payment hash is unknown, the final node MUST
|
|
|
|
// fail the HTLC.
|
2017-06-08 20:55:41 +03:00
|
|
|
//
|
2017-07-15 06:08:29 +03:00
|
|
|
// NOTE: May only be returned by the final node in the path.
|
2017-06-08 20:55:41 +03:00
|
|
|
type FailUnknownPaymentHash struct{}
|
|
|
|
|
|
|
|
// Code returns the failure unique code.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the FailureMessage interface.
|
|
|
|
func (f FailUnknownPaymentHash) Code() FailCode {
|
|
|
|
return CodeUnknownPaymentHash
|
|
|
|
}
|
|
|
|
|
|
|
|
// FailIncorrectPaymentAmount is returned if the amount paid is less than the
|
|
|
|
// amount expected, the final node MUST fail the HTLC. If the amount paid is
|
|
|
|
// more than twice the amount expected, the final node SHOULD fail the HTLC.
|
|
|
|
// This allows the sender to reduce information leakage by altering the amount,
|
|
|
|
// without allowing accidental gross overpayment.
|
|
|
|
//
|
2017-07-15 06:08:29 +03:00
|
|
|
// NOTE: May only be returned by the final node in the path.
|
2017-06-08 20:55:41 +03:00
|
|
|
type FailIncorrectPaymentAmount struct{}
|
|
|
|
|
|
|
|
// Code returns the failure unique code.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the FailureMessage interface.
|
|
|
|
func (f FailIncorrectPaymentAmount) Code() FailCode {
|
|
|
|
return CodeIncorrectPaymentAmount
|
|
|
|
}
|
|
|
|
|
|
|
|
// FailFinalExpiryTooSoon is returned if the cltv_expiry is too low, the final
|
|
|
|
// node MUST fail the HTLC.
|
|
|
|
//
|
2017-07-15 06:08:29 +03:00
|
|
|
// NOTE: May only be returned by the final node in the path.
|
2017-06-08 20:55:41 +03:00
|
|
|
type FailFinalExpiryTooSoon struct{}
|
|
|
|
|
|
|
|
// Code returns the failure unique code.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the FailureMessage interface.
|
|
|
|
func (f FailFinalExpiryTooSoon) Code() FailCode {
|
|
|
|
return CodeFinalExpiryTooSoon
|
|
|
|
}
|
|
|
|
|
|
|
|
// FailInvalidOnionVersion is returned if the onion version byte is unknown.
|
|
|
|
//
|
2017-07-15 06:08:29 +03:00
|
|
|
// NOTE: May be returned only by intermediate nodes.
|
2017-06-08 20:55:41 +03:00
|
|
|
type FailInvalidOnionVersion struct {
|
|
|
|
// OnionSHA256 hash of the onion blob which haven't been proceeded.
|
|
|
|
OnionSHA256 [sha256.Size]byte
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewInvalidOnionVersion creates new instance of the FailInvalidOnionVersion.
|
|
|
|
func NewInvalidOnionVersion(onion []byte) *FailInvalidOnionVersion {
|
|
|
|
return &FailInvalidOnionVersion{OnionSHA256: sha256.Sum256(onion)}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Code returns the failure unique code.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the FailureMessage interface.
|
|
|
|
func (f *FailInvalidOnionVersion) Code() FailCode {
|
|
|
|
return CodeInvalidOnionVersion
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decode decodes the failure from bytes stream.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the Serializable interface.
|
|
|
|
func (f *FailInvalidOnionVersion) Decode(r io.Reader, pver uint32) error {
|
|
|
|
return readElement(r, f.OnionSHA256[:])
|
|
|
|
}
|
|
|
|
|
|
|
|
// Encode writes the failure in bytes stream.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the Serializable interface.
|
|
|
|
func (f *FailInvalidOnionVersion) Encode(w io.Writer, pver uint32) error {
|
|
|
|
return writeElement(w, f.OnionSHA256[:])
|
|
|
|
}
|
|
|
|
|
|
|
|
// FailInvalidOnionHmac is return if the onion HMAC is incorrect.
|
|
|
|
//
|
2017-07-15 06:08:29 +03:00
|
|
|
// NOTE: May only be returned by intermediate nodes.
|
2017-06-08 20:55:41 +03:00
|
|
|
type FailInvalidOnionHmac struct {
|
|
|
|
// OnionSHA256 hash of the onion blob which haven't been proceeded.
|
|
|
|
OnionSHA256 [sha256.Size]byte
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewInvalidOnionHmac creates new instance of the FailInvalidOnionHmac.
|
|
|
|
func NewInvalidOnionHmac(onion []byte) *FailInvalidOnionHmac {
|
|
|
|
return &FailInvalidOnionHmac{OnionSHA256: sha256.Sum256(onion)}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Code returns the failure unique code.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the FailureMessage interface.
|
|
|
|
func (f *FailInvalidOnionHmac) Code() FailCode {
|
|
|
|
return CodeInvalidOnionHmac
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decode decodes the failure from bytes stream.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the Serializable interface.
|
|
|
|
func (f *FailInvalidOnionHmac) Decode(r io.Reader, pver uint32) error {
|
|
|
|
return readElement(r, f.OnionSHA256[:])
|
|
|
|
}
|
|
|
|
|
|
|
|
// Encode writes the failure in bytes stream.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the Serializable interface.
|
|
|
|
func (f *FailInvalidOnionHmac) Encode(w io.Writer, pver uint32) error {
|
|
|
|
return writeElement(w, f.OnionSHA256[:])
|
|
|
|
}
|
|
|
|
|
|
|
|
// FailInvalidOnionKey is return if the ephemeral key in the onion is
|
|
|
|
// unparsable.
|
|
|
|
//
|
2017-07-15 06:08:29 +03:00
|
|
|
// NOTE: May only be returned by intermediate nodes.
|
2017-06-08 20:55:41 +03:00
|
|
|
type FailInvalidOnionKey struct {
|
|
|
|
// OnionSHA256 hash of the onion blob which haven't been proceeded.
|
|
|
|
OnionSHA256 [sha256.Size]byte
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewInvalidOnionKey creates new instance of the FailInvalidOnionKey.
|
|
|
|
func NewInvalidOnionKey(onion []byte) *FailInvalidOnionKey {
|
|
|
|
return &FailInvalidOnionKey{OnionSHA256: sha256.Sum256(onion)}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Code returns the failure unique code.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the FailureMessage interface.
|
|
|
|
func (f *FailInvalidOnionKey) Code() FailCode {
|
|
|
|
return CodeInvalidOnionKey
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decode decodes the failure from bytes stream.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the Serializable interface.
|
|
|
|
func (f *FailInvalidOnionKey) Decode(r io.Reader, pver uint32) error {
|
|
|
|
return readElement(r, f.OnionSHA256[:])
|
|
|
|
}
|
|
|
|
|
|
|
|
// Encode writes the failure in bytes stream.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the Serializable interface.
|
|
|
|
func (f *FailInvalidOnionKey) Encode(w io.Writer, pver uint32) error {
|
|
|
|
return writeElement(w, f.OnionSHA256[:])
|
|
|
|
}
|
|
|
|
|
2017-07-15 06:08:29 +03:00
|
|
|
// FailTemporaryChannelFailure is if an otherwise unspecified transient error
|
|
|
|
// occurs for the outgoing channel (eg. channel capacity reached, too many
|
|
|
|
// in-flight htlcs)
|
2017-06-08 20:55:41 +03:00
|
|
|
//
|
2017-07-15 06:08:29 +03:00
|
|
|
// NOTE: May only be returned by intermediate nodes.
|
2017-06-08 20:55:41 +03:00
|
|
|
type FailTemporaryChannelFailure struct {
|
2017-07-15 06:08:29 +03:00
|
|
|
// Update is used to update information about state of the channel
|
|
|
|
// which caused the failure.
|
2017-06-08 20:55:41 +03:00
|
|
|
//
|
2017-07-15 06:08:29 +03:00
|
|
|
// NOTE: This field is optional.
|
2017-06-08 20:55:41 +03:00
|
|
|
Update *ChannelUpdate
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewTemporaryChannelFailure creates new instance of the FailTemporaryChannelFailure.
|
|
|
|
func NewTemporaryChannelFailure(update *ChannelUpdate) *FailTemporaryChannelFailure {
|
|
|
|
return &FailTemporaryChannelFailure{Update: update}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Code returns the failure unique code.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the FailureMessage interface.
|
|
|
|
func (f *FailTemporaryChannelFailure) Code() FailCode {
|
|
|
|
return CodeTemporaryChannelFailure
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decode decodes the failure from bytes stream.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the Serializable interface.
|
|
|
|
func (f *FailTemporaryChannelFailure) Decode(r io.Reader, pver uint32) error {
|
|
|
|
var length uint16
|
|
|
|
err := readElement(r, &length)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if length != 0 {
|
|
|
|
f.Update = &ChannelUpdate{}
|
|
|
|
return f.Update.Decode(r, pver)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Encode writes the failure in bytes stream.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the Serializable interface.
|
|
|
|
func (f *FailTemporaryChannelFailure) Encode(w io.Writer, pver uint32) error {
|
|
|
|
var payload []byte
|
|
|
|
if f.Update != nil {
|
|
|
|
var bw bytes.Buffer
|
|
|
|
if err := f.Update.Encode(&bw, pver); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
payload = bw.Bytes()
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := writeElement(w, uint16(len(payload))); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err := w.Write(payload)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2017-07-15 06:08:29 +03:00
|
|
|
// FailAmountBelowMinimum is returned if the HTLC does not reach the current
|
|
|
|
// minimum amount, we tell them the amount of the incoming HTLC and the current
|
|
|
|
// channel setting for the outgoing channel.
|
2017-06-08 20:55:41 +03:00
|
|
|
//
|
2017-07-15 06:08:29 +03:00
|
|
|
// NOTE: May only be returned by the intermediate nodes in the path.
|
2017-06-08 20:55:41 +03:00
|
|
|
type FailAmountBelowMinimum struct {
|
|
|
|
// HtlcMsat is the wrong amount of the incoming HTLC.
|
2017-08-22 08:33:20 +03:00
|
|
|
HtlcMsat MilliSatoshi
|
2017-06-08 20:55:41 +03:00
|
|
|
|
2017-08-22 08:33:20 +03:00
|
|
|
// Update is used to update information about state of the channel
|
|
|
|
// which caused the failure.
|
2017-06-08 20:55:41 +03:00
|
|
|
Update ChannelUpdate
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewAmountBelowMinimum creates new instance of the FailAmountBelowMinimum.
|
2017-08-22 08:33:20 +03:00
|
|
|
func NewAmountBelowMinimum(htlcMsat MilliSatoshi,
|
2017-06-08 20:55:41 +03:00
|
|
|
update ChannelUpdate) *FailAmountBelowMinimum {
|
2017-07-15 06:08:29 +03:00
|
|
|
|
2017-06-08 20:55:41 +03:00
|
|
|
return &FailAmountBelowMinimum{
|
|
|
|
HtlcMsat: htlcMsat,
|
|
|
|
Update: update,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Code returns the failure unique code.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the FailureMessage interface.
|
|
|
|
func (f *FailAmountBelowMinimum) Code() FailCode {
|
|
|
|
return CodeAmountBelowMinimum
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decode decodes the failure from bytes stream.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the Serializable interface.
|
|
|
|
func (f *FailAmountBelowMinimum) Decode(r io.Reader, pver uint32) error {
|
|
|
|
if err := readElement(r, &f.HtlcMsat); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
var length uint16
|
|
|
|
if err := readElement(r, &length); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
f.Update = ChannelUpdate{}
|
|
|
|
return f.Update.Decode(r, pver)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Encode writes the failure in bytes stream.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the Serializable interface.
|
|
|
|
func (f *FailAmountBelowMinimum) Encode(w io.Writer, pver uint32) error {
|
|
|
|
if err := writeElement(w, f.HtlcMsat); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
err := writeElement(w, uint16(f.Update.MaxPayloadLength(pver)))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return f.Update.Encode(w, pver)
|
|
|
|
}
|
|
|
|
|
2017-07-15 06:08:29 +03:00
|
|
|
// FailFeeInsufficient is returned if the HTLC does not pay sufficient fee, we
|
|
|
|
// tell them the amount of the incoming HTLC and the current channel setting
|
|
|
|
// for the outgoing channel.
|
2017-06-08 20:55:41 +03:00
|
|
|
//
|
2017-07-15 06:08:29 +03:00
|
|
|
// NOTE: May only be returned by intermediate nodes.
|
2017-06-08 20:55:41 +03:00
|
|
|
type FailFeeInsufficient struct {
|
|
|
|
// HtlcMsat is the wrong amount of the incoming HTLC.
|
2017-08-22 08:33:20 +03:00
|
|
|
HtlcMsat MilliSatoshi
|
2017-06-08 20:55:41 +03:00
|
|
|
|
2017-07-15 06:08:29 +03:00
|
|
|
// Update is used to update information about state of the channel
|
|
|
|
// which caused the failure.
|
2017-06-08 20:55:41 +03:00
|
|
|
Update ChannelUpdate
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewFeeInsufficient creates new instance of the FailFeeInsufficient.
|
2017-08-22 08:33:20 +03:00
|
|
|
func NewFeeInsufficient(htlcMsat MilliSatoshi,
|
2017-06-08 20:55:41 +03:00
|
|
|
update ChannelUpdate) *FailFeeInsufficient {
|
|
|
|
return &FailFeeInsufficient{
|
|
|
|
HtlcMsat: htlcMsat,
|
|
|
|
Update: update,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Code returns the failure unique code.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the FailureMessage interface.
|
|
|
|
func (f *FailFeeInsufficient) Code() FailCode {
|
|
|
|
return CodeFeeInsufficient
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decode decodes the failure from bytes stream.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the Serializable interface.
|
|
|
|
func (f *FailFeeInsufficient) Decode(r io.Reader, pver uint32) error {
|
|
|
|
if err := readElement(r, &f.HtlcMsat); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
var length uint16
|
|
|
|
if err := readElement(r, &length); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
f.Update = ChannelUpdate{}
|
|
|
|
return f.Update.Decode(r, pver)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Encode writes the failure in bytes stream.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the Serializable interface.
|
|
|
|
func (f *FailFeeInsufficient) Encode(w io.Writer, pver uint32) error {
|
|
|
|
if err := writeElement(w, f.HtlcMsat); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
err := writeElement(w, uint16(f.Update.MaxPayloadLength(pver)))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return f.Update.Encode(w, pver)
|
|
|
|
}
|
|
|
|
|
2017-07-15 06:08:29 +03:00
|
|
|
// FailIncorrectCltvExpiry is returned if outgoing cltv value does not match
|
|
|
|
// the update add htlc's cltv expiry minus cltv expiry delta for the outgoing
|
|
|
|
// channel, we tell them the cltv expiry and the current channel setting for
|
|
|
|
// the outgoing channel.
|
2017-06-08 20:55:41 +03:00
|
|
|
//
|
2017-07-15 06:08:29 +03:00
|
|
|
// NOTE: May only be returned by intermediate nodes.
|
2017-06-08 20:55:41 +03:00
|
|
|
type FailIncorrectCltvExpiry struct {
|
2017-07-15 06:08:29 +03:00
|
|
|
// CltvExpiry is the wrong absolute timeout in blocks, after which
|
|
|
|
// outgoing HTLC expires.
|
2017-06-08 20:55:41 +03:00
|
|
|
CltvExpiry uint32
|
|
|
|
|
2017-07-15 06:08:29 +03:00
|
|
|
// Update is used to update information about state of the channel
|
|
|
|
// which caused the failure.
|
2017-06-08 20:55:41 +03:00
|
|
|
Update ChannelUpdate
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewIncorrectCltvExpiry creates new instance of the FailIncorrectCltvExpiry.
|
2017-07-15 06:08:29 +03:00
|
|
|
func NewIncorrectCltvExpiry(cltvExpiry uint32,
|
|
|
|
update ChannelUpdate) *FailIncorrectCltvExpiry {
|
|
|
|
|
2017-06-08 20:55:41 +03:00
|
|
|
return &FailIncorrectCltvExpiry{
|
|
|
|
CltvExpiry: cltvExpiry,
|
|
|
|
Update: update,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Code returns the failure unique code.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the FailureMessage interface.
|
|
|
|
func (f *FailIncorrectCltvExpiry) Code() FailCode {
|
|
|
|
return CodeIncorrectCltvExpiry
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decode decodes the failure from bytes stream.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the Serializable interface.
|
|
|
|
func (f *FailIncorrectCltvExpiry) Decode(r io.Reader, pver uint32) error {
|
|
|
|
if err := readElement(r, &f.CltvExpiry); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
var length uint16
|
|
|
|
if err := readElement(r, &length); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
f.Update = ChannelUpdate{}
|
|
|
|
return f.Update.Decode(r, pver)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Encode writes the failure in bytes stream.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the Serializable interface.
|
|
|
|
func (f *FailIncorrectCltvExpiry) Encode(w io.Writer, pver uint32) error {
|
|
|
|
if err := writeElement(w, f.CltvExpiry); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
err := writeElement(w, uint16(f.Update.MaxPayloadLength(pver)))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return f.Update.Encode(w, pver)
|
|
|
|
}
|
|
|
|
|
2017-07-15 06:08:29 +03:00
|
|
|
// FailExpiryTooSoon is returned if the ctlv-expiry is too near, we tell them
|
|
|
|
// the current channel setting for the outgoing channel.
|
2017-06-08 20:55:41 +03:00
|
|
|
//
|
2017-07-15 06:08:29 +03:00
|
|
|
// NOTE: May only be returned by intermediate nodes.
|
2017-06-08 20:55:41 +03:00
|
|
|
type FailExpiryTooSoon struct {
|
2017-07-15 06:08:29 +03:00
|
|
|
// Update is used to update information about state of the channel
|
|
|
|
// which caused the failure.
|
2017-06-08 20:55:41 +03:00
|
|
|
Update ChannelUpdate
|
|
|
|
}
|
|
|
|
|
2017-07-15 06:08:29 +03:00
|
|
|
// NewExpiryTooSoon creates new instance of the FailExpiryTooSoon.
|
2017-06-08 20:55:41 +03:00
|
|
|
func NewExpiryTooSoon(update ChannelUpdate) *FailExpiryTooSoon {
|
|
|
|
return &FailExpiryTooSoon{
|
|
|
|
Update: update,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Code returns the failure unique code.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the FailureMessage interface.
|
|
|
|
func (f *FailExpiryTooSoon) Code() FailCode {
|
|
|
|
return CodeExpiryTooSoon
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decode decodes the failure from bytes stream.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the Serializable interface.
|
|
|
|
func (f *FailExpiryTooSoon) Decode(r io.Reader, pver uint32) error {
|
|
|
|
var length uint16
|
|
|
|
if err := readElement(r, &length); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
f.Update = ChannelUpdate{}
|
|
|
|
return f.Update.Decode(r, pver)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Encode writes the failure in bytes stream.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the Serializable interface.
|
|
|
|
func (f *FailExpiryTooSoon) Encode(w io.Writer, pver uint32) error {
|
|
|
|
err := writeElement(w, uint16(f.Update.MaxPayloadLength(pver)))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return f.Update.Encode(w, pver)
|
|
|
|
}
|
|
|
|
|
2017-07-15 06:08:29 +03:00
|
|
|
// FailChannelDisabled is returned if the channel is disabled, we tell them the
|
|
|
|
// current channel setting for the outgoing channel.
|
2017-06-08 20:55:41 +03:00
|
|
|
//
|
2017-07-15 06:08:29 +03:00
|
|
|
// NOTE: May only be returned by intermediate nodes.
|
2017-06-08 20:55:41 +03:00
|
|
|
type FailChannelDisabled struct {
|
|
|
|
// Flags least-significant bit must be set to 0 if the creating node
|
|
|
|
// corresponds to the first node in the previously sent channel
|
|
|
|
// announcement and 1 otherwise.
|
|
|
|
Flags uint16
|
|
|
|
|
2017-07-15 06:08:29 +03:00
|
|
|
// Update is used to update information about state of the channel
|
|
|
|
// which caused the failure.
|
2017-06-08 20:55:41 +03:00
|
|
|
Update ChannelUpdate
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewChannelDisabled creates new instance of the FailChannelDisabled.
|
|
|
|
func NewChannelDisabled(flags uint16, update ChannelUpdate) *FailChannelDisabled {
|
|
|
|
return &FailChannelDisabled{
|
|
|
|
Flags: flags,
|
|
|
|
Update: update,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Code returns the failure unique code.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the FailureMessage interface.
|
|
|
|
func (f *FailChannelDisabled) Code() FailCode {
|
|
|
|
return CodeChannelDisabled
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decode decodes the failure from bytes stream.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the Serializable interface.
|
|
|
|
func (f *FailChannelDisabled) Decode(r io.Reader, pver uint32) error {
|
|
|
|
if err := readElement(r, &f.Flags); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
var length uint16
|
|
|
|
if err := readElement(r, &length); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
f.Update = ChannelUpdate{}
|
|
|
|
return f.Update.Decode(r, pver)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Encode writes the failure in bytes stream.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the Serializable interface.
|
|
|
|
func (f *FailChannelDisabled) Encode(w io.Writer, pver uint32) error {
|
|
|
|
if err := writeElement(w, f.Flags); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
err := writeElement(w, uint16(f.Update.MaxPayloadLength(pver)))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return f.Update.Encode(w, pver)
|
|
|
|
}
|
|
|
|
|
|
|
|
// FailFinalIncorrectCltvExpiry is returned if the outgoing_cltv_value does not
|
|
|
|
// match the ctlv_expiry of the HTLC at the final hop.
|
|
|
|
//
|
|
|
|
// NOTE: might be returned by final node only.
|
|
|
|
type FailFinalIncorrectCltvExpiry struct {
|
2017-07-15 06:08:29 +03:00
|
|
|
// CltvExpiry is the wrong absolute timeout in blocks, after which
|
|
|
|
// outgoing HTLC expires.
|
2017-06-08 20:55:41 +03:00
|
|
|
CltvExpiry uint32
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewFinalIncorrectCltvExpiry creates new instance of the
|
|
|
|
// FailFinalIncorrectCltvExpiry.
|
|
|
|
func NewFinalIncorrectCltvExpiry(cltvExpiry uint32) *FailFinalIncorrectCltvExpiry {
|
|
|
|
return &FailFinalIncorrectCltvExpiry{
|
|
|
|
CltvExpiry: cltvExpiry,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Code returns the failure unique code.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the FailureMessage interface.
|
|
|
|
func (f *FailFinalIncorrectCltvExpiry) Code() FailCode {
|
|
|
|
return CodeFinalIncorrectCltvExpiry
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decode decodes the failure from bytes stream.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the Serializable interface.
|
|
|
|
func (f *FailFinalIncorrectCltvExpiry) Decode(r io.Reader, pver uint32) error {
|
|
|
|
return readElement(r, &f.CltvExpiry)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Encode writes the failure in bytes stream.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the Serializable interface.
|
|
|
|
func (f *FailFinalIncorrectCltvExpiry) Encode(w io.Writer, pver uint32) error {
|
|
|
|
return writeElement(w, f.CltvExpiry)
|
|
|
|
}
|
|
|
|
|
2017-07-15 06:08:29 +03:00
|
|
|
// FailFinalIncorrectHtlcAmount is returned if the amt_to_forward is higher
|
|
|
|
// than incoming_htlc_amt of the HTLC at the final hop.
|
2017-06-08 20:55:41 +03:00
|
|
|
//
|
2017-07-15 06:08:29 +03:00
|
|
|
// NOTE: May only be returned by the final node.
|
2017-06-08 20:55:41 +03:00
|
|
|
type FailFinalIncorrectHtlcAmount struct {
|
|
|
|
// IncomingHTLCAmount is the wrong forwarded htlc amount.
|
2017-08-22 08:33:20 +03:00
|
|
|
IncomingHTLCAmount MilliSatoshi
|
2017-06-08 20:55:41 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewFinalIncorrectHtlcAmount creates new instance of the
|
|
|
|
// FailFinalIncorrectHtlcAmount.
|
2017-08-22 08:33:20 +03:00
|
|
|
func NewFinalIncorrectHtlcAmount(amount MilliSatoshi) *FailFinalIncorrectHtlcAmount {
|
2017-06-08 20:55:41 +03:00
|
|
|
return &FailFinalIncorrectHtlcAmount{
|
|
|
|
IncomingHTLCAmount: amount,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Code returns the failure unique code.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the FailureMessage interface.
|
|
|
|
func (f *FailFinalIncorrectHtlcAmount) Code() FailCode {
|
|
|
|
return CodeFinalIncorrectHtlcAmount
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decode decodes the failure from bytes stream.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the Serializable interface.
|
|
|
|
func (f *FailFinalIncorrectHtlcAmount) Decode(r io.Reader, pver uint32) error {
|
|
|
|
return readElement(r, &f.IncomingHTLCAmount)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Encode writes the failure in bytes stream.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the Serializable interface.
|
|
|
|
func (f *FailFinalIncorrectHtlcAmount) Encode(w io.Writer, pver uint32) error {
|
|
|
|
return writeElement(w, f.IncomingHTLCAmount)
|
|
|
|
}
|
|
|
|
|
2017-07-15 06:08:29 +03:00
|
|
|
// DecodeFailure decodes, validates, and parses the lnwire onion failure, for
|
|
|
|
// the provided protocol version.
|
2017-06-08 20:55:41 +03:00
|
|
|
func DecodeFailure(r io.Reader, pver uint32) (FailureMessage, error) {
|
2017-08-22 08:38:48 +03:00
|
|
|
// First, we'll parse out the encapsulated failure message itself. This
|
|
|
|
// is a 2 byte length followed by the payload itself.
|
2017-06-08 20:55:41 +03:00
|
|
|
var failureLength uint16
|
|
|
|
if err := readElement(r, &failureLength); err != nil {
|
2017-09-12 18:55:20 +03:00
|
|
|
return nil, fmt.Errorf("unable to read error len: %v", err)
|
2017-06-08 20:55:41 +03:00
|
|
|
}
|
|
|
|
if failureLength > failureMessageLength {
|
2017-08-22 11:00:07 +03:00
|
|
|
return nil, fmt.Errorf("failure message is too "+
|
|
|
|
"long: %v", failureLength)
|
2017-06-08 20:55:41 +03:00
|
|
|
}
|
|
|
|
failureData := make([]byte, failureLength)
|
|
|
|
if _, err := io.ReadFull(r, failureData); err != nil {
|
2017-09-12 18:55:20 +03:00
|
|
|
return nil, fmt.Errorf("unable to full read payload of "+
|
|
|
|
"%v: %v", failureLength, err)
|
2017-06-08 20:55:41 +03:00
|
|
|
}
|
|
|
|
|
2017-08-22 08:38:48 +03:00
|
|
|
dataReader := bytes.NewReader(failureData)
|
|
|
|
|
|
|
|
// Once we have the failure data, we can obtain the failure code from
|
|
|
|
// the first two bytes of the buffer.
|
|
|
|
var codeBytes [2]byte
|
|
|
|
if _, err := io.ReadFull(dataReader, codeBytes[:]); err != nil {
|
2017-09-12 18:55:20 +03:00
|
|
|
return nil, fmt.Errorf("unable to read failure code: %v", err)
|
2017-08-22 08:38:48 +03:00
|
|
|
}
|
|
|
|
failCode := FailCode(binary.BigEndian.Uint16(codeBytes[:]))
|
|
|
|
|
|
|
|
// Create the empty failure by given code and populate the failure with
|
|
|
|
// additional data if needed.
|
|
|
|
failure, err := makeEmptyOnionError(failCode)
|
|
|
|
if err != nil {
|
2017-09-12 18:55:20 +03:00
|
|
|
return nil, fmt.Errorf("unable to make empty error: %v", err)
|
2017-08-22 08:38:48 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Finally, if this failure has a payload, then we'll read that now as
|
|
|
|
// well.
|
2017-06-08 20:55:41 +03:00
|
|
|
switch f := failure.(type) {
|
|
|
|
case Serializable:
|
2017-08-22 08:38:48 +03:00
|
|
|
if err := f.Decode(dataReader, pver); err != nil {
|
2017-09-12 18:55:20 +03:00
|
|
|
return nil, fmt.Errorf("unable to decode error "+
|
|
|
|
"update: %v", err)
|
2017-06-08 20:55:41 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return failure, nil
|
|
|
|
}
|
|
|
|
|
2017-07-15 06:08:29 +03:00
|
|
|
// EncodeFailure encodes, including the necessary onion failure header
|
|
|
|
// information.
|
2017-06-08 20:55:41 +03:00
|
|
|
func EncodeFailure(w io.Writer, failure FailureMessage, pver uint32) error {
|
|
|
|
var failureMessageBuffer bytes.Buffer
|
|
|
|
|
2017-08-22 08:38:48 +03:00
|
|
|
// First, we'll write out the error code itself into the failure
|
|
|
|
// buffer.
|
|
|
|
var codeBytes [2]byte
|
|
|
|
code := uint16(failure.Code())
|
|
|
|
binary.BigEndian.PutUint16(codeBytes[:], code)
|
|
|
|
_, err := failureMessageBuffer.Write(codeBytes[:])
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Next, some message have an additional message payload, if this is
|
|
|
|
// one of those types, then we'll also encode the error payload as
|
|
|
|
// well.
|
2017-06-08 20:55:41 +03:00
|
|
|
switch failure := failure.(type) {
|
|
|
|
case Serializable:
|
|
|
|
if err := failure.Encode(&failureMessageBuffer, pver); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-22 08:38:48 +03:00
|
|
|
// The combined size of this message must be below the max allowed
|
|
|
|
// failure message length.
|
2017-06-08 20:55:41 +03:00
|
|
|
failureMessage := failureMessageBuffer.Bytes()
|
|
|
|
if len(failureMessage) > failureMessageLength {
|
2017-08-22 11:00:07 +03:00
|
|
|
return fmt.Errorf("failure message exceed max "+
|
|
|
|
"available size: %v", len(failureMessage))
|
2017-06-08 20:55:41 +03:00
|
|
|
}
|
|
|
|
|
2017-08-22 08:38:48 +03:00
|
|
|
// Finally, we'll add some padding in order to ensure that all failure
|
|
|
|
// messages are fixed size.
|
2017-06-08 20:55:41 +03:00
|
|
|
pad := make([]byte, failureMessageLength-len(failureMessage))
|
|
|
|
|
|
|
|
return writeElements(w,
|
|
|
|
uint16(len(failureMessage)),
|
|
|
|
failureMessage,
|
|
|
|
uint16(len(pad)),
|
|
|
|
pad,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// makeEmptyOnionError creates a new empty onion error of the proper concrete
|
|
|
|
// type based on the passed failure code.
|
|
|
|
func makeEmptyOnionError(code FailCode) (FailureMessage, error) {
|
|
|
|
switch code {
|
|
|
|
case CodeInvalidRealm:
|
|
|
|
return &FailInvalidRealm{}, nil
|
|
|
|
|
|
|
|
case CodeTemporaryNodeFailure:
|
|
|
|
return &FailTemporaryNodeFailure{}, nil
|
|
|
|
|
|
|
|
case CodePermanentNodeFailure:
|
|
|
|
return &FailPermanentNodeFailure{}, nil
|
|
|
|
|
|
|
|
case CodeRequiredNodeFeatureMissing:
|
|
|
|
return &FailRequiredNodeFeatureMissing{}, nil
|
|
|
|
|
|
|
|
case CodePermanentChannelFailure:
|
|
|
|
return &FailPermanentChannelFailure{}, nil
|
|
|
|
|
|
|
|
case CodeRequiredChannelFeatureMissing:
|
|
|
|
return &FailRequiredChannelFeatureMissing{}, nil
|
|
|
|
|
|
|
|
case CodeUnknownNextPeer:
|
|
|
|
return &FailUnknownNextPeer{}, nil
|
|
|
|
|
|
|
|
case CodeUnknownPaymentHash:
|
|
|
|
return &FailUnknownPaymentHash{}, nil
|
|
|
|
|
|
|
|
case CodeIncorrectPaymentAmount:
|
|
|
|
return &FailIncorrectPaymentAmount{}, nil
|
|
|
|
|
|
|
|
case CodeFinalExpiryTooSoon:
|
|
|
|
return &FailFinalExpiryTooSoon{}, nil
|
|
|
|
|
|
|
|
case CodeInvalidOnionVersion:
|
|
|
|
return &FailInvalidOnionVersion{}, nil
|
|
|
|
|
|
|
|
case CodeInvalidOnionHmac:
|
|
|
|
return &FailInvalidOnionHmac{}, nil
|
|
|
|
|
|
|
|
case CodeInvalidOnionKey:
|
|
|
|
return &FailInvalidOnionKey{}, nil
|
|
|
|
|
|
|
|
case CodeTemporaryChannelFailure:
|
|
|
|
return &FailTemporaryChannelFailure{}, nil
|
|
|
|
|
|
|
|
case CodeAmountBelowMinimum:
|
|
|
|
return &FailAmountBelowMinimum{}, nil
|
|
|
|
|
|
|
|
case CodeFeeInsufficient:
|
|
|
|
return &FailFeeInsufficient{}, nil
|
|
|
|
|
|
|
|
case CodeIncorrectCltvExpiry:
|
|
|
|
return &FailIncorrectCltvExpiry{}, nil
|
|
|
|
|
|
|
|
case CodeExpiryTooSoon:
|
|
|
|
return &FailExpiryTooSoon{}, nil
|
|
|
|
|
|
|
|
case CodeChannelDisabled:
|
|
|
|
return &FailChannelDisabled{}, nil
|
|
|
|
|
|
|
|
case CodeFinalIncorrectCltvExpiry:
|
|
|
|
return &FailFinalIncorrectCltvExpiry{}, nil
|
|
|
|
|
|
|
|
case CodeFinalIncorrectHtlcAmount:
|
|
|
|
return &FailFinalIncorrectHtlcAmount{}, nil
|
|
|
|
default:
|
|
|
|
return nil, errors.Errorf("unknown error code: %v", code)
|
|
|
|
}
|
|
|
|
}
|