channeldb: move deprecated code to migration_09_legacy_serialization.go
And unexport deprecated code.
This commit is contained in:
parent
1b788904f0
commit
d78d3f50b9
@ -1,6 +1,8 @@
|
|||||||
package channeldb
|
package channeldb
|
||||||
|
|
||||||
import "io"
|
import (
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
// deserializeCloseChannelSummaryV6 reads the v6 database format for
|
// deserializeCloseChannelSummaryV6 reads the v6 database format for
|
||||||
// ChannelCloseSummary.
|
// ChannelCloseSummary.
|
||||||
|
255
channeldb/migration_09_legacy_serialization.go
Normal file
255
channeldb/migration_09_legacy_serialization.go
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
package channeldb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/coreos/bbolt"
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// paymentBucket is the name of the bucket within the database that
|
||||||
|
// stores all data related to payments.
|
||||||
|
//
|
||||||
|
// Within the payments bucket, each invoice is keyed by its invoice ID
|
||||||
|
// which is a monotonically increasing uint64. BoltDB's sequence
|
||||||
|
// feature is used for generating monotonically increasing id.
|
||||||
|
//
|
||||||
|
// NOTE: Deprecated. Kept around for migration purposes.
|
||||||
|
paymentBucket = []byte("payments")
|
||||||
|
|
||||||
|
// paymentStatusBucket is the name of the bucket within the database
|
||||||
|
// that stores the status of a payment indexed by the payment's
|
||||||
|
// preimage.
|
||||||
|
//
|
||||||
|
// NOTE: Deprecated. Kept around for migration purposes.
|
||||||
|
paymentStatusBucket = []byte("payment-status")
|
||||||
|
)
|
||||||
|
|
||||||
|
// outgoingPayment represents a successful payment between the daemon and a
|
||||||
|
// remote node. Details such as the total fee paid, and the time of the payment
|
||||||
|
// are stored.
|
||||||
|
//
|
||||||
|
// NOTE: Deprecated. Kept around for migration purposes.
|
||||||
|
type outgoingPayment struct {
|
||||||
|
Invoice
|
||||||
|
|
||||||
|
// Fee is the total fee paid for the payment in milli-satoshis.
|
||||||
|
Fee lnwire.MilliSatoshi
|
||||||
|
|
||||||
|
// TotalTimeLock is the total cumulative time-lock in the HTLC extended
|
||||||
|
// from the second-to-last hop to the destination.
|
||||||
|
TimeLockLength uint32
|
||||||
|
|
||||||
|
// Path encodes the path the payment took through the network. The path
|
||||||
|
// excludes the outgoing node and consists of the hex-encoded
|
||||||
|
// compressed public key of each of the nodes involved in the payment.
|
||||||
|
Path [][33]byte
|
||||||
|
|
||||||
|
// PaymentPreimage is the preImage of a successful payment. This is used
|
||||||
|
// to calculate the PaymentHash as well as serve as a proof of payment.
|
||||||
|
PaymentPreimage [32]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// addPayment saves a successful payment to the database. It is assumed that
|
||||||
|
// all payment are sent using unique payment hashes.
|
||||||
|
//
|
||||||
|
// NOTE: Deprecated. Kept around for migration purposes.
|
||||||
|
func (db *DB) addPayment(payment *outgoingPayment) error {
|
||||||
|
// Validate the field of the inner voice within the outgoing payment,
|
||||||
|
// these must also adhere to the same constraints as regular invoices.
|
||||||
|
if err := validateInvoice(&payment.Invoice); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// We first serialize the payment before starting the database
|
||||||
|
// transaction so we can avoid creating a DB payment in the case of a
|
||||||
|
// serialization error.
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := serializeOutgoingPayment(&b, payment); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
paymentBytes := b.Bytes()
|
||||||
|
|
||||||
|
return db.Batch(func(tx *bbolt.Tx) error {
|
||||||
|
payments, err := tx.CreateBucketIfNotExists(paymentBucket)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obtain the new unique sequence number for this payment.
|
||||||
|
paymentID, err := payments.NextSequence()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// We use BigEndian for keys as it orders keys in
|
||||||
|
// ascending order. This allows bucket scans to order payments
|
||||||
|
// in the order in which they were created.
|
||||||
|
paymentIDBytes := make([]byte, 8)
|
||||||
|
binary.BigEndian.PutUint64(paymentIDBytes, paymentID)
|
||||||
|
|
||||||
|
return payments.Put(paymentIDBytes, paymentBytes)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetchAllPayments returns all outgoing payments in DB.
|
||||||
|
//
|
||||||
|
// NOTE: Deprecated. Kept around for migration purposes.
|
||||||
|
func (db *DB) fetchAllPayments() ([]*outgoingPayment, error) {
|
||||||
|
var payments []*outgoingPayment
|
||||||
|
|
||||||
|
err := db.View(func(tx *bbolt.Tx) error {
|
||||||
|
bucket := tx.Bucket(paymentBucket)
|
||||||
|
if bucket == nil {
|
||||||
|
return ErrNoPaymentsCreated
|
||||||
|
}
|
||||||
|
|
||||||
|
return bucket.ForEach(func(k, v []byte) error {
|
||||||
|
// If the value is nil, then we ignore it as it may be
|
||||||
|
// a sub-bucket.
|
||||||
|
if v == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
r := bytes.NewReader(v)
|
||||||
|
payment, err := deserializeOutgoingPayment(r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
payments = append(payments, payment)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return payments, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetchPaymentStatus returns the payment status for outgoing payment.
|
||||||
|
// If status of the payment isn't found, it will default to "StatusGrounded".
|
||||||
|
//
|
||||||
|
// NOTE: Deprecated. Kept around for migration purposes.
|
||||||
|
func (db *DB) fetchPaymentStatus(paymentHash [32]byte) (PaymentStatus, error) {
|
||||||
|
var paymentStatus = StatusGrounded
|
||||||
|
err := db.View(func(tx *bbolt.Tx) error {
|
||||||
|
var err error
|
||||||
|
paymentStatus, err = fetchPaymentStatusTx(tx, paymentHash)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return StatusGrounded, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return paymentStatus, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetchPaymentStatusTx is a helper method that returns the payment status for
|
||||||
|
// outgoing payment. If status of the payment isn't found, it will default to
|
||||||
|
// "StatusGrounded". It accepts the boltdb transactions such that this method
|
||||||
|
// can be composed into other atomic operations.
|
||||||
|
//
|
||||||
|
// NOTE: Deprecated. Kept around for migration purposes.
|
||||||
|
func fetchPaymentStatusTx(tx *bbolt.Tx, paymentHash [32]byte) (PaymentStatus, error) {
|
||||||
|
// The default status for all payments that aren't recorded in database.
|
||||||
|
var paymentStatus = StatusGrounded
|
||||||
|
|
||||||
|
bucket := tx.Bucket(paymentStatusBucket)
|
||||||
|
if bucket == nil {
|
||||||
|
return paymentStatus, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
paymentStatusBytes := bucket.Get(paymentHash[:])
|
||||||
|
if paymentStatusBytes == nil {
|
||||||
|
return paymentStatus, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
paymentStatus.FromBytes(paymentStatusBytes)
|
||||||
|
|
||||||
|
return paymentStatus, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func serializeOutgoingPayment(w io.Writer, p *outgoingPayment) error {
|
||||||
|
var scratch [8]byte
|
||||||
|
|
||||||
|
if err := serializeInvoice(w, &p.Invoice); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
byteOrder.PutUint64(scratch[:], uint64(p.Fee))
|
||||||
|
if _, err := w.Write(scratch[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// First write out the length of the bytes to prefix the value.
|
||||||
|
pathLen := uint32(len(p.Path))
|
||||||
|
byteOrder.PutUint32(scratch[:4], pathLen)
|
||||||
|
if _, err := w.Write(scratch[:4]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then with the path written, we write out the series of public keys
|
||||||
|
// involved in the path.
|
||||||
|
for _, hop := range p.Path {
|
||||||
|
if _, err := w.Write(hop[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byteOrder.PutUint32(scratch[:4], p.TimeLockLength)
|
||||||
|
if _, err := w.Write(scratch[:4]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := w.Write(p.PaymentPreimage[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func deserializeOutgoingPayment(r io.Reader) (*outgoingPayment, error) {
|
||||||
|
var scratch [8]byte
|
||||||
|
|
||||||
|
p := &outgoingPayment{}
|
||||||
|
|
||||||
|
inv, err := deserializeInvoice(r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
p.Invoice = inv
|
||||||
|
|
||||||
|
if _, err := r.Read(scratch[:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
p.Fee = lnwire.MilliSatoshi(byteOrder.Uint64(scratch[:]))
|
||||||
|
|
||||||
|
if _, err = r.Read(scratch[:4]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pathLen := byteOrder.Uint32(scratch[:4])
|
||||||
|
|
||||||
|
path := make([][33]byte, pathLen)
|
||||||
|
for i := uint32(0); i < pathLen; i++ {
|
||||||
|
if _, err := r.Read(path[i][:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.Path = path
|
||||||
|
|
||||||
|
if _, err = r.Read(scratch[:4]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
p.TimeLockLength = byteOrder.Uint32(scratch[:4])
|
||||||
|
|
||||||
|
if _, err := r.Read(p.PaymentPreimage[:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return p, nil
|
||||||
|
}
|
@ -26,11 +26,11 @@ func TestPaymentStatusesMigration(t *testing.T) {
|
|||||||
// Add fake payment to test database, verifying that it was created,
|
// Add fake payment to test database, verifying that it was created,
|
||||||
// that we have only one payment, and its status is not "Completed".
|
// that we have only one payment, and its status is not "Completed".
|
||||||
beforeMigrationFunc := func(d *DB) {
|
beforeMigrationFunc := func(d *DB) {
|
||||||
if err := d.AddPayment(fakePayment); err != nil {
|
if err := d.addPayment(fakePayment); err != nil {
|
||||||
t.Fatalf("unable to add payment: %v", err)
|
t.Fatalf("unable to add payment: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
payments, err := d.FetchAllPayments()
|
payments, err := d.fetchAllPayments()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to fetch payments: %v", err)
|
t.Fatalf("unable to fetch payments: %v", err)
|
||||||
}
|
}
|
||||||
@ -40,7 +40,7 @@ func TestPaymentStatusesMigration(t *testing.T) {
|
|||||||
len(payments))
|
len(payments))
|
||||||
}
|
}
|
||||||
|
|
||||||
paymentStatus, err := d.FetchPaymentStatus(paymentHash)
|
paymentStatus, err := d.fetchPaymentStatus(paymentHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to fetch payment status: %v", err)
|
t.Fatalf("unable to fetch payment status: %v", err)
|
||||||
}
|
}
|
||||||
@ -141,7 +141,7 @@ func TestPaymentStatusesMigration(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check that our completed payments were migrated.
|
// Check that our completed payments were migrated.
|
||||||
paymentStatus, err := d.FetchPaymentStatus(paymentHash)
|
paymentStatus, err := d.fetchPaymentStatus(paymentHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to fetch payment status: %v", err)
|
t.Fatalf("unable to fetch payment status: %v", err)
|
||||||
}
|
}
|
||||||
@ -160,7 +160,7 @@ func TestPaymentStatusesMigration(t *testing.T) {
|
|||||||
|
|
||||||
// Check that the locally sourced payment was transitioned to
|
// Check that the locally sourced payment was transitioned to
|
||||||
// InFlight.
|
// InFlight.
|
||||||
paymentStatus, err = d.FetchPaymentStatus(inFlightHash)
|
paymentStatus, err = d.fetchPaymentStatus(inFlightHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to fetch payment status: %v", err)
|
t.Fatalf("unable to fetch payment status: %v", err)
|
||||||
}
|
}
|
||||||
@ -179,7 +179,7 @@ func TestPaymentStatusesMigration(t *testing.T) {
|
|||||||
|
|
||||||
// Check that non-locally sourced payments remain in the default
|
// Check that non-locally sourced payments remain in the default
|
||||||
// Grounded state.
|
// Grounded state.
|
||||||
paymentStatus, err = d.FetchPaymentStatus(groundedHash)
|
paymentStatus, err = d.fetchPaymentStatus(groundedHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to fetch payment status: %v", err)
|
t.Fatalf("unable to fetch payment status: %v", err)
|
||||||
}
|
}
|
||||||
@ -571,12 +571,12 @@ func TestOutgoingPaymentsMigration(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
const numPayments = 4
|
const numPayments = 4
|
||||||
var oldPayments []*OutgoingPayment
|
var oldPayments []*outgoingPayment
|
||||||
|
|
||||||
// Add fake payments to test database, verifying that it was created.
|
// Add fake payments to test database, verifying that it was created.
|
||||||
beforeMigrationFunc := func(d *DB) {
|
beforeMigrationFunc := func(d *DB) {
|
||||||
for i := 0; i < numPayments; i++ {
|
for i := 0; i < numPayments; i++ {
|
||||||
var p *OutgoingPayment
|
var p *outgoingPayment
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
// We fill the database with random payments. For the
|
// We fill the database with random payments. For the
|
||||||
@ -593,14 +593,14 @@ func TestOutgoingPaymentsMigration(t *testing.T) {
|
|||||||
p = oldPayments[0]
|
p = oldPayments[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := d.AddPayment(p); err != nil {
|
if err := d.addPayment(p); err != nil {
|
||||||
t.Fatalf("unable to add payment: %v", err)
|
t.Fatalf("unable to add payment: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
oldPayments = append(oldPayments, p)
|
oldPayments = append(oldPayments, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
payments, err := d.FetchAllPayments()
|
payments, err := d.fetchAllPayments()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to fetch payments: %v", err)
|
t.Fatalf("unable to fetch payments: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -84,18 +84,6 @@ var (
|
|||||||
// paymentFailInfoKey is a key used in the payment's sub-bucket to
|
// paymentFailInfoKey is a key used in the payment's sub-bucket to
|
||||||
// store information about the reason a payment failed.
|
// store information about the reason a payment failed.
|
||||||
paymentFailInfoKey = []byte("payment-fail-info")
|
paymentFailInfoKey = []byte("payment-fail-info")
|
||||||
|
|
||||||
// paymentBucket is the name of the bucket within the database that
|
|
||||||
// stores all data related to payments.
|
|
||||||
//
|
|
||||||
// Within the payments bucket, each invoice is keyed by its invoice ID
|
|
||||||
// which is a monotonically increasing uint64. BoltDB's sequence
|
|
||||||
// feature is used for generating monotonically increasing id.
|
|
||||||
paymentBucket = []byte("payments")
|
|
||||||
|
|
||||||
// paymentStatusBucket is the name of the bucket within the database that
|
|
||||||
// stores the status of a payment indexed by the payment's preimage.
|
|
||||||
paymentStatusBucket = []byte("payment-status")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// FailureReason encodes the reason a payment ultimately failed.
|
// FailureReason encodes the reason a payment ultimately failed.
|
||||||
@ -171,247 +159,6 @@ func (ps PaymentStatus) String() string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// OutgoingPayment represents a successful payment between the daemon and a
|
|
||||||
// remote node. Details such as the total fee paid, and the time of the payment
|
|
||||||
// are stored.
|
|
||||||
//
|
|
||||||
// NOTE: Deprecated. Kept around for migration purposes.
|
|
||||||
type OutgoingPayment struct {
|
|
||||||
Invoice
|
|
||||||
|
|
||||||
// Fee is the total fee paid for the payment in milli-satoshis.
|
|
||||||
Fee lnwire.MilliSatoshi
|
|
||||||
|
|
||||||
// TotalTimeLock is the total cumulative time-lock in the HTLC extended
|
|
||||||
// from the second-to-last hop to the destination.
|
|
||||||
TimeLockLength uint32
|
|
||||||
|
|
||||||
// Path encodes the path the payment took through the network. The path
|
|
||||||
// excludes the outgoing node and consists of the hex-encoded
|
|
||||||
// compressed public key of each of the nodes involved in the payment.
|
|
||||||
Path [][33]byte
|
|
||||||
|
|
||||||
// PaymentPreimage is the preImage of a successful payment. This is used
|
|
||||||
// to calculate the PaymentHash as well as serve as a proof of payment.
|
|
||||||
PaymentPreimage [32]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddPayment saves a successful payment to the database. It is assumed that
|
|
||||||
// all payment are sent using unique payment hashes.
|
|
||||||
//
|
|
||||||
// NOTE: Deprecated. Kept around for migration purposes.
|
|
||||||
func (db *DB) AddPayment(payment *OutgoingPayment) error {
|
|
||||||
// Validate the field of the inner voice within the outgoing payment,
|
|
||||||
// these must also adhere to the same constraints as regular invoices.
|
|
||||||
if err := validateInvoice(&payment.Invoice); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// We first serialize the payment before starting the database
|
|
||||||
// transaction so we can avoid creating a DB payment in the case of a
|
|
||||||
// serialization error.
|
|
||||||
var b bytes.Buffer
|
|
||||||
if err := serializeOutgoingPayment(&b, payment); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
paymentBytes := b.Bytes()
|
|
||||||
|
|
||||||
return db.Batch(func(tx *bbolt.Tx) error {
|
|
||||||
payments, err := tx.CreateBucketIfNotExists(paymentBucket)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtain the new unique sequence number for this payment.
|
|
||||||
paymentID, err := payments.NextSequence()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// We use BigEndian for keys as it orders keys in
|
|
||||||
// ascending order. This allows bucket scans to order payments
|
|
||||||
// in the order in which they were created.
|
|
||||||
paymentIDBytes := make([]byte, 8)
|
|
||||||
binary.BigEndian.PutUint64(paymentIDBytes, paymentID)
|
|
||||||
|
|
||||||
return payments.Put(paymentIDBytes, paymentBytes)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// FetchAllPayments returns all outgoing payments in DB.
|
|
||||||
//
|
|
||||||
// NOTE: Deprecated. Kept around for migration purposes.
|
|
||||||
func (db *DB) FetchAllPayments() ([]*OutgoingPayment, error) {
|
|
||||||
var payments []*OutgoingPayment
|
|
||||||
|
|
||||||
err := db.View(func(tx *bbolt.Tx) error {
|
|
||||||
bucket := tx.Bucket(paymentBucket)
|
|
||||||
if bucket == nil {
|
|
||||||
return ErrNoPaymentsCreated
|
|
||||||
}
|
|
||||||
|
|
||||||
return bucket.ForEach(func(k, v []byte) error {
|
|
||||||
// If the value is nil, then we ignore it as it may be
|
|
||||||
// a sub-bucket.
|
|
||||||
if v == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
r := bytes.NewReader(v)
|
|
||||||
payment, err := deserializeOutgoingPayment(r)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
payments = append(payments, payment)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return payments, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteAllPayments deletes all payments from DB.
|
|
||||||
//
|
|
||||||
// NOTE: Deprecated. Kept around for migration purposes.
|
|
||||||
func (db *DB) DeleteAllPayments() error {
|
|
||||||
return db.Update(func(tx *bbolt.Tx) error {
|
|
||||||
err := tx.DeleteBucket(paymentBucket)
|
|
||||||
if err != nil && err != bbolt.ErrBucketNotFound {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = tx.CreateBucket(paymentBucket)
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// FetchPaymentStatus returns the payment status for outgoing payment.
|
|
||||||
// If status of the payment isn't found, it will default to "StatusGrounded".
|
|
||||||
//
|
|
||||||
// NOTE: Deprecated. Kept around for migration purposes.
|
|
||||||
func (db *DB) FetchPaymentStatus(paymentHash [32]byte) (PaymentStatus, error) {
|
|
||||||
var paymentStatus = StatusGrounded
|
|
||||||
err := db.View(func(tx *bbolt.Tx) error {
|
|
||||||
var err error
|
|
||||||
paymentStatus, err = FetchPaymentStatusTx(tx, paymentHash)
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return StatusGrounded, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return paymentStatus, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// FetchPaymentStatusTx is a helper method that returns the payment status for
|
|
||||||
// outgoing payment. If status of the payment isn't found, it will default to
|
|
||||||
// "StatusGrounded". It accepts the boltdb transactions such that this method
|
|
||||||
// can be composed into other atomic operations.
|
|
||||||
//
|
|
||||||
// NOTE: Deprecated. Kept around for migration purposes.
|
|
||||||
func FetchPaymentStatusTx(tx *bbolt.Tx, paymentHash [32]byte) (PaymentStatus, error) {
|
|
||||||
// The default status for all payments that aren't recorded in database.
|
|
||||||
var paymentStatus = StatusGrounded
|
|
||||||
|
|
||||||
bucket := tx.Bucket(paymentStatusBucket)
|
|
||||||
if bucket == nil {
|
|
||||||
return paymentStatus, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
paymentStatusBytes := bucket.Get(paymentHash[:])
|
|
||||||
if paymentStatusBytes == nil {
|
|
||||||
return paymentStatus, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
paymentStatus.FromBytes(paymentStatusBytes)
|
|
||||||
|
|
||||||
return paymentStatus, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func serializeOutgoingPayment(w io.Writer, p *OutgoingPayment) error {
|
|
||||||
var scratch [8]byte
|
|
||||||
|
|
||||||
if err := serializeInvoice(w, &p.Invoice); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
byteOrder.PutUint64(scratch[:], uint64(p.Fee))
|
|
||||||
if _, err := w.Write(scratch[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// First write out the length of the bytes to prefix the value.
|
|
||||||
pathLen := uint32(len(p.Path))
|
|
||||||
byteOrder.PutUint32(scratch[:4], pathLen)
|
|
||||||
if _, err := w.Write(scratch[:4]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then with the path written, we write out the series of public keys
|
|
||||||
// involved in the path.
|
|
||||||
for _, hop := range p.Path {
|
|
||||||
if _, err := w.Write(hop[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
byteOrder.PutUint32(scratch[:4], p.TimeLockLength)
|
|
||||||
if _, err := w.Write(scratch[:4]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := w.Write(p.PaymentPreimage[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func deserializeOutgoingPayment(r io.Reader) (*OutgoingPayment, error) {
|
|
||||||
var scratch [8]byte
|
|
||||||
|
|
||||||
p := &OutgoingPayment{}
|
|
||||||
|
|
||||||
inv, err := deserializeInvoice(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
p.Invoice = inv
|
|
||||||
|
|
||||||
if _, err := r.Read(scratch[:]); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
p.Fee = lnwire.MilliSatoshi(byteOrder.Uint64(scratch[:]))
|
|
||||||
|
|
||||||
if _, err = r.Read(scratch[:4]); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
pathLen := byteOrder.Uint32(scratch[:4])
|
|
||||||
|
|
||||||
path := make([][33]byte, pathLen)
|
|
||||||
for i := uint32(0); i < pathLen; i++ {
|
|
||||||
if _, err := r.Read(path[i][:]); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p.Path = path
|
|
||||||
|
|
||||||
if _, err = r.Read(scratch[:4]); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
p.TimeLockLength = byteOrder.Uint32(scratch[:4])
|
|
||||||
|
|
||||||
if _, err := r.Read(p.PaymentPreimage[:]); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return p, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PaymentCreationInfo is the information necessary to have ready when
|
// PaymentCreationInfo is the information necessary to have ready when
|
||||||
// initiating a payment, moving it into state InFlight.
|
// initiating a payment, moving it into state InFlight.
|
||||||
type PaymentCreationInfo struct {
|
type PaymentCreationInfo struct {
|
||||||
|
@ -37,7 +37,7 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeFakePayment() *OutgoingPayment {
|
func makeFakePayment() *outgoingPayment {
|
||||||
fakeInvoice := &Invoice{
|
fakeInvoice := &Invoice{
|
||||||
// Use single second precision to avoid false positive test
|
// Use single second precision to avoid false positive test
|
||||||
// failures due to the monotonic time component.
|
// failures due to the monotonic time component.
|
||||||
@ -55,7 +55,7 @@ func makeFakePayment() *OutgoingPayment {
|
|||||||
copy(fakePath[i][:], bytes.Repeat([]byte{byte(i)}, 33))
|
copy(fakePath[i][:], bytes.Repeat([]byte{byte(i)}, 33))
|
||||||
}
|
}
|
||||||
|
|
||||||
fakePayment := &OutgoingPayment{
|
fakePayment := &outgoingPayment{
|
||||||
Invoice: *fakeInvoice,
|
Invoice: *fakeInvoice,
|
||||||
Fee: 101,
|
Fee: 101,
|
||||||
Path: fakePath,
|
Path: fakePath,
|
||||||
@ -106,7 +106,7 @@ func randomBytes(minLen, maxLen int) ([]byte, error) {
|
|||||||
return randBuf, nil
|
return randBuf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeRandomFakePayment() (*OutgoingPayment, error) {
|
func makeRandomFakePayment() (*outgoingPayment, error) {
|
||||||
var err error
|
var err error
|
||||||
fakeInvoice := &Invoice{
|
fakeInvoice := &Invoice{
|
||||||
// Use single second precision to avoid false positive test
|
// Use single second precision to avoid false positive test
|
||||||
@ -147,7 +147,7 @@ func makeRandomFakePayment() (*OutgoingPayment, error) {
|
|||||||
copy(fakePath[i][:], b)
|
copy(fakePath[i][:], b)
|
||||||
}
|
}
|
||||||
|
|
||||||
fakePayment := &OutgoingPayment{
|
fakePayment := &outgoingPayment{
|
||||||
Invoice: *fakeInvoice,
|
Invoice: *fakeInvoice,
|
||||||
Fee: lnwire.MilliSatoshi(rand.Intn(1001)),
|
Fee: lnwire.MilliSatoshi(rand.Intn(1001)),
|
||||||
Path: fakePath,
|
Path: fakePath,
|
||||||
@ -199,77 +199,6 @@ func TestSentPaymentSerialization(t *testing.T) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOutgoingPaymentWorkflow(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
db, cleanUp, err := makeTestDB()
|
|
||||||
defer cleanUp()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to make test db: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fakePayment := makeFakePayment()
|
|
||||||
if err = db.AddPayment(fakePayment); err != nil {
|
|
||||||
t.Fatalf("unable to put payment in DB: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
payments, err := db.FetchAllPayments()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to fetch payments from DB: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedPayments := []*OutgoingPayment{fakePayment}
|
|
||||||
if !reflect.DeepEqual(payments, expectedPayments) {
|
|
||||||
t.Fatalf("Wrong payments after reading from DB."+
|
|
||||||
"Got %v, want %v",
|
|
||||||
spew.Sdump(payments),
|
|
||||||
spew.Sdump(expectedPayments),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make some random payments
|
|
||||||
for i := 0; i < 5; i++ {
|
|
||||||
randomPayment, err := makeRandomFakePayment()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Internal error in tests: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = db.AddPayment(randomPayment); err != nil {
|
|
||||||
t.Fatalf("unable to put payment in DB: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedPayments = append(expectedPayments, randomPayment)
|
|
||||||
}
|
|
||||||
|
|
||||||
payments, err = db.FetchAllPayments()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Can't get payments from DB: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(payments, expectedPayments) {
|
|
||||||
t.Fatalf("Wrong payments after reading from DB."+
|
|
||||||
"Got %v, want %v",
|
|
||||||
spew.Sdump(payments),
|
|
||||||
spew.Sdump(expectedPayments),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete all payments.
|
|
||||||
if err = db.DeleteAllPayments(); err != nil {
|
|
||||||
t.Fatalf("unable to delete payments from DB: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that there is no payments after deletion
|
|
||||||
paymentsAfterDeletion, err := db.FetchAllPayments()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Can't get payments after deletion: %v", err)
|
|
||||||
}
|
|
||||||
if len(paymentsAfterDeletion) != 0 {
|
|
||||||
t.Fatalf("After deletion DB has %v payments, want %v",
|
|
||||||
len(paymentsAfterDeletion), 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRouteSerialization(t *testing.T) {
|
func TestRouteSerialization(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user