diff --git a/lnwire/onion_error.go b/lnwire/onion_error.go index adf12781a..af2db1d23 100644 --- a/lnwire/onion_error.go +++ b/lnwire/onion_error.go @@ -81,6 +81,7 @@ const ( CodeExpiryTooFar FailCode = 21 CodeInvalidOnionPayload = FlagPerm | 22 CodeMPPTimeout FailCode = 23 + CodeInvalidBlinding = FlagBadOnion | FlagPerm | 24 //nolint:lll ) // String returns the string representation of the failure code. @@ -158,6 +159,9 @@ func (c FailCode) String() string { case CodeMPPTimeout: return "MPPTimeout" + case CodeInvalidBlinding: + return "InvalidBlinding" + default: return "" } @@ -1233,6 +1237,51 @@ func (f *FailMPPTimeout) Error() string { return f.Code().String() } +// FailInvalidBlinding is returned if there has been a route blinding related +// error. +type FailInvalidBlinding struct { + OnionSHA256 [sha256.Size]byte +} + +// Code returns the failure unique code. +// +// NOTE: Part of the FailureMessage interface. +func (f *FailInvalidBlinding) Code() FailCode { + return CodeInvalidBlinding +} + +// Returns a human readable string describing the target FailureMessage. +// +// NOTE: Implements the error interface. +func (f *FailInvalidBlinding) Error() string { + return f.Code().String() +} + +// Decode decodes the failure from bytes stream. +// +// NOTE: Part of the Serializable interface. +func (f *FailInvalidBlinding) Decode(r io.Reader, _ uint32) error { + return ReadElement(r, f.OnionSHA256[:]) +} + +// Encode writes the failure in bytes stream. +// +// NOTE: Part of the Serializable interface. +func (f *FailInvalidBlinding) Encode(w *bytes.Buffer, _ uint32) error { + return WriteBytes(w, f.OnionSHA256[:]) +} + +// NewInvalidBlinding creates new instance of FailInvalidBlinding. +func NewInvalidBlinding(onion []byte) *FailInvalidBlinding { + // The spec allows empty onion hashes for invalid blinding, so we only + // include our onion hash if it's provided. + if onion == nil { + return &FailInvalidBlinding{} + } + + return &FailInvalidBlinding{OnionSHA256: sha256.Sum256(onion)} +} + // DecodeFailure decodes, validates, and parses the lnwire onion failure, for // the provided protocol version. func DecodeFailure(r io.Reader, pver uint32) (FailureMessage, error) { @@ -1451,6 +1500,9 @@ func makeEmptyOnionError(code FailCode) (FailureMessage, error) { case CodeMPPTimeout: return &FailMPPTimeout{}, nil + case CodeInvalidBlinding: + return &FailInvalidBlinding{}, nil + default: return nil, errors.Errorf("unknown error code: %v", code) } diff --git a/lnwire/onion_error_test.go b/lnwire/onion_error_test.go index 438306b66..a06c572dc 100644 --- a/lnwire/onion_error_test.go +++ b/lnwire/onion_error_test.go @@ -56,6 +56,7 @@ var onionFailures = []FailureMessage{ NewFinalIncorrectCltvExpiry(testCtlvExpiry), NewFinalIncorrectHtlcAmount(testAmount), NewInvalidOnionPayload(testType, testOffset), + NewInvalidBlinding(testOnionHash), } // TestEncodeDecodeCode tests the ability of onion errors to be properly encoded