Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Namespaced mc #134

Closed
wants to merge 11 commits into from
10 changes: 10 additions & 0 deletions channeldb/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import (
"github.com/lightningnetwork/lnd/channeldb/migration29"
"github.com/lightningnetwork/lnd/channeldb/migration30"
"github.com/lightningnetwork/lnd/channeldb/migration31"
"github.com/lightningnetwork/lnd/channeldb/migration32"
"github.com/lightningnetwork/lnd/channeldb/migration33"
"github.com/lightningnetwork/lnd/channeldb/migration_01_to_11"
"github.com/lightningnetwork/lnd/clock"
"github.com/lightningnetwork/lnd/invoices"
Expand Down Expand Up @@ -286,6 +288,14 @@ var (
number: 31,
migration: migration31.DeleteLastPublishedTxTLB,
},
{
number: 32,
migration: migration32.MigrateMCRouteSerialisation,
},
{
number: 33,
migration: migration33.MigrateMCStoreNameSpacedResults,
},
}

// optionalVersions stores all optional migrations that are applied
Expand Down
4 changes: 4 additions & 0 deletions channeldb/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"github.com/lightningnetwork/lnd/channeldb/migration24"
"github.com/lightningnetwork/lnd/channeldb/migration30"
"github.com/lightningnetwork/lnd/channeldb/migration31"
"github.com/lightningnetwork/lnd/channeldb/migration32"
"github.com/lightningnetwork/lnd/channeldb/migration33"
"github.com/lightningnetwork/lnd/channeldb/migration_01_to_11"
"github.com/lightningnetwork/lnd/kvdb"
)
Expand Down Expand Up @@ -42,5 +44,7 @@ func UseLogger(logger btclog.Logger) {
migration24.UseLogger(logger)
migration30.UseLogger(logger)
migration31.UseLogger(logger)
migration32.UseLogger(logger)
migration33.UseLogger(logger)
kvdb.UseLogger(logger)
}
49 changes: 49 additions & 0 deletions channeldb/migration/lnwire21/onion_error.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ const (
CodeExpiryTooFar FailCode = 21
CodeInvalidOnionPayload = FlagPerm | 22
CodeMPPTimeout FailCode = 23
CodeInvalidBlinding = FlagBadOnion | FlagPerm | 24
)

// String returns the string representation of the failure code.
Expand Down Expand Up @@ -157,6 +158,9 @@ func (c FailCode) String() string {
case CodeMPPTimeout:
return "MPPTimeout"

case CodeInvalidBlinding:
return "InvalidBlinding"

default:
return "<unknown>"
}
Expand Down Expand Up @@ -571,6 +575,51 @@ func (f *FailInvalidOnionKey) Error() string {
return fmt.Sprintf("InvalidOnionKey(onion_sha=%x)", f.OnionSHA256[:])
}

// 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 WriteElement(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)}
}

// parseChannelUpdateCompatabilityMode will attempt to parse a channel updated
// encoded into an onion error payload in two ways. First, we'll try the
// compatibility oriented version wherein we'll _skip_ the length prefixing on
Expand Down
146 changes: 146 additions & 0 deletions channeldb/migration32/codec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package migration32

import (
"encoding/binary"
"fmt"
"io"

"github.com/btcsuite/btcd/wire"
lnwire "github.com/lightningnetwork/lnd/channeldb/migration/lnwire21"
)

var (
// Big endian is the preferred byte order, due to cursor scans over
// integer keys iterating in order.
byteOrder = binary.BigEndian
)

// ReadElement is a one-stop utility function to deserialize any datastructure
// encoded using the serialization format of the database.
func ReadElement(r io.Reader, element interface{}) error {
switch e := element.(type) {
case *uint32:
if err := binary.Read(r, byteOrder, e); err != nil {
return err
}

case *lnwire.MilliSatoshi:
var a uint64
if err := binary.Read(r, byteOrder, &a); err != nil {
return err
}

*e = lnwire.MilliSatoshi(a)

case *[]byte:
bytes, err := wire.ReadVarBytes(r, 0, 66000, "[]byte")
if err != nil {
return err
}

*e = bytes

case *int64, *uint64:
if err := binary.Read(r, byteOrder, e); err != nil {
return err
}

case *bool:
if err := binary.Read(r, byteOrder, e); err != nil {
return err
}

case *int32:
if err := binary.Read(r, byteOrder, e); err != nil {
return err
}

default:
return UnknownElementType{"ReadElement", e}
}

return nil
}

// ReadElements deserializes a variable number of elements into the passed
// io.Reader, with each element being deserialized according to the ReadElement
// function.
func ReadElements(r io.Reader, elements ...interface{}) error {
for _, element := range elements {
err := ReadElement(r, element)
if err != nil {
return err
}
}

return nil
}

// UnknownElementType is an error returned when the codec is unable to encode or
// decode a particular type.
type UnknownElementType struct {
method string
element interface{}
}

// Error returns the name of the method that encountered the error, as well as
// the type that was unsupported.
func (e UnknownElementType) Error() string {
return fmt.Sprintf("Unknown type in %s: %T", e.method, e.element)
}

