Merge pull request #3887 from bhandras/channeldb_cleanup

channeldb: remove FetchAllInvoices which was test only and unused
This commit is contained in:
Olaoluwa Osuntokun 2020-01-13 23:16:58 -08:00 committed by GitHub
commit a0639c234f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 73 additions and 145 deletions

@ -2,6 +2,7 @@ package channeldb
import ( import (
"crypto/rand" "crypto/rand"
"math"
"reflect" "reflect"
"testing" "testing"
"time" "time"
@ -14,6 +15,7 @@ import (
var ( var (
emptyFeatures = lnwire.NewFeatureVector(nil, lnwire.Features) emptyFeatures = lnwire.NewFeatureVector(nil, lnwire.Features)
testNow = time.Unix(1, 0)
) )
func randInvoice(value lnwire.MilliSatoshi) (*Invoice, error) { func randInvoice(value lnwire.MilliSatoshi) (*Invoice, error) {
@ -23,9 +25,7 @@ func randInvoice(value lnwire.MilliSatoshi) (*Invoice, error) {
} }
i := &Invoice{ i := &Invoice{
// Use single second precision to avoid false positive test CreationDate: testNow,
// failures due to the monotonic time component.
CreationDate: time.Unix(time.Now().Unix(), 0),
Terms: ContractTerm{ Terms: ContractTerm{
Expiry: 4000, Expiry: 4000,
PaymentPreimage: pre, PaymentPreimage: pre,
@ -52,6 +52,21 @@ func randInvoice(value lnwire.MilliSatoshi) (*Invoice, error) {
return i, nil return i, nil
} }
// settleTestInvoice settles a test invoice.
func settleTestInvoice(invoice *Invoice, settleIndex uint64) {
invoice.SettleDate = testNow
invoice.AmtPaid = invoice.Terms.Value
invoice.State = ContractSettled
invoice.Htlcs[CircuitKey{}] = &InvoiceHTLC{
Amt: invoice.Terms.Value,
AcceptTime: testNow,
ResolveTime: testNow,
State: HtlcStateSettled,
CustomRecords: make(record.CustomSet),
}
invoice.SettleIndex = settleIndex
}
// Tests that pending invoices are those which are either in ContractOpen or // Tests that pending invoices are those which are either in ContractOpen or
// in ContractAccepted state. // in ContractAccepted state.
func TestInvoiceIsPending(t *testing.T) { func TestInvoiceIsPending(t *testing.T) {
@ -87,9 +102,7 @@ func TestInvoiceWorkflow(t *testing.T) {
// Create a fake invoice which we'll use several times in the tests // Create a fake invoice which we'll use several times in the tests
// below. // below.
fakeInvoice := &Invoice{ fakeInvoice := &Invoice{
// Use single second precision to avoid false positive test CreationDate: testNow,
// failures due to the monotonic time component.
CreationDate: time.Unix(time.Now().Unix(), 0),
Htlcs: map[CircuitKey]*InvoiceHTLC{}, Htlcs: map[CircuitKey]*InvoiceHTLC{},
} }
fakeInvoice.Memo = []byte("memo") fakeInvoice.Memo = []byte("memo")
@ -176,7 +189,7 @@ func TestInvoiceWorkflow(t *testing.T) {
amt := lnwire.NewMSatFromSatoshis(1000) amt := lnwire.NewMSatFromSatoshis(1000)
invoices := make([]*Invoice, numInvoices+1) invoices := make([]*Invoice, numInvoices+1)
invoices[0] = &dbInvoice2 invoices[0] = &dbInvoice2
for i := 1; i < len(invoices)-1; i++ { for i := 1; i < len(invoices); i++ {
invoice, err := randInvoice(amt) invoice, err := randInvoice(amt)
if err != nil { if err != nil {
t.Fatalf("unable to create invoice: %v", err) t.Fatalf("unable to create invoice: %v", err)
@ -191,20 +204,26 @@ func TestInvoiceWorkflow(t *testing.T) {
} }
// Perform a scan to collect all the active invoices. // Perform a scan to collect all the active invoices.
dbInvoices, err := db.FetchAllInvoices(false) query := InvoiceQuery{
IndexOffset: 0,
NumMaxInvoices: math.MaxUint64,
PendingOnly: false,
}
response, err := db.QueryInvoices(query)
if err != nil { if err != nil {
t.Fatalf("unable to fetch all invoices: %v", err) t.Fatalf("invoice query failed: %v", err)
} }
// The retrieve list of invoices should be identical as since we're // The retrieve list of invoices should be identical as since we're
// using big endian, the invoices should be retrieved in ascending // using big endian, the invoices should be retrieved in ascending
// order (and the primary key should be incremented with each // order (and the primary key should be incremented with each
// insertion). // insertion).
for i := 0; i < len(invoices)-1; i++ { for i := 0; i < len(invoices); i++ {
if !reflect.DeepEqual(*invoices[i], dbInvoices[i]) { if !reflect.DeepEqual(*invoices[i], response.Invoices[i]) {
t.Fatalf("retrieved invoices don't match %v vs %v", t.Fatalf("retrieved invoices don't match %v vs %v",
spew.Sdump(invoices[i]), spew.Sdump(invoices[i]),
spew.Sdump(dbInvoices[i])) spew.Sdump(response.Invoices[i]))
} }
} }
} }
@ -285,6 +304,7 @@ func TestInvoiceAddTimeSeries(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("unable to make test db: %v", err) t.Fatalf("unable to make test db: %v", err)
} }
db.Now = func() time.Time { return testNow }
// We'll start off by creating 20 random invoices, and inserting them // We'll start off by creating 20 random invoices, and inserting them
// into the database. // into the database.
@ -353,6 +373,8 @@ func TestInvoiceAddTimeSeries(t *testing.T) {
} }
} }
var settledInvoices []Invoice
var settleIndex uint64 = 1
// We'll now only settle the latter half of each of those invoices. // We'll now only settle the latter half of each of those invoices.
for i := 10; i < len(invoices); i++ { for i := 10; i < len(invoices); i++ {
invoice := &invoices[i] invoice := &invoices[i]
@ -360,21 +382,18 @@ func TestInvoiceAddTimeSeries(t *testing.T) {
paymentHash := invoice.Terms.PaymentPreimage.Hash() paymentHash := invoice.Terms.PaymentPreimage.Hash()
_, err := db.UpdateInvoice( _, err := db.UpdateInvoice(
paymentHash, getUpdateInvoice(0), paymentHash, getUpdateInvoice(invoice.Terms.Value),
) )
if err != nil { if err != nil {
t.Fatalf("unable to settle invoice: %v", err) t.Fatalf("unable to settle invoice: %v", err)
} }
}
invoices, err = db.FetchAllInvoices(false) // Create the settled invoice for the expectation set.
if err != nil { settleTestInvoice(invoice, settleIndex)
t.Fatalf("unable to fetch invoices: %v", err) settleIndex++
}
// We'll slice off the first 10 invoices, as we only settled the last settledInvoices = append(settledInvoices, *invoice)
// 10. }
invoices = invoices[10:]
// We'll now prepare an additional set of queries to ensure the settle // We'll now prepare an additional set of queries to ensure the settle
// time series has properly been maintained in the database. // time series has properly been maintained in the database.
@ -399,7 +418,7 @@ func TestInvoiceAddTimeSeries(t *testing.T) {
// being returned, as we only settled those. // being returned, as we only settled those.
{ {
sinceSettleIndex: 1, sinceSettleIndex: 1,
resp: invoices[1:], resp: settledInvoices[1:],
}, },
} }
@ -537,7 +556,7 @@ func TestDuplicateSettleInvoice(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("unable to make test db: %v", err) t.Fatalf("unable to make test db: %v", err)
} }
db.Now = func() time.Time { return time.Unix(1, 0) } db.Now = func() time.Time { return testNow }
// We'll start out by creating an invoice and writing it to the DB. // We'll start out by creating an invoice and writing it to the DB.
amt := lnwire.NewMSatFromSatoshis(1000) amt := lnwire.NewMSatFromSatoshis(1000)
@ -602,69 +621,6 @@ func TestDuplicateSettleInvoice(t *testing.T) {
} }
} }
// TestFetchAllInvoices tests that FetchAllInvoices works as expected.
func TestFetchAllInvoices(t *testing.T) {
t.Parallel()
db, cleanUp, err := makeTestDB()
defer cleanUp()
if err != nil {
t.Fatalf("unable to make test db: %v", err)
}
contractStates := []ContractState{
ContractOpen, ContractSettled, ContractCanceled, ContractAccepted,
}
numInvoices := len(contractStates) * 2
var expectedPendingInvoices []Invoice
var expectedAllInvoices []Invoice
for i := 1; i <= numInvoices; i++ {
invoice, err := randInvoice(lnwire.MilliSatoshi(i))
if err != nil {
t.Fatalf("unable to create invoice: %v", err)
}
invoice.AddIndex = uint64(i)
// Set the contract state of the next invoice such that there's an equal
// number for all possbile states.
invoice.State = contractStates[i%len(contractStates)]
paymentHash := invoice.Terms.PaymentPreimage.Hash()
if invoice.IsPending() {
expectedPendingInvoices = append(expectedPendingInvoices, *invoice)
}
expectedAllInvoices = append(expectedAllInvoices, *invoice)
if _, err := db.AddInvoice(invoice, paymentHash); err != nil {
t.Fatalf("unable to add invoice: %v", err)
}
}
pendingInvoices, err := db.FetchAllInvoices(true)
if err != nil {
t.Fatalf("unable to fetch all pending invoices: %v", err)
}
allInvoices, err := db.FetchAllInvoices(false)
if err != nil {
t.Fatalf("unable to fetch all non pending invoices: %v", err)
}
if !reflect.DeepEqual(pendingInvoices, expectedPendingInvoices) {
t.Fatalf("pending invoices: %v\n != \n expected einvoices: %v",
spew.Sdump(pendingInvoices), spew.Sdump(expectedPendingInvoices))
}
if !reflect.DeepEqual(allInvoices, expectedAllInvoices) {
t.Fatalf("pending + non pending: %v\n != \n expected: %v",
spew.Sdump(allInvoices), spew.Sdump(expectedAllInvoices))
}
}
// TestQueryInvoices ensures that we can properly query the invoice database for // TestQueryInvoices ensures that we can properly query the invoice database for
// invoices using different types of queries. // invoices using different types of queries.
func TestQueryInvoices(t *testing.T) { func TestQueryInvoices(t *testing.T) {
@ -675,13 +631,19 @@ func TestQueryInvoices(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("unable to make test db: %v", err) t.Fatalf("unable to make test db: %v", err)
} }
db.Now = func() time.Time { return testNow }
// To begin the test, we'll add 50 invoices to the database. We'll // To begin the test, we'll add 50 invoices to the database. We'll
// assume that the index of the invoice within the database is the same // assume that the index of the invoice within the database is the same
// as the amount of the invoice itself. // as the amount of the invoice itself.
const numInvoices = 50 const numInvoices = 50
for i := lnwire.MilliSatoshi(1); i <= numInvoices; i++ { var settleIndex uint64 = 1
invoice, err := randInvoice(i) var invoices []Invoice
var pendingInvoices []Invoice
for i := 1; i <= numInvoices; i++ {
amt := lnwire.MilliSatoshi(i)
invoice, err := randInvoice(amt)
if err != nil { if err != nil {
t.Fatalf("unable to create invoice: %v", err) t.Fatalf("unable to create invoice: %v", err)
} }
@ -695,24 +657,20 @@ func TestQueryInvoices(t *testing.T) {
// We'll only settle half of all invoices created. // We'll only settle half of all invoices created.
if i%2 == 0 { if i%2 == 0 {
_, err := db.UpdateInvoice( _, err := db.UpdateInvoice(
paymentHash, getUpdateInvoice(i), paymentHash, getUpdateInvoice(amt),
) )
if err != nil { if err != nil {
t.Fatalf("unable to settle invoice: %v", err) t.Fatalf("unable to settle invoice: %v", err)
} }
}
}
// We'll then retrieve the set of all invoices and pending invoices. // Create the settled invoice for the expectation set.
// This will serve useful when comparing the expected responses of the settleTestInvoice(invoice, settleIndex)
// query with the actual ones. settleIndex++
invoices, err := db.FetchAllInvoices(false) } else {
if err != nil { pendingInvoices = append(pendingInvoices, *invoice)
t.Fatalf("unable to retrieve invoices: %v", err) }
}
pendingInvoices, err := db.FetchAllInvoices(true) invoices = append(invoices, *invoice)
if err != nil {
t.Fatalf("unable to retrieve pending invoices: %v", err)
} }
// The test will consist of several queries along with their respective // The test will consist of several queries along with their respective

@ -642,49 +642,6 @@ func (d *DB) FetchAllInvoicesWithPaymentHash(pendingOnly bool) (
return result, nil return result, nil
} }
// FetchAllInvoices returns all invoices currently stored within the database.
// If the pendingOnly param is set to true, then only invoices in open or
// accepted state will be returned, skipping all invoices that are fully
// settled or canceled.
func (d *DB) FetchAllInvoices(pendingOnly bool) ([]Invoice, error) {
var invoices []Invoice
err := d.View(func(tx *bbolt.Tx) error {
invoiceB := tx.Bucket(invoiceBucket)
if invoiceB == nil {
return ErrNoInvoicesCreated
}
// Iterate through the entire key space of the top-level
// invoice bucket. If key with a non-nil value stores the next
// invoice ID which maps to the corresponding invoice.
return invoiceB.ForEach(func(k, v []byte) error {
if v == nil {
return nil
}
invoiceReader := bytes.NewReader(v)
invoice, err := deserializeInvoice(invoiceReader)
if err != nil {
return err
}
if pendingOnly && !invoice.IsPending() {
return nil
}
invoices = append(invoices, invoice)
return nil
})
})
if err != nil {
return nil, err
}
return invoices, nil
}
// InvoiceQuery represents a query to the invoice database. The query allows a // InvoiceQuery represents a query to the invoice database. The query allows a
// caller to retrieve all invoices starting from a particular add index and // caller to retrieve all invoices starting from a particular add index and
// limit the number of results returned. // limit the number of results returned.
@ -1327,6 +1284,19 @@ func copySlice(src []byte) []byte {
return dest return dest
} }
// copyInvoiceHTLC makes a deep copy of the supplied invoice HTLC.
func copyInvoiceHTLC(src *InvoiceHTLC) *InvoiceHTLC {
result := *src
// Make a copy of the CustomSet map.
result.CustomRecords = make(record.CustomSet)
for k, v := range src.CustomRecords {
result.CustomRecords[k] = v
}
return &result
}
// copyInvoice makes a deep copy of the supplied invoice. // copyInvoice makes a deep copy of the supplied invoice.
func copyInvoice(src *Invoice) *Invoice { func copyInvoice(src *Invoice) *Invoice {
dest := Invoice{ dest := Invoice{
@ -1347,7 +1317,7 @@ func copyInvoice(src *Invoice) *Invoice {
dest.Terms.Features = src.Terms.Features.Clone() dest.Terms.Features = src.Terms.Features.Clone()
for k, v := range src.Htlcs { for k, v := range src.Htlcs {
dest.Htlcs[k] = v dest.Htlcs[k] = copyInvoiceHTLC(v)
} }
return &dest return &dest