2
0
mirror of https://github.com/lightninglabs/loop synced 2024-11-08 01:10:29 +00:00
loop/loopdb/store_test.go
Joost Jager 6a0a9556a0
loopdb: add loop in
This commit adds the required code to persist loop in swaps. It also
introduces the file loop.go to which shared code is moved.

Sharing of contract serialization/deserialization code has been
reverted. The prepay fields do not apply to loop in, but were part of
the shared contract struct. Without also adding a migration, it wouldn't
be possible to keep the shared code.

In general it is probably more flexible to keep the contract
serialization code separated between in and out swaps.
2019-03-28 11:47:38 +01:00

283 lines
6.8 KiB
Go

package loopdb
import (
"crypto/sha256"
"io/ioutil"
"os"
"reflect"
"testing"
"time"
"github.com/btcsuite/btcd/chaincfg"
"github.com/lightninglabs/loop/test"
"github.com/lightningnetwork/lnd/lntypes"
)
var (
senderKey = [33]byte{
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
}
receiverKey = [33]byte{
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3,
}
testPreimage = lntypes.Preimage([32]byte{
1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 4,
1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 4,
})
testTime = time.Date(2018, time.January, 9, 14, 00, 00, 0, time.UTC)
)
// TestLoopOutStore tests all the basic functionality of the current bbolt
// swap store.
func TestLoopOutStore(t *testing.T) {
tempDirName, err := ioutil.TempDir("", "clientstore")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tempDirName)
store, err := NewBoltSwapStore(tempDirName, &chaincfg.MainNetParams)
if err != nil {
t.Fatal(err)
}
// First, verify that an empty database has no active swaps.
swaps, err := store.FetchLoopOutSwaps()
if err != nil {
t.Fatal(err)
}
if len(swaps) != 0 {
t.Fatal("expected empty store")
}
destAddr := test.GetDestAddr(t, 0)
hash := sha256.Sum256(testPreimage[:])
initiationTime := time.Date(2018, 11, 1, 0, 0, 0, 0, time.UTC)
// Next, we'll make a new pending swap that we'll insert into the
// database shortly.
pendingSwap := LoopOutContract{
SwapContract: SwapContract{
AmountRequested: 100,
Preimage: testPreimage,
CltvExpiry: 144,
SenderKey: senderKey,
ReceiverKey: receiverKey,
MaxMinerFee: 10,
MaxSwapFee: 20,
InitiationHeight: 99,
// Convert to/from unix to remove timezone, so that it
// doesn't interfere with DeepEqual.
InitiationTime: time.Unix(0, initiationTime.UnixNano()),
},
MaxPrepayRoutingFee: 40,
PrepayInvoice: "prepayinvoice",
DestAddr: destAddr,
SwapInvoice: "swapinvoice",
MaxSwapRoutingFee: 30,
SweepConfTarget: 2,
}
// checkSwap is a test helper function that'll assert the state of a
// swap.
checkSwap := func(expectedState SwapState) {
t.Helper()
swaps, err := store.FetchLoopOutSwaps()
if err != nil {
t.Fatal(err)
}
if len(swaps) != 1 {
t.Fatal("expected pending swap in store")
}
swap := swaps[0].Contract
if !reflect.DeepEqual(swap, &pendingSwap) {
t.Fatal("invalid pending swap data")
}
if swaps[0].State() != expectedState {
t.Fatalf("expected state %v, but got %v",
expectedState, swaps[0].State(),
)
}
}
// If we create a new swap, then it should show up as being initialized
// right after.
if err := store.CreateLoopOut(hash, &pendingSwap); err != nil {
t.Fatal(err)
}
checkSwap(StateInitiated)
// Trying to make the same swap again should result in an error.
if err := store.CreateLoopOut(hash, &pendingSwap); err == nil {
t.Fatal("expected error on storing duplicate")
}
checkSwap(StateInitiated)
// Next, we'll update to the next state of the pre-image being
// revealed. The state should be reflected here again.
err = store.UpdateLoopOut(
hash, testTime, StatePreimageRevealed,
)
if err != nil {
t.Fatal(err)
}
checkSwap(StatePreimageRevealed)
// Next, we'll update to the final state to ensure that the state is
// properly updated.
err = store.UpdateLoopOut(
hash, testTime, StateFailInsufficientValue,
)
if err != nil {
t.Fatal(err)
}
checkSwap(StateFailInsufficientValue)
if err := store.Close(); err != nil {
t.Fatal(err)
}
// If we re-open the same store, then the state of the current swap
// should be the same.
store, err = NewBoltSwapStore(tempDirName, &chaincfg.MainNetParams)
if err != nil {
t.Fatal(err)
}
checkSwap(StateFailInsufficientValue)
}
// TestLoopInStore tests all the basic functionality of the current bbolt
// swap store.
func TestLoopInStore(t *testing.T) {
tempDirName, err := ioutil.TempDir("", "clientstore")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tempDirName)
store, err := NewBoltSwapStore(tempDirName, &chaincfg.MainNetParams)
if err != nil {
t.Fatal(err)
}
// First, verify that an empty database has no active swaps.
swaps, err := store.FetchLoopInSwaps()
if err != nil {
t.Fatal(err)
}
if len(swaps) != 0 {
t.Fatal("expected empty store")
}
hash := sha256.Sum256(testPreimage[:])
initiationTime := time.Date(2018, 11, 1, 0, 0, 0, 0, time.UTC)
// Next, we'll make a new pending swap that we'll insert into the
// database shortly.
loopInChannel := uint64(123)
pendingSwap := LoopInContract{
SwapContract: SwapContract{
AmountRequested: 100,
Preimage: testPreimage,
CltvExpiry: 144,
SenderKey: senderKey,
ReceiverKey: receiverKey,
MaxMinerFee: 10,
MaxSwapFee: 20,
InitiationHeight: 99,
// Convert to/from unix to remove timezone, so that it
// doesn't interfere with DeepEqual.
InitiationTime: time.Unix(0, initiationTime.UnixNano()),
},
HtlcConfTarget: 2,
LoopInChannel: &loopInChannel,
}
// checkSwap is a test helper function that'll assert the state of a
// swap.
checkSwap := func(expectedState SwapState) {
t.Helper()
swaps, err := store.FetchLoopInSwaps()
if err != nil {
t.Fatal(err)
}
if len(swaps) != 1 {
t.Fatal("expected pending swap in store")
}
swap := swaps[0].Contract
if !reflect.DeepEqual(swap, &pendingSwap) {
t.Fatal("invalid pending swap data")
}
if swaps[0].State() != expectedState {
t.Fatalf("expected state %v, but got %v",
expectedState, swaps[0].State(),
)
}
}
// If we create a new swap, then it should show up as being initialized
// right after.
if err := store.CreateLoopIn(hash, &pendingSwap); err != nil {
t.Fatal(err)
}
checkSwap(StateInitiated)
// Trying to make the same swap again should result in an error.
if err := store.CreateLoopIn(hash, &pendingSwap); err == nil {
t.Fatal("expected error on storing duplicate")
}
checkSwap(StateInitiated)
// Next, we'll update to the next state of the pre-image being
// revealed. The state should be reflected here again.
err = store.UpdateLoopIn(
hash, testTime, StatePreimageRevealed,
)
if err != nil {
t.Fatal(err)
}
checkSwap(StatePreimageRevealed)
// Next, we'll update to the final state to ensure that the state is
// properly updated.
err = store.UpdateLoopIn(
hash, testTime, StateFailInsufficientValue,
)
if err != nil {
t.Fatal(err)
}
checkSwap(StateFailInsufficientValue)
if err := store.Close(); err != nil {
t.Fatal(err)
}
// If we re-open the same store, then the state of the current swap
// should be the same.
store, err = NewBoltSwapStore(tempDirName, &chaincfg.MainNetParams)
if err != nil {
t.Fatal(err)
}
checkSwap(StateFailInsufficientValue)
}