lnwire: convert ErrorGeneric to Error
With this change we move one step closer to matching the wire protocol currently defined within the spec.
This commit is contained in:
parent
c06894a2e6
commit
d17b11862b
123
lnwire/error.go
Normal file
123
lnwire/error.go
Normal file
@ -0,0 +1,123 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
)
|
||||
|
||||
// ErrorCode represents the short error code for each of the defined errors
|
||||
// within the Lightning Network protocol spec.
|
||||
type ErrorCode uint16
|
||||
|
||||
// ToGrpcCode is used to generate gRPC specific code which will be propagated
|
||||
// to the ln rpc client. This code is used to have more detailed view of what
|
||||
// goes wrong and also in order to have the ability pragmatically determine
|
||||
// the error and take specific actions on the client side.
|
||||
func (e ErrorCode) ToGrpcCode() codes.Code {
|
||||
return (codes.Code)(e) + 100
|
||||
}
|
||||
|
||||
const (
|
||||
// ErrMaxPendingChannels is returned by remote peer when the number of
|
||||
// active pending channels exceeds their maximum policy limit.
|
||||
ErrMaxPendingChannels ErrorCode = 1
|
||||
|
||||
// ErrSynchronizingChain is returned by a remote peer that receives a
|
||||
// channel update or a funding request while their still syncing to the
|
||||
// latest state of the blockchain.
|
||||
ErrSynchronizingChain ErrorCode = 2
|
||||
)
|
||||
|
||||
// ErrorData is a set of bytes associated with a particular sent error. A
|
||||
// receiving node SHOULD only print out data verbatim if the string is composed
|
||||
// solely of printable ASCII characters. For reference, the printable character
|
||||
// set includes byte values 32 through 127 inclusive.
|
||||
type ErrorData []byte
|
||||
|
||||
// Error represents a generic error bound to an exact channel. The message
|
||||
// format is purposefully general in order to allow expression of a wide array
|
||||
// of possible errors. Each Error message is directed at a particular open
|
||||
// channel referenced by ChannelPoint.
|
||||
type Error struct {
|
||||
// ChanID references the active channel in which the error occurred
|
||||
// within. If the ChanID is all zeroes, then this error applies to the
|
||||
// entire established connection.
|
||||
ChanID ChannelID
|
||||
|
||||
// Code is the short error code that succinctly identifies the error
|
||||
// code. This is similar field is similar to HTTP error codes.
|
||||
//
|
||||
// TODO(roasbeef): make PR to repo to add error codes, in addition to
|
||||
// what's there atm
|
||||
Code ErrorCode
|
||||
|
||||
// Data is the attached error data that describes the exact failure
|
||||
// which caused the error message to be sent.
|
||||
Data ErrorData
|
||||
}
|
||||
|
||||
// NewError creates a new Error message.
|
||||
func NewError() *Error {
|
||||
return &Error{}
|
||||
}
|
||||
|
||||
// A compile time check to ensure Error implements the lnwire.Message
|
||||
// interface.
|
||||
var _ Message = (*Error)(nil)
|
||||
|
||||
// Decode deserializes a serialized Error message stored in the passed
|
||||
// io.Reader observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *Error) Decode(r io.Reader, pver uint32) error {
|
||||
return readElements(r,
|
||||
&c.ChanID,
|
||||
&c.Code,
|
||||
&c.Data,
|
||||
)
|
||||
}
|
||||
|
||||
// Encode serializes the target Error into the passed io.Writer observing the
|
||||
// protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *Error) Encode(w io.Writer, pver uint32) error {
|
||||
return writeElements(w,
|
||||
c.ChanID,
|
||||
c.Code,
|
||||
c.Data,
|
||||
)
|
||||
}
|
||||
|
||||
// Command returns the integer uniquely identifying an Error message on the
|
||||
// wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *Error) Command() uint32 {
|
||||
return CmdError
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for a Error
|
||||
// complete message observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *Error) MaxPayloadLength(uint32) uint32 {
|
||||
// 32 + 2 + 655326
|
||||
return 65536
|
||||
}
|
||||
|
||||
// Validate performs any necessary sanity checks to ensure all fields present
|
||||
// on the Error are valid.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *Error) Validate() error {
|
||||
if len(c.Data) > math.MaxUint16 {
|
||||
return fmt.Errorf("problem string length too long")
|
||||
}
|
||||
|
||||
// We're good!
|
||||
return nil
|
||||
}
|
@ -1,125 +0,0 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/roasbeef/btcd/wire"
|
||||
"google.golang.org/grpc/codes"
|
||||
)
|
||||
|
||||
// ErrorCode represents the short error code for each of the defined errors
|
||||
// within the Lightning Network protocol spec.
|
||||
type ErrorCode uint16
|
||||
|
||||
// ToGrpcCode is used to generate gRPC specific code which will be propagated
|
||||
// to the ln rpc client. This code is used to have more detailed view of what
|
||||
// goes wrong and also in order to have the ability pragmatically determine
|
||||
// the error and take specific actions on the client side.
|
||||
func (e ErrorCode) ToGrpcCode() codes.Code {
|
||||
return (codes.Code)(e) + 100
|
||||
}
|
||||
|
||||
const (
|
||||
// ErrMaxPendingChannels is returned by remote peer when the number of
|
||||
// active pending channels exceeds their maximum policy limit.
|
||||
ErrMaxPendingChannels ErrorCode = 1
|
||||
|
||||
// ErrSynchronizingChain is returned by a remote peer that receives a
|
||||
// channel update or a funding request while their still syncing to the
|
||||
// latest state of the blockchain.
|
||||
ErrSynchronizingChain ErrorCode = 2
|
||||
)
|
||||
|
||||
// ErrorGeneric represents a generic error bound to an exact channel. The
|
||||
// message format is purposefully general in order to allow expression of a wide
|
||||
// array of possible errors. Each ErrorGeneric message is directed at a particular
|
||||
// open channel referenced by ChannelPoint.
|
||||
type ErrorGeneric struct {
|
||||
// ChannelPoint references the active channel in which the error
|
||||
// occurred within. A ChannelPoint of zeroHash:0 denotes this error
|
||||
// applies to the entire established connection.
|
||||
ChannelPoint wire.OutPoint
|
||||
|
||||
// PendingChannelID allows peers communicate errors in the context of a
|
||||
// particular pending channel. With this field, once a peer reads an
|
||||
// ErrorGeneric message with the PendingChannelID field set, then they
|
||||
// can forward the error to the fundingManager who can handle it
|
||||
// properly.
|
||||
PendingChannelID uint64
|
||||
|
||||
// Code is the short error ID which describes the nature of the error.
|
||||
Code ErrorCode
|
||||
|
||||
// Problem is a human-readable string further elaborating upon the
|
||||
// nature of the exact error. The maximum allowed length of this
|
||||
// message is 8192 bytes.
|
||||
Problem string
|
||||
}
|
||||
|
||||
// NewErrorGeneric creates a new ErrorGeneric message.
|
||||
func NewErrorGeneric() *ErrorGeneric {
|
||||
return &ErrorGeneric{}
|
||||
}
|
||||
|
||||
// A compile time check to ensure ErrorGeneric implements the lnwire.Message
|
||||
// interface.
|
||||
var _ Message = (*ErrorGeneric)(nil)
|
||||
|
||||
// Decode deserializes a serialized ErrorGeneric message stored in the
|
||||
// passed io.Reader observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *ErrorGeneric) Decode(r io.Reader, pver uint32) error {
|
||||
// ChannelPoint(8)
|
||||
// Problem
|
||||
return readElements(r,
|
||||
&c.ChannelPoint,
|
||||
&c.Code,
|
||||
&c.Problem,
|
||||
&c.PendingChannelID,
|
||||
)
|
||||
}
|
||||
|
||||
// Encode serializes the target ErrorGeneric into the passed io.Writer
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *ErrorGeneric) Encode(w io.Writer, pver uint32) error {
|
||||
return writeElements(w,
|
||||
c.ChannelPoint,
|
||||
c.Code,
|
||||
c.Problem,
|
||||
c.PendingChannelID,
|
||||
)
|
||||
}
|
||||
|
||||
// Command returns the integer uniquely identifying an ErrorGeneric message on
|
||||
// the wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *ErrorGeneric) Command() uint32 {
|
||||
return CmdErrorGeneric
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for a
|
||||
// ErrorGeneric complete message observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *ErrorGeneric) MaxPayloadLength(uint32) uint32 {
|
||||
// 8+8192
|
||||
return 8208
|
||||
}
|
||||
|
||||
// Validate performs any necessary sanity checks to ensure all fields present
|
||||
// on the ErrorGeneric are valid.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *ErrorGeneric) Validate() error {
|
||||
if len(c.Problem) > 8192 {
|
||||
return fmt.Errorf("problem string length too long")
|
||||
}
|
||||
|
||||
// We're good!
|
||||
return nil
|
||||
}
|
@ -6,22 +6,21 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestErrorGenericEncodeDecode(t *testing.T) {
|
||||
eg := &ErrorGeneric{
|
||||
ChannelPoint: *outpoint1,
|
||||
PendingChannelID: 1,
|
||||
Code: 99,
|
||||
Problem: "Hello world!",
|
||||
func TestErrorEncodeDecode(t *testing.T) {
|
||||
eg := &Error{
|
||||
ChanID: ChannelID(revHash),
|
||||
Code: 99,
|
||||
Data: []byte{'k', 'e', 'k'},
|
||||
}
|
||||
|
||||
// Next encode the EG message into an empty bytes buffer.
|
||||
// Next encode the error message into an empty bytes buffer.
|
||||
var b bytes.Buffer
|
||||
if err := eg.Encode(&b, 0); err != nil {
|
||||
t.Fatalf("unable to encode ErrorGeneric: %v", err)
|
||||
}
|
||||
|
||||
// Deserialize the encoded EG message into a new empty struct.
|
||||
eg2 := &ErrorGeneric{}
|
||||
// Deserialize the encoded error message into a new empty struct.
|
||||
eg2 := &Error{}
|
||||
if err := eg2.Decode(&b, 0); err != nil {
|
||||
t.Fatalf("unable to decode ErrorGeneric: %v", err)
|
||||
}
|
@ -174,6 +174,16 @@ func writeElement(w io.Writer, element interface{}) error {
|
||||
if _, err := w.Write(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case ErrorData:
|
||||
var l [2]byte
|
||||
binary.BigEndian.PutUint16(l[:], uint16(len(e)))
|
||||
if _, err := w.Write(l[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := w.Write(e[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case OpaqueReason:
|
||||
var l [2]byte
|
||||
binary.BigEndian.PutUint16(l[:], uint16(len(e)))
|
||||
@ -514,6 +524,17 @@ func readElement(r io.Reader, element interface{}) error {
|
||||
if _, err := io.ReadFull(r, *e); err != nil {
|
||||
return err
|
||||
}
|
||||
case *ErrorData:
|
||||
var l [2]byte
|
||||
if _, err := io.ReadFull(r, l[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
errorLen := binary.BigEndian.Uint16(l[:])
|
||||
|
||||
*e = ErrorData(make([]byte, errorLen))
|
||||
if _, err := io.ReadFull(r, *e); err != nil {
|
||||
return err
|
||||
}
|
||||
case *[6]byte:
|
||||
if _, err := io.ReadFull(r, e[:]); err != nil {
|
||||
return err
|
||||
|
@ -49,7 +49,7 @@ const (
|
||||
CmdRevokeAndAck = uint32(2010)
|
||||
|
||||
// Commands for reporting protocol errors.
|
||||
CmdErrorGeneric = uint32(4000)
|
||||
CmdError = uint32(4000)
|
||||
|
||||
// Commands for discovery service.
|
||||
CmdChannelAnnouncement = uint32(5000)
|
||||
@ -119,8 +119,8 @@ func makeEmptyMessage(command uint32) (Message, error) {
|
||||
msg = &CommitSig{}
|
||||
case CmdRevokeAndAck:
|
||||
msg = &RevokeAndAck{}
|
||||
case CmdErrorGeneric:
|
||||
msg = &ErrorGeneric{}
|
||||
case CmdError:
|
||||
msg = &Error{}
|
||||
case CmdChannelAnnouncement:
|
||||
msg = &ChannelAnnouncement{}
|
||||
case CmdChannelUpdateAnnouncement:
|
||||
|
Loading…
Reference in New Issue
Block a user