fix vendor folder

This commit is contained in:
Juan Pablo Civile
2019-12-16 17:59:11 -03:00
parent 240b7f00bd
commit a60e97ace6
72 changed files with 1551 additions and 6487 deletions

View File

@@ -1,6 +1,8 @@
package lnwire
import "io"
import (
"io"
)
// CommitSig is sent by either side to stage any pending HTLC's in the
// receiver's pending set into a new commitment state. Implicitly, the new
@@ -83,3 +85,11 @@ func (c *CommitSig) MaxPayloadLength(uint32) uint32 {
// 32 + 64 + 2 + max_allowed_htlcs
return MaxMessagePayload
}
// TargetChanID returns the channel id of the link for which this message is
// intended.
//
// NOTE: Part of lnd.LinkUpdater interface.
func (c *CommitSig) TargetChanID() ChannelID {
return c.ChanID
}

View File

@@ -1,41 +1,32 @@
package lnwire
import (
"fmt"
"io"
"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 uint8
// 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
}
// FundingError represents a set of errors that can be encountered and sent
// during the funding workflow.
type FundingError uint8
const (
// ErrMaxPendingChannels is returned by remote peer when the number of
// active pending channels exceeds their maximum policy limit.
ErrMaxPendingChannels ErrorCode = 1
ErrMaxPendingChannels FundingError = 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
ErrSynchronizingChain FundingError = 2
// ErrChanTooLarge is returned by a remote peer that receives a
// FundingOpen request for a channel that is above their current
// soft-limit.
ErrChanTooLarge ErrorCode = 3
ErrChanTooLarge FundingError = 3
)
// String returns a human readable version of the target ErrorCode.
func (e ErrorCode) String() string {
// String returns a human readable version of the target FundingError.
func (e FundingError) String() string {
switch e {
case ErrMaxPendingChannels:
return "Number of pending channels exceed maximum"
@@ -48,10 +39,10 @@ func (e ErrorCode) String() string {
}
}
// Error returns the human redable version of the target ErrorCode.
// Error returns the human redable version of the target FundingError.
//
// Satisfies the Error interface.
func (e ErrorCode) Error() string {
// NOTE: Satisfies the Error interface.
func (e FundingError) Error() string {
return e.String()
}
@@ -65,8 +56,6 @@ type ErrorData []byte
// 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.
//
// TODO(roasbeef): remove the error code
type Error struct {
// ChanID references the active channel in which the error occurred
// within. If the ChanID is all zeros, then this error applies to the
@@ -87,6 +76,18 @@ func NewError() *Error {
// interface.
var _ Message = (*Error)(nil)
// Error returns the string representation to Error.
//
// NOTE: Satisfies the error interface.
func (c *Error) Error() string {
errMsg := "non-ascii data"
if isASCII(c.Data) {
errMsg = string(c.Data)
}
return fmt.Sprintf("chan_id=%v, err=%v", c.ChanID, errMsg)
}
// Decode deserializes a serialized Error message stored in the passed
// io.Reader observing the specified protocol version.
//
@@ -125,3 +126,14 @@ func (c *Error) MaxPayloadLength(uint32) uint32 {
// 32 + 2 + 65501
return 65535
}
// isASCII is a helper method that checks whether all bytes in `data` would be
// printable ASCII characters if interpreted as a string.
func isASCII(data []byte) bool {
for _, c := range data {
if c < 32 || c > 126 {
return false
}
}
return true
}

View File

@@ -46,6 +46,25 @@ const (
// efficient network view reconciliation.
GossipQueriesOptional FeatureBit = 7
// TLVOnionPayloadRequired is a feature bit that indicates a node is
// able to decode the new TLV information included in the onion packet.
TLVOnionPayloadRequired FeatureBit = 8
// TLVOnionPayloadRequired is an optional feature bit that indicates a
// node is able to decode the new TLV information included in the onion
// packet.
TLVOnionPayloadOptional FeatureBit = 9
// StaticRemoteKeyRequired is a required feature bit that signals that
// within one's commitment transaction, the key used for the remote
// party's non-delay output should not be tweaked.
StaticRemoteKeyRequired FeatureBit = 12
// StaticRemoteKeyOptional is an optional feature bit that signals that
// within one's commitment transaction, the key used for the remote
// party's non-delay output should not be tweaked.
StaticRemoteKeyOptional FeatureBit = 13
// maxAllowedSize is a maximum allowed size of feature vector.
//
// NOTE: Within the protocol, the maximum allowed message size is 65535
@@ -76,7 +95,12 @@ var LocalFeatures = map[FeatureBit]string{
// name. All known global feature bits must be assigned a name in this mapping.
// Global features are those which are advertised to the entire network. A full
// description of these feature bits is provided in the BOLT-09 specification.
var GlobalFeatures map[FeatureBit]string
var GlobalFeatures = map[FeatureBit]string{
TLVOnionPayloadRequired: "tlv-onion",
TLVOnionPayloadOptional: "tlv-onion",
StaticRemoteKeyOptional: "static-remote-key",
StaticRemoteKeyRequired: "static-remote-key",
}
// RawFeatureVector represents a set of feature bits as defined in BOLT-09. A
// RawFeatureVector itself just stores a set of bit flags but can be used to
@@ -115,6 +139,20 @@ func (fv *RawFeatureVector) Unset(feature FeatureBit) {
// SerializeSize returns the number of bytes needed to represent feature vector
// in byte format.
func (fv *RawFeatureVector) SerializeSize() int {
// We calculate byte-length via the largest bit index.
return fv.serializeSize(8)
}
// SerializeSize32 returns the number of bytes needed to represent feature
// vector in base32 format.
func (fv *RawFeatureVector) SerializeSize32() int {
// We calculate base32-length via the largest bit index.
return fv.serializeSize(5)
}
// serializeSize returns the number of bytes required to encode the feature
// vector using at most width bits per encoded byte.
func (fv *RawFeatureVector) serializeSize(width int) int {
// Find the largest feature bit index
max := -1
for feature := range fv.features {
@@ -127,8 +165,7 @@ func (fv *RawFeatureVector) SerializeSize() int {
return 0
}
// We calculate byte-length via the largest bit index
return max/8 + 1
return max/width + 1
}
// Encode writes the feature vector in byte representation. Every feature
@@ -144,12 +181,25 @@ func (fv *RawFeatureVector) Encode(w io.Writer) error {
return err
}
return fv.encode(w, length, 8)
}
// EncodeBase32 writes the feature vector in base32 representation. Every feature
// encoded as a bit, and the bit vector is serialized using the least number of
// bytes.
func (fv *RawFeatureVector) EncodeBase32(w io.Writer) error {
length := fv.SerializeSize32()
return fv.encode(w, length, 5)
}
// encode writes the feature vector
func (fv *RawFeatureVector) encode(w io.Writer, length, width int) error {
// Generate the data and write it.
data := make([]byte, length)
for feature := range fv.features {
byteIndex := int(feature / 8)
bitIndex := feature % 8
data[length-byteIndex-1] |= 1 << bitIndex
byteIndex := int(feature) / width
bitIndex := int(feature) % width
data[length-byteIndex-1] |= 1 << uint(bitIndex)
}
_, err := w.Write(data)
@@ -168,6 +218,19 @@ func (fv *RawFeatureVector) Decode(r io.Reader) error {
}
length := binary.BigEndian.Uint16(l[:])
return fv.decode(r, int(length), 8)
}
// DecodeBase32 reads the feature vector from its base32 representation. Every
// feature encoded as a bit, and the bit vector is serialized using the least
// number of bytes.
func (fv *RawFeatureVector) DecodeBase32(r io.Reader, length int) error {
return fv.decode(r, length, 5)
}
// decode reads a feature vector from the next length bytes of the io.Reader,
// assuming each byte has width feature bits encoded per byte.
func (fv *RawFeatureVector) decode(r io.Reader, length, width int) error {
// Read the feature vector data.
data := make([]byte, length)
if _, err := io.ReadFull(r, data); err != nil {
@@ -175,10 +238,10 @@ func (fv *RawFeatureVector) Decode(r io.Reader) error {
}
// Set feature bits from parsed data.
bitsNumber := len(data) * 8
bitsNumber := len(data) * width
for i := 0; i < bitsNumber; i++ {
byteIndex := uint16(i / 8)
bitIndex := uint(i % 8)
byteIndex := int(i / width)
bitIndex := uint(i % width)
if (data[length-byteIndex-1]>>bitIndex)&1 == 1 {
fv.Set(FeatureBit(i))
}

View File

@@ -117,12 +117,6 @@ func WriteElement(w io.Writer, element interface{}) error {
if _, err := w.Write(b[:]); err != nil {
return err
}
case ErrorCode:
var b [2]byte
binary.BigEndian.PutUint16(b[:], uint16(e))
if _, err := w.Write(b[:]); err != nil {
return err
}
case MilliSatoshi:
var b [8]byte
binary.BigEndian.PutUint64(b[:], uint64(e))
@@ -506,12 +500,6 @@ func ReadElement(r io.Reader, element interface{}) error {
return err
}
*e = ChanUpdateChanFlags(b[0])
case *ErrorCode:
var b [2]byte
if _, err := io.ReadFull(r, b[:]); err != nil {
return err
}
*e = ErrorCode(binary.BigEndian.Uint16(b[:]))
case *uint32:
var b [4]byte
if _, err := io.ReadFull(r, b[:]); err != nil {

View File

@@ -10,11 +10,6 @@ import (
"unicode/utf8"
)
var (
startPort uint16 = 1024
endPort uint16 = 49151
)
// ErrUnknownAddrType is an error returned if we encounter an unknown address type
// when parsing addresses.
type ErrUnknownAddrType struct {

View File

@@ -46,7 +46,7 @@ const (
FlagUpdate FailCode = 0x1000
)
// FailCode specifies the precise reason that an upstream HTLC was cancelled.
// FailCode specifies the precise reason that an upstream HTLC was canceled.
// 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.
@@ -55,29 +55,29 @@ 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
CodeExpiryTooFar FailCode = 21
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
CodeIncorrectOrUnknownPaymentDetails = FlagPerm | 15
CodeIncorrectPaymentAmount = FlagPerm | 16
CodeFinalExpiryTooSoon FailCode = 17
CodeFinalIncorrectCltvExpiry FailCode = 18
CodeFinalIncorrectHtlcAmount FailCode = 19
CodeExpiryTooFar FailCode = 21
)
// String returns the string representation of the failure code.
@@ -134,8 +134,8 @@ func (c FailCode) String() string {
case CodeChannelDisabled:
return "ChannelDisabled"
case CodeUnknownPaymentHash:
return "UnknownPaymentHash"
case CodeIncorrectOrUnknownPaymentDetails:
return "IncorrectOrUnknownPaymentDetails"
case CodeFinalExpiryTooSoon:
return "FinalExpiryTooSoon"
@@ -317,7 +317,7 @@ func (f *FailIncorrectPaymentAmount) Error() string {
return f.Code().String()
}
// FailUnknownPaymentHash is returned for two reasons:
// FailIncorrectDetails is returned for two reasons:
//
// 1) 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
@@ -330,42 +330,56 @@ func (f *FailIncorrectPaymentAmount) Error() string {
// gross overpayment.
//
// NOTE: May only be returned by the final node in the path.
type FailUnknownPaymentHash struct {
type FailIncorrectDetails struct {
// amount is the value of the extended HTLC.
amount MilliSatoshi
// height is the block height when the htlc was received.
height uint32
}
// NewFailUnknownPaymentHash makes a new instance of the FailUnknownPaymentHash
// error bound to the specified HTLC amount.
func NewFailUnknownPaymentHash(amt MilliSatoshi) *FailUnknownPaymentHash {
return &FailUnknownPaymentHash{
// NewFailIncorrectDetails makes a new instance of the FailIncorrectDetails
// error bound to the specified HTLC amount and acceptance height.
func NewFailIncorrectDetails(amt MilliSatoshi,
height uint32) *FailIncorrectDetails {
return &FailIncorrectDetails{
amount: amt,
height: height,
}
}
// Amount is the value of the extended HTLC.
func (f *FailUnknownPaymentHash) Amount() MilliSatoshi {
func (f *FailIncorrectDetails) Amount() MilliSatoshi {
return f.amount
}
// Height is the block height when the htlc was received.
func (f *FailIncorrectDetails) Height() uint32 {
return f.height
}
// Code returns the failure unique code.
//
// NOTE: Part of the FailureMessage interface.
func (f *FailUnknownPaymentHash) Code() FailCode {
return CodeUnknownPaymentHash
func (f *FailIncorrectDetails) Code() FailCode {
return CodeIncorrectOrUnknownPaymentDetails
}
// Returns a human readable string describing the target FailureMessage.
//
// NOTE: Implements the error interface.
func (f *FailUnknownPaymentHash) Error() string {
return fmt.Sprintf("UnknownPaymentHash(amt=%v)", f.amount)
func (f *FailIncorrectDetails) Error() string {
return fmt.Sprintf(
"%v(amt=%v, height=%v)", CodeIncorrectOrUnknownPaymentDetails,
f.amount, f.height,
)
}
// Decode decodes the failure from bytes stream.
//
// NOTE: Part of the Serializable interface.
func (f *FailUnknownPaymentHash) Decode(r io.Reader, pver uint32) error {
func (f *FailIncorrectDetails) Decode(r io.Reader, pver uint32) error {
err := ReadElement(r, &f.amount)
switch {
// This is an optional tack on that was added later in the protocol. As
@@ -379,14 +393,25 @@ func (f *FailUnknownPaymentHash) Decode(r io.Reader, pver uint32) error {
return err
}
// At a later stage, the height field was also tacked on. We need to
// check for io.EOF here as well.
err = ReadElement(r, &f.height)
switch {
case err == io.EOF:
return nil
case err != nil:
return err
}
return nil
}
// Encode writes the failure in bytes stream.
//
// NOTE: Part of the Serializable interface.
func (f *FailUnknownPaymentHash) Encode(w io.Writer, pver uint32) error {
return WriteElement(w, f.amount)
func (f *FailIncorrectDetails) Encode(w io.Writer, pver uint32) error {
return WriteElements(w, f.amount, f.height)
}
// FailFinalExpiryTooSoon is returned if the cltv_expiry is too low, the final
@@ -1113,10 +1138,16 @@ func DecodeFailure(r io.Reader, pver uint32) (FailureMessage, error) {
dataReader := bytes.NewReader(failureData)
return DecodeFailureMessage(dataReader, pver)
}
// DecodeFailureMessage decodes just the failure message, ignoring any padding
// that may be present at the end.
func DecodeFailureMessage(r io.Reader, pver uint32) (FailureMessage, error) {
// 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 {
if _, err := io.ReadFull(r, codeBytes[:]); err != nil {
return nil, fmt.Errorf("unable to read failure code: %v", err)
}
failCode := FailCode(binary.BigEndian.Uint16(codeBytes[:]))
@@ -1132,10 +1163,9 @@ func DecodeFailure(r io.Reader, pver uint32) (FailureMessage, error) {
// well.
switch f := failure.(type) {
case Serializable:
if err := f.Decode(dataReader, pver); err != nil {
if err := f.Decode(r, pver); err != nil {
return nil, fmt.Errorf("unable to decode error "+
"update (type=%T, len_bytes=%v, bytes=%x): %v",
failure, failureLength, failureData[:], err)
"update (type=%T): %v", failure, err)
}
}
@@ -1147,26 +1177,11 @@ func DecodeFailure(r io.Reader, pver uint32) (FailureMessage, error) {
func EncodeFailure(w io.Writer, failure FailureMessage, pver uint32) error {
var failureMessageBuffer bytes.Buffer
// 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[:])
err := EncodeFailureMessage(&failureMessageBuffer, failure, pver)
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.
switch failure := failure.(type) {
case Serializable:
if err := failure.Encode(&failureMessageBuffer, pver); err != nil {
return err
}
}
// The combined size of this message must be below the max allowed
// failure message length.
failureMessage := failureMessageBuffer.Bytes()
@@ -1187,6 +1202,32 @@ func EncodeFailure(w io.Writer, failure FailureMessage, pver uint32) error {
)
}
// EncodeFailureMessage encodes just the failure message without adding a length
// and padding the message for the onion protocol.
func EncodeFailureMessage(w io.Writer, failure FailureMessage, pver uint32) error {
// 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 := w.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.
switch failure := failure.(type) {
case Serializable:
if err := failure.Encode(w, pver); err != nil {
return err
}
}
return nil
}
// makeEmptyOnionError creates a new empty onion error of the proper concrete
// type based on the passed failure code.
func makeEmptyOnionError(code FailCode) (FailureMessage, error) {
@@ -1212,8 +1253,8 @@ func makeEmptyOnionError(code FailCode) (FailureMessage, error) {
case CodeUnknownNextPeer:
return &FailUnknownNextPeer{}, nil
case CodeUnknownPaymentHash:
return &FailUnknownPaymentHash{}, nil
case CodeIncorrectOrUnknownPaymentDetails:
return &FailIncorrectDetails{}, nil
case CodeIncorrectPaymentAmount:
return &FailIncorrectPaymentAmount{}, nil

View File

@@ -81,3 +81,11 @@ func (c *RevokeAndAck) MaxPayloadLength(uint32) uint32 {
// 32 + 32 + 33
return 97
}
// TargetChanID returns the channel id of the link for which this message is
// intended.
//
// NOTE: Part of lnd.LinkUpdater interface.
func (c *RevokeAndAck) TargetChanID() ChannelID {
return c.ChanID
}

View File

@@ -1,6 +1,8 @@
package lnwire
import "io"
import (
"io"
)
// OnionPacketSize is the size of the serialized Sphinx onion packet included
// in each UpdateAddHTLC message. The breakdown of the onion packet is as
@@ -107,3 +109,11 @@ func (c *UpdateAddHTLC) MaxPayloadLength(uint32) uint32 {
// 1450
return 32 + 8 + 4 + 8 + 32 + 1366
}
// TargetChanID returns the channel id of the link for which this message is
// intended.
//
// NOTE: Part of lnd.LinkUpdater interface.
func (c *UpdateAddHTLC) TargetChanID() ChannelID {
return c.ChanID
}

View File

@@ -1,6 +1,8 @@
package lnwire
import "io"
import (
"io"
)
// OpaqueReason is an opaque encrypted byte slice that encodes the exact
// failure reason and additional some supplemental data. The contents of this
@@ -83,3 +85,11 @@ func (c *UpdateFailHTLC) MaxPayloadLength(uint32) uint32 {
return length
}
// TargetChanID returns the channel id of the link for which this message is
// intended.
//
// NOTE: Part of lnd.LinkUpdater interface.
func (c *UpdateFailHTLC) TargetChanID() ChannelID {
return c.ChanID
}

View File

@@ -73,3 +73,11 @@ func (c *UpdateFailMalformedHTLC) MaxPayloadLength(uint32) uint32 {
// 32 + 8 + 32 + 2
return 74
}
// TargetChanID returns the channel id of the link for which this message is
// intended.
//
// NOTE: Part of lnd.LinkUpdater interface.
func (c *UpdateFailMalformedHTLC) TargetChanID() ChannelID {
return c.ChanID
}

View File

@@ -68,3 +68,11 @@ func (c *UpdateFee) MaxPayloadLength(uint32) uint32 {
// 32 + 4
return 36
}
// TargetChanID returns the channel id of the link for which this message is
// intended.
//
// NOTE: Part of lnd.LinkUpdater interface.
func (c *UpdateFee) TargetChanID() ChannelID {
return c.ChanID
}

View File

@@ -1,6 +1,8 @@
package lnwire
import "io"
import (
"io"
)
// UpdateFulfillHTLC is sent by Alice to Bob when she wishes to settle a
// particular HTLC referenced by its HTLCKey within a specific active channel
@@ -76,3 +78,11 @@ func (c *UpdateFulfillHTLC) MaxPayloadLength(uint32) uint32 {
// 32 + 8 + 32
return 72
}
// TargetChanID returns the channel id of the link for which this message is
// intended.
//
// NOTE: Part of lnd.LinkUpdater interface.
func (c *UpdateFulfillHTLC) TargetChanID() ChannelID {
return c.ChanID
}

View File

@@ -3,6 +3,7 @@ package zpay32
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"strings"
"time"
@@ -67,6 +68,24 @@ const (
// fieldTypeC contains an optional requested final CLTV delta.
fieldTypeC = 24
// fieldType9 contains one or more bytes for signaling features
// supported or required by the receiver.
fieldType9 = 5
// maxInvoiceLength is the maximum total length an invoice can have.
// This is chosen to be the maximum number of bytes that can fit into a
// single QR code: https://en.wikipedia.org/wiki/QR_code#Storage
maxInvoiceLength = 7089
)
var (
// InvoiceFeatures holds the set of all known feature bits that are
// exposed as BOLT 11 features.
InvoiceFeatures = map[lnwire.FeatureBit]string{}
// ErrInvoiceTooLarge is returned when an invoice exceeds maxInvoiceLength.
ErrInvoiceTooLarge = errors.New("invoice is too large")
)
// MessageSigner is passed to the Encode method to provide a signature
@@ -146,6 +165,10 @@ type Invoice struct {
//
// NOTE: This is optional.
RouteHints [][]HopHint
// Features represents an optional field used to signal optional or
// required support for features by the receiver.
Features *lnwire.FeatureVector
}
// Amount is a functional option that allows callers of NewInvoice to set the
@@ -249,6 +272,12 @@ func NewInvoice(net *chaincfg.Params, paymentHash [32]byte,
func Decode(invoice string, net *chaincfg.Params) (*Invoice, error) {
decodedInvoice := Invoice{}
// Before bech32 decoding the invoice, make sure that it is not too large.
// This is done as an anti-DoS measure since bech32 decoding is expensive.
if len(invoice) > maxInvoiceLength {
return nil, ErrInvoiceTooLarge
}
// Decode the invoice using the modified bech32 decoder.
hrp, data, err := decodeBech32(invoice)
if err != nil {
@@ -453,6 +482,12 @@ func (invoice *Invoice) Encode(signer MessageSigner) (string, error) {
return "", err
}
// Before returning, check that the bech32 encoded string is not greater
// than our largest supported invoice size.
if len(b32) > maxInvoiceLength {
return "", ErrInvoiceTooLarge
}
return b32, nil
}
@@ -504,21 +539,6 @@ func validateInvoice(invoice *Invoice) error {
return fmt.Errorf("neither description nor description hash set")
}
// We'll restrict invoices to include up to 20 different private route
// hints. We do this to avoid overly large invoices.
if len(invoice.RouteHints) > 20 {
return fmt.Errorf("too many private routes: %d",
len(invoice.RouteHints))
}
// Each route hint can have at most 20 hops.
for i, routeHint := range invoice.RouteHints {
if len(routeHint) > 20 {
return fmt.Errorf("route hint %d has too many extra "+
"hops: %d", i, len(routeHint))
}
}
// Check that we support the field lengths.
if len(invoice.PaymentHash) != 32 {
return fmt.Errorf("unsupported payment hash length: %d",
@@ -663,6 +683,14 @@ func parseTaggedFields(invoice *Invoice, fields []byte, net *chaincfg.Params) er
}
invoice.RouteHints = append(invoice.RouteHints, routeHint)
case fieldType9:
if invoice.Features != nil {
// We skip the field if we have already seen a
// supported one.
continue
}
invoice.Features, err = parseFeatures(base32Data)
default:
// Ignore unknown type.
}
@@ -848,6 +876,7 @@ func parseRouteHint(data []byte) ([]HopHint, error) {
return nil, err
}
// Check that base256Data is a multiple of hopHintLen.
if len(base256Data)%hopHintLen != 0 {
return nil, fmt.Errorf("expected length multiple of %d bytes, "+
"got %d", hopHintLen, len(base256Data))
@@ -874,6 +903,25 @@ func parseRouteHint(data []byte) ([]HopHint, error) {
return routeHint, nil
}
// parseFeatures decodes any feature bits directly from the base32
// representation.
func parseFeatures(data []byte) (*lnwire.FeatureVector, error) {
rawFeatures := lnwire.NewRawFeatureVector()
err := rawFeatures.DecodeBase32(bytes.NewReader(data), len(data))
if err != nil {
return nil, err
}
fv := lnwire.NewFeatureVector(rawFeatures, InvoiceFeatures)
unknownFeatures := fv.UnknownRequiredFeatures()
if len(unknownFeatures) > 0 {
return nil, fmt.Errorf("invoice contains unknown required "+
"features: %v", unknownFeatures)
}
return fv, nil
}
// writeTaggedFields writes the non-nil tagged fields of the Invoice to the
// base32 buffer.
func writeTaggedFields(bufferBase32 *bytes.Buffer, invoice *Invoice) error {
@@ -1011,7 +1059,7 @@ func writeTaggedFields(bufferBase32 *bytes.Buffer, invoice *Invoice) error {
pubKeyBase32, err := bech32.ConvertBits(
invoice.Destination.SerializeCompressed(), 8, 5, true)
if err != nil {
return nil
return err
}
if len(pubKeyBase32) != pubKeyBase32Len {
@@ -1024,6 +1072,18 @@ func writeTaggedFields(bufferBase32 *bytes.Buffer, invoice *Invoice) error {
return err
}
}
if invoice.Features != nil && invoice.Features.SerializeSize32() > 0 {
var b bytes.Buffer
err := invoice.Features.RawFeatureVector.EncodeBase32(&b)
if err != nil {
return err
}
err = writeTaggedField(bufferBase32, fieldType9, b.Bytes())
if err != nil {
return err
}
}
return nil
}