You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
184 lines
4.0 KiB
184 lines
4.0 KiB
package migration_01_to_11 |
|
|
|
import ( |
|
"bytes" |
|
"fmt" |
|
"testing" |
|
"time" |
|
|
|
"github.com/btcsuite/btcd/btcec" |
|
bitcoinCfg "github.com/btcsuite/btcd/chaincfg" |
|
"github.com/lightningnetwork/lnd/kvdb" |
|
"github.com/lightningnetwork/lnd/zpay32" |
|
litecoinCfg "github.com/ltcsuite/ltcd/chaincfg" |
|
) |
|
|
|
var ( |
|
testPrivKeyBytes = []byte{ |
|
0x2b, 0xd8, 0x06, 0xc9, 0x7f, 0x0e, 0x00, 0xaf, |
|
0x1a, 0x1f, 0xc3, 0x32, 0x8f, 0xa7, 0x63, 0xa9, |
|
0x26, 0x97, 0x23, 0xc8, 0xdb, 0x8f, 0xac, 0x4f, |
|
0x93, 0xaf, 0x71, 0xdb, 0x18, 0x6d, 0x6e, 0x90, |
|
} |
|
|
|
testCltvDelta = int32(50) |
|
) |
|
|
|
// beforeMigrationFuncV11 insert the test invoices in the database. |
|
func beforeMigrationFuncV11(t *testing.T, d *DB, invoices []Invoice) { |
|
err := kvdb.Update(d, func(tx kvdb.RwTx) error { |
|
invoicesBucket, err := tx.CreateTopLevelBucket( |
|
invoiceBucket, |
|
) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
invoiceNum := uint32(1) |
|
for _, invoice := range invoices { |
|
var invoiceKey [4]byte |
|
byteOrder.PutUint32(invoiceKey[:], invoiceNum) |
|
invoiceNum++ |
|
|
|
var buf bytes.Buffer |
|
err := serializeInvoiceLegacy(&buf, &invoice) // nolint:scopelint |
|
if err != nil { |
|
return err |
|
} |
|
|
|
err = invoicesBucket.Put( |
|
invoiceKey[:], buf.Bytes(), |
|
) |
|
if err != nil { |
|
return err |
|
} |
|
} |
|
|
|
return nil |
|
}, func() {}) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
} |
|
|
|
// TestMigrateInvoices checks that invoices are migrated correctly. |
|
func TestMigrateInvoices(t *testing.T) { |
|
t.Parallel() |
|
|
|
payReqBtc, err := getPayReq(&bitcoinCfg.MainNetParams) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
var ltcNetParams bitcoinCfg.Params |
|
ltcNetParams.Bech32HRPSegwit = litecoinCfg.MainNetParams.Bech32HRPSegwit |
|
payReqLtc, err := getPayReq(<cNetParams) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
invoices := []Invoice{ |
|
{ |
|
PaymentRequest: []byte(payReqBtc), |
|
}, |
|
{ |
|
PaymentRequest: []byte(payReqLtc), |
|
}, |
|
} |
|
|
|
// Verify that all invoices were migrated. |
|
afterMigrationFunc := func(d *DB) { |
|
dbInvoices, err := d.FetchAllInvoices(false) |
|
if err != nil { |
|
t.Fatalf("unable to fetch invoices: %v", err) |
|
} |
|
|
|
if len(invoices) != len(dbInvoices) { |
|
t.Fatalf("expected %d invoices, got %d", len(invoices), |
|
len(dbInvoices)) |
|
} |
|
|
|
for _, dbInvoice := range dbInvoices { |
|
if dbInvoice.FinalCltvDelta != testCltvDelta { |
|
t.Fatal("incorrect final cltv delta") |
|
} |
|
if dbInvoice.Expiry != 3600*time.Second { |
|
t.Fatal("incorrect expiry") |
|
} |
|
if len(dbInvoice.Htlcs) != 0 { |
|
t.Fatal("expected no htlcs after migration") |
|
} |
|
} |
|
} |
|
|
|
applyMigration(t, |
|
func(d *DB) { beforeMigrationFuncV11(t, d, invoices) }, |
|
afterMigrationFunc, |
|
MigrateInvoices, |
|
false) |
|
} |
|
|
|
// TestMigrateInvoicesHodl checks that a hodl invoice in the accepted state |
|
// fails the migration. |
|
func TestMigrateInvoicesHodl(t *testing.T) { |
|
t.Parallel() |
|
|
|
payReqBtc, err := getPayReq(&bitcoinCfg.MainNetParams) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
invoices := []Invoice{ |
|
{ |
|
PaymentRequest: []byte(payReqBtc), |
|
Terms: ContractTerm{ |
|
State: ContractAccepted, |
|
}, |
|
}, |
|
} |
|
|
|
applyMigration(t, |
|
func(d *DB) { beforeMigrationFuncV11(t, d, invoices) }, |
|
func(d *DB) {}, |
|
MigrateInvoices, |
|
true) |
|
} |
|
|
|
// signDigestCompact generates a test signature to be used in the generation of |
|
// test payment requests. |
|
func signDigestCompact(hash []byte) ([]byte, error) { |
|
// Should the signature reference a compressed public key or not. |
|
isCompressedKey := true |
|
|
|
privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), testPrivKeyBytes) |
|
|
|
// btcec.SignCompact returns a pubkey-recoverable signature |
|
sig, err := btcec.SignCompact( |
|
btcec.S256(), privKey, hash, isCompressedKey, |
|
) |
|
if err != nil { |
|
return nil, fmt.Errorf("can't sign the hash: %v", err) |
|
} |
|
|
|
return sig, nil |
|
} |
|
|
|
// getPayReq creates a payment request for the given net. |
|
func getPayReq(net *bitcoinCfg.Params) (string, error) { |
|
options := []func(*zpay32.Invoice){ |
|
zpay32.CLTVExpiry(uint64(testCltvDelta)), |
|
zpay32.Description("test"), |
|
} |
|
|
|
payReq, err := zpay32.NewInvoice( |
|
net, [32]byte{}, time.Unix(1, 0), options..., |
|
) |
|
if err != nil { |
|
return "", err |
|
} |
|
return payReq.Encode( |
|
zpay32.MessageSigner{ |
|
SignCompact: signDigestCompact, |
|
}, |
|
) |
|
}
|
|
|