// WriteElement is a one-stop shop to write the big endian representation of
// any element which is to be serialized for storage on disk. The passed
// io.Writer should be backed by an appropriately sized byte slice, or be able
// to dynamically expand to accommodate additional data.
func WriteElement(w io.Writer, element interface{}) error {
switch e := element.(type) {
case int64, uint64:
if err := binary.Write(w, byteOrder, e); err != nil {
return err
}

case uint32:
if err := binary.Write(w, byteOrder, e); err != nil {
return err
}

case int32:
if err := binary.Write(w, byteOrder, e); err != nil {
return err
}

case bool:
if err := binary.Write(w, byteOrder, e); err != nil {
return err
}

case lnwire.MilliSatoshi:
if err := binary.Write(w, byteOrder, uint64(e)); err != nil {
return err
}

case []byte:
if err := wire.WriteVarBytes(w, 0, e); err != nil {
return err
}

default:
return UnknownElementType{"WriteElement", e}
}

return nil
}

// WriteElements is writes each element in the elements slice to the passed
// io.Writer using WriteElement.
func WriteElements(w io.Writer, elements ...interface{}) error {
for _, element := range elements {
err := WriteElement(w, element)
if err != nil {
return err
}
}

return nil
}
99 changes: 99 additions & 0 deletions channeldb/migration32/hop.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package migration32

import (
"github.com/btcsuite/btcd/btcec/v2"
"github.com/lightningnetwork/lnd/tlv"
)

const (
// AmtOnionType is the type used in the onion to reference the amount to
// send to the next hop.
AmtOnionType tlv.Type = 2

// LockTimeOnionType is the type used in the onion to reference the CLTV
// value that should be used for the next hop's HTLC.
LockTimeOnionType tlv.Type = 4

// NextHopOnionType is the type used in the onion to reference the ID
// of the next hop.
NextHopOnionType tlv.Type = 6

// EncryptedDataOnionType is the type used to include encrypted data
// provided by the receiver in the onion for use in blinded paths.
EncryptedDataOnionType tlv.Type = 10

// BlindingPointOnionType is the type used to include receiver provided
// ephemeral keys in the onion that are used in blinded paths.
BlindingPointOnionType tlv.Type = 12

// MetadataOnionType is the type used in the onion for the payment
// metadata.
MetadataOnionType tlv.Type = 16

// TotalAmtMsatBlindedType is the type used in the onion for the total
// amount field that is included in the final hop for blinded payments.
TotalAmtMsatBlindedType tlv.Type = 18
)

// NewAmtToFwdRecord creates a tlv.Record that encodes the amount_to_forward
// (type 2) for an onion payload.
func NewAmtToFwdRecord(amt *uint64) tlv.Record {
return tlv.MakeDynamicRecord(
AmtOnionType, amt, func() uint64 {
return tlv.SizeTUint64(*amt)
},
tlv.ETUint64, tlv.DTUint64,
)
}

// NewLockTimeRecord creates a tlv.Record that encodes the outgoing_cltv_value
// (type 4) for an onion payload.
func NewLockTimeRecord(lockTime *uint32) tlv.Record {
return tlv.MakeDynamicRecord(
LockTimeOnionType, lockTime, func() uint64 {
return tlv.SizeTUint32(*lockTime)
},
tlv.ETUint32, tlv.DTUint32,
)
}

// NewNextHopIDRecord creates a tlv.Record that encodes the short_channel_id
// (type 6) for an onion payload.
func NewNextHopIDRecord(cid *uint64) tlv.Record {
return tlv.MakePrimitiveRecord(NextHopOnionType, cid)
}

// NewEncryptedDataRecord creates a tlv.Record that encodes the encrypted_data
// (type 10) record for an onion payload.
func NewEncryptedDataRecord(data *[]byte) tlv.Record {
return tlv.MakePrimitiveRecord(EncryptedDataOnionType, data)
}

// NewBlindingPointRecord creates a tlv.Record that encodes the blinding_point
// (type 12) record for an onion payload.
func NewBlindingPointRecord(point **btcec.PublicKey) tlv.Record {
return tlv.MakePrimitiveRecord(BlindingPointOnionType, point)
}

// NewMetadataRecord creates a tlv.Record that encodes the metadata (type 10)
// for an onion payload.
func NewMetadataRecord(metadata *[]byte) tlv.Record {
return tlv.MakeDynamicRecord(
MetadataOnionType, metadata,
func() uint64 {
return uint64(len(*metadata))
},
tlv.EVarBytes, tlv.DVarBytes,
)
}

// NewTotalAmtMsatBlinded creates a tlv.Record that encodes the
// total_amount_msat for the final an onion payload within a blinded route.
func NewTotalAmtMsatBlinded(amt *uint64) tlv.Record {
return tlv.MakeDynamicRecord(
TotalAmtMsatBlindedType, amt, func() uint64 {
return tlv.SizeTUint64(*amt)
},
tlv.ETUint64, tlv.DTUint64,
)
}
14 changes: 14 additions & 0 deletions channeldb/migration32/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package migration32

import (
"github.com/btcsuite/btclog"
)

// log is a logger that is initialized as disabled. This means the package will
// not perform any logging by default until a logger is set.
var log = btclog.Disabled

// UseLogger uses a specified Logger to output package logging info.
func UseLogger(logger btclog.Logger) {
log = logger
}
Loading
Loading