Also freeze the lnwire and record packages used by the migration. Copy the minimal subset of lnwire files (16) into payments/db/migration1/lnwire/ and all record files (6) into payments/db/migration1/record/. Three lnwire files are trimmed to avoid pulling in the full message-type dispatch tree — all changes are purely subtractive and can be verified with: diff lnwire/message.go payments/db/migration1/lnwire/message.go diff lnwire/writer.go payments/db/migration1/lnwire/writer.go diff lnwire/lnwire.go payments/db/migration1/lnwire/lnwire.go All migration1 files now import only the frozen packages, removing the live dependency on lnwire and record so future changes to those packages cannot affect migration correctness.
199 lines
5.0 KiB
Go
199 lines
5.0 KiB
Go
package migration1
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"fmt"
|
|
"io"
|
|
"time"
|
|
|
|
"github.com/btcsuite/btcd/wire"
|
|
"github.com/lightningnetwork/lnd/payments/db/migration1/lnwire"
|
|
)
|
|
|
|
// Big endian is the preferred byte order, due to cursor scans over
|
|
// integer keys iterating in order.
|
|
var byteOrder = binary.BigEndian
|
|
|
|
// UnknownElementType is an error returned when the codec is unable to encode
|
|
// or decode a particular type.
|
|
//
|
|
// NOTE: This is a frozen, self-contained copy of the serialization error type
|
|
// to ensure that this migration package has no dependency on live packages
|
|
// whose implementation may change after this migration was released.
|
|
type UnknownElementType struct {
|
|
method string
|
|
element interface{}
|
|
}
|
|
|
|
// NewUnknownElementType creates a new UnknownElementType error from the passed
|
|
// method name and element.
|
|
func NewUnknownElementType(method string, el interface{}) UnknownElementType {
|
|
return UnknownElementType{method: method, element: el}
|
|
}
|
|
|
|
// 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 serializes a single element into the provided io.Writer using
|
|
// big-endian byte order. Only the types required by the migration1 package are
|
|
// supported. This is a frozen, self-contained copy of the serialization logic
|
|
// to ensure that this migration package has no dependency on live packages
|
|
// whose implementation may change after this migration was released.
|
|
func WriteElement(w io.Writer, element interface{}) error {
|
|
switch e := element.(type) {
|
|
case paymentIndexType:
|
|
if err := binary.Write(w, byteOrder, e); err != nil {
|
|
return err
|
|
}
|
|
|
|
case uint8:
|
|
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 uint64:
|
|
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 [32]byte:
|
|
if _, err := w.Write(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 serializes a variadic list of elements into the given
|
|
// io.Writer.
|
|
func WriteElements(w io.Writer, elements ...interface{}) error {
|
|
for _, element := range elements {
|
|
if err := WriteElement(w, element); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ReadElement deserializes a single element from the provided io.Reader using
|
|
// big-endian byte order. Only the types required by the migration1 package are
|
|
// supported. This is a frozen, self-contained copy of the deserialization
|
|
// logic to ensure that this migration package has no dependency on live
|
|
// packages whose implementation may change after this migration was released.
|
|
func ReadElement(r io.Reader, element interface{}) error {
|
|
switch e := element.(type) {
|
|
case *paymentIndexType:
|
|
if err := binary.Read(r, byteOrder, e); err != nil {
|
|
return err
|
|
}
|
|
|
|
case *uint8:
|
|
if err := binary.Read(r, byteOrder, e); err != nil {
|
|
return err
|
|
}
|
|
|
|
case *uint32:
|
|
if err := binary.Read(r, byteOrder, e); err != nil {
|
|
return err
|
|
}
|
|
|
|
case *uint64:
|
|
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 *[32]byte:
|
|
if _, err := io.ReadFull(r, e[:]); err != nil {
|
|
return err
|
|
}
|
|
|
|
case *[]byte:
|
|
b, err := wire.ReadVarBytes(r, 0, 66000, "[]byte")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*e = b
|
|
|
|
default:
|
|
return UnknownElementType{"ReadElement", e}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ReadElements deserializes the provided io.Reader into a variadic list of
|
|
// target elements.
|
|
func ReadElements(r io.Reader, elements ...interface{}) error {
|
|
for _, element := range elements {
|
|
if err := ReadElement(r, element); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// deserializeTime deserializes time as unix nanoseconds.
|
|
func deserializeTime(r io.Reader) (time.Time, error) {
|
|
var scratch [8]byte
|
|
if _, err := io.ReadFull(r, scratch[:]); err != nil {
|
|
return time.Time{}, err
|
|
}
|
|
|
|
// Convert to time.Time. Interpret unix nano time zero as a zero
|
|
// time.Time value.
|
|
unixNano := byteOrder.Uint64(scratch[:])
|
|
if unixNano == 0 {
|
|
return time.Time{}, nil
|
|
}
|
|
|
|
return time.Unix(0, int64(unixNano)), nil
|
|
}
|
|
|
|
// serializeTime serializes time as unix nanoseconds.
|
|
func serializeTime(w io.Writer, t time.Time) error {
|
|
var scratch [8]byte
|
|
|
|
// Convert to unix nano seconds, but only if time is non-zero. Calling
|
|
// UnixNano() on a zero time yields an undefined result.
|
|
var unixNano int64
|
|
if !t.IsZero() {
|
|
unixNano = t.UnixNano()
|
|
}
|
|
|
|
byteOrder.PutUint64(scratch[:], uint64(unixNano))
|
|
_, err := w.Write(scratch[:])
|
|
|
|
return err
|
|
}
|