mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 01:43:16 +01:00
217 lines
5.3 KiB
Go
217 lines
5.3 KiB
Go
package chanbackup
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"net"
|
|
"testing"
|
|
|
|
"github.com/btcsuite/btcd/btcec/v2"
|
|
"github.com/lightningnetwork/lnd/lnencrypt"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
var (
|
|
errRestoreFail = errors.New("restore fail")
|
|
|
|
errConnectFail = errors.New("connect fail")
|
|
)
|
|
|
|
type mockChannelRestorer struct {
|
|
fail bool
|
|
|
|
callCount int
|
|
}
|
|
|
|
func (m *mockChannelRestorer) RestoreChansFromSingles(...Single) error {
|
|
if m.fail {
|
|
return errRestoreFail
|
|
}
|
|
|
|
m.callCount++
|
|
|
|
return nil
|
|
}
|
|
|
|
type mockPeerConnector struct {
|
|
fail bool
|
|
|
|
callCount int
|
|
}
|
|
|
|
func (m *mockPeerConnector) ConnectPeer(_ *btcec.PublicKey,
|
|
_ []net.Addr) error {
|
|
|
|
if m.fail {
|
|
return errConnectFail
|
|
}
|
|
|
|
m.callCount++
|
|
|
|
return nil
|
|
}
|
|
|
|
// TestUnpackAndRecoverSingles tests that we're able to properly unpack and
|
|
// recover a set of packed singles.
|
|
func TestUnpackAndRecoverSingles(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
keyRing := &lnencrypt.MockKeyRing{}
|
|
|
|
// First, we'll create a number of single chan backups that we'll
|
|
// shortly back to so we can begin our recovery attempt.
|
|
numSingles := 10
|
|
backups := make([]Single, 0, numSingles)
|
|
var packedBackups PackedSingles
|
|
for i := 0; i < numSingles; i++ {
|
|
channel, err := genRandomOpenChannelShell()
|
|
require.NoError(t, err)
|
|
|
|
single := NewSingle(channel, nil)
|
|
|
|
var b bytes.Buffer
|
|
err = single.PackToWriter(&b, keyRing)
|
|
require.NoError(t, err)
|
|
|
|
backups = append(backups, single)
|
|
packedBackups = append(packedBackups, b.Bytes())
|
|
}
|
|
|
|
chanRestorer := mockChannelRestorer{}
|
|
peerConnector := mockPeerConnector{}
|
|
|
|
// Now that we have our backups (packed and unpacked), we'll attempt to
|
|
// restore them all in a single batch.
|
|
|
|
// If we make the channel restore fail, then the entire method should
|
|
// as well
|
|
chanRestorer.fail = true
|
|
_, err := UnpackAndRecoverSingles(
|
|
packedBackups, keyRing, &chanRestorer, &peerConnector,
|
|
)
|
|
require.ErrorIs(t, err, errRestoreFail)
|
|
|
|
chanRestorer.fail = false
|
|
|
|
// If we make the peer connector fail, then the entire method should as
|
|
// well
|
|
peerConnector.fail = true
|
|
_, err = UnpackAndRecoverSingles(
|
|
packedBackups, keyRing, &chanRestorer, &peerConnector,
|
|
)
|
|
require.ErrorIs(t, err, errConnectFail)
|
|
|
|
chanRestorer.callCount--
|
|
peerConnector.fail = false
|
|
|
|
// Next, we'll ensure that if all the interfaces function as expected,
|
|
// then the channels will properly be unpacked and restored.
|
|
numRestored, err := UnpackAndRecoverSingles(
|
|
packedBackups, keyRing, &chanRestorer, &peerConnector,
|
|
)
|
|
require.NoError(t, err)
|
|
require.EqualValues(t, numSingles, numRestored)
|
|
|
|
// Both the restorer, and connector should have been called 10 times,
|
|
// once for each backup.
|
|
require.EqualValues(
|
|
t, numSingles, chanRestorer.callCount, "restorer call count",
|
|
)
|
|
require.EqualValues(
|
|
t, numSingles, peerConnector.callCount, "peer call count",
|
|
)
|
|
|
|
// If we modify the keyRing, then unpacking should fail.
|
|
keyRing.Fail = true
|
|
_, err = UnpackAndRecoverSingles(
|
|
packedBackups, keyRing, &chanRestorer, &peerConnector,
|
|
)
|
|
require.ErrorContains(t, err, "fail")
|
|
|
|
// TODO(roasbeef): verify proper call args
|
|
}
|
|
|
|
// TestUnpackAndRecoverMulti tests that we're able to properly unpack and
|
|
// recover a packed multi.
|
|
func TestUnpackAndRecoverMulti(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
keyRing := &lnencrypt.MockKeyRing{}
|
|
|
|
// First, we'll create a number of single chan backups that we'll
|
|
// shortly back to so we can begin our recovery attempt.
|
|
numSingles := 10
|
|
backups := make([]Single, 0, numSingles)
|
|
for i := 0; i < numSingles; i++ {
|
|
channel, err := genRandomOpenChannelShell()
|
|
require.NoError(t, err)
|
|
|
|
single := NewSingle(channel, nil)
|
|
|
|
backups = append(backups, single)
|
|
}
|
|
|
|
multi := Multi{
|
|
StaticBackups: backups,
|
|
}
|
|
|
|
var b bytes.Buffer
|
|
err := multi.PackToWriter(&b, keyRing)
|
|
require.NoError(t, err)
|
|
|
|
// Next, we'll pack the set of singles into a packed multi, and also
|
|
// create the set of interfaces we need to carry out the remainder of
|
|
// the test.
|
|
packedMulti := PackedMulti(b.Bytes())
|
|
|
|
chanRestorer := mockChannelRestorer{}
|
|
peerConnector := mockPeerConnector{}
|
|
|
|
// If we make the channel restore fail, then the entire method should
|
|
// as well
|
|
chanRestorer.fail = true
|
|
_, err = UnpackAndRecoverMulti(
|
|
packedMulti, keyRing, &chanRestorer, &peerConnector,
|
|
)
|
|
require.ErrorIs(t, err, errRestoreFail)
|
|
|
|
chanRestorer.fail = false
|
|
|
|
// If we make the peer connector fail, then the entire method should as
|
|
// well
|
|
peerConnector.fail = true
|
|
_, err = UnpackAndRecoverMulti(
|
|
packedMulti, keyRing, &chanRestorer, &peerConnector,
|
|
)
|
|
require.ErrorIs(t, err, errConnectFail)
|
|
|
|
chanRestorer.callCount--
|
|
peerConnector.fail = false
|
|
|
|
// Next, we'll ensure that if all the interfaces function as expected,
|
|
// then the channels will properly be unpacked and restored.
|
|
numRestored, err := UnpackAndRecoverMulti(
|
|
packedMulti, keyRing, &chanRestorer, &peerConnector,
|
|
)
|
|
require.NoError(t, err)
|
|
require.EqualValues(t, numSingles, numRestored)
|
|
|
|
// Both the restorer, and connector should have been called 10 times,
|
|
// once for each backup.
|
|
require.EqualValues(
|
|
t, numSingles, chanRestorer.callCount, "restorer call count",
|
|
)
|
|
require.EqualValues(
|
|
t, numSingles, peerConnector.callCount, "peer call count",
|
|
)
|
|
|
|
// If we modify the keyRing, then unpacking should fail.
|
|
keyRing.Fail = true
|
|
_, err = UnpackAndRecoverMulti(
|
|
packedMulti, keyRing, &chanRestorer, &peerConnector,
|
|
)
|
|
require.ErrorContains(t, err, "fail")
|
|
|
|
// TODO(roasbeef): verify proper call args
|
|
}
|